use std::{
path::{Path, PathBuf},
sync::Arc,
};
use crate::{
data::{
object::ObsObjectTrait,
output::{ObsOutputRef, ObsOutputTraitSealed},
},
forward_obs_object_impl, forward_obs_output_impl, impl_signal_manager, run_with_obs,
runtime::ObsRuntime,
unsafe_send::{Sendable, SmartPointerSendable},
utils::{ObsCalldataExt, ObsError, ObsString, OutputInfo},
};
#[derive(Debug, Clone)]
pub struct ObsReplayBufferOutputRef {
replay_signal_manager: Arc<ObsReplayOutputSignals>,
output: ObsOutputRef,
}
impl ObsOutputTraitSealed for ObsReplayBufferOutputRef {
fn new(mut output: OutputInfo, runtime: ObsRuntime) -> Result<Self, ObsError> {
output.id = ObsString::new("replay_buffer");
let output = ObsOutputRef::new(output, runtime.clone())?;
let replay_signal_manager = ObsReplayOutputSignals::new(&output.as_ptr(), runtime)?;
Ok(Self {
replay_signal_manager: Arc::new(replay_signal_manager),
output,
})
}
}
forward_obs_object_impl!(ObsReplayBufferOutputRef, output, *mut libobs::obs_output);
forward_obs_output_impl!(ObsReplayBufferOutputRef, output);
impl_signal_manager!(|ptr: SmartPointerSendable<*mut libobs::obs_output>| {
unsafe {
libobs::obs_output_get_signal_handler(ptr.get_ptr())
}
}, ObsReplayOutputSignals for *mut libobs::obs_output, [
"saved": {}
]);
impl ObsReplayBufferOutputRef {
pub fn replay_signals(&self) -> &Arc<ObsReplayOutputSignals> {
&self.replay_signal_manager
}
pub fn save_buffer(&self) -> Result<Box<Path>, ObsError> {
log::trace!("Saving replay buffer...");
let output_ptr = self.as_ptr();
log::trace!("Getting procedure handler for replay buffer output...");
let proc_handler = run_with_obs!(self.runtime().clone(), (output_ptr), move || {
let ph = unsafe { libobs::obs_output_get_proc_handler(output_ptr.get_ptr()) };
if ph.is_null() {
return Err(ObsError::OutputSaveBufferFailure(
"Failed to get proc handler.".to_string(),
));
}
Ok(Sendable(ph))
})??;
log::trace!("Calling 'save' procedure on replay buffer output...");
unsafe { self.runtime().call_proc_handler(&proc_handler, "save")? };
log::trace!("Waiting for 'saved' signal from replay buffer output...");
self.replay_signals()
.on_saved()?
.blocking_recv()
.map_err(|_e| {
ObsError::OutputSaveBufferFailure(
"Failed to receive saved replay buffer path.".to_string(),
)
})?;
log::trace!("Retrieving last replay path from replay buffer output...");
let mut calldata = unsafe {
self.runtime()
.call_proc_handler(&proc_handler, "get_last_replay")?
};
log::trace!("Extracting path from calldata...");
let path = calldata.get_string("path")?;
let path = PathBuf::from(path);
Ok(path.into_boxed_path())
}
}