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
#![deny(missing_docs)]
extern crate current;
extern crate sdl2;
use sdl2::mixer as mix;
use current::{ Current, CurrentGuard };
use std::collections::HashMap;
use std::hash::Hash;
use std::any::Any;
use std::path::Path;
pub const MIN_VOLUME: f64 = 0.0;
pub const MAX_VOLUME: f64 = 1.0;
fn init_audio() {
let _ = mix::init(
mix::INIT_MP3
| mix::INIT_FLAC
| mix::INIT_MOD
| mix::INIT_FLUIDSYNTH
| mix::INIT_MODPLUG
| mix::INIT_OGG
);
mix::open_audio(
mix::DEFAULT_FREQUENCY,
mix::DEFAULT_FORMAT,
mix::DEFAULT_CHANNELS,
1024
).unwrap();
mix::allocate_channels(mix::DEFAULT_CHANNELS);
}
unsafe fn current_music_tracks<T: 'static + Any>() -> Current<HashMap<T, mix::Music>> {
Current::new()
}
pub fn start<T: Eq + Hash + 'static + Any, F: FnOnce()>(f: F) {
let sdl = sdl2::init().unwrap();
let audio = sdl.audio().unwrap();
let timer = sdl.timer().unwrap();
init_audio();
let mut music_tracks: HashMap<T, mix::Music> = HashMap::new();
let music_tracks_guard = CurrentGuard::new(&mut music_tracks);
f();
drop(music_tracks_guard);
drop(timer);
drop(audio);
drop(sdl);
}
pub fn bind_file<T, P>(val: T, file: P)
where T: 'static + Eq + Hash + Any,
P: AsRef<Path>
{
let track = mix::Music::from_file(&file.as_ref()).unwrap();
unsafe { current_music_tracks() }.insert(val, track);
}
#[derive(Copy, Clone)]
pub enum Repeat {
Forever,
Times(u16),
}
impl Repeat {
fn to_sdl2_repeats(&self) -> i32 {
match self {
&Repeat::Forever => -1,
&Repeat::Times(val) => {
val as i32
}
}
}
}
pub fn set_volume(volume: f64) {
mix::Music::set_volume((volume.max(MIN_VOLUME).min(MAX_VOLUME) * mix::MAX_VOLUME as f64)
as i32);
}
pub fn play<T: Eq + Hash + 'static + Any>(val: &T, repeat: Repeat) {
let _ = unsafe { current_music_tracks::<T>() }.get(val)
.expect("music: Attempted to play value that is not bound to asset")
.play(repeat.to_sdl2_repeats());
}