use std::collections::HashMap; use gst::{glib, prelude::*}; pub fn gvalue_to_json(val: &gst::glib::Value) -> Option { match val.type_() { glib::Type::STRING => Some(val.get::().unwrap().into()), glib::Type::BOOL => Some(val.get::().unwrap().into()), glib::Type::I32 => Some(val.get::().unwrap().into()), glib::Type::U32 => Some(val.get::().unwrap().into()), glib::Type::I_LONG | glib::Type::I64 => Some(val.get::().unwrap().into()), glib::Type::U_LONG | glib::Type::U64 => Some(val.get::().unwrap().into()), glib::Type::F32 => Some(val.get::().unwrap().into()), glib::Type::F64 => Some(val.get::().unwrap().into()), _ => { if let Ok(s) = val.get::() { serde_json::to_value( s.iter() .filter_map(|(name, value)| { gvalue_to_json(value).map(|value| (name.to_string(), value)) }) .collect::>(), ) .ok() } else if let Ok(a) = val.get::() { serde_json::to_value( a.iter() .filter_map(|value| gvalue_to_json(value)) .collect::>(), ) .ok() } else if let Some((_klass, values)) = gst::glib::FlagsValue::from_value(val) { Some( values .iter() .map(|value| value.nick()) .collect::>() .join("+") .into(), ) } else if let Ok(value) = val.serialize() { Some(value.as_str().into()) } else { None } } } } fn json_to_gststructure(val: &serde_json::Value) -> Option { match val { serde_json::Value::Bool(v) => Some(v.to_send_value()), serde_json::Value::Number(n) => { if n.is_u64() { Some(n.as_u64().unwrap().to_send_value()) } else if n.is_i64() { Some(n.as_i64().unwrap().to_send_value()) } else if n.is_f64() { Some(n.as_f64().unwrap().to_send_value()) } else { todo!("Unhandled case {n:?}"); } } serde_json::Value::String(v) => Some(v.to_send_value()), serde_json::Value::Array(v) => { let array = v .iter() .filter_map(json_to_gststructure) .collect::>(); Some(gst::Array::from_values(array).to_send_value()) } serde_json::Value::Object(v) => Some(serialize_json_object(v).to_send_value()), _ => None, } } pub fn serialize_json_object(val: &serde_json::Map) -> gst::Structure { let mut res = gst::Structure::new_empty("v"); val.iter().for_each(|(k, v)| { if let Some(gvalue) = json_to_gststructure(v) { res.set_value(k, gvalue); } }); res } /// Wrapper around `gst::ElementFactory::make` with a better error /// message pub fn make_element(element: &str, name: Option<&str>) -> Result { let mut builder = gst::ElementFactory::make(element); if let Some(name) = name { builder = builder.name(name); } builder .build() .with_context(|| format!("Failed to make element {element}")) }