144 lines
4.1 KiB
Rust
144 lines
4.1 KiB
Rust
use {
|
|
crate::video::drm::{
|
|
DrmError, DrmMaster, DrmObject, DrmProperty, DrmPropertyDefinition, DrmPropertyType,
|
|
},
|
|
ahash::AHashMap,
|
|
bstr::{BString, ByteSlice},
|
|
std::rc::Rc,
|
|
};
|
|
|
|
#[derive(Debug)]
|
|
pub struct DefaultProperty {
|
|
pub name: &'static str,
|
|
pub prop: DrmProperty,
|
|
pub value: u64,
|
|
}
|
|
|
|
#[derive(Copy, Clone)]
|
|
pub(super) enum DefaultValue {
|
|
Fixed(u64),
|
|
Enum(&'static str),
|
|
Bitmask(&'static [&'static str]),
|
|
RangeMax,
|
|
}
|
|
|
|
pub(super) fn create_default_properties(
|
|
props: &CollectedProperties,
|
|
defaults: &[(&'static str, DefaultValue)],
|
|
) -> Vec<DefaultProperty> {
|
|
let mut res = vec![];
|
|
let mut defaults = defaults.iter();
|
|
'outer: loop {
|
|
let Some(&(name, def)) = defaults.next() else {
|
|
break;
|
|
};
|
|
if let Some((definition, _)) = props.props.get(name.as_bytes().as_bstr()) {
|
|
let value = match def {
|
|
DefaultValue::Fixed(v) => v,
|
|
DefaultValue::Enum(e) => match &definition.ty {
|
|
DrmPropertyType::Enum {
|
|
values,
|
|
bitmask: false,
|
|
} => match values.iter().find(|v| v.name == e) {
|
|
None => continue,
|
|
Some(v) => v.value,
|
|
},
|
|
_ => continue,
|
|
},
|
|
DefaultValue::Bitmask(e) => match &definition.ty {
|
|
DrmPropertyType::Enum {
|
|
values,
|
|
bitmask: true,
|
|
} => {
|
|
let mut res = 0;
|
|
for &e in e {
|
|
match values.iter().find(|v| v.name == e) {
|
|
None => continue 'outer,
|
|
Some(v) => res |= 1 << v.value,
|
|
}
|
|
}
|
|
res
|
|
}
|
|
_ => continue,
|
|
},
|
|
DefaultValue::RangeMax => match &definition.ty {
|
|
DrmPropertyType::Range { max, .. } => *max,
|
|
DrmPropertyType::SignedRange { max, .. } => *max as u64,
|
|
_ => continue,
|
|
},
|
|
};
|
|
res.push(DefaultProperty {
|
|
name,
|
|
prop: definition.id,
|
|
value,
|
|
});
|
|
}
|
|
}
|
|
res
|
|
}
|
|
|
|
pub(super) fn collect_properties<T: DrmObject>(
|
|
master: &Rc<DrmMaster>,
|
|
t: T,
|
|
) -> Result<CollectedProperties, DrmError> {
|
|
let mut props = AHashMap::new();
|
|
for prop in master.get_properties(t)? {
|
|
let def = master.get_property(prop.id)?;
|
|
props.insert(def.name.clone(), (def, prop.value));
|
|
}
|
|
Ok(CollectedProperties { props })
|
|
}
|
|
|
|
pub(super) fn collect_untyped_properties<T: DrmObject>(
|
|
master: &Rc<DrmMaster>,
|
|
t: T,
|
|
props: &mut AHashMap<DrmProperty, u64>,
|
|
) -> Result<(), DrmError> {
|
|
props.clear();
|
|
for prop in master.get_properties(t)? {
|
|
props.insert(prop.id, prop.value);
|
|
}
|
|
Ok(())
|
|
}
|
|
|
|
pub(super) struct CollectedProperties {
|
|
pub(super) props: AHashMap<BString, (DrmPropertyDefinition, u64)>,
|
|
}
|
|
|
|
impl CollectedProperties {
|
|
pub(super) fn get(&self, name: &str) -> Result<TypedProperty<u64>, DrmError> {
|
|
match self.props.get(name.as_bytes().as_bstr()) {
|
|
Some((def, value)) => Ok(TypedProperty {
|
|
id: def.id,
|
|
value: *value,
|
|
}),
|
|
_ => Err(DrmError::MissingProperty(name.to_string().into_boxed_str())),
|
|
}
|
|
}
|
|
|
|
pub(super) fn to_untyped(&self) -> AHashMap<DrmProperty, u64> {
|
|
let mut res = AHashMap::new();
|
|
for (def, val) in self.props.values() {
|
|
res.insert(def.id, *val);
|
|
}
|
|
res
|
|
}
|
|
}
|
|
|
|
#[derive(Copy, Clone, Debug)]
|
|
pub struct TypedProperty<T> {
|
|
pub id: DrmProperty,
|
|
pub value: T,
|
|
}
|
|
|
|
impl<T: Copy> TypedProperty<T> {
|
|
pub(super) fn map<U, F>(self, f: F) -> TypedProperty<U>
|
|
where
|
|
F: FnOnce(T) -> U,
|
|
{
|
|
TypedProperty {
|
|
id: self.id,
|
|
value: f(self.value),
|
|
}
|
|
}
|
|
}
|