mod enums;
mod macros;
pub mod prop_impl;
pub mod types;
use std::{collections::HashMap, ffi::CStr};
use libobs::obs_properties;
use macros::*;
pub use enums::*;
use types::*;
use crate::{
impl_obs_drop, run_with_obs,
runtime::ObsRuntime,
unsafe_send::{Sendable, SmartPointerSendable},
utils::{ObsDropGuard, ObsError, ObsString},
};
#[derive(Debug)]
pub(crate) struct _ObsPropertiesDropGuard {
properties: Sendable<*mut obs_properties>,
runtime: ObsRuntime,
}
impl ObsDropGuard for _ObsPropertiesDropGuard {}
impl_obs_drop!(_ObsPropertiesDropGuard, (properties), move || unsafe {
libobs::obs_properties_destroy(properties.0);
});
impl _ObsPropertiesDropGuard {
pub(crate) fn new(properties: Sendable<*mut obs_properties>, runtime: ObsRuntime) -> Self {
Self {
properties,
runtime,
}
}
}
#[derive(Debug, Clone)]
pub enum ObsProperty {
Invalid,
Bool,
Int(ObsNumberProperty<i32>),
Float(ObsNumberProperty<f64>),
Text(ObsTextProperty),
Path(ObsPathProperty),
List(ObsListProperty),
Color(ObsColorProperty),
Button(ObsButtonProperty),
Font(ObsFontProperty),
EditableList(ObsEditableListProperty),
FrameRate(ObsFrameRateProperty),
Group(ObsGroupProperty),
ColorAlpha(ObsColorAlphaProperty),
}
pub trait ObsPropertyObjectPrivate {
fn get_properties_raw(
&self,
) -> Result<SmartPointerSendable<*mut libobs::obs_properties_t>, ObsError>;
fn get_properties_by_id_raw<T: Into<ObsString> + Sync + Send>(
id: T,
runtime: ObsRuntime,
) -> Result<SmartPointerSendable<*mut libobs::obs_properties_t>, ObsError>;
}
pub(crate) fn property_ptr_to_struct(
properties_raw: SmartPointerSendable<*mut obs_properties>,
runtime: ObsRuntime,
) -> Result<HashMap<String, ObsProperty>, ObsError> {
let runtime_clone = runtime.clone();
run_with_obs!(runtime, (properties_raw, runtime_clone), move || {
let mut result = HashMap::new();
let mut property = unsafe {
libobs::obs_properties_first(properties_raw.get_ptr())
};
while !property.is_null() {
let name = unsafe { libobs::obs_property_name(property) };
if name.is_null() {
let success = unsafe {
libobs::obs_property_next(&mut property)
};
if !success {
break;
}
continue;
}
let name = unsafe {
CStr::from_ptr(name as _)
};
let name = name.to_string_lossy().to_string();
let p_type = unsafe {
libobs::obs_property_get_type(property)
};
let p_type = crate::macros::enum_from_number!(ObsPropertyType, p_type);
log::trace!("Property: {:?}", name);
match p_type {
Some(p_type) => {
let prop_struct = unsafe {
p_type.get_property_struct(&runtime_clone, Sendable(property))
};
if let Ok(r) = prop_struct {
result.insert(name, r);
}
}
None => {
result.insert(name, ObsProperty::Invalid);
}
}
let has_next = unsafe {
libobs::obs_property_next(&mut property)
};
if !has_next {
break;
}
}
result
})
}
pub trait ObsPropertyObject: ObsPropertyObjectPrivate {
fn get_properties(&self) -> Result<HashMap<String, ObsProperty>, ObsError>;
fn get_properties_by_source_id<T: Into<ObsString> + Sync + Send>(
id: T,
runtime: &ObsRuntime,
) -> Result<HashMap<String, ObsProperty>, ObsError> {
let properties_raw = Self::get_properties_by_id_raw(id, runtime.clone())?;
property_ptr_to_struct(properties_raw, runtime.clone())
}
}