la crate des playlists

This commit is contained in:
2025-10-27 12:32:31 +01:00
parent a0e5d92bf9
commit 92c35116f8
23 changed files with 1943 additions and 837 deletions

View File

@@ -31,6 +31,7 @@ anyhow = "1.0"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
quick-xml = { version = "0.37", features = ["serialize"] }
paste = "1.0"
# Async
tokio = { version = "1.0", features = ["full"] }

View File

@@ -78,6 +78,7 @@
pub mod cache;
pub mod metadata;
pub mod metadata_ext;
#[cfg(feature = "pmoserver")]
pub mod openapi;
@@ -88,6 +89,7 @@ pub mod config_ext;
// Re-exports principaux
pub use cache::{add_with_metadata_extraction, get_metadata, new_cache, AudioConfig, Cache};
pub use metadata::AudioMetadata;
pub use metadata_ext::AudioMetadataExt;
#[cfg(feature = "pmoconfig")]
pub use config_ext::AudioCacheConfigExt;

View File

@@ -159,6 +159,81 @@ impl AudioMetadata {
_ => None,
}
}
/// Retourne la durée formatée pour DIDL-Lite (H:MM:SS)
///
/// # Exemple
///
/// ```
/// use pmoaudiocache::AudioMetadata;
///
/// let metadata = AudioMetadata {
/// duration_secs: Some(3665),
/// ..Default::default()
/// };
///
/// assert_eq!(metadata.duration_formatted(), Some("1:01:05".to_string()));
/// ```
pub fn duration_formatted(&self) -> Option<String> {
self.duration_secs.map(|d| {
let hours = d / 3600;
let minutes = (d % 3600) / 60;
let seconds = d % 60;
format!("{}:{:02}:{:02}", hours, minutes, seconds)
})
}
/// Convertit les métadonnées en Resource DIDL-Lite
///
/// # Arguments
///
/// * `url` - URL de la ressource audio
///
/// # Exemple
///
/// ```no_run
/// use pmoaudiocache::AudioMetadata;
///
/// let metadata = AudioMetadata {
/// duration_secs: Some(180),
/// sample_rate: Some(44100),
/// channels: Some(2),
/// ..Default::default()
/// };
///
/// let resource = metadata.to_didl_resource("http://localhost:8080/audio/tracks/abc123".into());
/// assert_eq!(resource.url, "http://localhost:8080/audio/tracks/abc123");
/// ```
pub fn to_didl_resource(&self, url: String) -> pmodidl::Resource {
pmodidl::Resource {
protocol_info: "http-get:*:audio/flac:*".to_string(),
bits_per_sample: None,
sample_frequency: self.sample_rate.map(|sr| sr.to_string()),
nr_audio_channels: self.channels.map(|ch| ch.to_string()),
duration: self.duration_formatted(),
url,
}
}
}
impl Default for AudioMetadata {
fn default() -> Self {
Self {
title: None,
artist: None,
album: None,
year: None,
track_number: None,
track_total: None,
disc_number: None,
disc_total: None,
genre: None,
duration_secs: None,
sample_rate: None,
channels: None,
bitrate: None,
}
}
}
#[cfg(test)]

View File

@@ -0,0 +1,35 @@
//! Extension trait pour accéder aux métadonnées audio de manière typée
//!
//! Ce module utilise la macro `define_metadata_properties!` de pmocache
//! pour générer automatiquement des méthodes d'accès typées aux métadonnées audio.
use pmocache::define_metadata_properties;
use crate::AudioConfig;
// Génération automatique du trait AudioMetadataExt avec toutes les propriétés audio
define_metadata_properties! {
AudioMetadataExt for pmocache::Cache<AudioConfig> {
// Métadonnées textuelles
title: String as string,
artist: String as string,
album: String as string,
album_artist: String as string,
genre: String as string,
composer: String as string,
comment: String as string,
// Métadonnées numériques (année, numéros de piste)
year: i64 as i64,
track_number: i64 as i64,
disc_number: i64 as i64,
total_tracks: i64 as i64,
total_discs: i64 as i64,
// Métadonnées techniques audio
duration_secs: i64 as i64,
sample_rate: i64 as i64,
bitrate: i64 as i64,
channels: i64 as i64,
bit_depth: i64 as i64,
}
}