libobs_wrapper\encoders/
audio.rs

1use libobs::{audio_output, obs_audio_encoder_create, obs_encoder_release, obs_encoder_set_audio};
2use std::{borrow::Borrow, ptr};
3
4use crate::{
5    data::ObsData,
6    impl_obs_drop, run_with_obs,
7    runtime::ObsRuntime,
8    unsafe_send::Sendable,
9    utils::{ObsError, ObsString},
10};
11
12#[derive(Debug)]
13#[allow(dead_code)]
14pub struct ObsAudioEncoder {
15    pub(crate) encoder: Sendable<*mut libobs::obs_encoder_t>,
16    pub(crate) id: ObsString,
17    pub(crate) name: ObsString,
18    pub(crate) settings: Option<ObsData>,
19    pub(crate) hotkey_data: Option<ObsData>,
20    pub(crate) runtime: ObsRuntime,
21}
22
23impl ObsAudioEncoder {
24    #[cfg_attr(feature = "blocking", remove_async_await::remove_async_await)]
25    pub async fn new<T: Into<ObsString> + Sync + Send, K: Into<ObsString> + Sync + Send>(
26        id: T,
27        name: K,
28        settings: Option<ObsData>,
29        mixer_idx: usize,
30        hotkey_data: Option<ObsData>,
31        runtime: ObsRuntime,
32    ) -> Result<Self, ObsError> {
33        let id = id.into();
34        let name = name.into();
35
36        let settings_ptr = match settings.borrow() {
37            Some(x) => x.as_ptr(),
38            None => Sendable(ptr::null_mut()),
39        };
40
41        let hotkey_data_ptr = match hotkey_data.borrow() {
42            Some(x) => x.as_ptr(),
43            None => Sendable(ptr::null_mut()),
44        };
45
46        let id_ptr = id.as_ptr();
47        let name_ptr = name.as_ptr();
48
49        let encoder = run_with_obs!(
50            runtime,
51            (hotkey_data_ptr, settings_ptr, id_ptr, name_ptr),
52            move || unsafe {
53                let ptr = obs_audio_encoder_create(id_ptr, name_ptr, settings_ptr, mixer_idx, hotkey_data_ptr);
54                Sendable(ptr)
55            }
56        ).await?;
57
58        if encoder.0 == ptr::null_mut() {
59            return Err(ObsError::NullPointer);
60        }
61
62        Ok(Self {
63            encoder,
64            id,
65            name,
66            settings,
67            hotkey_data,
68            runtime,
69        })
70    }
71
72    /// This is only needed once for global audio context
73    #[cfg_attr(feature = "blocking", remove_async_await::remove_async_await)]
74    pub async fn set_audio_context(
75        &mut self,
76        handler: Sendable<*mut audio_output>,
77    ) -> Result<(), ObsError> {
78        let encoder_ptr = self.encoder.clone();
79
80        run_with_obs!(self.runtime, (handler, encoder_ptr), move || unsafe {
81            obs_encoder_set_audio(encoder_ptr, handler)
82        }).await
83    }
84}
85
86impl_obs_drop!(ObsAudioEncoder, (encoder), move || unsafe {
87    obs_encoder_release(encoder)
88});