use crate::{ffi, option_from_ptr, Chan, Error, FontId, FontRef, PresetRef, Result, Status, Synth};
use std::{ffi::CString, marker::PhantomData, path::Path};
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(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
}
}