From b962a1882b5bdacb1ef2c30e886e0e248695f68b Mon Sep 17 00:00:00 2001 From: Jan-Henrik Bruhn Date: Tue, 19 Mar 2024 22:21:14 +0100 Subject: [PATCH] Less error prone interstitial playback --- src/main.rs | 58 ++++++++++++++++++++++++++++++------------------- src/streamer.rs | 34 ++++++++++++++--------------- 2 files changed, 53 insertions(+), 39 deletions(-) diff --git a/src/main.rs b/src/main.rs index 7a237ea..ee36efb 100644 --- a/src/main.rs +++ b/src/main.rs @@ -28,6 +28,9 @@ struct Config { #[envconfig(from = "SONG_PREFETCH", default = "2")] pub song_prefetch: u32, + + #[envconfig(from = "INTERSTITIAL_PATH")] + pub interstitial_path: Option, } async fn get_time_file_map( @@ -53,13 +56,11 @@ async fn get_time_file_map( let hour = name_split .next() .ok_or(anyhow::anyhow!("No hour!"))? - .parse() - .unwrap(); + .parse()?; let minute = name_split .next() .ok_or(anyhow::anyhow!("No minute!"))? - .parse() - .unwrap(); + .parse()?; let time = chrono::NaiveTime::from_hms_opt(hour, minute, 0) .ok_or(anyhow::anyhow!("Can't parse time"))?; Ok::<_, anyhow::Error>((time, path)) @@ -149,8 +150,16 @@ async fn main() -> anyhow::Result<()> { let mut time_announce_mixer_controller = mixer_controller.clone(); tokio::task::spawn(async move { - let time_file_map = - get_time_file_map(&std::path::PathBuf::from("./interstitials/time")).await; + if config.interstitial_path.is_none() { + println!("No interstitials, skipping interstitial task. Specify a folder with INTERSTITIAL_PATH."); + return; + } + + let mut time_file_path = std::path::PathBuf::from(config.interstitial_path.unwrap()); + time_file_path.push("time"); + println!("Looking for time files at {:?}", time_file_path); + + let time_file_map = get_time_file_map(&time_file_path).await; loop { tokio::task::yield_now().await; @@ -196,31 +205,36 @@ async fn main() -> anyhow::Result<()> { } .unwrap(); - println!("Next Internstitial time {}", interstitial_time); + println!( + "Next Internstitial time {interstitial_time}: {:?}", + next_path + ); tokio::time::sleep_until( tokio::time::Instant::now() + (interstitial_time - now).to_std().unwrap(), ) .await; - println!("Internstitial time {}", interstitial_time); + println!("Playing interstitial {:?}", next_path); - for v in (fade_steps_min..=fade_steps_max).rev() { - let volume = v as f32 / fade_steps as f32; - announce_downmix_player_controller.set_volume(volume); - tokio::time::sleep(fade_duration / (fade_steps_max - fade_steps_min)).await; - } + if let Ok(sound) = awedio::sounds::open_file(next_path.as_path()) { + let (sound, completion_notifier) = sound.with_async_completion_notifier(); + for v in (fade_steps_min..=fade_steps_max).rev() { + let volume = v as f32 / fade_steps as f32; + announce_downmix_player_controller.set_volume(volume); + tokio::time::sleep(fade_duration / (fade_steps_max - fade_steps_min)).await; + } - let (sound, completion_notifier) = awedio::sounds::open_file(next_path.as_path()) - .unwrap() - .with_async_completion_notifier(); - time_announce_mixer_controller.add(Box::new(sound)); - let _ = completion_notifier.await; + time_announce_mixer_controller.add(Box::new(sound)); + let _ = completion_notifier.await; - for v in fade_steps_min..=fade_steps_max { - let volume = v as f32 / fade_steps as f32; - announce_downmix_player_controller.set_volume(volume); - tokio::time::sleep(fade_duration / (fade_steps_max - fade_steps_min)).await; + for v in fade_steps_min..=fade_steps_max { + let volume = v as f32 / fade_steps as f32; + announce_downmix_player_controller.set_volume(volume); + tokio::time::sleep(fade_duration / (fade_steps_max - fade_steps_min)).await; + } + } else { + println!("Error playing interstitial"); } } } diff --git a/src/streamer.rs b/src/streamer.rs index 435b346..40e203a 100644 --- a/src/streamer.rs +++ b/src/streamer.rs @@ -40,25 +40,25 @@ impl StreamerBackend { )) .map(move |_| { let mut buffer = [0_i16; BUFFER_SIZE]; - renderer.on_start_of_batch(); - tokio::task::block_in_place(|| { - buffer.fill_with(|| { - let sample = renderer - .next_sample() - .expect("renderer should never return an Error"); - let sample = match sample { - awedio::NextSample::Sample(s) => s, - awedio::NextSample::MetadataChanged => { - unreachable!("we never change metadata mid-batch") - } - awedio::NextSample::Paused => 0, - awedio::NextSample::Finished => 0, - }; - sample - }); + renderer.on_start_of_batch(); + tokio::task::block_in_place(|| { + buffer.fill_with(|| { + let sample = renderer + .next_sample() + .expect("renderer should never return an Error"); + let sample = match sample { + awedio::NextSample::Sample(s) => s, + awedio::NextSample::MetadataChanged => { + unreachable!("we never change metadata mid-batch") + } + awedio::NextSample::Paused => 0, + awedio::NextSample::Finished => 0, + }; + sample }); - Box::new(buffer) }); + Box::new(buffer) + }); loop { s.broadcast(stream.next().await.expect("Should not end!"))