diff --git a/Gir_Gst.toml b/Gir_Gst.toml index dc51f0312..424067944 100644 --- a/Gir_Gst.toml +++ b/Gir_Gst.toml @@ -71,6 +71,7 @@ generate = [ "Gst.DebugLevel", "Gst.StackTraceFlags", "Gst.DebugGraphDetails", + "Gst.ParseFlags", ] manual = [ @@ -142,6 +143,11 @@ name = "Gst.Structure" status = "manual" ref_mode = "ref-mut" +[[object]] +name = "Gst.ParseContext" +status = "manual" +ref_mode = "ref-mut" + [[object]] name = "Gst.Caps" status = "manual" @@ -712,3 +718,8 @@ status = "generate" [[object.function]] name = "util_set_value_from_string" ignore = true + + [[object.function]] + pattern = "parse.*full" + # wrong mutable for context parameter + ignore = true diff --git a/examples/src/bin/launch.rs b/examples/src/bin/launch.rs index cb16ec06b..4b96ea181 100644 --- a/examples/src/bin/launch.rs +++ b/examples/src/bin/launch.rs @@ -3,13 +3,27 @@ use gst::*; use std::u64; use std::env; +use std::process; fn main() { let pipeline_str = env::args().collect::>()[1..].join(" "); gst::init().unwrap(); - let pipeline = gst::parse_launch(&pipeline_str).unwrap(); + let mut context = ParseContext::new(); + let pipeline = + match gst::parse_launch_full(&pipeline_str, Some(&mut context), PARSE_FLAG_NONE) { + Ok(pipeline) => pipeline, + Err(err) => { + if let Some(ParseError::NoSuchElement) = err.kind::() { + println!("Missing element(s): {:?}", context.get_missing_elements()); + } else { + println!("Failed to parse pipeline: {}", err); + } + + process::exit(-1); + } + }; let bus = pipeline.get_bus().unwrap(); let ret = pipeline.set_state(gst::State::Playing); diff --git a/gstreamer/src/auto/flags.rs b/gstreamer/src/auto/flags.rs index d60dca01a..2eb1498f2 100644 --- a/gstreamer/src/auto/flags.rs +++ b/gstreamer/src/auto/flags.rs @@ -293,6 +293,56 @@ impl SetValue for PadProbeType { } } +bitflags! { + pub struct ParseFlags: u32 { + const PARSE_FLAG_NONE = 0; + const PARSE_FLAG_FATAL_ERRORS = 1; + const PARSE_FLAG_NO_SINGLE_ELEMENT_BINS = 2; + const PARSE_FLAG_PLACE_IN_BIN = 4; + } +} + +#[doc(hidden)] +impl ToGlib for ParseFlags { + type GlibType = ffi::GstParseFlags; + + fn to_glib(&self) -> ffi::GstParseFlags { + ffi::GstParseFlags::from_bits_truncate(self.bits()) + } +} + +#[doc(hidden)] +impl FromGlib for ParseFlags { + fn from_glib(value: ffi::GstParseFlags) -> ParseFlags { + skip_assert_initialized!(); + ParseFlags::from_bits_truncate(value.bits()) + } +} + +impl StaticType for ParseFlags { + fn static_type() -> Type { + unsafe { from_glib(ffi::gst_parse_flags_get_type()) } + } +} + +impl<'a> FromValueOptional<'a> for ParseFlags { + unsafe fn from_value_optional(value: &Value) -> Option { + Some(FromValue::from_value(value)) + } +} + +impl<'a> FromValue<'a> for ParseFlags { + unsafe fn from_value(value: &Value) -> Self { + from_glib(ffi::GstParseFlags::from_bits_truncate(gobject_ffi::g_value_get_flags(value.to_glib_none().0))) + } +} + +impl SetValue for ParseFlags { + unsafe fn set_value(value: &mut Value, this: &Self) { + gobject_ffi::g_value_set_flags(value.to_glib_none_mut().0, this.to_glib().bits()) + } +} + bitflags! { pub struct SchedulingFlags: u32 { const SCHEDULING_FLAG_SEEKABLE = 1; diff --git a/gstreamer/src/auto/functions.rs b/gstreamer/src/auto/functions.rs index 404e8e5cd..c86682d50 100644 --- a/gstreamer/src/auto/functions.rs +++ b/gstreamer/src/auto/functions.rs @@ -125,10 +125,6 @@ pub fn parse_bin_from_description(bin_description: &str, ghost_unlinked_pads: bo } } -//pub fn parse_bin_from_description_full<'a, P: Into>>(bin_description: &str, ghost_unlinked_pads: bool, context: P, flags: /*Ignored*/ParseFlags) -> Result { -// unsafe { TODO: call ffi::gst_parse_bin_from_description_full() } -//} - pub fn parse_launch(pipeline_description: &str) -> Result { assert_initialized_main_thread!(); unsafe { @@ -138,10 +134,6 @@ pub fn parse_launch(pipeline_description: &str) -> Result { } } -//pub fn parse_launch_full<'a, P: Into>>(pipeline_description: &str, context: P, flags: /*Ignored*/ParseFlags) -> Result { -// unsafe { TODO: call ffi::gst_parse_launch_full() } -//} - pub fn parse_launchv(argv: &[&str]) -> Result { assert_initialized_main_thread!(); unsafe { @@ -151,10 +143,6 @@ pub fn parse_launchv(argv: &[&str]) -> Result { } } -//pub fn parse_launchv_full<'a, P: Into>>(argv: &[&str], context: P, flags: /*Ignored*/ParseFlags) -> Result { -// unsafe { TODO: call ffi::gst_parse_launchv_full() } -//} - pub fn update_registry() -> Result<(), glib::error::BoolError> { assert_initialized_main_thread!(); unsafe { diff --git a/gstreamer/src/auto/mod.rs b/gstreamer/src/auto/mod.rs index 22a803dd7..c0dcbc367 100644 --- a/gstreamer/src/auto/mod.rs +++ b/gstreamer/src/auto/mod.rs @@ -196,6 +196,11 @@ pub use self::flags::PAD_PROBE_TYPE_EVENT_BOTH; pub use self::flags::PAD_PROBE_TYPE_QUERY_BOTH; pub use self::flags::PAD_PROBE_TYPE_ALL_BOTH; pub use self::flags::PAD_PROBE_TYPE_SCHEDULING; +pub use self::flags::ParseFlags; +pub use self::flags::PARSE_FLAG_NONE; +pub use self::flags::PARSE_FLAG_FATAL_ERRORS; +pub use self::flags::PARSE_FLAG_NO_SINGLE_ELEMENT_BINS; +pub use self::flags::PARSE_FLAG_PLACE_IN_BIN; pub use self::flags::SchedulingFlags; pub use self::flags::SCHEDULING_FLAG_SEEKABLE; pub use self::flags::SCHEDULING_FLAG_SEQUENTIAL; diff --git a/gstreamer/src/functions.rs b/gstreamer/src/functions.rs new file mode 100644 index 000000000..8408d974c --- /dev/null +++ b/gstreamer/src/functions.rs @@ -0,0 +1,87 @@ +// Copyright (C) 2017 Sebastian Dröge +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use ffi; +use glib::translate::*; +use std::ptr; + +use ParseContext; +use ParseFlags; +use Element; +use Error; + +pub fn parse_bin_from_description_full<'a, P: Into>>( + bin_description: &str, + ghost_unlinked_pads: bool, + context: P, + flags: ParseFlags, +) -> Result { + assert_initialized_main_thread!(); + let mut context = context.into(); + unsafe { + let mut error = ptr::null_mut(); + let ret = ffi::gst_parse_bin_from_description_full( + bin_description.to_glib_none().0, + ghost_unlinked_pads.to_glib(), + context.to_glib_none_mut().0, + flags.to_glib(), + &mut error, + ); + if error.is_null() { + Ok(from_glib_none(ret)) + } else { + Err(from_glib_full(error)) + } + } +} + +pub fn parse_launch_full<'a, P: Into>>( + pipeline_description: &str, + context: P, + flags: ParseFlags, +) -> Result { + assert_initialized_main_thread!(); + let mut context = context.into(); + unsafe { + let mut error = ptr::null_mut(); + let ret = ffi::gst_parse_launch_full( + pipeline_description.to_glib_none().0, + context.to_glib_none_mut().0, + flags.to_glib(), + &mut error, + ); + if error.is_null() { + Ok(from_glib_none(ret)) + } else { + Err(from_glib_full(error)) + } + } +} + +pub fn parse_launchv_full<'a, P: Into>>( + argv: &[&str], + context: P, + flags: ParseFlags, +) -> Result { + assert_initialized_main_thread!(); + let mut context = context.into(); + unsafe { + let mut error = ptr::null_mut(); + let ret = ffi::gst_parse_launchv_full( + argv.to_glib_none().0, + context.to_glib_none_mut().0, + flags.to_glib(), + &mut error, + ); + if error.is_null() { + Ok(from_glib_none(ret)) + } else { + Err(from_glib_full(error)) + } + } +} diff --git a/gstreamer/src/lib.rs b/gstreamer/src/lib.rs index c7a693d79..288cb808e 100644 --- a/gstreamer/src/lib.rs +++ b/gstreamer/src/lib.rs @@ -89,6 +89,7 @@ mod child_proxy; mod tag_setter; mod iterator; mod device_provider; +mod parse_context; pub use element::ElementExtManual; pub use element::{ ELEMENT_METADATA_AUTHOR, @@ -105,6 +106,7 @@ pub use child_proxy::ChildProxyExtManual; pub use tag_setter::TagSetterExtManual; pub use self::iterator::Iterator; pub use device_provider::DeviceProviderExtManual; +pub use parse_context::ParseContext; #[cfg(feature = "futures")] pub use bus::BusStream; @@ -120,6 +122,9 @@ pub use toc::{Toc, TocEntry, TocEntryRef, TocRef}; mod clock; pub use clock::{ClockId, ClockExtManual}; +pub mod functions; +pub use functions::*; + use std::ptr; pub fn init() -> Result<(), glib::Error> { diff --git a/gstreamer/src/parse_context.rs b/gstreamer/src/parse_context.rs new file mode 100644 index 000000000..d3921d2b7 --- /dev/null +++ b/gstreamer/src/parse_context.rs @@ -0,0 +1,45 @@ +// Copyright (C) 2017 Sebastian Dröge +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use glib::translate::*; +use ffi; +use glib_ffi; +use gobject_ffi; + +use std::mem; +use std::ptr; + +glib_wrapper! { + pub struct ParseContext(Boxed); + + match fn { + copy => |ptr| { + gobject_ffi::g_boxed_copy(ffi::gst_parse_context_get_type(), ptr as *mut _) as *mut ffi::GstParseContext + }, + free => |ptr| { + gobject_ffi::g_boxed_free(ffi::gst_parse_context_get_type(), ptr as *mut _) + }, + get_type => || ffi::gst_parse_context_get_type(), + } +} + +impl ParseContext { + pub fn new() -> Self { + unsafe { + from_glib_full(ffi::gst_parse_context_new()) + } + } + + pub fn get_missing_elements(&self) -> Vec { + unsafe { + FromGlibPtrContainer::from_glib_full(ffi::gst_parse_context_get_missing_elements( + mut_override(self.to_glib_none().0), + )) + } + } +}