use crate::index::*;
use crate::resample::*;
use crate::*;
use ffms2_sys::*;
use std::ffi::c_void;
use std::ffi::CString;
use std::mem;
use std::path::Path;
simple_enum!(
AudioChannel,
(
CH_FRONT_LEFT,
CH_FRONT_RIGHT,
CH_FRONT_CENTER,
CH_LOW_FREQUENCY,
CH_BACK_LEFT,
CH_BACK_RIGHT,
CH_FRONT_LEFT_OF_CENTER,
CH_FRONT_RIGHT_OF_CENTER,
CH_BACK_CENTER,
CH_SIDE_LEFT,
CH_SIDE_RIGHT,
CH_TOP_CENTER,
CH_TOP_FRONT_LEFT,
CH_TOP_FRONT_CENTER,
CH_TOP_FRONT_RIGHT,
CH_TOP_BACK_LEFT,
CH_TOP_BACK_CENTER,
CH_TOP_BACK_RIGHT,
CH_STEREO_LEFT,
CH_STEREO_RIGHT,
)
);
simple_enum!(
AudioDelay,
(DELAY_NO_SHIFT, DELAY_TIME_ZERO, DELAY_FIRST_VIDEO_TRACK)
);
simple_enum!(
MatrixEncoding,
(
MATRIX_ENCODING_NONE,
MATRIX_ENCODING_DOBLY,
MATRIX_ENCODING_PRO_LOGIC_II,
MATRIX_ENCODING_PRO_LOGIC_IIX,
MATRIX_ENCODING_PRO_LOGIC_IIZ,
MATRIX_ENCODING_DOLBY_EX,
MATRIX_ENCODING_DOLBY_HEADPHONE,
)
);
create_struct!(
AudioProperties,
audio_properties,
FFMS_AudioProperties,
(
SampleFormat,
SampleRate,
BitsPerSample,
Channels,
ChannelLayout,
NumSamples,
FirstTime,
LastTime,
LastEndTime,
),
(0, 0, 0, 0, 0, 0, 0.0, 0.0, 0.0)
);
pub struct AudioSource {
audio_source: *mut FFMS_AudioSource,
}
unsafe impl Send for AudioSource {}
impl AudioSource {
pub fn new(
SourceFile: &Path,
Track: usize,
Index: &Index,
DelayMode: isize,
) -> Result<Self, Error> {
let source = CString::new(SourceFile.to_str().unwrap()).unwrap();
let mut error: Error = Default::default();
let audio_source = unsafe {
FFMS_CreateAudioSource(
source.as_ptr(),
Track as i32,
Index.as_mut_ptr(),
DelayMode as i32,
error.as_mut_ptr(),
)
};
if audio_source.is_null() {
Err(error)
} else {
Ok(AudioSource { audio_source })
}
}
pub fn GetAudioProperties(&self) -> AudioProperties {
let audio_prop = unsafe { FFMS_GetAudioProperties(self.audio_source) };
let ref_audio = unsafe { &*audio_prop };
AudioProperties {
audio_properties: *ref_audio,
}
}
pub fn GetAudio<T>(
&self,
Start: usize,
Count: usize,
) -> Result<Vec<T>, Error> {
let mut error: Error = Default::default();
let audio_prop = self.GetAudioProperties();
let num_samples = audio_prop.NumSamples;
if Start as i64 > (num_samples - 1) || Count as i64 > (num_samples - 1)
{
panic!("Requesting samples beyond the stream end");
}
let num_channels = audio_prop.Channels;
let num_elements = Count * num_channels as usize;
let Buf: Vec<T> = Vec::with_capacity(num_elements);
let mut Buf = mem::ManuallyDrop::new(Buf);
let buf_ptr = Buf.as_mut_ptr();
let err = unsafe {
FFMS_GetAudio(
self.audio_source,
buf_ptr as *mut c_void,
Start as i64,
Count as i64,
error.as_mut_ptr(),
)
};
if err != 0 {
Err(error)
} else {
let audio_vec = unsafe {
Vec::from_raw_parts(buf_ptr, num_elements, num_elements)
};
Ok(audio_vec)
}
}
pub fn CreateResampleOptions(&self) -> ResampleOptions {
let res_opt = unsafe { FFMS_CreateResampleOptions(self.audio_source) };
let ref_res = unsafe { &*res_opt };
ResampleOptions::create_struct(ref_res)
}
pub fn SetOutputFormatA(
&self,
options: &ResampleOptions,
) -> Result<(), Error> {
let mut error: Error = Default::default();
let err = unsafe {
FFMS_SetOutputFormatA(
self.audio_source,
options.as_ptr(),
error.as_mut_ptr(),
)
};
if err != 0 {
Err(error)
} else {
Ok(())
}
}
pub(crate) fn as_mut_ptr(&mut self) -> *mut FFMS_AudioSource {
self.audio_source
}
}
impl Drop for AudioSource {
fn drop(&mut self) {
unsafe {
FFMS_DestroyAudioSource(self.audio_source);
}
}
}