Browse and listen to thousands of radio stations across the globe right from your terminal ๐ŸŒŽ ๐Ÿ“ป ๐ŸŽตโœจ
radio rust tokio web-radio command-line-tool tui

Merge pull request #36 from tsirysndr/fix/empty-nowplaying

fix: preserve original station ID when creating Station from StationLinkDetails

authored by tsiry-sandratraina.com and committed by GitHub e8224c31 5ee3fcff

Changed files
+54 -3
src
+1 -1
src/app.rs
··· 887 } 888 889 /// Send [`os_media_controls::Command`]. 890 - fn send_os_media_controls_command( 891 os_media_controls: Option<&mut OsMediaControls>, 892 command: os_media_controls::Command<'_>, 893 ) {
··· 887 } 888 889 /// Send [`os_media_controls::Command`]. 890 + pub fn send_os_media_controls_command( 891 os_media_controls: Option<&mut OsMediaControls>, 892 command: os_media_controls::Command<'_>, 893 ) {
+47 -1
src/interactive.rs
··· 7 use ratatui::prelude::*; 8 use ratatui::widgets::{Block, Borders, List, ListItem, ListState, Paragraph}; 9 use tokio::sync::mpsc; 10 11 use crate::audio::{AudioController, PlaybackEvent, PlaybackState}; 12 use crate::extract::get_currently_playing; 13 use crate::favorites::{FavoriteStation, FavoritesStore}; ··· 42 let (input_tx, mut input_rx) = mpsc::unbounded_channel(); 43 spawn_input_thread(input_tx.clone()); 44 45 let mut app = HubApp::new( 46 provider_name.to_string(), 47 provider, 48 audio, 49 favorites, 50 metadata_tx, 51 ); 52 53 let result = loop { ··· 103 metadata_tx: mpsc::UnboundedSender<HubMessage>, 104 now_playing_station_id: Option<String>, 105 next_now_playing_poll: Instant, 106 } 107 108 impl HubApp { ··· 112 audio: AudioController, 113 favorites: FavoritesStore, 114 metadata_tx: mpsc::UnboundedSender<HubMessage>, 115 ) -> Self { 116 let mut ui = UiState::default(); 117 ui.menu_state.select(Some(0)); ··· 129 metadata_tx, 130 now_playing_station_id: None, 131 next_now_playing_poll: Instant::now(), 132 } 133 } 134 ··· 202 }) 203 }) 204 .unwrap_or_else(|| "Unknown".to_string()); 205 - self.render_labeled_line(frame, area, row, "Station ", &station_name); 206 row += 1; 207 208 let now_playing = self ··· 969 self.current_playback = Some(state.clone()); 970 if let Some(station) = self.current_station.as_mut() { 971 station.station.playing = Some(state.now_playing.clone()); 972 } 973 self.set_status(&format!("Now playing {}", state.stream_name)); 974 self.prepare_now_playing_poll(); ··· 996 station.station.playing = Some(now_playing.clone()); 997 } 998 self.set_status(&format!("Now Playing {}", now_playing)); 999 } 1000 } 1001 }
··· 7 use ratatui::prelude::*; 8 use ratatui::widgets::{Block, Borders, List, ListItem, ListState, Paragraph}; 9 use tokio::sync::mpsc; 10 + use tunein_cli::os_media_controls::{self, OsMediaControls}; 11 12 + use crate::app::send_os_media_controls_command; 13 use crate::audio::{AudioController, PlaybackEvent, PlaybackState}; 14 use crate::extract::get_currently_playing; 15 use crate::favorites::{FavoriteStation, FavoritesStore}; ··· 44 let (input_tx, mut input_rx) = mpsc::unbounded_channel(); 45 spawn_input_thread(input_tx.clone()); 46 47 + let os_media_controls = OsMediaControls::new() 48 + .inspect_err(|err| { 49 + eprintln!( 50 + "error: failed to initialize os media controls due to `{}`", 51 + err 52 + ); 53 + }) 54 + .ok(); 55 + 56 let mut app = HubApp::new( 57 provider_name.to_string(), 58 provider, 59 audio, 60 favorites, 61 metadata_tx, 62 + os_media_controls, 63 ); 64 65 let result = loop { ··· 115 metadata_tx: mpsc::UnboundedSender<HubMessage>, 116 now_playing_station_id: Option<String>, 117 next_now_playing_poll: Instant, 118 + os_media_controls: Option<OsMediaControls>, 119 } 120 121 impl HubApp { ··· 125 audio: AudioController, 126 favorites: FavoritesStore, 127 metadata_tx: mpsc::UnboundedSender<HubMessage>, 128 + os_media_controls: Option<OsMediaControls>, 129 ) -> Self { 130 let mut ui = UiState::default(); 131 ui.menu_state.select(Some(0)); ··· 143 metadata_tx, 144 now_playing_station_id: None, 145 next_now_playing_poll: Instant::now(), 146 + os_media_controls, 147 } 148 } 149 ··· 217 }) 218 }) 219 .unwrap_or_else(|| "Unknown".to_string()); 220 + let station_id = self 221 + .current_playback 222 + .as_ref() 223 + .map(|p| p.station.id.as_str()) 224 + .or_else(|| self.current_station.as_ref().map(|s| s.station.id.as_str())) 225 + .unwrap_or("N/A"); 226 + 227 + self.render_labeled_line( 228 + frame, 229 + area, 230 + row, 231 + "Station ", 232 + &format!("{} - {}", station_name, station_id), 233 + ); 234 row += 1; 235 236 let now_playing = self ··· 997 self.current_playback = Some(state.clone()); 998 if let Some(station) = self.current_station.as_mut() { 999 station.station.playing = Some(state.now_playing.clone()); 1000 + station.station.id = state.station.id.clone(); 1001 } 1002 self.set_status(&format!("Now playing {}", state.stream_name)); 1003 self.prepare_now_playing_poll(); ··· 1025 station.station.playing = Some(now_playing.clone()); 1026 } 1027 self.set_status(&format!("Now Playing {}", now_playing)); 1028 + 1029 + let name = self 1030 + .current_station 1031 + .as_ref() 1032 + .map(|s| s.station.name.clone()) 1033 + .unwrap_or_default(); 1034 + 1035 + send_os_media_controls_command( 1036 + self.os_media_controls.as_mut(), 1037 + os_media_controls::Command::SetMetadata(souvlaki::MediaMetadata { 1038 + title: (!now_playing.is_empty()).then_some(now_playing.as_str()), 1039 + album: (!name.is_empty()).then_some(name.as_str()), 1040 + artist: None, 1041 + cover_url: None, 1042 + duration: None, 1043 + }), 1044 + ); 1045 } 1046 } 1047 }
+6 -1
src/provider/tunein.rs
··· 55 None => Ok(None), 56 } 57 } 58 - _ => Ok(Some(Station::from(stations[0].clone()))), 59 } 60 } 61
··· 55 None => Ok(None), 56 } 57 } 58 + _ => { 59 + let mut station = Station::from(stations[0].clone()); 60 + // Preserve the original station ID since StationLinkDetails doesn't contain it 61 + station.id = id; 62 + Ok(Some(station)) 63 + } 64 } 65 } 66