+63
-8
src/app.rs
+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
+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
}