1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
use std::error::Error;
use std::io::Cursor;
use rodio::{Decoder, OutputStream, Sink};
use widgetry::{
Btn, Checkbox, EventCtx, GfxCtx, HorizontalAlignment, Outcome, Panel, VerticalAlignment,
};
pub struct Music {
inner: Option<Inner>,
}
impl std::default::Default for Music {
fn default() -> Music {
Music::empty()
}
}
struct Inner {
_stream: OutputStream,
sink: Sink,
panel: Panel,
}
impl Music {
pub fn empty() -> Music {
Music { inner: None }
}
pub fn start(ctx: &mut EventCtx, play_music: bool) -> Music {
match Inner::new(ctx, play_music) {
Ok(inner) => Music { inner: Some(inner) },
Err(err) => {
error!("No music, sorry: {}", err);
Music::empty()
}
}
}
pub fn event(&mut self, ctx: &mut EventCtx, play_music: &mut bool) {
if let Some(ref mut inner) = self.inner {
match inner.panel.event(ctx) {
Outcome::Clicked(_) => unreachable!(),
Outcome::Changed => {
if inner.panel.is_checked("play music") {
*play_music = true;
inner.unmute();
} else {
*play_music = false;
inner.mute();
}
}
_ => {}
}
}
}
pub fn draw(&self, g: &mut GfxCtx) {
if let Some(ref inner) = self.inner {
inner.panel.draw(g);
}
}
}
impl Inner {
fn new(ctx: &mut EventCtx, play_music: bool) -> Result<Inner, Box<dyn Error>> {
let (stream, stream_handle) = OutputStream::try_default()?;
let sink = rodio::Sink::try_new(&stream_handle)?;
let raw_bytes =
Cursor::new(include_bytes!("../../data/system/assets/music/jingle_bells.ogg").to_vec());
sink.append(Decoder::new_looped(raw_bytes)?);
if !play_music {
sink.set_volume(0.0);
}
let panel = Panel::new(
Checkbox::new(
play_music,
Btn::svg_def("system/assets/tools/volume_off.svg").build(ctx, "play music", None),
Btn::svg_def("system/assets/tools/volume_on.svg").build(ctx, "mute music", None),
)
.named("play music")
.container(),
)
.aligned(
HorizontalAlignment::LeftInset,
VerticalAlignment::BottomInset,
)
.build(ctx);
Ok(Inner {
_stream: stream,
sink,
panel,
})
}
fn unmute(&mut self) {
self.sink.set_volume(1.0);
}
fn mute(&mut self) {
self.sink.set_volume(0.0);
}
}