use std::{
marker::PhantomData,
ffi::CString,
path::Path,
};
use crate::{ffi, Synth, Result, Status, Error, FontId, FontRef, PresetRef, Chan, option_from_ptr};
impl Synth {
pub fn sfload<P: AsRef<Path>>(&self, filename: P, reset_presets: bool) -> Result<FontId> {
let filename = filename.as_ref().to_str().ok_or_else(|| Error::Path)?;
let filename = CString::new(filename).map_err(|_| Error::Path)?;
self.neg_err(unsafe { ffi::fluid_synth_sfload(self.handle, filename.as_ptr(), reset_presets as _) })
.map(|id| id as _)
}
pub fn sfreload(&self, id: FontId) -> Result<FontId> {
self.neg_err(unsafe { ffi::fluid_synth_sfreload(self.handle, id as _) })
.map(|id| id as _)
}
pub fn sfunload(&self, id: FontId, reset_presets: bool) -> Status {
self.zero_ok(unsafe { ffi::fluid_synth_sfunload(self.handle, id, reset_presets as _) })
}
pub fn sfcount(&self) -> u32 {
unsafe { ffi::fluid_synth_sfcount(self.handle) as _ }
}
pub fn get_sfont(&self, num: u32) -> Option<FontRef<'_>> {
option_from_ptr(unsafe { ffi::fluid_synth_get_sfont(self.handle, num) })
.map(FontRef::from_ptr)
}
pub fn sfont_iter(&self) -> FontIter<'_> {
FontIter::from_ptr(self.handle)
}
pub fn get_sfont_by_id(&self, id: FontId) -> Option<FontRef<'_>> {
option_from_ptr(unsafe { ffi::fluid_synth_get_sfont_by_id(self.handle, id) })
.map(FontRef::from_ptr)
}
pub fn remove_sfont(&self, sfont: FontRef<'_>) {
unsafe { ffi::fluid_synth_remove_sfont(self.handle, sfont.as_ptr()); }
}
pub fn get_channel_preset(&self, chan: Chan) -> Option<PresetRef<'_>> {
option_from_ptr(unsafe { ffi::fluid_synth_get_channel_preset(self.handle, chan as _) })
.map(PresetRef::from_ptr)
}
pub fn set_bank_offset(&self, sfont_id: FontId, offset: u32) -> Status {
self.zero_ok(unsafe { ffi::fluid_synth_set_bank_offset(self.handle, sfont_id as _, offset as _) })
}
pub fn get_bank_offset(&self, sfont_id: FontId) -> Result<u32> {
self.neg_err(unsafe { ffi::fluid_synth_get_bank_offset(self.handle, sfont_id as _) })
.map(|val| val as _)
}
}
#[cfg(test)]
mod test {
use crate::{IsFont, IsPreset, Settings, Synth};
#[test]
fn font_and_preset() {
let synth = Synth::new(Settings::new().unwrap()).unwrap();
assert_eq!(synth.sfcount(), 0);
synth.sfload("../sf_/Boomwhacker.sf2", true).unwrap();
assert_eq!(synth.sfcount(), 1);
let font = synth.get_sfont(0).unwrap();
assert_eq!(font.get_id(), 1);
assert_eq!(font.get_name().unwrap(), "../sf_/Boomwhacker.sf2");
let preset = font.get_preset(0, 0).unwrap();
assert_eq!(preset.get_name().unwrap(), "Boomwhacker");
assert_eq!(preset.get_banknum().unwrap(), 0);
assert_eq!(preset.get_num().unwrap(), 0);
}
}
pub struct FontIter<'a> {
handle: *mut ffi::fluid_synth_t,
phantom: PhantomData<&'a ()>,
font_no: u32,
}
impl<'a> FontIter<'a> {
fn from_ptr(handle: *mut ffi::fluid_synth_t) -> Self {
Self { handle, phantom: PhantomData, font_no: 0 }
}
}
impl<'a> Iterator for FontIter<'a> {
type Item = FontRef<'a>;
fn next(&mut self) -> Option<Self::Item> {
let font = option_from_ptr(unsafe { ffi::fluid_synth_get_sfont(self.handle, self.font_no) })
.map(FontRef::from_ptr);
if font.is_some() {
self.font_no += 1;
}
font
}
}