linear_model_allen/
device.rs1use crate::{AllenError, AllenResult, Context};
2use std::{ffi::CStr, ptr, sync::Arc};
3use oal_sys_windows::*;
4
5pub(crate) struct DeviceInner {
6 pub(crate) handle: *mut ALCdevice,
7}
8
9impl Drop for DeviceInner {
10 fn drop(&mut self) {
11 unsafe { alcCloseDevice(self.handle) };
12 }
13}
14
15#[derive(Clone)]
17pub struct Device {
18 pub(crate) inner: Arc<DeviceInner>,
19}
20
21impl Device {
22 pub fn open(device_name: Option<&CStr>) -> Option<Self> {
24 let handle =
25 unsafe { alcOpenDevice(device_name.map(|s| s.as_ptr()).unwrap_or(ptr::null())) };
26
27 if handle == ptr::null_mut() {
28 None
29 } else {
30 Some(Device {
31 inner: Arc::new(DeviceInner { handle }),
32 })
33 }
34 }
35
36 pub fn device_name(&self) -> &str {
38 unsafe { CStr::from_ptr(alcGetString(self.inner.handle, ALC_DEVICE_SPECIFIER)) }
39 .to_str()
40 .unwrap()
41 }
42
43 pub fn create_context(&self) -> AllenResult<Context> {
45 Context::new(self.clone())
46 }
47
48 pub fn is_extension_present(&self, name: &CStr) -> AllenResult<bool> {
49 let result = unsafe { alcIsExtensionPresent(self.inner.handle, name.as_ptr()) };
50 self.check_alc_error()?;
51 Ok(result != 0)
52 }
53
54 pub fn check_alc_extension(&self, name: &CStr) -> AllenResult<()> {
55 if self.is_extension_present(name)? {
56 Ok(())
57 } else {
58 Err(AllenError::MissingExtension(
59 name.to_string_lossy().to_string(),
61 ))
62 }
63 }
64
65 pub(crate) fn check_alc_error(&self) -> AllenResult<()> {
66 let error = unsafe { alcGetError(self.inner.handle) };
67
68 if error == ALC_NO_ERROR {
69 Ok(())
70 } else {
71 Err(match error {
72 ALC_INVALID_DEVICE => AllenError::InvalidDevice,
73 ALC_INVALID_CONTEXT => AllenError::InvalidContext,
74 ALC_INVALID_ENUM => AllenError::InvalidEnum,
75 ALC_INVALID_VALUE => AllenError::InvalidValue,
76 ALC_OUT_OF_MEMORY => AllenError::OutOfMemory,
77 e => AllenError::Unknown(e),
78 })
79 }
80 }
81}