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
109
110
111
112
use crate::errors::{Error};
use wasm_bindgen::prelude::*;
use wasm_bindgen::JsCast;
use web_sys::{AudioBuffer, AudioBufferSourceNode, AudioContext};
use std::rc::Rc;
use std::cell::RefCell;
pub struct AudioPlayer {
pub node: AudioBufferSourceNode,
pub cb: Option<Closure<dyn FnMut() -> ()>>,
}
impl AudioPlayer {
pub fn play<F>(
ctx: &AudioContext,
buffer: &AudioBuffer,
on_ended: Option<F>,
) -> Result<Self, Error>
where
F: FnMut() -> () + 'static,
{
let node = ctx.create_buffer_source()?;
node.set_buffer(Some(buffer));
node.connect_with_audio_node(&ctx.destination())?;
let cb: Option<Closure<dyn FnMut() -> ()>> = match on_ended {
Some(f) => {
let cb = Closure::wrap(Box::new(f) as Box<dyn FnMut() -> ()>);
node.set_onended(Some(cb.as_ref().unchecked_ref()));
Some(cb)
}
None => None,
};
node.start()?;
Ok(Self { node, cb })
}
pub fn play_oneshot<F>(
ctx: &AudioContext,
buffer: &AudioBuffer,
on_ended: Option<F>,
) -> Result<Rc<RefCell<Option<AudioPlayer>>>, Error>
where
F: FnMut() -> () + 'static,
{
let player = Rc::new(RefCell::new(None));
let on_ended = Rc::new(RefCell::new(on_ended));
let _player = AudioPlayer::play(ctx, buffer, Some({
let player = Rc::clone(&player);
move || {
on_ended.borrow_mut().as_mut().map(|cb| cb());
player.borrow_mut().take();
}
}))?;
*player.borrow_mut() = Some(_player);
Ok(player)
}
}
impl Drop for AudioPlayer {
fn drop(&mut self) {
self.node.stop().unwrap_throw();
self.node.set_onended(None);
self.cb.take();
}
}
pub struct AudioOneShot {
pub player: Rc<RefCell<Option<AudioPlayer>>>,
}
impl AudioOneShot {
pub fn play<F>(
ctx: &AudioContext,
buffer: &AudioBuffer,
on_ended: Option<F>,
) -> Result<Self, Error>
where
F: FnMut() -> () + 'static,
{
let player = Rc::new(RefCell::new(None));
let on_ended = Rc::new(RefCell::new(on_ended));
let _player = AudioPlayer::play(ctx, buffer, Some({
let player = Rc::clone(&player);
move || {
on_ended.borrow_mut().as_mut().map(|cb| cb());
player.borrow_mut().take();
}
}))?;
*player.borrow_mut() = Some(_player);
Ok(Self{
player
})
}
}