From 1970a043d47ec9818d63e77d54d602506a945f02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Tue, 11 Jun 2024 08:34:46 +0300 Subject: [PATCH] pbutils: Add missing/install plugins API bindings Part-of: --- gstreamer-pbutils/Gir.toml | 2 + gstreamer-pbutils/src/auto/enums.rs | 153 +++++- .../src/auto/install_plugins_context.rs | 72 +++ gstreamer-pbutils/src/auto/mod.rs | 4 + gstreamer-pbutils/src/lib.rs | 3 + gstreamer-pbutils/src/missing_plugins.rs | 498 ++++++++++++++++++ 6 files changed, 731 insertions(+), 1 deletion(-) create mode 100644 gstreamer-pbutils/src/auto/install_plugins_context.rs create mode 100644 gstreamer-pbutils/src/missing_plugins.rs diff --git a/gstreamer-pbutils/Gir.toml b/gstreamer-pbutils/Gir.toml index 86f7e6de1..0e6628d5f 100644 --- a/gstreamer-pbutils/Gir.toml +++ b/gstreamer-pbutils/Gir.toml @@ -21,6 +21,8 @@ generate = [ "GstPbutils.AudioVisualizerShader", "GstPbutils.DiscovererInfo", "GstPbutils.DiscovererResult", + "GstPbutils.InstallPluginsContext", + "GstPbutils.InstallPluginsReturn", "GstPbutils.PbUtilsCapsDescriptionFlags", ] diff --git a/gstreamer-pbutils/src/auto/enums.rs b/gstreamer-pbutils/src/auto/enums.rs index fca38fc61..854d51409 100644 --- a/gstreamer-pbutils/src/auto/enums.rs +++ b/gstreamer-pbutils/src/auto/enums.rs @@ -4,7 +4,7 @@ // DO NOT EDIT use crate::ffi; -use glib::{prelude::*, translate::*}; +use glib::{prelude::*, translate::*, GStr}; #[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Clone, Copy)] #[non_exhaustive] @@ -245,3 +245,154 @@ impl From for glib::Value { ToValue::to_value(&v) } } + +#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Clone, Copy)] +#[non_exhaustive] +#[doc(alias = "GstInstallPluginsReturn")] +pub enum InstallPluginsReturn { + #[doc(alias = "GST_INSTALL_PLUGINS_SUCCESS")] + Success, + #[doc(alias = "GST_INSTALL_PLUGINS_NOT_FOUND")] + NotFound, + #[doc(alias = "GST_INSTALL_PLUGINS_ERROR")] + Error, + #[doc(alias = "GST_INSTALL_PLUGINS_PARTIAL_SUCCESS")] + PartialSuccess, + #[doc(alias = "GST_INSTALL_PLUGINS_USER_ABORT")] + UserAbort, + #[doc(alias = "GST_INSTALL_PLUGINS_CRASHED")] + Crashed, + #[doc(alias = "GST_INSTALL_PLUGINS_INVALID")] + Invalid, + #[doc(alias = "GST_INSTALL_PLUGINS_STARTED_OK")] + StartedOk, + #[doc(alias = "GST_INSTALL_PLUGINS_INTERNAL_FAILURE")] + InternalFailure, + #[doc(alias = "GST_INSTALL_PLUGINS_HELPER_MISSING")] + HelperMissing, + #[doc(alias = "GST_INSTALL_PLUGINS_INSTALL_IN_PROGRESS")] + InstallInProgress, + #[doc(hidden)] + __Unknown(i32), +} + +impl InstallPluginsReturn { + pub fn name<'a>(self) -> &'a GStr { + unsafe { + GStr::from_ptr( + ffi::gst_install_plugins_return_get_name(self.into_glib()) + .as_ref() + .expect("gst_install_plugins_return_get_name returned NULL"), + ) + } + } +} + +impl std::fmt::Display for InstallPluginsReturn { + #[inline] + fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + f.write_str(&self.name()) + } +} + +#[doc(hidden)] +impl IntoGlib for InstallPluginsReturn { + type GlibType = ffi::GstInstallPluginsReturn; + + #[inline] + fn into_glib(self) -> ffi::GstInstallPluginsReturn { + match self { + Self::Success => ffi::GST_INSTALL_PLUGINS_SUCCESS, + Self::NotFound => ffi::GST_INSTALL_PLUGINS_NOT_FOUND, + Self::Error => ffi::GST_INSTALL_PLUGINS_ERROR, + Self::PartialSuccess => ffi::GST_INSTALL_PLUGINS_PARTIAL_SUCCESS, + Self::UserAbort => ffi::GST_INSTALL_PLUGINS_USER_ABORT, + Self::Crashed => ffi::GST_INSTALL_PLUGINS_CRASHED, + Self::Invalid => ffi::GST_INSTALL_PLUGINS_INVALID, + Self::StartedOk => ffi::GST_INSTALL_PLUGINS_STARTED_OK, + Self::InternalFailure => ffi::GST_INSTALL_PLUGINS_INTERNAL_FAILURE, + Self::HelperMissing => ffi::GST_INSTALL_PLUGINS_HELPER_MISSING, + Self::InstallInProgress => ffi::GST_INSTALL_PLUGINS_INSTALL_IN_PROGRESS, + Self::__Unknown(value) => value, + } + } +} + +#[doc(hidden)] +impl FromGlib for InstallPluginsReturn { + #[inline] + unsafe fn from_glib(value: ffi::GstInstallPluginsReturn) -> Self { + skip_assert_initialized!(); + + match value { + ffi::GST_INSTALL_PLUGINS_SUCCESS => Self::Success, + ffi::GST_INSTALL_PLUGINS_NOT_FOUND => Self::NotFound, + ffi::GST_INSTALL_PLUGINS_ERROR => Self::Error, + ffi::GST_INSTALL_PLUGINS_PARTIAL_SUCCESS => Self::PartialSuccess, + ffi::GST_INSTALL_PLUGINS_USER_ABORT => Self::UserAbort, + ffi::GST_INSTALL_PLUGINS_CRASHED => Self::Crashed, + ffi::GST_INSTALL_PLUGINS_INVALID => Self::Invalid, + ffi::GST_INSTALL_PLUGINS_STARTED_OK => Self::StartedOk, + ffi::GST_INSTALL_PLUGINS_INTERNAL_FAILURE => Self::InternalFailure, + ffi::GST_INSTALL_PLUGINS_HELPER_MISSING => Self::HelperMissing, + ffi::GST_INSTALL_PLUGINS_INSTALL_IN_PROGRESS => Self::InstallInProgress, + value => Self::__Unknown(value), + } + } +} + +impl StaticType for InstallPluginsReturn { + #[inline] + #[doc(alias = "gst_install_plugins_return_get_type")] + fn static_type() -> glib::Type { + unsafe { from_glib(ffi::gst_install_plugins_return_get_type()) } + } +} + +impl glib::HasParamSpec for InstallPluginsReturn { + type ParamSpec = glib::ParamSpecEnum; + type SetValue = Self; + type BuilderFn = fn(&str, Self) -> glib::ParamSpecEnumBuilder; + + fn param_spec_builder() -> Self::BuilderFn { + Self::ParamSpec::builder_with_default + } +} + +impl glib::value::ValueType for InstallPluginsReturn { + type Type = Self; +} + +unsafe impl<'a> glib::value::FromValue<'a> for InstallPluginsReturn { + type Checker = glib::value::GenericValueTypeChecker; + + #[inline] + unsafe fn from_value(value: &'a glib::Value) -> Self { + skip_assert_initialized!(); + from_glib(glib::gobject_ffi::g_value_get_enum(value.to_glib_none().0)) + } +} + +impl ToValue for InstallPluginsReturn { + #[inline] + fn to_value(&self) -> glib::Value { + let mut value = glib::Value::for_value_type::(); + unsafe { + glib::gobject_ffi::g_value_set_enum(value.to_glib_none_mut().0, self.into_glib()); + } + value + } + + #[inline] + fn value_type(&self) -> glib::Type { + Self::static_type() + } +} + +impl From for glib::Value { + #[inline] + fn from(v: InstallPluginsReturn) -> Self { + skip_assert_initialized!(); + ToValue::to_value(&v) + } +} diff --git a/gstreamer-pbutils/src/auto/install_plugins_context.rs b/gstreamer-pbutils/src/auto/install_plugins_context.rs new file mode 100644 index 000000000..48e19844d --- /dev/null +++ b/gstreamer-pbutils/src/auto/install_plugins_context.rs @@ -0,0 +1,72 @@ +// 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::ffi; +use glib::translate::*; + +glib::wrapper! { + #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] + pub struct InstallPluginsContext(Boxed); + + match fn { + copy => |ptr| ffi::gst_install_plugins_context_copy(mut_override(ptr)), + free => |ptr| ffi::gst_install_plugins_context_free(ptr), + type_ => || ffi::gst_install_plugins_context_get_type(), + } +} + +impl InstallPluginsContext { + #[doc(alias = "gst_install_plugins_context_new")] + pub fn new() -> InstallPluginsContext { + assert_initialized_main_thread!(); + unsafe { from_glib_full(ffi::gst_install_plugins_context_new()) } + } + + #[doc(alias = "gst_install_plugins_context_set_confirm_search")] + pub fn set_confirm_search(&mut self, confirm_search: bool) { + unsafe { + ffi::gst_install_plugins_context_set_confirm_search( + self.to_glib_none_mut().0, + confirm_search.into_glib(), + ); + } + } + + #[doc(alias = "gst_install_plugins_context_set_desktop_id")] + pub fn set_desktop_id(&mut self, desktop_id: &str) { + unsafe { + ffi::gst_install_plugins_context_set_desktop_id( + self.to_glib_none_mut().0, + desktop_id.to_glib_none().0, + ); + } + } + + #[doc(alias = "gst_install_plugins_context_set_startup_notification_id")] + pub fn set_startup_notification_id(&mut self, startup_id: &str) { + unsafe { + ffi::gst_install_plugins_context_set_startup_notification_id( + self.to_glib_none_mut().0, + startup_id.to_glib_none().0, + ); + } + } + + #[doc(alias = "gst_install_plugins_context_set_xid")] + pub fn set_xid(&mut self, xid: u32) { + unsafe { + ffi::gst_install_plugins_context_set_xid(self.to_glib_none_mut().0, xid); + } + } +} + +impl Default for InstallPluginsContext { + fn default() -> Self { + Self::new() + } +} + +unsafe impl Send for InstallPluginsContext {} +unsafe impl Sync for InstallPluginsContext {} diff --git a/gstreamer-pbutils/src/auto/mod.rs b/gstreamer-pbutils/src/auto/mod.rs index b4143e68b..63d4ccaf1 100644 --- a/gstreamer-pbutils/src/auto/mod.rs +++ b/gstreamer-pbutils/src/auto/mod.rs @@ -42,9 +42,13 @@ pub use self::encoding_target::EncodingTarget; mod encoding_video_profile; pub use self::encoding_video_profile::EncodingVideoProfile; +mod install_plugins_context; +pub use self::install_plugins_context::InstallPluginsContext; + mod enums; pub use self::enums::AudioVisualizerShader; pub use self::enums::DiscovererResult; +pub use self::enums::InstallPluginsReturn; mod flags; pub use self::flags::DiscovererSerializeFlags; diff --git a/gstreamer-pbutils/src/lib.rs b/gstreamer-pbutils/src/lib.rs index 692dc1787..eda876360 100644 --- a/gstreamer-pbutils/src/lib.rs +++ b/gstreamer-pbutils/src/lib.rs @@ -27,6 +27,7 @@ macro_rules! skip_assert_initialized { () => {}; } +#[allow(clippy::needless_borrow)] mod auto; pub use crate::auto::*; @@ -46,6 +47,8 @@ mod discoverer_container_info; pub mod discoverer_stream_info; mod discoverer_subtitle_info; mod discoverer_video_info; +pub mod missing_plugins; +pub use missing_plugins::MissingPluginMessage; pub mod encoding_profile; diff --git a/gstreamer-pbutils/src/missing_plugins.rs b/gstreamer-pbutils/src/missing_plugins.rs new file mode 100644 index 000000000..689465f19 --- /dev/null +++ b/gstreamer-pbutils/src/missing_plugins.rs @@ -0,0 +1,498 @@ +// Take a look at the license at the top of the repository in the LICENSE file. + +use glib::{translate::*, value::ToSendValue}; +use gst::{ffi as gst_ffi, prelude::*, Element, Message, Seqnum}; + +use crate::ffi; + +macro_rules! message_builder_generic_impl { + ($new_fn:expr) => { + #[allow(clippy::needless_update)] + pub fn src + Cast + Clone>(self, src: &O) -> Self { + Self { + builder: self.builder.src(src), + ..self + } + } + + #[allow(clippy::needless_update)] + pub fn src_if_some + Cast + Clone>(self, src: Option<&O>) -> Self { + if let Some(src) = src { + self.src(src) + } else { + self + } + } + + #[doc(alias = "gst_message_set_seqnum")] + #[allow(clippy::needless_update)] + pub fn seqnum(self, seqnum: Seqnum) -> Self { + Self { + builder: self.builder.seqnum(seqnum), + ..self + } + } + + #[doc(alias = "gst_message_set_seqnum")] + #[allow(clippy::needless_update)] + pub fn seqnum_if_some(self, seqnum: Option) -> Self { + if let Some(seqnum) = seqnum { + self.seqnum(seqnum) + } else { + self + } + } + + #[cfg(feature = "v1_26")] + #[cfg_attr(docsrs, doc(cfg(feature = "v1_26")))] + #[doc(alias = "gst_message_set_details")] + pub fn details(self, details: gst::Structure) -> Self { + Self { + builder: self.builder.details(details), + ..self + } + } + + #[cfg(feature = "v1_26")] + #[cfg_attr(docsrs, doc(cfg(feature = "v1_26")))] + #[doc(alias = "gst_message_set_details")] + pub fn details_if_some(self, details: Option) -> Self { + if let Some(details) = details { + self.details(details) + } else { + self + } + } + + #[cfg(feature = "v1_26")] + #[cfg_attr(docsrs, doc(cfg(feature = "v1_26")))] + #[doc(alias = "gst_missing_plugin_message_set_stream_id")] + pub fn stream_id(self, stream_id: &'a str) -> Self { + Self { + stream_id: Some(stream_id), + ..self + } + } + + #[cfg(feature = "v1_26")] + #[cfg_attr(docsrs, doc(cfg(feature = "v1_26")))] + #[doc(alias = "gst_missing_plugin_message_set_stream_id")] + pub fn stream_id_if_some(self, stream_id: Option<&'a str>) -> Self { + if let Some(stream_id) = stream_id { + self.stream_id(stream_id) + } else { + self + } + } + + pub fn other_field(self, name: &'a str, value: impl ToSendValue) -> Self { + Self { + builder: self.builder.other_field(name, value), + ..self + } + } + + pub fn other_field_if_some(self, name: &'a str, value: Option) -> Self { + if let Some(value) = value { + self.other_field(name, value) + } else { + self + } + } + + #[deprecated = "use builder.other_field() instead"] + #[allow(clippy::needless_update)] + pub fn other_fields( + self, + other_fields: &[(&'a str, &'a (dyn ToSendValue + Sync))], + ) -> Self { + Self { + builder: self.builder.other_fields(other_fields), + ..self + } + } + + #[must_use = "Building the message without using it has no effect"] + #[allow(clippy::redundant_closure_call)] + pub fn build(mut self) -> Message { + skip_assert_initialized!(); + unsafe { + let src = self.builder.src.to_glib_none().0; + let msg = $new_fn(&mut self, src); + if let Some(seqnum) = self.builder.seqnum { + gst_ffi::gst_message_set_seqnum(msg, seqnum.into_glib()); + } + + #[cfg(feature = "v1_26")] + if let Some(details) = self.builder.details { + gst_ffi::gst_message_set_details(msg, details.into_glib_ptr()); + } + + if !self.builder.other_fields.is_empty() { + let structure = gst_ffi::gst_message_writable_structure(msg); + + if !structure.is_null() { + let structure = + gst::StructureRef::from_glib_borrow_mut(structure as *mut _); + + for (k, v) in self.builder.other_fields { + structure.set_value(k, v); + } + } + } + + from_glib_full(msg) + } + } + }; +} + +struct MessageBuilder<'a> { + src: Option, + seqnum: Option, + #[cfg(feature = "v1_26")] + details: Option, + other_fields: Vec<(&'a str, glib::SendValue)>, +} + +impl<'a> MessageBuilder<'a> { + fn new() -> Self { + skip_assert_initialized!(); + Self { + src: None, + seqnum: None, + #[cfg(feature = "v1_26")] + details: None, + other_fields: Vec::new(), + } + } + + fn src + Cast + Clone>(self, src: &O) -> Self { + Self { + src: Some(src.clone().upcast::()), + ..self + } + } + + fn seqnum(self, seqnum: Seqnum) -> Self { + Self { + seqnum: Some(seqnum), + ..self + } + } + + #[cfg(feature = "v1_26")] + #[cfg_attr(docsrs, doc(cfg(feature = "v1_26")))] + #[doc(alias = "gst_message_set_details")] + fn details(self, details: gst::Structure) -> Self { + Self { + details: Some(details), + ..self + } + } + + fn other_field(self, name: &'a str, value: impl ToSendValue) -> Self { + let mut other_fields = self.other_fields; + other_fields.push((name, value.to_send_value())); + + Self { + other_fields, + ..self + } + } + + fn other_fields(self, other_fields: &[(&'a str, &'a (dyn ToSendValue + Sync))]) -> Self { + let mut s = self; + + for (name, value) in other_fields { + s = s.other_field(name, value.to_send_value()); + } + + s + } +} + +enum MessageBuilderDetail<'a> { + Decoder(&'a gst::Caps), + Encoder(&'a gst::Caps), + Element(&'a str), + Sink(&'a str), + Src(&'a str), +} + +#[must_use = "The builder must be built to be used"] +pub struct MissingPluginMessageBuilder<'a> { + builder: MessageBuilder<'a>, + detail: MessageBuilderDetail<'a>, + #[cfg(feature = "v1_26")] + stream_id: Option<&'a str>, +} + +impl<'a> MissingPluginMessageBuilder<'a> { + fn new(detail: MessageBuilderDetail<'a>) -> Self { + skip_assert_initialized!(); + Self { + builder: MessageBuilder::new(), + detail, + #[cfg(feature = "v1_26")] + stream_id: None, + } + } + + message_builder_generic_impl!(|s: &Self, src| { + let msg = match s.detail { + MessageBuilderDetail::Decoder(caps) => { + ffi::gst_missing_decoder_message_new(src, caps.to_glib_none().0) + } + MessageBuilderDetail::Encoder(caps) => { + ffi::gst_missing_encoder_message_new(src, caps.to_glib_none().0) + } + MessageBuilderDetail::Element(name) => { + ffi::gst_missing_element_message_new(src, name.to_glib_none().0) + } + MessageBuilderDetail::Sink(protocol) => { + ffi::gst_missing_uri_sink_message_new(src, protocol.to_glib_none().0) + } + MessageBuilderDetail::Src(protocol) => { + ffi::gst_missing_uri_source_message_new(src, protocol.to_glib_none().0) + } + }; + + #[cfg(feature = "v1_26")] + if let Some(stream_id) = s.stream_id { + ffi::gst_missing_plugin_message_set_stream_id(msg, stream_id.to_glib_none().0); + } + + msg + }); +} + +#[derive(Clone, Debug)] +pub struct MissingPluginMessage<'a> { + pub msg: &'a gst::MessageRef, +} + +impl<'a> MissingPluginMessage<'a> { + #[doc(alias = "gst_missing_decoder_message_new")] + #[allow(clippy::new_ret_no_self)] + pub fn for_decoder(caps: &'a gst::Caps) -> gst::Message { + skip_assert_initialized!(); + MissingPluginMessageBuilder::new(MessageBuilderDetail::Decoder(caps)).build() + } + + #[doc(alias = "gst_missing_decoder_message_new")] + pub fn builder_for_decoder(caps: &'a gst::Caps) -> MissingPluginMessageBuilder<'a> { + skip_assert_initialized!(); + MissingPluginMessageBuilder::new(MessageBuilderDetail::Decoder(caps)) + } + + #[doc(alias = "gst_missing_encoder_message_new")] + #[allow(clippy::new_ret_no_self)] + pub fn for_encoder(caps: &'a gst::Caps) -> gst::Message { + skip_assert_initialized!(); + MissingPluginMessageBuilder::new(MessageBuilderDetail::Encoder(caps)).build() + } + + #[doc(alias = "gst_missing_encoder_message_new")] + pub fn builder_for_encoder(caps: &'a gst::Caps) -> MissingPluginMessageBuilder<'a> { + skip_assert_initialized!(); + MissingPluginMessageBuilder::new(MessageBuilderDetail::Encoder(caps)) + } + + #[doc(alias = "gst_missing_element_message_new")] + #[allow(clippy::new_ret_no_self)] + pub fn for_element(name: &'a str) -> gst::Message { + skip_assert_initialized!(); + MissingPluginMessageBuilder::new(MessageBuilderDetail::Element(name)).build() + } + + #[doc(alias = "gst_missing_element_message_new")] + pub fn builder_for_element(name: &'a str) -> MissingPluginMessageBuilder<'a> { + skip_assert_initialized!(); + MissingPluginMessageBuilder::new(MessageBuilderDetail::Element(name)) + } + + #[doc(alias = "gst_missing_uri_source_message_new")] + #[allow(clippy::new_ret_no_self)] + pub fn for_uri_source(protocol: &'a str) -> gst::Message { + skip_assert_initialized!(); + MissingPluginMessageBuilder::new(MessageBuilderDetail::Src(protocol)).build() + } + + #[doc(alias = "gst_missing_uri_source_message_new")] + pub fn builder_for_uri_source(protocol: &'a str) -> MissingPluginMessageBuilder<'a> { + skip_assert_initialized!(); + MissingPluginMessageBuilder::new(MessageBuilderDetail::Src(protocol)) + } + + #[doc(alias = "gst_missing_uri_sink_message_new")] + #[allow(clippy::new_ret_no_self)] + pub fn for_uri_sink(protocol: &'a str) -> gst::Message { + skip_assert_initialized!(); + MissingPluginMessageBuilder::new(MessageBuilderDetail::Sink(protocol)).build() + } + + #[doc(alias = "gst_missing_uri_sink_message_new")] + pub fn builder_for_uri_sink(protocol: &'a str) -> MissingPluginMessageBuilder<'a> { + skip_assert_initialized!(); + MissingPluginMessageBuilder::new(MessageBuilderDetail::Sink(protocol)) + } + + #[doc(alias = "gst_is_missing_plugin_message")] + pub fn is(msg: &gst::MessageRef) -> bool { + skip_assert_initialized!(); + unsafe { + from_glib(ffi::gst_is_missing_plugin_message(mut_override( + msg.as_ptr(), + ))) + } + } + + pub fn parse(msg: &'a gst::MessageRef) -> Result { + skip_assert_initialized!(); + if Self::is(msg) { + Ok(MissingPluginMessage { msg }) + } else { + Err(glib::bool_error!("Invalid missing plugin message")) + } + } + + #[doc(alias = "gst_missing_plugin_message_get_description")] + pub fn description(&self) -> glib::GString { + unsafe { + from_glib_full(ffi::gst_missing_plugin_message_get_description( + mut_override(self.msg.as_ptr()), + )) + } + } + + #[doc(alias = "gst_missing_plugin_message_get_installer_detail")] + pub fn installer_detail(&self) -> glib::GString { + unsafe { + from_glib_full(ffi::gst_missing_plugin_message_get_installer_detail( + mut_override(self.msg.as_ptr()), + )) + } + } + + #[cfg(feature = "v1_26")] + #[cfg_attr(docsrs, doc(cfg(feature = "v1_26")))] + #[doc(alias = "gst_missing_plugin_message_get_stream_id")] + pub fn stream_id(&self) -> Option<&glib::GStr> { + unsafe { + let stream_id = + ffi::gst_missing_plugin_message_get_stream_id(mut_override(self.msg.as_ptr())); + if stream_id.is_null() { + None + } else { + Some(glib::GStr::from_ptr(stream_id)) + } + } + } +} + +#[doc(alias = "gst_missing_decoder_installer_detail_new")] +pub fn missing_decoder_installer_detail_new(caps: &gst::Caps) -> glib::GString { + skip_assert_initialized!(); + unsafe { + from_glib_full(ffi::gst_missing_decoder_installer_detail_new(mut_override( + caps.as_ptr(), + ))) + } +} + +#[doc(alias = "gst_missing_encoder_installer_detail_new")] +pub fn missing_encoder_installer_detail_new(caps: &gst::Caps) -> glib::GString { + skip_assert_initialized!(); + unsafe { + from_glib_full(ffi::gst_missing_encoder_installer_detail_new(mut_override( + caps.as_ptr(), + ))) + } +} + +#[doc(alias = "gst_missing_element_installer_detail_new")] +pub fn missing_element_installer_detail_new(name: &str) -> glib::GString { + skip_assert_initialized!(); + unsafe { + from_glib_full(ffi::gst_missing_element_installer_detail_new(mut_override( + name.to_glib_none().0, + ))) + } +} + +#[doc(alias = "gst_missing_uri_source_installer_detail_new")] +pub fn missing_uri_source_installer_detail_new(protocol: &str) -> glib::GString { + skip_assert_initialized!(); + unsafe { + from_glib_full(ffi::gst_missing_uri_source_installer_detail_new( + mut_override(protocol.to_glib_none().0), + )) + } +} + +#[doc(alias = "gst_missing_uri_sink_installer_detail_new")] +pub fn missing_uri_sink_installer_detail_new(protocol: &str) -> glib::GString { + skip_assert_initialized!(); + unsafe { + from_glib_full(ffi::gst_missing_uri_sink_installer_detail_new( + mut_override(protocol.to_glib_none().0), + )) + } +} + +#[doc(alias = "gst_install_plugins_supported")] +pub fn install_plugins_supported() -> bool { + skip_assert_initialized!(); + unsafe { from_glib(ffi::gst_install_plugins_supported()) } +} + +#[doc(alias = "gst_install_plugins_installation_in_progress")] +pub fn install_plugins_installation_in_progress() -> bool { + skip_assert_initialized!(); + unsafe { from_glib(ffi::gst_install_plugins_installation_in_progress()) } +} + +#[doc(alias = "gst_install_plugins_sync")] +pub fn install_plugins_sync( + details: &[&str], + ctx: Option<&crate::InstallPluginsContext>, +) -> crate::InstallPluginsReturn { + skip_assert_initialized!(); + unsafe { + from_glib(ffi::gst_install_plugins_sync( + ToGlibPtr::<*const *mut _>::to_glib_none(&glib::StrV::from(details)).0 + as *const *const _, + ctx.to_glib_none().0, + )) + } +} + +#[doc(alias = "gst_install_plugins_async")] +pub fn install_plugins_async( + details: &[&str], + ctx: Option<&crate::InstallPluginsContext>, + func: F, +) -> crate::InstallPluginsReturn { + skip_assert_initialized!(); + + let user_data: Box> = Box::new(Some(func)); + + unsafe extern "C" fn trampoline( + ret: ffi::GstInstallPluginsReturn, + user_data: glib::ffi::gpointer, + ) { + let callback = Box::from_raw(user_data as *mut F); + callback(from_glib(ret)); + } + + unsafe { + from_glib(ffi::gst_install_plugins_async( + ToGlibPtr::<*const *mut _>::to_glib_none(&glib::StrV::from(details)).0 + as *const *const _, + ctx.to_glib_none().0, + Some(trampoline::), + Box::into_raw(user_data) as *mut _, + )) + } +}