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

play: SinkCommand: SetVolume

Allow user to set volume.

Changed files
+70 -9
src
+63 -8
src/app.rs
··· 30 30 pub genre: String, 31 31 pub description: String, 32 32 pub br: String, 33 + /// [`Volume`]. 34 + pub volume: Volume, 33 35 } 34 36 35 37 /// Volume of the player. ··· 52 54 if self.is_muted { 53 55 0.0 54 56 } else { 55 - 1.0 57 + self.volume 56 58 } 57 59 } 58 60 ··· 229 231 }, 230 232 frame, 231 233 ); 234 + render_line( 235 + "Volume ", 236 + &if state.volume.is_muted() { 237 + format!("{} muted", state.volume.volume()) 238 + } else { 239 + format!("{}", state.volume.volume()) 240 + }, 241 + Rect { 242 + x: size.x, 243 + y: match state.now_playing.is_empty() { 244 + true => size.y + 5, 245 + false => size.y + 6, 246 + }, 247 + width: size.width, 248 + height: 1, 249 + }, 250 + frame, 251 + ) 232 252 } 233 253 234 254 fn render_line(label: &str, value: &str, area: Rect, frame: &mut Frame) { ··· 327 347 let event = event::read().unwrap(); 328 348 329 349 if self 330 - .process_events(event.clone(), &mut sink_cmd_tx) 350 + .process_events(event.clone(), new_state.clone(), &mut sink_cmd_tx) 331 351 .unwrap() 332 352 { 333 353 return; ··· 356 376 fn process_events( 357 377 &mut self, 358 378 event: Event, 379 + state: Arc<Mutex<State>>, 359 380 sink_cmd_tx: &mut UnboundedSender<SinkCommand>, 360 381 ) -> Result<bool, io::Error> { 361 382 let mut quit = false; 383 + 384 + let lower_volume = || { 385 + let mut state = state.lock().unwrap(); 386 + state.volume.change_volume(-0.01); 387 + sink_cmd_tx 388 + .send(SinkCommand::SetVolume(state.volume.volume())) 389 + .expect("receiver never dropped"); 390 + }; 391 + 392 + let raise_volume = || { 393 + let mut state = state.lock().unwrap(); 394 + state.volume.change_volume(0.01); 395 + sink_cmd_tx 396 + .send(SinkCommand::SetVolume(state.volume.volume())) 397 + .expect("receiver never dropped"); 398 + }; 399 + 400 + let mute_volume = || { 401 + let mut state = state.lock().unwrap(); 402 + state.volume.toggle_mute(); 403 + sink_cmd_tx 404 + .send(SinkCommand::SetVolume(state.volume.volume())) 405 + .expect("receiver never dropped"); 406 + }; 407 + 362 408 if let Event::Key(key) = event { 363 409 if let KeyModifiers::CONTROL = key.modifiers { 364 410 match key.code { ··· 374 420 _ => 1.0, 375 421 }; 376 422 match key.code { 377 - KeyCode::Up => update_value_f(&mut self.graph.scale, 0.01, magnitude, 0.0..10.0), // inverted to act as zoom 378 - KeyCode::Down => update_value_f(&mut self.graph.scale, -0.01, magnitude, 0.0..10.0), // inverted to act as zoom 423 + KeyCode::Up => { 424 + // inverted to act as zoom 425 + update_value_f(&mut self.graph.scale, 0.01, magnitude, 0.0..10.0); 426 + raise_volume(); 427 + } 428 + KeyCode::Down => { 429 + // inverted to act as zoom 430 + update_value_f(&mut self.graph.scale, -0.01, magnitude, 0.0..10.0); 431 + lower_volume(); 432 + } 379 433 KeyCode::Right => update_value_i( 380 434 &mut self.graph.samples, 381 435 true, ··· 403 457 KeyCode::Char('s') => self.graph.scatter = !self.graph.scatter, 404 458 KeyCode::Char('h') => self.graph.show_ui = !self.graph.show_ui, 405 459 KeyCode::Char('r') => self.graph.references = !self.graph.references, 460 + KeyCode::Char('m') => mute_volume(), 406 461 KeyCode::Esc => { 407 462 self.graph.samples = self.graph.width; 408 463 self.graph.scale = 1.; ··· 449 504 MediaKeyCode::Stop => { 450 505 quit = true; 451 506 } 452 - MediaKeyCode::LowerVolume 453 - | MediaKeyCode::RaiseVolume 454 - | MediaKeyCode::MuteVolume 455 - | MediaKeyCode::TrackNext 507 + MediaKeyCode::LowerVolume => lower_volume(), 508 + MediaKeyCode::RaiseVolume => raise_volume(), 509 + MediaKeyCode::MuteVolume => mute_volume(), 510 + MediaKeyCode::TrackNext 456 511 | MediaKeyCode::TrackPrevious 457 512 | MediaKeyCode::Reverse 458 513 | MediaKeyCode::FastForward
+7 -1
src/play.rs
··· 4 4 use hyper::header::HeaderValue; 5 5 6 6 use crate::{ 7 - app::{App, State}, 7 + app::{App, State, Volume}, 8 8 cfg::{SourceOptions, UiOptions}, 9 9 decoder::Mp3Decoder, 10 10 provider::{radiobrowser::Radiobrowser, tunein::Tunein, Provider}, ··· 91 91 .to_str() 92 92 .unwrap() 93 93 .to_string(), 94 + volume: Volume::default(), 94 95 }) 95 96 .unwrap(); 96 97 let location = response.headers().get("location"); ··· 121 122 SinkCommand::Pause => { 122 123 sink.pause(); 123 124 } 125 + SinkCommand::SetVolume(volume) => { 126 + sink.set_volume(volume); 127 + } 124 128 } 125 129 } 126 130 std::thread::sleep(Duration::from_millis(10)); ··· 140 144 Play, 141 145 /// Pause. 142 146 Pause, 147 + /// Set the volume. 148 + SetVolume(f32), 143 149 }