From 49ad12ff14387b4e00385a2e9d4e9f14f0f78bde Mon Sep 17 00:00:00 2001 From: bart Date: Sat, 7 Nov 2026 17:21:24 +0100 Subject: [PATCH] fix(metadata): clear stream_title when DJ is talking --- jellyfin-kiosk-rs/src/mqtt.rs | 25 +++++++++++++++- jellyfin-kiosk-rs/src/player.rs | 52 ++++++++++++++++++++++++--------- 2 files changed, 63 insertions(+), 14 deletions(-) diff --git a/jellyfin-kiosk-rs/src/mqtt.rs b/jellyfin-kiosk-rs/src/mqtt.rs index 79490f9..9112995 100644 --- a/jellyfin-kiosk-rs/src/mqtt.rs +++ b/jellyfin-kiosk-rs/src/mqtt.rs @@ -43,7 +43,11 @@ impl MqttPlaybackState { artist: st.artist.clone(), playlist: st.playlist.clone(), genre: st.genre.clone(), - stream_title: st.stream_title.clone(), + stream_title: if st.artist == "Radio Chicken DJ" || st.stream_title.contains("Radio Chicken DJ") { + String::new() + } else { + st.stream_title.clone() + }, } } } @@ -524,6 +528,25 @@ mod tests { assert_eq!(mqtt_state.stream_title, ""); } + #[test] + fn test_dj_announcement_stream_title_empty() { + let st = PlayerStatus { + state: PlaybackState::Playing, + media_type: "video".to_string(), + title: "Radio Chicken TV: Up next: Iron Maiden - The Trooper".to_string(), + artist: "Radio Chicken DJ".to_string(), + playlist: "HEUL_HARD".to_string(), + genre: "DJ".to_string(), + stream_title: "Radio Chicken DJ - Up next: Iron Maiden - The Trooper".to_string(), + ..PlayerStatus::default() + }; + + let mqtt_state = MqttPlaybackState::from_status(&st); + assert_eq!(mqtt_state.state, "playing"); + assert_eq!(mqtt_state.artist, "Radio Chicken DJ"); + assert_eq!(mqtt_state.stream_title, ""); + } + #[test] fn test_yaml_config_deserialization() { let yaml_str = r#" diff --git a/jellyfin-kiosk-rs/src/player.rs b/jellyfin-kiosk-rs/src/player.rs index 561deed..a283e98 100644 --- a/jellyfin-kiosk-rs/src/player.rs +++ b/jellyfin-kiosk-rs/src/player.rs @@ -502,7 +502,12 @@ impl PlayerController { InternalMpvEvent::MediaTitle(mt) => { if !is_url_or_query_string(&mt) { if st.media_type == "stream" { - if (st.stream_title.is_empty() || st.stream_title != mt) && !st.stream_title.contains(" - ") { + if st.artist == "Radio Chicken DJ" || mt.contains("Radio Chicken DJ") { + if !st.stream_title.is_empty() { + st.stream_title.clear(); + notify = true; + } + } else if (st.stream_title.is_empty() || st.stream_title != mt) && !st.stream_title.contains(" - ") { st.stream_title = mt; notify = true; } @@ -513,16 +518,23 @@ impl PlayerController { } } InternalMpvEvent::IcyTitle(icy) => { - if !is_url_or_query_string(&icy) && st.stream_title != icy { - st.stream_title = icy.clone(); - st.media_type = "stream".to_string(); - if let Some((art, tit)) = parse_artist_title(&icy) { - if st.artist.is_empty() { - st.artist = art; + if !is_url_or_query_string(&icy) { + if st.artist == "Radio Chicken DJ" || icy.contains("Radio Chicken DJ") { + if !st.stream_title.is_empty() { + st.stream_title.clear(); + notify = true; } - st.title = tit; + } else if st.stream_title != icy { + st.stream_title = icy.clone(); + st.media_type = "stream".to_string(); + if let Some((art, tit)) = parse_artist_title(&icy) { + if st.artist.is_empty() { + st.artist = art; + } + st.title = tit; + } + notify = true; } - notify = true; } } InternalMpvEvent::Metadata { artist, genre, stream_title, title } => { @@ -545,7 +557,12 @@ impl PlayerController { } } if let Some(s) = stream_title { - if !is_url_or_query_string(&s) && st.stream_title != s { + if st.artist == "Radio Chicken DJ" || s.contains("Radio Chicken DJ") { + if !st.stream_title.is_empty() { + st.stream_title.clear(); + notify = true; + } + } else if !is_url_or_query_string(&s) && st.stream_title != s { st.stream_title = s.clone(); st.media_type = "stream".to_string(); if let Some((art, tit)) = parse_artist_title(&s) { @@ -917,7 +934,13 @@ impl PlayerController { st.artist = song.artist.clone(); st.playlist = playlist_name.clone(); st.genre = song.genre.clone(); - st.stream_title = format!("{} - {}", song.artist, song.name); + if song.is_tts || song.artist == "Radio Chicken DJ" { + st.stream_title.clear(); + } else if let Some(ref st_title) = song.stream_title { + st.stream_title = st_title.clone(); + } else { + st.stream_title = format!("{} - {}", song.artist, song.name); + } st.title = if is_video { format!("Radio Chicken TV: {}", song.name) } else { @@ -926,11 +949,12 @@ impl PlayerController { drop(st); player.notify_status().await; tracing::info!( - "Radio Chicken metadata updated: artist='{}', title='{}', playlist='{}', genre='{}'", + "Radio Chicken metadata updated: artist='{}', title='{}', playlist='{}', genre='{}', stream_title='{}'", song.artist, song.name, playlist_name, - song.genre + song.genre, + if song.is_tts || song.artist == "Radio Chicken DJ" { "" } else { &song.name } ); } } @@ -969,6 +993,8 @@ pub struct RadioChickenCurrentSong { #[serde(default)] pub genre: String, #[serde(default)] + pub stream_title: Option, + #[serde(default)] pub is_tts: bool, }