mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer-rs.git
synced 2024-11-22 09:31:06 +00:00
validate: Implement action types registration support
This is implemented mostly manually because the API is a bit weird and we need to do some extra work to make it work properly. Also basing it on a Builder makes it much nicer to user. This commit also includes required new types either generated with `gir` or manually implemented when required. Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer-rs/-/merge_requests/1227>
This commit is contained in:
parent
68db910bc8
commit
8eae37c525
12 changed files with 671 additions and 52 deletions
|
@ -1 +1 @@
|
||||||
Subproject commit ae0d1447f5204ddf882ff08d2163b299db5da228
|
Subproject commit 8dd059f42a8da104b53baf82bf5f5d2596176627
|
|
@ -22,6 +22,7 @@ bitflags = "1.0"
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
gir-format-check = "0.1"
|
gir-format-check = "0.1"
|
||||||
|
tempfile = "3"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
default = []
|
default = []
|
||||||
|
|
|
@ -17,7 +17,6 @@ external_libraries = [
|
||||||
]
|
]
|
||||||
|
|
||||||
generate = [
|
generate = [
|
||||||
"GstValidate.Action",
|
|
||||||
"GstValidate.Reporter",
|
"GstValidate.Reporter",
|
||||||
"GstValidate.BinMonitor",
|
"GstValidate.BinMonitor",
|
||||||
"GstValidate.Monitor",
|
"GstValidate.Monitor",
|
||||||
|
@ -31,6 +30,8 @@ generate = [
|
||||||
"GstValidate.ReportLevel",
|
"GstValidate.ReportLevel",
|
||||||
"GstValidate.IssueFlags",
|
"GstValidate.IssueFlags",
|
||||||
"GstValidate.IssueId",
|
"GstValidate.IssueId",
|
||||||
|
"GstValidate.ActionTypeFlags",
|
||||||
|
"GstValidate.ActionType",
|
||||||
]
|
]
|
||||||
|
|
||||||
manual = [
|
manual = [
|
||||||
|
@ -48,6 +49,7 @@ manual = [
|
||||||
"Gst.Format",
|
"Gst.Format",
|
||||||
"Gst.SeekFlags",
|
"Gst.SeekFlags",
|
||||||
"Gst.SeekType",
|
"Gst.SeekType",
|
||||||
|
"GstValidate.Action",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[object]]
|
[[object]]
|
||||||
|
|
65
gstreamer-validate/src/action.rs
Normal file
65
gstreamer-validate/src/action.rs
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
// Take a look at the license at the top of the repository in the LICENSE file.
|
||||||
|
|
||||||
|
use glib::prelude::*;
|
||||||
|
use glib::translate::*;
|
||||||
|
|
||||||
|
use crate::ActionType;
|
||||||
|
use crate::Scenario;
|
||||||
|
|
||||||
|
gst::mini_object_wrapper!(Action, ActionRef, ffi::GstValidateAction, || {
|
||||||
|
ffi::gst_validate_action_get_type()
|
||||||
|
});
|
||||||
|
|
||||||
|
impl ActionRef {
|
||||||
|
pub fn structure(&self) -> &gst::StructureRef {
|
||||||
|
unsafe {
|
||||||
|
let action = &self.0 as *const ffi::GstValidateAction;
|
||||||
|
|
||||||
|
gst::StructureRef::from_glib_borrow((*action).structure)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn structure_mut(&mut self) -> &mut gst::StructureRef {
|
||||||
|
unsafe {
|
||||||
|
let action = &mut self.0 as *mut ffi::GstValidateAction;
|
||||||
|
|
||||||
|
gst::StructureRef::from_glib_borrow_mut((*action).structure)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Action {
|
||||||
|
#[doc(alias = "gst_validate_action_new")]
|
||||||
|
pub fn new(
|
||||||
|
scenario: Option<&impl IsA<Scenario>>,
|
||||||
|
action_type: &ActionType,
|
||||||
|
structure: &gst::StructureRef,
|
||||||
|
add_to_lists: bool,
|
||||||
|
) -> Action {
|
||||||
|
assert_initialized_main_thread!();
|
||||||
|
unsafe {
|
||||||
|
from_glib_full(ffi::gst_validate_action_new(
|
||||||
|
scenario.map(|p| p.as_ref()).to_glib_none().0,
|
||||||
|
action_type.to_glib_none().0,
|
||||||
|
structure.as_mut_ptr(),
|
||||||
|
add_to_lists.into_glib(),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[doc(alias = "gst_validate_execute_action")]
|
||||||
|
pub fn execute(&self) -> Result<crate::ActionSuccess, crate::ActionError> {
|
||||||
|
unsafe {
|
||||||
|
let action: *mut ffi::GstValidateAction = self.to_glib_none().0;
|
||||||
|
let action_type = ffi::gst_validate_get_action_type((*action).type_);
|
||||||
|
|
||||||
|
let res = ffi::gst_validate_execute_action(action_type, action);
|
||||||
|
|
||||||
|
if let Some(v) = crate::ActionSuccess::from_value(res) {
|
||||||
|
Ok(v)
|
||||||
|
} else {
|
||||||
|
Err(crate::ActionError::from_value(res))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
318
gstreamer-validate/src/action_type.rs
Normal file
318
gstreamer-validate/src/action_type.rs
Normal file
|
@ -0,0 +1,318 @@
|
||||||
|
use std::{ffi::c_int, ptr};
|
||||||
|
|
||||||
|
use glib::once_cell::sync::Lazy;
|
||||||
|
use glib::translate::*;
|
||||||
|
|
||||||
|
static QUARK_ACTION_TYPE_FUNC: Lazy<glib::Quark> =
|
||||||
|
Lazy::new(|| glib::Quark::from_str("rs-action-type-function"));
|
||||||
|
|
||||||
|
#[derive(Debug)]
|
||||||
|
#[repr(transparent)]
|
||||||
|
#[doc(alias = "GstValidateActionParameter")]
|
||||||
|
pub struct ActionParameter(pub(crate) ffi::GstValidateActionParameter);
|
||||||
|
impl Drop for ActionParameter {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
unsafe {
|
||||||
|
if let Some(free_fn) = self.0.free {
|
||||||
|
(free_fn)(self as *const _ as glib::ffi::gpointer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn into_glib_content(mut t: Vec<ActionParameter>) -> *mut ffi::GstValidateActionParameter {
|
||||||
|
assert_initialized_main_thread!();
|
||||||
|
if t.is_empty() {
|
||||||
|
return ptr::null_mut();
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
let size = std::mem::size_of::<ffi::GstValidateActionParameter>() * (t.len() + 1);
|
||||||
|
let v_ptr = glib::ffi::g_malloc0(size) as *mut ffi::GstValidateActionParameter;
|
||||||
|
|
||||||
|
ptr::copy_nonoverlapping(
|
||||||
|
t.as_ptr() as *const ffi::GstValidateActionParameter,
|
||||||
|
v_ptr,
|
||||||
|
t.len(),
|
||||||
|
);
|
||||||
|
|
||||||
|
// C side is owning the memory now
|
||||||
|
t.set_len(0);
|
||||||
|
|
||||||
|
v_ptr
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe extern "C" fn action_parameter_free(param: glib::ffi::gpointer) {
|
||||||
|
let param = param as *mut ffi::GstValidateActionParameter;
|
||||||
|
|
||||||
|
glib::ffi::g_free((*param).name as *mut _);
|
||||||
|
glib::ffi::g_free((*param).description as *mut _);
|
||||||
|
glib::ffi::g_free((*param).def as *mut _);
|
||||||
|
glib::ffi::g_free((*param).possible_variables as *mut _);
|
||||||
|
glib::ffi::g_free((*param).types as *mut _);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct ActionParameterBuilder<'a> {
|
||||||
|
name: &'a str,
|
||||||
|
description: &'a str,
|
||||||
|
possible_variables: Vec<String>,
|
||||||
|
mandatory: bool,
|
||||||
|
default_value: Option<&'a str>,
|
||||||
|
types: Vec<String>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> ActionParameterBuilder<'a> {
|
||||||
|
pub fn new(name: &'a str, description: &'a str) -> Self {
|
||||||
|
assert_initialized_main_thread!();
|
||||||
|
|
||||||
|
Self {
|
||||||
|
name,
|
||||||
|
description,
|
||||||
|
possible_variables: Default::default(),
|
||||||
|
mandatory: false,
|
||||||
|
default_value: None,
|
||||||
|
types: Default::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// rustdoc-stripper-ignore-next
|
||||||
|
/// The name of the variables that can be used to compute the value of the
|
||||||
|
/// parameter. For example for the start value of a seek action, we will
|
||||||
|
/// accept to take 'duration' which will be replace by the total duration of
|
||||||
|
/// the stream on which the action is executed.
|
||||||
|
pub fn add_possible_variable(mut self, possible_variables: &str) -> Self {
|
||||||
|
self.possible_variables.push(possible_variables.to_owned());
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn mandatory(mut self) -> Self {
|
||||||
|
self.mandatory = true;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn default_value(mut self, default_value: &'a str) -> Self {
|
||||||
|
self.default_value = Some(default_value);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
// rustdoc-stripper-ignore-next
|
||||||
|
/// The types the parameter can take described as a string.
|
||||||
|
///
|
||||||
|
/// NOTE: The types should end with `(GstClockTime)` if
|
||||||
|
/// its final type is a GstClockTime, this way it will be processed when
|
||||||
|
/// preparing the actions.
|
||||||
|
pub fn add_type(mut self, types: &str) -> Self {
|
||||||
|
self.types.push(types.to_owned());
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn build(self) -> ActionParameter {
|
||||||
|
let types = if self.types.is_empty() {
|
||||||
|
ptr::null()
|
||||||
|
} else {
|
||||||
|
self.types.join("\n").to_glib_full()
|
||||||
|
};
|
||||||
|
let possible_variables = if self.possible_variables.is_empty() {
|
||||||
|
ptr::null()
|
||||||
|
} else {
|
||||||
|
self.possible_variables.join("\n").to_glib_full()
|
||||||
|
};
|
||||||
|
ActionParameter(ffi::GstValidateActionParameter {
|
||||||
|
name: self.name.to_glib_full(),
|
||||||
|
description: self.description.to_glib_full(),
|
||||||
|
mandatory: self.mandatory.into_glib(),
|
||||||
|
def: self.default_value.to_glib_full(),
|
||||||
|
possible_variables,
|
||||||
|
types,
|
||||||
|
free: Some(action_parameter_free),
|
||||||
|
_gst_reserved: [ptr::null_mut(); 3],
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
type ActionFunction = dyn Fn(&crate::Scenario, &mut crate::ActionRef) -> Result<crate::ActionSuccess, crate::ActionError>
|
||||||
|
+ Sync
|
||||||
|
+ Send
|
||||||
|
+ 'static;
|
||||||
|
|
||||||
|
unsafe extern "C" fn destroy_notify(ptr: glib::ffi::gpointer) {
|
||||||
|
let _ = Box::from_raw(ptr as *mut Box<ActionFunction>);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct ActionTypeBuilder<'a> {
|
||||||
|
type_name: &'a str,
|
||||||
|
implementer_namespace: Option<&'a str>,
|
||||||
|
description: Option<&'a str>,
|
||||||
|
parameters: Vec<ActionParameter>,
|
||||||
|
flags: crate::ActionTypeFlags,
|
||||||
|
function: Box<ActionFunction>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> ActionTypeBuilder<'a> {
|
||||||
|
pub fn new<
|
||||||
|
F: Fn(
|
||||||
|
&crate::Scenario,
|
||||||
|
&mut crate::ActionRef,
|
||||||
|
) -> Result<crate::ActionSuccess, crate::ActionError>
|
||||||
|
+ Send
|
||||||
|
+ Sync
|
||||||
|
+ 'static,
|
||||||
|
>(
|
||||||
|
type_name: &'a str,
|
||||||
|
func: F,
|
||||||
|
) -> Self {
|
||||||
|
Self {
|
||||||
|
type_name,
|
||||||
|
implementer_namespace: None,
|
||||||
|
description: None,
|
||||||
|
parameters: Vec::new(),
|
||||||
|
flags: crate::ActionTypeFlags::empty(),
|
||||||
|
function: Box::new(func),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn implementer_namespace(mut self, implementer_namespace: &'a str) -> Self {
|
||||||
|
self.implementer_namespace = Some(implementer_namespace);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn description(mut self, description: &'a str) -> Self {
|
||||||
|
self.description = Some(description);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn parameter(mut self, parameter: ActionParameter) -> Self {
|
||||||
|
self.parameters.push(parameter);
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn flags(mut self, flags: crate::ActionTypeFlags) -> Self {
|
||||||
|
self.flags |= flags;
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn build(self) -> crate::ActionType {
|
||||||
|
unsafe extern "C" fn execute_func_trampoline(
|
||||||
|
scenario: *mut ffi::GstValidateScenario,
|
||||||
|
action: *mut ffi::GstValidateAction,
|
||||||
|
) -> c_int {
|
||||||
|
let action_type = ffi::gst_validate_get_action_type((*action).type_);
|
||||||
|
let scenario = from_glib_borrow(scenario);
|
||||||
|
let action = crate::ActionRef::from_mut_ptr(action as *mut ffi::GstValidateAction);
|
||||||
|
|
||||||
|
let func: &ActionFunction = &*(gst::ffi::gst_mini_object_get_qdata(
|
||||||
|
action_type as *mut gst::ffi::GstMiniObject,
|
||||||
|
QUARK_ACTION_TYPE_FUNC.into_glib(),
|
||||||
|
) as *const Box<ActionFunction>);
|
||||||
|
|
||||||
|
(*func)(&scenario, action).into_glib()
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
let params = into_glib_content(self.parameters);
|
||||||
|
let action_type = ffi::gst_validate_register_action_type(
|
||||||
|
self.type_name.to_glib_none().0,
|
||||||
|
self.implementer_namespace
|
||||||
|
.unwrap_or("validaters")
|
||||||
|
.to_glib_none()
|
||||||
|
.0,
|
||||||
|
Some(execute_func_trampoline),
|
||||||
|
params,
|
||||||
|
self.description.to_glib_none().0,
|
||||||
|
self.flags.into_glib(),
|
||||||
|
);
|
||||||
|
|
||||||
|
// gst_validate_register_action_type() takes ownership of the content
|
||||||
|
// of the params array but not of the container itself so we need to
|
||||||
|
// free it manually.
|
||||||
|
glib::ffi::g_free(params as *mut _);
|
||||||
|
|
||||||
|
let f = self.function;
|
||||||
|
|
||||||
|
gst::ffi::gst_mini_object_set_qdata(
|
||||||
|
action_type as *mut gst::ffi::GstMiniObject,
|
||||||
|
QUARK_ACTION_TYPE_FUNC.into_glib(),
|
||||||
|
Box::into_raw(Box::new(f)) as *mut _,
|
||||||
|
Some(destroy_notify),
|
||||||
|
);
|
||||||
|
|
||||||
|
from_glib_none(action_type)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use std::{
|
||||||
|
io::Write,
|
||||||
|
sync::{Arc, Mutex},
|
||||||
|
};
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_action_types() {
|
||||||
|
gst::init().unwrap();
|
||||||
|
crate::init();
|
||||||
|
|
||||||
|
let failling_action_type = crate::ActionTypeBuilder::new("fails", |_, action| {
|
||||||
|
action.structure_mut().set("called", true);
|
||||||
|
|
||||||
|
Err(crate::ActionError::Error)
|
||||||
|
})
|
||||||
|
.build();
|
||||||
|
|
||||||
|
let called = Arc::new(Mutex::new(false));
|
||||||
|
let succeeding_action_type = crate::ActionTypeBuilder::new(
|
||||||
|
"succeeds",
|
||||||
|
glib::clone!(@strong called => move |_, _action| {
|
||||||
|
*called.lock().unwrap() = true;
|
||||||
|
|
||||||
|
Ok(crate::ActionSuccess::Ok)
|
||||||
|
}),
|
||||||
|
)
|
||||||
|
.parameter(
|
||||||
|
crate::ActionParameterBuilder::new("always", "Does the action always succeeds")
|
||||||
|
.add_type("boolean")
|
||||||
|
.default_value("true")
|
||||||
|
.build(),
|
||||||
|
)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
// Write scenario to temporary file
|
||||||
|
let mut file = tempfile::NamedTempFile::new().unwrap();
|
||||||
|
file.write_all(b"succeeds").unwrap();
|
||||||
|
|
||||||
|
let runner = crate::Runner::new();
|
||||||
|
let pipeline = gst::Pipeline::new(None);
|
||||||
|
let scenario =
|
||||||
|
crate::Scenario::factory_create(&runner, &pipeline, file.path().to_str().unwrap())
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
let action = crate::Action::new(
|
||||||
|
Some(&scenario),
|
||||||
|
&succeeding_action_type,
|
||||||
|
gst::Structure::builder("succeeds").build().as_ref(),
|
||||||
|
false,
|
||||||
|
);
|
||||||
|
|
||||||
|
assert!(!*called.lock().unwrap());
|
||||||
|
action.execute().expect("Failed to execute action");
|
||||||
|
assert!(*called.lock().unwrap());
|
||||||
|
|
||||||
|
let action = crate::Action::new(
|
||||||
|
Some(&scenario),
|
||||||
|
&failling_action_type,
|
||||||
|
gst::Structure::builder("fails").build().as_ref(),
|
||||||
|
false,
|
||||||
|
);
|
||||||
|
|
||||||
|
assert!(action.structure().get::<bool>("called").is_err());
|
||||||
|
action.execute().expect_err("Action should have failed");
|
||||||
|
assert_eq!(action.structure().get::<bool>("called"), Ok(true));
|
||||||
|
|
||||||
|
crate::ActionParameterBuilder::new("unused", "Verify unused param are properly cleaned")
|
||||||
|
.default_value("true")
|
||||||
|
.add_possible_variable("position")
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,47 +0,0 @@
|
||||||
// This file was generated by gir (https://github.com/gtk-rs/gir)
|
|
||||||
// from gir-files (https://github.com/gtk-rs/gir-files)
|
|
||||||
// from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git)
|
|
||||||
// DO NOT EDIT
|
|
||||||
|
|
||||||
use crate::Scenario;
|
|
||||||
use glib::translate::*;
|
|
||||||
|
|
||||||
glib::wrapper! {
|
|
||||||
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
|
||||||
pub struct Action(Shared<ffi::GstValidateAction>);
|
|
||||||
|
|
||||||
match fn {
|
|
||||||
ref => |ptr| ffi::gst_validate_action_ref(ptr),
|
|
||||||
unref => |ptr| ffi::gst_validate_action_unref(ptr),
|
|
||||||
type_ => || ffi::gst_validate_action_get_type(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Action {
|
|
||||||
//#[doc(alias = "gst_validate_action_new")]
|
|
||||||
//pub fn new(scenario: Option<&impl IsA<Scenario>>, action_type: /*Ignored*/&mut ActionType, structure: &mut gst::Structure, add_to_lists: bool) -> Action {
|
|
||||||
// unsafe { TODO: call ffi:gst_validate_action_new() }
|
|
||||||
//}
|
|
||||||
|
|
||||||
#[doc(alias = "gst_validate_action_get_scenario")]
|
|
||||||
#[doc(alias = "get_scenario")]
|
|
||||||
pub fn scenario(&self) -> Option<Scenario> {
|
|
||||||
unsafe { from_glib_full(ffi::gst_validate_action_get_scenario(self.to_glib_none().0)) }
|
|
||||||
}
|
|
||||||
|
|
||||||
#[doc(alias = "gst_validate_action_set_done")]
|
|
||||||
pub fn set_done(&self) {
|
|
||||||
unsafe {
|
|
||||||
ffi::gst_validate_action_set_done(self.to_glib_none().0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//#[doc(alias = "gst_validate_action_get_clocktime")]
|
|
||||||
//#[doc(alias = "get_clocktime")]
|
|
||||||
//pub fn clocktime(scenario: &impl IsA<Scenario>, action: &Action, name: &str) -> Option</*Ignored*/gst::ClockTime> {
|
|
||||||
// unsafe { TODO: call ffi:gst_validate_action_get_clocktime() }
|
|
||||||
//}
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe impl Send for Action {}
|
|
||||||
unsafe impl Sync for Action {}
|
|
18
gstreamer-validate/src/auto/action_type.rs
Normal file
18
gstreamer-validate/src/auto/action_type.rs
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
// This file was generated by gir (https://github.com/gtk-rs/gir)
|
||||||
|
// from gir-files (https://github.com/gtk-rs/gir-files)
|
||||||
|
// from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git)
|
||||||
|
// DO NOT EDIT
|
||||||
|
|
||||||
|
glib::wrapper! {
|
||||||
|
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
|
pub struct ActionType(Boxed<ffi::GstValidateActionType>);
|
||||||
|
|
||||||
|
match fn {
|
||||||
|
copy => |ptr| glib::gobject_ffi::g_boxed_copy(ffi::gst_validate_action_type_get_type(), ptr as *mut _) as *mut ffi::GstValidateActionType,
|
||||||
|
free => |ptr| glib::gobject_ffi::g_boxed_free(ffi::gst_validate_action_type_get_type(), ptr as *mut _),
|
||||||
|
type_ => || ffi::gst_validate_action_type_get_type(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe impl Send for ActionType {}
|
||||||
|
unsafe impl Sync for ActionType {}
|
|
@ -6,6 +6,110 @@
|
||||||
use bitflags::bitflags;
|
use bitflags::bitflags;
|
||||||
use glib::{translate::*, value::FromValue, value::ToValue, StaticType, Type};
|
use glib::{translate::*, value::FromValue, value::ToValue, StaticType, Type};
|
||||||
|
|
||||||
|
bitflags! {
|
||||||
|
#[doc(alias = "GstValidateActionTypeFlags")]
|
||||||
|
pub struct ActionTypeFlags: u32 {
|
||||||
|
#[doc(alias = "GST_VALIDATE_ACTION_TYPE_NONE")]
|
||||||
|
const NONE = ffi::GST_VALIDATE_ACTION_TYPE_NONE as _;
|
||||||
|
#[doc(alias = "GST_VALIDATE_ACTION_TYPE_CONFIG")]
|
||||||
|
const CONFIG = ffi::GST_VALIDATE_ACTION_TYPE_CONFIG as _;
|
||||||
|
#[doc(alias = "GST_VALIDATE_ACTION_TYPE_ASYNC")]
|
||||||
|
const ASYNC = ffi::GST_VALIDATE_ACTION_TYPE_ASYNC as _;
|
||||||
|
#[doc(alias = "GST_VALIDATE_ACTION_TYPE_NON_BLOCKING")]
|
||||||
|
const NON_BLOCKING = ffi::GST_VALIDATE_ACTION_TYPE_NON_BLOCKING as _;
|
||||||
|
#[doc(alias = "GST_VALIDATE_ACTION_TYPE_INTERLACED")]
|
||||||
|
const INTERLACED = ffi::GST_VALIDATE_ACTION_TYPE_INTERLACED as _;
|
||||||
|
#[doc(alias = "GST_VALIDATE_ACTION_TYPE_CAN_EXECUTE_ON_ADDITION")]
|
||||||
|
const CAN_EXECUTE_ON_ADDITION = ffi::GST_VALIDATE_ACTION_TYPE_CAN_EXECUTE_ON_ADDITION as _;
|
||||||
|
#[doc(alias = "GST_VALIDATE_ACTION_TYPE_NEEDS_CLOCK")]
|
||||||
|
const NEEDS_CLOCK = ffi::GST_VALIDATE_ACTION_TYPE_NEEDS_CLOCK as _;
|
||||||
|
#[doc(alias = "GST_VALIDATE_ACTION_TYPE_NO_EXECUTION_NOT_FATAL")]
|
||||||
|
const NO_EXECUTION_NOT_FATAL = ffi::GST_VALIDATE_ACTION_TYPE_NO_EXECUTION_NOT_FATAL as _;
|
||||||
|
#[doc(alias = "GST_VALIDATE_ACTION_TYPE_CAN_BE_OPTIONAL")]
|
||||||
|
const CAN_BE_OPTIONAL = ffi::GST_VALIDATE_ACTION_TYPE_CAN_BE_OPTIONAL as _;
|
||||||
|
#[doc(alias = "GST_VALIDATE_ACTION_TYPE_DOESNT_NEED_PIPELINE")]
|
||||||
|
const DOESNT_NEED_PIPELINE = ffi::GST_VALIDATE_ACTION_TYPE_DOESNT_NEED_PIPELINE as _;
|
||||||
|
#[doc(alias = "GST_VALIDATE_ACTION_TYPE_HANDLED_IN_CONFIG")]
|
||||||
|
const HANDLED_IN_CONFIG = ffi::GST_VALIDATE_ACTION_TYPE_HANDLED_IN_CONFIG as _;
|
||||||
|
#[doc(alias = "GST_VALIDATE_ACTION_TYPE_CHECK")]
|
||||||
|
const CHECK = ffi::GST_VALIDATE_ACTION_TYPE_CHECK as _;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
|
impl IntoGlib for ActionTypeFlags {
|
||||||
|
type GlibType = ffi::GstValidateActionTypeFlags;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn into_glib(self) -> ffi::GstValidateActionTypeFlags {
|
||||||
|
self.bits()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
|
impl FromGlib<ffi::GstValidateActionTypeFlags> for ActionTypeFlags {
|
||||||
|
#[inline]
|
||||||
|
unsafe fn from_glib(value: ffi::GstValidateActionTypeFlags) -> Self {
|
||||||
|
skip_assert_initialized!();
|
||||||
|
Self::from_bits_truncate(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl StaticType for ActionTypeFlags {
|
||||||
|
#[inline]
|
||||||
|
fn static_type() -> Type {
|
||||||
|
unsafe { from_glib(ffi::gst_validate_action_type_flags_get_type()) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl glib::HasParamSpec for ActionTypeFlags {
|
||||||
|
type ParamSpec = glib::ParamSpecFlags;
|
||||||
|
type SetValue = Self;
|
||||||
|
type BuilderFn = fn(&str) -> glib::ParamSpecFlagsBuilder<Self>;
|
||||||
|
|
||||||
|
fn param_spec_builder() -> Self::BuilderFn {
|
||||||
|
|name| Self::ParamSpec::builder(name)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl glib::value::ValueType for ActionTypeFlags {
|
||||||
|
type Type = Self;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe impl<'a> FromValue<'a> for ActionTypeFlags {
|
||||||
|
type Checker = glib::value::GenericValueTypeChecker<Self>;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
unsafe fn from_value(value: &'a glib::Value) -> Self {
|
||||||
|
skip_assert_initialized!();
|
||||||
|
from_glib(glib::gobject_ffi::g_value_get_flags(value.to_glib_none().0))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ToValue for ActionTypeFlags {
|
||||||
|
#[inline]
|
||||||
|
fn to_value(&self) -> glib::Value {
|
||||||
|
let mut value = glib::Value::for_value_type::<Self>();
|
||||||
|
unsafe {
|
||||||
|
glib::gobject_ffi::g_value_set_flags(value.to_glib_none_mut().0, self.into_glib());
|
||||||
|
}
|
||||||
|
value
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn value_type(&self) -> glib::Type {
|
||||||
|
Self::static_type()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<ActionTypeFlags> for glib::Value {
|
||||||
|
#[inline]
|
||||||
|
fn from(v: ActionTypeFlags) -> Self {
|
||||||
|
skip_assert_initialized!();
|
||||||
|
ToValue::to_value(&v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bitflags! {
|
bitflags! {
|
||||||
#[doc(alias = "GstValidateIssueFlags")]
|
#[doc(alias = "GstValidateIssueFlags")]
|
||||||
pub struct IssueFlags: u32 {
|
pub struct IssueFlags: u32 {
|
||||||
|
|
|
@ -27,8 +27,8 @@ pub use self::runner::Runner;
|
||||||
mod scenario;
|
mod scenario;
|
||||||
pub use self::scenario::Scenario;
|
pub use self::scenario::Scenario;
|
||||||
|
|
||||||
mod action;
|
mod action_type;
|
||||||
pub use self::action::Action;
|
pub use self::action_type::ActionType;
|
||||||
|
|
||||||
mod issue;
|
mod issue;
|
||||||
pub use self::issue::Issue;
|
pub use self::issue::Issue;
|
||||||
|
@ -41,6 +41,7 @@ pub use self::enums::ReportLevel;
|
||||||
pub use self::enums::ReportingDetails;
|
pub use self::enums::ReportingDetails;
|
||||||
|
|
||||||
mod flags;
|
mod flags;
|
||||||
|
pub use self::flags::ActionTypeFlags;
|
||||||
pub use self::flags::IssueFlags;
|
pub use self::flags::IssueFlags;
|
||||||
|
|
||||||
mod alias;
|
mod alias;
|
||||||
|
|
149
gstreamer-validate/src/enums.rs
Normal file
149
gstreamer-validate/src/enums.rs
Normal file
|
@ -0,0 +1,149 @@
|
||||||
|
use glib::translate::*;
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
|
||||||
|
#[repr(i32)]
|
||||||
|
pub enum ActionSuccess {
|
||||||
|
Ok = ffi::GST_VALIDATE_EXECUTE_ACTION_OK,
|
||||||
|
Async = ffi::GST_VALIDATE_EXECUTE_ACTION_ASYNC,
|
||||||
|
NonBlocking = ffi::GST_VALIDATE_EXECUTE_ACTION_NON_BLOCKING,
|
||||||
|
InProgress = ffi::GST_VALIDATE_EXECUTE_ACTION_IN_PROGRESS,
|
||||||
|
Done = ffi::GST_VALIDATE_EXECUTE_ACTION_DONE,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ActionSuccess {
|
||||||
|
pub fn from_value(value: impl Into<i32>) -> Option<Self> {
|
||||||
|
skip_assert_initialized!();
|
||||||
|
Some(match value.into() {
|
||||||
|
ffi::GST_VALIDATE_EXECUTE_ACTION_OK => ActionSuccess::Ok,
|
||||||
|
ffi::GST_VALIDATE_EXECUTE_ACTION_ASYNC => ActionSuccess::Async,
|
||||||
|
ffi::GST_VALIDATE_EXECUTE_ACTION_NON_BLOCKING => ActionSuccess::NonBlocking,
|
||||||
|
ffi::GST_VALIDATE_EXECUTE_ACTION_IN_PROGRESS => ActionSuccess::InProgress,
|
||||||
|
ffi::GST_VALIDATE_EXECUTE_ACTION_DONE => ActionSuccess::Done,
|
||||||
|
_ => return None,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IntoGlib for ActionSuccess {
|
||||||
|
type GlibType = ffi::GstValidateActionReturn;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn into_glib(self) -> ffi::GstValidateActionReturn {
|
||||||
|
skip_assert_initialized!();
|
||||||
|
self as ffi::GstValidateActionReturn
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
|
||||||
|
#[repr(i32)]
|
||||||
|
pub enum ActionError {
|
||||||
|
Error = ffi::GST_VALIDATE_EXECUTE_ACTION_ERROR,
|
||||||
|
ErrorReported = ffi::GST_VALIDATE_EXECUTE_ACTION_ERROR_REPORTED,
|
||||||
|
None = ffi::GST_VALIDATE_EXECUTE_ACTION_NONE,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ActionError {
|
||||||
|
pub fn from_value(value: impl Into<i32>) -> Self {
|
||||||
|
skip_assert_initialized!();
|
||||||
|
match value.into() {
|
||||||
|
ffi::GST_VALIDATE_EXECUTE_ACTION_ERROR => ActionError::Error,
|
||||||
|
ffi::GST_VALIDATE_EXECUTE_ACTION_ERROR_REPORTED => ActionError::ErrorReported,
|
||||||
|
ffi::GST_VALIDATE_EXECUTE_ACTION_NONE => ActionError::None,
|
||||||
|
_ => ActionError::Error,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IntoGlib for ActionError {
|
||||||
|
type GlibType = ffi::GstValidateActionReturn;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn into_glib(self) -> ffi::GstValidateActionReturn {
|
||||||
|
self as ffi::GstValidateActionReturn
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[must_use]
|
||||||
|
#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Clone, Copy)]
|
||||||
|
#[doc(alias = "GstValidateActionReturn")]
|
||||||
|
#[repr(i32)]
|
||||||
|
pub enum ActionReturn {
|
||||||
|
#[doc(alias = "GST_VALIDATE_EXECUTE_ACTION_ERROR")]
|
||||||
|
Error = ffi::GST_VALIDATE_EXECUTE_ACTION_ERROR,
|
||||||
|
#[doc(alias = "GST_VALIDATE_EXECUTE_ACTION_OK")]
|
||||||
|
Ok = ffi::GST_VALIDATE_EXECUTE_ACTION_OK,
|
||||||
|
#[doc(alias = "GST_VALIDATE_EXECUTE_ACTION_ASYNC")]
|
||||||
|
Async = ffi::GST_VALIDATE_EXECUTE_ACTION_ASYNC,
|
||||||
|
#[doc(alias = "GST_VALIDATE_EXECUTE_ACTION_NON_BLOCKING")]
|
||||||
|
NonBlocking = ffi::GST_VALIDATE_EXECUTE_ACTION_NON_BLOCKING,
|
||||||
|
#[doc(alias = "GST_VALIDATE_EXECUTE_ACTION_ERROR_REPORTED")]
|
||||||
|
ErrorReported = ffi::GST_VALIDATE_EXECUTE_ACTION_ERROR_REPORTED,
|
||||||
|
#[doc(alias = "GST_VALIDATE_EXECUTE_ACTION_IN_PROGRESS")]
|
||||||
|
InProgress = ffi::GST_VALIDATE_EXECUTE_ACTION_IN_PROGRESS,
|
||||||
|
#[doc(alias = "GST_VALIDATE_EXECUTE_ACTION_NONE")]
|
||||||
|
None = ffi::GST_VALIDATE_EXECUTE_ACTION_NONE,
|
||||||
|
#[doc(alias = "GST_VALIDATE_EXECUTE_ACTION_DONE")]
|
||||||
|
Done = ffi::GST_VALIDATE_EXECUTE_ACTION_DONE,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
|
impl IntoGlib for ActionReturn {
|
||||||
|
type GlibType = ffi::GstValidateActionReturn;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn into_glib(self) -> ffi::GstValidateActionReturn {
|
||||||
|
self as ffi::GstValidateActionReturn
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
|
impl FromGlib<ffi::GstValidateActionReturn> for ActionReturn {
|
||||||
|
#[inline]
|
||||||
|
unsafe fn from_glib(value: ffi::GstValidateActionReturn) -> Self {
|
||||||
|
skip_assert_initialized!();
|
||||||
|
|
||||||
|
if !(ffi::GST_VALIDATE_EXECUTE_ACTION_ERROR..=ffi::GST_VALIDATE_EXECUTE_ACTION_DONE)
|
||||||
|
.contains(&value)
|
||||||
|
{
|
||||||
|
ActionReturn::Error
|
||||||
|
} else {
|
||||||
|
std::mem::transmute(value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TryFromGlib<ffi::GstValidateActionReturn> for ActionSuccess {
|
||||||
|
type Error = ActionError;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
unsafe fn try_from_glib(
|
||||||
|
val: ffi::GstValidateActionReturn,
|
||||||
|
) -> Result<ActionSuccess, ActionError> {
|
||||||
|
skip_assert_initialized!();
|
||||||
|
ActionReturn::from_glib(val).into_result()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ActionReturn {
|
||||||
|
#[inline]
|
||||||
|
pub fn into_result(self) -> Result<ActionSuccess, ActionError> {
|
||||||
|
match self {
|
||||||
|
Self::Error | Self::ErrorReported | Self::None => {
|
||||||
|
Err(unsafe { std::mem::transmute(self) })
|
||||||
|
}
|
||||||
|
_ => Ok(unsafe { std::mem::transmute(self) }),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn from_error(v: ActionError) -> Self {
|
||||||
|
skip_assert_initialized!();
|
||||||
|
unsafe { std::mem::transmute(v) }
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
pub fn from_ok(v: ActionSuccess) -> Self {
|
||||||
|
skip_assert_initialized!();
|
||||||
|
unsafe { std::mem::transmute(v) }
|
||||||
|
}
|
||||||
|
}
|
|
@ -31,7 +31,6 @@ pub fn setup_test_file(test_file: &str, use_fakesinks: bool) -> gst::Structure {
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_init() {
|
fn test_init() {
|
||||||
gst::init().unwrap();
|
gst::init().unwrap();
|
||||||
|
|
|
@ -41,6 +41,15 @@ pub use crate::auto::*;
|
||||||
mod functions;
|
mod functions;
|
||||||
pub use functions::*;
|
pub use functions::*;
|
||||||
|
|
||||||
|
mod action_type;
|
||||||
|
pub use action_type::*;
|
||||||
|
|
||||||
|
mod enums;
|
||||||
|
pub use enums::*;
|
||||||
|
|
||||||
|
mod action;
|
||||||
|
pub use action::{Action, ActionRef};
|
||||||
|
|
||||||
// Re-export all the traits in a prelude module, so that applications
|
// Re-export all the traits in a prelude module, so that applications
|
||||||
// can always "use gst_validate::prelude::*" without getting conflicts
|
// can always "use gst_validate::prelude::*" without getting conflicts
|
||||||
pub mod prelude {
|
pub mod prelude {
|
||||||
|
|
Loading…
Reference in a new issue