Ajout de la gestion des couvertures d'albums par le FlacCacheSink
This commit is contained in:
170
old_code/pmoplaylist/examples/basic_usage.rs
Normal file
170
old_code/pmoplaylist/examples/basic_usage.rs
Normal file
@@ -0,0 +1,170 @@
|
||||
//! Exemple d'utilisation basique de pmoplaylist
|
||||
//!
|
||||
//! Pour exécuter cet exemple :
|
||||
//! ```bash
|
||||
//! cargo run -p pmoplaylist --example basic_usage
|
||||
//! ```
|
||||
|
||||
use pmoplaylist::{FifoPlaylist, Track, DEFAULT_IMAGE};
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
println!("=== Exemple pmoplaylist ===\n");
|
||||
|
||||
// 1. Créer une playlist FIFO
|
||||
println!("1. Création d'une playlist avec capacité de 5 tracks...");
|
||||
let playlist = FifoPlaylist::new(
|
||||
"my-radio".to_string(),
|
||||
"Ma Radio Préférée".to_string(),
|
||||
5,
|
||||
DEFAULT_IMAGE,
|
||||
);
|
||||
println!(" ✓ Playlist créée: {}", playlist.title().await);
|
||||
println!(" ✓ ID: {}", playlist.id().await);
|
||||
println!(" ✓ Capacité: 5 tracks");
|
||||
println!(" ✓ Update ID initial: {}\n", playlist.update_id().await);
|
||||
|
||||
// 2. Ajouter des tracks
|
||||
println!("2. Ajout de 3 tracks...");
|
||||
let tracks = vec![
|
||||
Track::new(
|
||||
"track-1",
|
||||
"Bohemian Rhapsody",
|
||||
"http://example.com/queen/bohemian.flac",
|
||||
)
|
||||
.with_artist("Queen")
|
||||
.with_album("A Night at the Opera")
|
||||
.with_duration(354)
|
||||
.with_image("http://example.com/covers/queen-anato.jpg"),
|
||||
Track::new(
|
||||
"track-2",
|
||||
"Stairway to Heaven",
|
||||
"http://example.com/zeppelin/stairway.mp3",
|
||||
)
|
||||
.with_artist("Led Zeppelin")
|
||||
.with_album("Led Zeppelin IV")
|
||||
.with_duration(482),
|
||||
Track::new(
|
||||
"track-3",
|
||||
"Hotel California",
|
||||
"http://example.com/eagles/hotel.flac",
|
||||
)
|
||||
.with_artist("Eagles")
|
||||
.with_album("Hotel California")
|
||||
.with_duration(391),
|
||||
];
|
||||
|
||||
for track in tracks {
|
||||
playlist.append_track(track.clone()).await;
|
||||
println!(
|
||||
" ✓ Ajouté: {} - {}",
|
||||
track.title,
|
||||
track.artist.unwrap_or_default()
|
||||
);
|
||||
}
|
||||
|
||||
println!("\n Total tracks: {}", playlist.len().await);
|
||||
println!(" Update ID: {}\n", playlist.update_id().await);
|
||||
|
||||
// 3. Tester le comportement FIFO
|
||||
println!("3. Test du comportement FIFO (capacité = 5)...");
|
||||
println!(" Ajout de 4 tracks supplémentaires...");
|
||||
|
||||
for i in 4..=7 {
|
||||
let track = Track::new(
|
||||
format!("track-{}", i),
|
||||
format!("Song Number {}", i),
|
||||
format!("http://example.com/songs/{}.mp3", i),
|
||||
);
|
||||
playlist.append_track(track).await;
|
||||
}
|
||||
|
||||
println!(
|
||||
" ✓ Total tracks (limité par capacité): {}",
|
||||
playlist.len().await
|
||||
);
|
||||
|
||||
// Afficher les tracks actuels
|
||||
let items = playlist.get_items(0, 10).await;
|
||||
println!("\n Tracks actuels dans la FIFO:");
|
||||
for (idx, track) in items.iter().enumerate() {
|
||||
println!(" {}. {} ({})", idx + 1, track.title, track.id);
|
||||
}
|
||||
println!(" (Les tracks 1 et 2 ont été supprimés automatiquement)\n");
|
||||
|
||||
// 4. Supprimer le plus ancien
|
||||
println!("4. Suppression du track le plus ancien...");
|
||||
if let Some(removed) = playlist.remove_oldest().await {
|
||||
println!(" ✓ Supprimé: {} ({})", removed.title, removed.id);
|
||||
}
|
||||
println!(" Total tracks: {}", playlist.len().await);
|
||||
println!(" Update ID: {}\n", playlist.update_id().await);
|
||||
|
||||
// 5. Supprimer par ID
|
||||
println!("5. Suppression d'un track par ID (track-5)...");
|
||||
if playlist.remove_by_id("track-5").await {
|
||||
println!(" ✓ Track supprimé");
|
||||
}
|
||||
println!(" Total tracks: {}", playlist.len().await);
|
||||
println!(" Update ID: {}\n", playlist.update_id().await);
|
||||
|
||||
// 6. Générer un Container DIDL-Lite
|
||||
println!("6. Génération du Container DIDL-Lite...");
|
||||
let container = playlist.as_container().await;
|
||||
println!(" Container:");
|
||||
println!(" - ID: {}", container.id);
|
||||
println!(" - Parent ID: {}", container.parent_id);
|
||||
println!(" - Title: {}", container.title);
|
||||
println!(" - Class: {}", container.class);
|
||||
println!(
|
||||
" - Child Count: {}\n",
|
||||
container.child_count.unwrap_or_default()
|
||||
);
|
||||
|
||||
// 7. Générer des Items DIDL-Lite
|
||||
println!("7. Génération des Items DIDL-Lite...");
|
||||
let didl_items = playlist
|
||||
.as_objects(0, 10, Some("http://myserver/api/default-image"))
|
||||
.await;
|
||||
|
||||
println!(" Items DIDL-Lite:");
|
||||
for (idx, item) in didl_items.iter().enumerate() {
|
||||
println!("\n Item {}:", idx + 1);
|
||||
println!(" - ID: {}", item.id);
|
||||
println!(" - Title: {}", item.title);
|
||||
println!(" - Artist: {}", item.artist.as_deref().unwrap_or("N/A"));
|
||||
println!(" - Album: {}", item.album.as_deref().unwrap_or("N/A"));
|
||||
println!(" - Class: {}", item.class);
|
||||
println!(" - Parent ID: {}", item.parent_id);
|
||||
|
||||
if !item.resources.is_empty() {
|
||||
println!(" - Resource URI: {}", item.resources[0].url);
|
||||
if let Some(ref duration) = item.resources[0].duration {
|
||||
println!(" - Duration: {}", duration);
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(ref art) = item.album_art {
|
||||
println!(" - Album Art: {}", art);
|
||||
}
|
||||
}
|
||||
|
||||
// 8. Image par défaut
|
||||
println!("\n8. Image par défaut...");
|
||||
let default_image = playlist.default_image().await;
|
||||
println!(
|
||||
" ✓ Taille de l'image par défaut: {} bytes",
|
||||
default_image.len()
|
||||
);
|
||||
println!(" (Cette image peut être servie via un endpoint HTTP)\n");
|
||||
|
||||
// 9. Vider la playlist
|
||||
println!("9. Vidage de la playlist...");
|
||||
playlist.clear().await;
|
||||
println!(" ✓ Playlist vidée");
|
||||
println!(" Total tracks: {}", playlist.len().await);
|
||||
println!(" Is empty: {}", playlist.is_empty().await);
|
||||
println!(" Update ID final: {}\n", playlist.update_id().await);
|
||||
|
||||
println!("=== Exemple terminé ===");
|
||||
}
|
||||
217
old_code/pmoplaylist/examples/http_server_integration.rs
Normal file
217
old_code/pmoplaylist/examples/http_server_integration.rs
Normal file
@@ -0,0 +1,217 @@
|
||||
//! Exemple d'intégration avec un serveur HTTP
|
||||
//!
|
||||
//! Cet exemple montre comment exposer une playlist FIFO via des endpoints HTTP simples.
|
||||
//! Dans un vrai MediaServer UPnP, ces endpoints seraient appelés par le protocole ContentDirectory.
|
||||
//!
|
||||
//! Pour exécuter :
|
||||
//! ```bash
|
||||
//! cargo run -p pmoplaylist --example http_server_integration
|
||||
//! ```
|
||||
|
||||
use pmoplaylist::{FifoPlaylist, Track, DEFAULT_IMAGE};
|
||||
use std::sync::Arc;
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
println!("=== Intégration HTTP Server ===\n");
|
||||
|
||||
// Créer une playlist partagée
|
||||
let playlist = Arc::new(FifoPlaylist::new(
|
||||
"my-radio".to_string(),
|
||||
"My Internet Radio".to_string(),
|
||||
20,
|
||||
DEFAULT_IMAGE,
|
||||
));
|
||||
|
||||
println!("📻 Playlist créée: {}", playlist.title().await);
|
||||
println!("🆔 ID: {}\n", playlist.id().await);
|
||||
|
||||
// Ajouter quelques tracks initiaux
|
||||
println!("📝 Ajout de tracks initiaux...");
|
||||
let initial_tracks = vec![
|
||||
("The Beatles", "Come Together", "Abbey Road", 259),
|
||||
("Nirvana", "Smells Like Teen Spirit", "Nevermind", 301),
|
||||
("Queen", "Bohemian Rhapsody", "A Night at the Opera", 354),
|
||||
];
|
||||
|
||||
for (idx, (artist, title, album, duration)) in initial_tracks.iter().enumerate() {
|
||||
playlist
|
||||
.append_track(
|
||||
Track::new(
|
||||
format!("track-{}", idx),
|
||||
*title,
|
||||
format!("http://media.server/music/{}.flac", idx),
|
||||
)
|
||||
.with_artist(*artist)
|
||||
.with_album(*album)
|
||||
.with_duration(*duration)
|
||||
.with_image(format!("http://media.server/covers/{}.jpg", idx)),
|
||||
)
|
||||
.await;
|
||||
println!(" ✓ {} - {}", artist, title);
|
||||
}
|
||||
println!();
|
||||
|
||||
// Simuler différents endpoints HTTP
|
||||
|
||||
// 1. GET /playlist/container - Retourne le container DIDL-Lite
|
||||
println!("🌐 Endpoint: GET /playlist/container");
|
||||
simulate_get_container(playlist.clone()).await;
|
||||
println!();
|
||||
|
||||
// 2. GET /playlist/items?offset=0&count=10 - Retourne les items
|
||||
println!("🌐 Endpoint: GET /playlist/items?offset=0&count=10");
|
||||
simulate_get_items(playlist.clone(), 0, 10).await;
|
||||
println!();
|
||||
|
||||
// 3. GET /playlist/metadata - Retourne les métadonnées
|
||||
println!("🌐 Endpoint: GET /playlist/metadata");
|
||||
simulate_get_metadata(playlist.clone()).await;
|
||||
println!();
|
||||
|
||||
// 4. POST /playlist/track - Ajoute un nouveau track
|
||||
println!("🌐 Endpoint: POST /playlist/track");
|
||||
let new_track = Track::new(
|
||||
"track-new-1",
|
||||
"Stairway to Heaven",
|
||||
"http://media.server/music/stairway.flac",
|
||||
)
|
||||
.with_artist("Led Zeppelin")
|
||||
.with_album("Led Zeppelin IV")
|
||||
.with_duration(482);
|
||||
|
||||
simulate_add_track(playlist.clone(), new_track).await;
|
||||
println!();
|
||||
|
||||
// 5. DELETE /playlist/oldest - Supprime le plus ancien
|
||||
println!("🌐 Endpoint: DELETE /playlist/oldest");
|
||||
simulate_delete_oldest(playlist.clone()).await;
|
||||
println!();
|
||||
|
||||
// 6. GET /playlist/default-image - Retourne l'image par défaut
|
||||
println!("🌐 Endpoint: GET /playlist/default-image");
|
||||
simulate_get_default_image(playlist.clone()).await;
|
||||
println!();
|
||||
|
||||
// 7. Vérifier l'état final
|
||||
println!("📊 État final:");
|
||||
let final_items = playlist.get_items(0, 10).await;
|
||||
println!(" Total tracks: {}", playlist.len().await);
|
||||
println!(" Update ID: {}", playlist.update_id().await);
|
||||
println!("\n Tracks actuels:");
|
||||
for (idx, track) in final_items.iter().enumerate() {
|
||||
let artist = track.artist.as_deref().unwrap_or("Unknown");
|
||||
println!(" {}. {} - {}", idx + 1, artist, track.title);
|
||||
}
|
||||
|
||||
println!("\n=== Exemple terminé ===");
|
||||
}
|
||||
|
||||
/// Simule GET /playlist/container
|
||||
async fn simulate_get_container(playlist: Arc<FifoPlaylist>) {
|
||||
let container = playlist.as_container().await;
|
||||
|
||||
println!(" Response (JSON representation):");
|
||||
println!(" {{");
|
||||
println!(" \"id\": \"{}\",", container.id);
|
||||
println!(" \"parentId\": \"{}\",", container.parent_id);
|
||||
println!(" \"title\": \"{}\",", container.title);
|
||||
println!(" \"class\": \"{}\",", container.class);
|
||||
println!(
|
||||
" \"childCount\": {}",
|
||||
container.child_count.unwrap_or_default()
|
||||
);
|
||||
println!(" }}");
|
||||
}
|
||||
|
||||
/// Simule GET /playlist/items?offset=X&count=Y
|
||||
async fn simulate_get_items(playlist: Arc<FifoPlaylist>, offset: usize, count: usize) {
|
||||
let items = playlist
|
||||
.as_objects(offset, count, Some("http://media.server/api/default-image"))
|
||||
.await;
|
||||
|
||||
println!(" Response: {} items", items.len());
|
||||
println!(" [");
|
||||
for (idx, item) in items.iter().enumerate() {
|
||||
println!(" {{");
|
||||
println!(" \"id\": \"{}\",", item.id);
|
||||
println!(" \"title\": \"{}\",", item.title);
|
||||
println!(
|
||||
" \"artist\": \"{}\",",
|
||||
item.artist.as_deref().unwrap_or("")
|
||||
);
|
||||
println!(
|
||||
" \"album\": \"{}\",",
|
||||
item.album.as_deref().unwrap_or("")
|
||||
);
|
||||
println!(" \"class\": \"{}\",", item.class);
|
||||
if !item.resources.is_empty() {
|
||||
println!(" \"uri\": \"{}\",", item.resources[0].url);
|
||||
}
|
||||
print!(" }}");
|
||||
if idx < items.len() - 1 {
|
||||
println!(",");
|
||||
} else {
|
||||
println!();
|
||||
}
|
||||
}
|
||||
println!(" ]");
|
||||
}
|
||||
|
||||
/// Simule GET /playlist/metadata
|
||||
async fn simulate_get_metadata(playlist: Arc<FifoPlaylist>) {
|
||||
let update_id = playlist.update_id().await;
|
||||
let last_change = playlist.last_change().await;
|
||||
let count = playlist.len().await;
|
||||
let id = playlist.id().await;
|
||||
let title = playlist.title().await;
|
||||
|
||||
println!(" Response:");
|
||||
println!(" {{");
|
||||
println!(" \"id\": \"{}\",", id);
|
||||
println!(" \"title\": \"{}\",", title);
|
||||
println!(" \"trackCount\": {},", count);
|
||||
println!(" \"updateId\": {},", update_id);
|
||||
println!(" \"lastChange\": \"{:?}\"", last_change);
|
||||
println!(" }}");
|
||||
}
|
||||
|
||||
/// Simule POST /playlist/track
|
||||
async fn simulate_add_track(playlist: Arc<FifoPlaylist>, track: Track) {
|
||||
let old_update_id = playlist.update_id().await;
|
||||
|
||||
playlist.append_track(track.clone()).await;
|
||||
|
||||
let new_update_id = playlist.update_id().await;
|
||||
|
||||
println!(
|
||||
" Track added: {} - {}",
|
||||
track.artist.as_deref().unwrap_or("Unknown"),
|
||||
track.title
|
||||
);
|
||||
println!(" Update ID: {} → {}", old_update_id, new_update_id);
|
||||
println!(" Response: 201 Created");
|
||||
}
|
||||
|
||||
/// Simule DELETE /playlist/oldest
|
||||
async fn simulate_delete_oldest(playlist: Arc<FifoPlaylist>) {
|
||||
if let Some(removed) = playlist.remove_oldest().await {
|
||||
println!(" Track removed: {} ({})", removed.title, removed.id);
|
||||
println!(" New update ID: {}", playlist.update_id().await);
|
||||
println!(" Response: 200 OK");
|
||||
} else {
|
||||
println!(" No tracks to remove");
|
||||
println!(" Response: 404 Not Found");
|
||||
}
|
||||
}
|
||||
|
||||
/// Simule GET /playlist/default-image
|
||||
async fn simulate_get_default_image(playlist: Arc<FifoPlaylist>) {
|
||||
let image_bytes = playlist.default_image().await;
|
||||
|
||||
println!(" Response:");
|
||||
println!(" Content-Type: image/webp");
|
||||
println!(" Content-Length: {} bytes", image_bytes.len());
|
||||
println!(" Status: 200 OK");
|
||||
println!(" (Image WebP {} bytes ready to serve)", image_bytes.len());
|
||||
}
|
||||
198
old_code/pmoplaylist/examples/radio_streaming.rs
Normal file
198
old_code/pmoplaylist/examples/radio_streaming.rs
Normal file
@@ -0,0 +1,198 @@
|
||||
//! Exemple simulant une radio en streaming
|
||||
//!
|
||||
//! Cet exemple démontre :
|
||||
//! - L'utilisation de FifoPlaylist dans un contexte multi-thread
|
||||
//! - La simulation d'un flux radio continu
|
||||
//! - La surveillance des changements via update_id
|
||||
//!
|
||||
//! Pour exécuter :
|
||||
//! ```bash
|
||||
//! cargo run -p pmoplaylist --example radio_streaming
|
||||
//! ```
|
||||
|
||||
use pmoplaylist::{FifoPlaylist, Track, DEFAULT_IMAGE};
|
||||
use std::time::Duration;
|
||||
use tokio::time::sleep;
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() {
|
||||
println!("=== Simulation Radio en Streaming ===\n");
|
||||
|
||||
// Créer une radio avec historique limité à 10 tracks
|
||||
let radio = FifoPlaylist::new(
|
||||
"radio-paradise".to_string(),
|
||||
"Radio Paradise - Main Mix".to_string(),
|
||||
10,
|
||||
DEFAULT_IMAGE,
|
||||
);
|
||||
|
||||
println!("📻 Radio créée: {}", radio.title().await);
|
||||
println!("📊 Capacité: 10 tracks (historique limité)");
|
||||
println!("🆔 ID: {}\n", radio.id().await);
|
||||
|
||||
// Cloner pour les différentes tâches
|
||||
let radio_streamer = radio.clone();
|
||||
let radio_monitor = radio.clone();
|
||||
let radio_client = radio.clone();
|
||||
|
||||
// Tâche 1: Simuler le streaming (ajoute des tracks régulièrement)
|
||||
let streamer = tokio::spawn(async move {
|
||||
println!("🎵 [STREAMER] Démarrage du flux radio...\n");
|
||||
|
||||
let tracks_data = vec![
|
||||
("Radiohead", "Paranoid Android", "OK Computer", 383),
|
||||
("Massive Attack", "Teardrop", "Mezzanine", 329),
|
||||
(
|
||||
"Pink Floyd",
|
||||
"Shine On You Crazy Diamond",
|
||||
"Wish You Were Here",
|
||||
810,
|
||||
),
|
||||
("Portishead", "Glory Box", "Dummy", 305),
|
||||
("Dire Straits", "Sultans of Swing", "Dire Straits", 349),
|
||||
("The Cure", "Pictures of You", "Disintegration", 428),
|
||||
("David Bowie", "Heroes", "Heroes", 371),
|
||||
(
|
||||
"Talking Heads",
|
||||
"Once in a Lifetime",
|
||||
"Remain in Light",
|
||||
259,
|
||||
),
|
||||
("Fleetwood Mac", "Dreams", "Rumours", 257),
|
||||
(
|
||||
"The Smiths",
|
||||
"There Is a Light That Never Goes Out",
|
||||
"The Queen Is Dead",
|
||||
244,
|
||||
),
|
||||
("Joy Division", "Love Will Tear Us Apart", "Closer", 206),
|
||||
("New Order", "Blue Monday", "Power, Corruption & Lies", 448),
|
||||
("Depeche Mode", "Enjoy the Silence", "Violator", 376),
|
||||
("R.E.M.", "Losing My Religion", "Out of Time", 269),
|
||||
(
|
||||
"U2",
|
||||
"Where the Streets Have No Name",
|
||||
"The Joshua Tree",
|
||||
337,
|
||||
),
|
||||
];
|
||||
|
||||
for (idx, (artist, title, album, duration)) in tracks_data.iter().enumerate() {
|
||||
let track = Track::new(
|
||||
format!("radio-track-{}", idx),
|
||||
*title,
|
||||
format!("http://stream.radioparadise.com/track/{}", idx),
|
||||
)
|
||||
.with_artist(*artist)
|
||||
.with_album(*album)
|
||||
.with_duration(*duration);
|
||||
|
||||
radio_streamer.append_track(track).await;
|
||||
|
||||
println!("🎵 [STREAMER] Now Playing: {} - {}", artist, title);
|
||||
|
||||
// Simuler l'attente entre les tracks
|
||||
sleep(Duration::from_millis(500)).await;
|
||||
}
|
||||
|
||||
println!("\n🎵 [STREAMER] Fin du streaming");
|
||||
});
|
||||
|
||||
// Tâche 2: Monitorer les changements (update_id)
|
||||
let monitor = tokio::spawn(async move {
|
||||
sleep(Duration::from_millis(100)).await;
|
||||
|
||||
println!("👁️ [MONITOR] Surveillance des changements...\n");
|
||||
|
||||
let mut last_update_id = 0;
|
||||
let mut iterations = 0;
|
||||
|
||||
loop {
|
||||
let current_update_id = radio_monitor.update_id().await;
|
||||
let count = radio_monitor.len().await;
|
||||
|
||||
if current_update_id != last_update_id {
|
||||
println!(
|
||||
"👁️ [MONITOR] Changement détecté! Update ID: {} → {} | Tracks: {}",
|
||||
last_update_id, current_update_id, count
|
||||
);
|
||||
last_update_id = current_update_id;
|
||||
}
|
||||
|
||||
iterations += 1;
|
||||
if iterations >= 50 {
|
||||
break;
|
||||
}
|
||||
|
||||
sleep(Duration::from_millis(200)).await;
|
||||
}
|
||||
|
||||
println!("\n👁️ [MONITOR] Fin de la surveillance");
|
||||
});
|
||||
|
||||
// Tâche 3: Client consultant l'historique
|
||||
let client = tokio::spawn(async move {
|
||||
sleep(Duration::from_millis(2000)).await;
|
||||
|
||||
println!("\n📱 [CLIENT] Consultation de l'historique de la radio...\n");
|
||||
|
||||
// Consulter plusieurs fois pendant le streaming
|
||||
for i in 0..3 {
|
||||
sleep(Duration::from_millis(2000)).await;
|
||||
|
||||
let history = radio_client.get_items(0, 10).await;
|
||||
let update_id = radio_client.update_id().await;
|
||||
|
||||
println!(
|
||||
"📱 [CLIENT] Consultation #{} (Update ID: {})",
|
||||
i + 1,
|
||||
update_id
|
||||
);
|
||||
println!(" Historique actuel ({} tracks):", history.len());
|
||||
|
||||
for (idx, track) in history.iter().enumerate() {
|
||||
let artist = track.artist.as_deref().unwrap_or("Unknown");
|
||||
println!(" {}. {} - {}", idx + 1, artist, track.title);
|
||||
}
|
||||
println!();
|
||||
}
|
||||
|
||||
// Générer le container DIDL-Lite à la fin
|
||||
println!("📱 [CLIENT] Génération du Container DIDL-Lite...");
|
||||
let container = radio_client.as_container().await;
|
||||
println!(" Container ID: {}", container.id);
|
||||
println!(" Title: {}", container.title);
|
||||
println!(
|
||||
" Child Count: {}",
|
||||
container.child_count.unwrap_or_default()
|
||||
);
|
||||
|
||||
println!("\n📱 [CLIENT] Fin de la consultation");
|
||||
});
|
||||
|
||||
// Attendre que toutes les tâches se terminent
|
||||
let _ = tokio::join!(streamer, monitor, client);
|
||||
|
||||
// Afficher l'état final
|
||||
println!("\n=== État Final ===");
|
||||
println!("📊 Total tracks dans la radio: {}", radio.len().await);
|
||||
println!("🆔 Update ID final: {}", radio.update_id().await);
|
||||
|
||||
let final_history = radio.get_items(0, 10).await;
|
||||
println!("\n🎵 Historique final (10 derniers tracks):");
|
||||
for (idx, track) in final_history.iter().enumerate() {
|
||||
let artist = track.artist.as_deref().unwrap_or("Unknown");
|
||||
let duration_min = track.duration.map(|d| d / 60).unwrap_or(0);
|
||||
let duration_sec = track.duration.map(|d| d % 60).unwrap_or(0);
|
||||
println!(
|
||||
" {}. {} - {} ({}:{:02})",
|
||||
idx + 1,
|
||||
artist,
|
||||
track.title,
|
||||
duration_min,
|
||||
duration_sec
|
||||
);
|
||||
}
|
||||
|
||||
println!("\n=== Simulation terminée ===");
|
||||
}
|
||||
Reference in New Issue
Block a user