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
use std::ffi::{CStr, c_void};
use steam_audio_sys::ffi::{self, iplContextRetain};
use crate::prelude::*;
#[derive(Debug, Default)]
pub struct ContextSettings {
version: Option<u32>,
simd_level: Option<ffi::IPLSIMDLevel>,
}
unsafe extern "C" fn log_callback(level: ffi::IPLLogLevel, message: *const ::std::os::raw::c_char) {
dbg!();
let c_str: &CStr = CStr::from_ptr(message);
let str = c_str.to_str().unwrap();
eprintln!("{:?}: {}", level, str);
}
unsafe extern "C" fn alloc_callback(size: ffi::IPLsize, alignment: ffi::IPLsize) -> *mut c_void {
let layout = match std::alloc::Layout::from_size_align(size as usize, alignment as usize) {
Ok(layout) => layout,
_ => return std::ptr::null_mut(),
};
std::alloc::alloc(layout) as *mut c_void
}
unsafe extern "C" fn free_callback(size: ffi::IPLsize, alignment: ffi::IPLsize) -> *mut c_void {
let layout = match std::alloc::Layout::from_size_align(size as usize, alignment as usize) {
Ok(layout) => layout,
_ => return std::ptr::null_mut(),
};
std::alloc::alloc(layout) as *mut c_void
}
impl Into<ffi::IPLContextSettings> for ContextSettings {
fn into(self) -> ffi::IPLContextSettings {
ffi::IPLContextSettings {
version: self.version.unwrap_or(ffi::STEAMAUDIO_VERSION),
logCallback: Some(log_callback),
allocateCallback: Some(alloc_callback),
simdLevel: self
.simd_level
.unwrap_or(ffi::IPLSIMDLevel::IPL_SIMDLEVEL_SSE2),
freeCallback: None,
}
}
}
pub struct Context {
pub(crate) inner: ffi::IPLContext,
settings: ffi::IPLContextSettings,
}
impl Context {
pub fn new(settings: ContextSettings) -> Result<Self, SteamAudioError> {
let mut ipl_settings: ffi::IPLContextSettings = settings.into();
let mut context = Self {
inner: unsafe { std::mem::zeroed() },
settings: ipl_settings,
};
unsafe {
match ffi::iplContextCreate(&mut context.settings, &mut context.inner) {
ffi::IPLerror::IPL_STATUS_SUCCESS => Ok(context),
err => Err(SteamAudioError::IPLError(err)),
}
}
}
pub unsafe fn inner(&self) -> ffi::IPLContext {
self.inner
}
pub fn retain(&self) -> Context {
unsafe {
let new_context = iplContextRetain(self.inner);
Context {
inner: new_context,
settings: self.settings,
}
}
}
pub fn debug(&mut self) {
dbg!(self.inner);
dbg!(self.settings);
}
}
impl Drop for Context {
fn drop(&mut self) {
unsafe {
ffi::iplContextRelease(&mut self.inner);
}
}
}