sfml_modstream/
lib.rs

1extern crate openmpt_sys;
2extern crate sfml;
3
4use crate::string::OpenMptString;
5use openmpt_sys::*;
6use sfml::audio::SoundStream;
7use sfml::system::Time;
8use std::fs::File;
9use std::io;
10use std::io::prelude::*;
11use std::path::Path;
12use std::ptr;
13
14mod string;
15
16pub struct ModStream {
17    module: *mut openmpt_module,
18    buffer: [i16; 2048],
19}
20
21impl ModStream {
22    pub fn from_file<P: AsRef<Path>>(path: P) -> Result<Self, io::Error> {
23        let mut file = File::open(path)?;
24        let mut buf = Vec::new();
25        file.read_to_end(&mut buf)?;
26        Ok(Self::from_memory(&buf))
27    }
28    pub fn from_memory(data: &[u8]) -> Self {
29        unsafe {
30            let module = openmpt_module_create_from_memory(
31                data.as_ptr() as *const _,
32                data.len(),
33                None,
34                ptr::null_mut(),
35                ptr::null(),
36            );
37            if module.is_null() {
38                panic!("Failed load module");
39            }
40            Self {
41                module,
42                buffer: [0; 2048],
43            }
44        }
45    }
46    pub fn get_duration_seconds(&self) -> f64 {
47        unsafe { openmpt_module_get_duration_seconds(self.module) }
48    }
49    pub fn metadata<'a, K: Key<'a>>(&self, key: K) -> Option<OpenMptString> {
50        let key = std::ffi::CString::new(key.into_str()).unwrap();
51        let ret = unsafe { openmpt_module_get_metadata(self.module, key.as_ptr()) };
52        OpenMptString::new(ret)
53    }
54}
55
56pub trait Key<'a> {
57    fn into_str(self) -> &'a str;
58}
59
60impl<'a> Key<'a> for &'a str {
61    fn into_str(self) -> &'a str {
62        self
63    }
64}
65
66pub enum Metadata {
67    Tracker,
68    Artist,
69    Title,
70    Date,
71    Message,
72}
73
74impl Key<'static> for Metadata {
75    fn into_str(self) -> &'static str {
76        match self {
77            Self::Tracker => "tracker",
78            Self::Artist => "artist",
79            Self::Title => "title",
80            Self::Date => "date",
81            Self::Message => "message",
82        }
83    }
84}
85
86impl SoundStream for ModStream {
87    fn get_data(&mut self) -> (&mut [i16], bool) {
88        unsafe {
89            let keep_playing = openmpt_module_read_interleaved_stereo(
90                self.module,
91                44_100,
92                1024,
93                self.buffer.as_mut_ptr(),
94            ) != 0;
95            (&mut self.buffer[..], keep_playing)
96        }
97    }
98    fn seek(&mut self, offset: Time) {
99        unsafe {
100            openmpt_module_set_position_seconds(self.module, f64::from(offset.as_seconds()));
101        }
102    }
103    fn sample_rate(&self) -> u32 {
104        44_100
105    }
106    fn channel_count(&self) -> u32 {
107        2
108    }
109}
110
111impl Drop for ModStream {
112    fn drop(&mut self) {
113        unsafe {
114            openmpt_module_destroy(self.module);
115        }
116    }
117}