diff --git a/src/output/context.rs b/src/output/context.rs index 9cbbf00..e529587 100644 --- a/src/output/context.rs +++ b/src/output/context.rs @@ -14,38 +14,28 @@ use obs_sys::{ use crate::hotkey::HotkeyCallbacks; use crate::media::{audio::AudioRef, video::VideoRef}; +use crate::string::TryIntoObsString; use crate::{hotkey::Hotkey, prelude::DataObj, string::ObsString, wrapper::PtrWrapper}; +use crate::{Error, Result}; + +#[deprecated = "use `OutputRef` instead"] +pub type OutputContext = OutputRef; /// Context wrapping an OBS output - video / audio elements which are displayed /// to the screen. /// /// See [OBS documentation](https://obsproject.com/docs/reference-outputs.html#c.obs_output_t) -pub struct OutputContext { +pub struct OutputRef { pub(crate) inner: *mut obs_output_t, } -impl OutputContext { - /// # Safety - /// - /// Pointer must be valid. - pub unsafe fn from_raw(output: *mut obs_output_t) -> Self { - Self { - inner: obs_output_get_ref(output), - } - } -} - -impl Clone for OutputContext { - fn clone(&self) -> Self { - unsafe { Self::from_raw(self.inner) } - } -} - -impl Drop for OutputContext { - fn drop(&mut self) { - unsafe { obs_output_release(self.inner) } - } -} +impl_ptr_wrapper!( + @ptr: inner, + OutputRef, + obs_output_t, + obs_output_get_ref, + obs_output_release +); extern "C" fn enum_proc(params: *mut std::ffi::c_void, output: *mut obs_output_t) -> bool { let mut v = unsafe { Box::>::from_raw(params as *mut _) }; @@ -54,8 +44,8 @@ extern "C" fn enum_proc(params: *mut std::ffi::c_void, output: *mut obs_output_t true } -impl OutputContext { - pub fn new(id: ObsString, name: ObsString, settings: Option>) -> Self { +impl OutputRef { + pub fn new(id: ObsString, name: ObsString, settings: Option>) -> Result { let settings = match settings { Some(data) => unsafe { data.as_ptr_mut() }, None => std::ptr::null_mut(), @@ -64,18 +54,19 @@ impl OutputContext { obs_output_create(id.as_ptr(), name.as_ptr(), settings, std::ptr::null_mut()) }; - unsafe { Self::from_raw(output) } + unsafe { Self::from_raw_unchecked(output) }.ok_or(Error::NulPointer("obs_output_cretae")) } pub fn all_outputs() -> Vec { let outputs = Vec::<*mut obs_output_t>::new(); let params = Box::into_raw(Box::new(outputs)); unsafe { + // `obs_enum_outputs` would return `weak_ref`, so `get_ref` needed obs_enum_outputs(Some(enum_proc), params as *mut _); } let outputs = unsafe { Box::from_raw(params) }; outputs .into_iter() - .map(|i| unsafe { OutputContext::from_raw(i) }) + .filter_map(OutputRef::from_raw) .collect() } pub fn all_types() -> Vec { @@ -96,26 +87,12 @@ impl OutputContext { types } - pub fn output_id(&self) -> Option<&str> { - unsafe { - let ptr = obs_output_get_id(self.inner); - if ptr.is_null() { - None - } else { - Some(CStr::from_ptr(ptr).to_str().unwrap()) - } - } + pub fn output_id(&self) -> Result { + unsafe { obs_output_get_id(self.inner) }.try_into_obs_string() } - pub fn name(&self) -> Option<&str> { - unsafe { - let ptr = obs_output_get_name(self.inner); - if ptr.is_null() { - None - } else { - Some(CStr::from_ptr(ptr).to_str().unwrap()) - } - } + pub fn name(&self) -> Result { + unsafe { obs_output_get_name(self.inner) }.try_into_obs_string() } pub fn start(&mut self) -> bool { diff --git a/src/output/ffi.rs b/src/output/ffi.rs index 0b674ce..84ae395 100644 --- a/src/output/ffi.rs +++ b/src/output/ffi.rs @@ -1,4 +1,4 @@ -use super::{traits::*, CreatableOutputContext, OutputContext}; +use super::{traits::*, CreatableOutputContext, OutputRef}; use crate::hotkey::{Hotkey, HotkeyCallbacks}; use crate::{data::DataObj, wrapper::PtrWrapper}; use obs_sys::{ @@ -53,9 +53,10 @@ pub unsafe extern "C" fn create( settings: *mut obs_data_t, output: *mut obs_output_t, ) -> *mut c_void { - let settings = DataObj::from_raw(settings).unwrap(); + // this is later forgotten + let settings = DataObj::from_raw_unchecked(settings).unwrap(); let mut context = CreatableOutputContext::from_raw(settings); - let output_context = OutputContext::from_raw(output); + let output_context = OutputRef::from_raw(output).expect("create"); let data = D::create(&mut context, output_context); let wrapper = Box::new(DataWrapper::from(data)); @@ -129,13 +130,15 @@ pub unsafe extern "C" fn encoded_packet( pub unsafe extern "C" fn update(data: *mut c_void, settings: *mut obs_data_t) { let data: &mut DataWrapper = &mut *(data as *mut DataWrapper); - let mut settings = DataObj::from_raw(settings).unwrap(); + // this is later forgotten + let mut settings = DataObj::from_raw_unchecked(settings).unwrap(); D::update(&mut data.data, &mut settings); forget(settings); } pub unsafe extern "C" fn get_defaults(settings: *mut obs_data_t) { - let mut settings = DataObj::from_raw(settings).unwrap(); + // this is later forgotten + let mut settings = DataObj::from_raw_unchecked(settings).unwrap(); D::get_defaults(&mut settings); forget(settings); } diff --git a/src/output/traits.rs b/src/output/traits.rs index 4382833..1d0ef93 100644 --- a/src/output/traits.rs +++ b/src/output/traits.rs @@ -2,11 +2,11 @@ use obs_sys::{audio_data, encoder_packet, video_data}; use crate::{prelude::DataObj, properties::Properties, string::ObsString}; -use super::{CreatableOutputContext, OutputContext}; +use super::{CreatableOutputContext, OutputRef}; pub trait Outputable: Sized { fn get_id() -> ObsString; - fn create(context: &mut CreatableOutputContext<'_, Self>, output: OutputContext) -> Self; + fn create(context: &mut CreatableOutputContext<'_, Self>, output: OutputRef) -> Self; fn start(&mut self) -> bool { true diff --git a/src/source/ffi.rs b/src/source/ffi.rs index 0df4cb2..1e148e7 100644 --- a/src/source/ffi.rs +++ b/src/source/ffi.rs @@ -87,7 +87,8 @@ pub unsafe extern "C" fn create( source: *mut obs_source_t, ) -> *mut c_void { let mut global = GlobalContext; - let settings = DataObj::from_raw(settings).unwrap(); + // this is later forgotten + let settings = DataObj::from_raw_unchecked(settings).unwrap(); let mut context = CreatableSourceContext::from_raw(settings, &mut global); let source_context = SourceRef::from_raw(source).expect("create"); @@ -115,7 +116,7 @@ pub unsafe extern "C" fn destroy(data: *mut c_void) { pub unsafe extern "C" fn update(data: *mut c_void, settings: *mut obs_data_t) { let mut global = GlobalContext; let data: &mut DataWrapper = &mut *(data as *mut DataWrapper); - let mut settings = DataObj::from_raw(settings).unwrap(); + let mut settings = DataObj::from_raw_unchecked(settings).unwrap(); D::update(&mut data.data, &mut settings, &mut global); forget(settings); } @@ -252,7 +253,8 @@ impl_media!( ); pub unsafe extern "C" fn get_defaults(settings: *mut obs_data_t) { - let mut settings = DataObj::from_raw(settings).unwrap(); + // this is later forgotten + let mut settings = DataObj::from_raw_unchecked(settings).unwrap(); D::get_defaults(&mut settings); forget(settings); } diff --git a/src/source/mod.rs b/src/source/mod.rs index bdf14a7..40f02dd 100644 --- a/src/source/mod.rs +++ b/src/source/mod.rs @@ -125,6 +125,7 @@ impl SourceRef { pub fn do_with_target(&mut self, func: F) { unsafe { if let Ok(SourceType::Filter) = SourceType::from_raw(obs_source_get_type(self.inner)) { + // doc says "Does not increment the reference." let target = obs_filter_get_target(self.inner); if let Some(mut context) = SourceRef::from_raw(target) { func(&mut context); diff --git a/src/wrapper.rs b/src/wrapper.rs index 2348188..098afe4 100644 --- a/src/wrapper.rs +++ b/src/wrapper.rs @@ -8,8 +8,8 @@ pub trait PtrWrapperInternal: PtrWrapper { unsafe fn new_internal(ptr: *mut Self::Pointer) -> Self; /// # Safety /// - /// This function should not be called directly, use `from_raw` and - /// `from_raw_unchecked` instead. + /// This function should not be called directly, use `as_ptr`, + /// `as_ptr_mut` and `into_raw` instead. unsafe fn get_internal(&self) -> *mut Self::Pointer; }