diff --git a/Gir_Gst.toml b/Gir_Gst.toml index 694f50701..59109de49 100644 --- a/Gir_Gst.toml +++ b/Gir_Gst.toml @@ -40,6 +40,7 @@ generate = [ "Gst.StreamFlags", "Gst.ProgressType", "Gst.BusSyncReply", + "Gst.TagFlag", "Gst.TagMergeMode", "Gst.PadProbeType", "Gst.PadProbeReturn", diff --git a/gstreamer/src/auto/enums.rs b/gstreamer/src/auto/enums.rs index 43deb5ebb..83b2f9dda 100644 --- a/gstreamer/src/auto/enums.rs +++ b/gstreamer/src/auto/enums.rs @@ -2387,6 +2387,73 @@ impl SetValue for StructureChangeType { } } +#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash)] +#[derive(Clone, Copy)] +pub enum TagFlag { + Undefined, + Meta, + Encoded, + Decoded, + Count, + #[doc(hidden)] + __Unknown(i32), +} + +#[doc(hidden)] +impl ToGlib for TagFlag { + type GlibType = ffi::GstTagFlag; + + fn to_glib(&self) -> ffi::GstTagFlag { + match *self { + TagFlag::Undefined => ffi::GST_TAG_FLAG_UNDEFINED, + TagFlag::Meta => ffi::GST_TAG_FLAG_META, + TagFlag::Encoded => ffi::GST_TAG_FLAG_ENCODED, + TagFlag::Decoded => ffi::GST_TAG_FLAG_DECODED, + TagFlag::Count => ffi::GST_TAG_FLAG_COUNT, + TagFlag::__Unknown(value) => value + } + } +} + +#[doc(hidden)] +impl FromGlib for TagFlag { + fn from_glib(value: ffi::GstTagFlag) -> Self { + skip_assert_initialized!(); + match value { + 0 => TagFlag::Undefined, + 1 => TagFlag::Meta, + 2 => TagFlag::Encoded, + 3 => TagFlag::Decoded, + 4 => TagFlag::Count, + value => TagFlag::__Unknown(value), + } + } +} + +impl StaticType for TagFlag { + fn static_type() -> Type { + unsafe { from_glib(ffi::gst_tag_flag_get_type()) } + } +} + +impl<'a> FromValueOptional<'a> for TagFlag { + unsafe fn from_value_optional(value: &Value) -> Option { + Some(FromValue::from_value(value)) + } +} + +impl<'a> FromValue<'a> for TagFlag { + unsafe fn from_value(value: &Value) -> Self { + from_glib(gobject_ffi::g_value_get_enum(value.to_glib_none().0)) + } +} + +impl SetValue for TagFlag { + unsafe fn set_value(value: &mut Value, this: &Self) { + gobject_ffi::g_value_set_enum(value.to_glib_none_mut().0, this.to_glib()) + } +} + #[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash)] #[derive(Clone, Copy)] pub enum TagMergeMode { diff --git a/gstreamer/src/auto/mod.rs b/gstreamer/src/auto/mod.rs index 4f1e2db08..5319e158b 100644 --- a/gstreamer/src/auto/mod.rs +++ b/gstreamer/src/auto/mod.rs @@ -144,6 +144,7 @@ pub use self::enums::StateChangeReturn; pub use self::enums::StreamError; pub use self::enums::StreamStatusType; pub use self::enums::StructureChangeType; +pub use self::enums::TagFlag; pub use self::enums::TagMergeMode; pub use self::enums::TaskState; pub use self::enums::TocEntryType; diff --git a/gstreamer/src/lib.rs b/gstreamer/src/lib.rs index 80dc6b6be..69b9fcd56 100644 --- a/gstreamer/src/lib.rs +++ b/gstreamer/src/lib.rs @@ -335,7 +335,7 @@ pub mod prelude { pub use value::GstValueExt; pub use miniobject::MiniObject; - pub use tags::Tag; + pub use tags::{CustomTag, Tag}; pub use muldiv::MulDiv; diff --git a/gstreamer/src/tags.rs b/gstreamer/src/tags.rs index 0c1cf8500..b59519578 100644 --- a/gstreamer/src/tags.rs +++ b/gstreamer/src/tags.rs @@ -1,4 +1,4 @@ -// Copyright (C) 2016-2017 Sebastian Dröge +// Copyright (C) 2016-2018 Sebastian Dröge // // Licensed under the Apache License, Version 2.0 or the MIT license @@ -14,7 +14,9 @@ use std::mem; use ffi; use glib; use glib::translate::{from_glib, from_glib_full, ToGlib, ToGlibPtr, ToGlibPtrMut}; -use glib::value::{FromValueOptional, SendValue, SetValue, ToSendValue, TypedValue}; +use glib::value::{FromValueOptional, SendValue, SetValue, ToSendValue, TypedValue, Value}; +use glib::StaticType; +use gobject_ffi; use miniobject::*; @@ -765,6 +767,60 @@ impl<'a> DoubleEndedIterator for Iter<'a> { impl<'a> ExactSizeIterator for Iter<'a> {} +pub trait CustomTag<'a>: Tag<'a> { + const FLAG: ::TagFlag; + const NICK: &'static str; + const DESCRIPTION: &'static str; + + fn merge_func(src: &Value) -> Value { + merge_use_first(src) + } +} + +pub fn register CustomTag<'a>>() { + unsafe extern "C" fn merge_func_trampoline CustomTag<'a>>( + dest: *mut gobject_ffi::GValue, + src: *const gobject_ffi::GValue, + ) { + *dest = T::merge_func(&*(src as *const Value)).into_raw(); + } + + unsafe { + ffi::gst_tag_register( + T::tag_name().to_glib_none().0, + T::FLAG.to_glib(), + T::TagType::static_type().to_glib(), + T::NICK.to_glib_none().0, + T::DESCRIPTION.to_glib_none().0, + Some(merge_func_trampoline::), + ) + } +} + +pub fn merge_use_first(src: &Value) -> Value { + assert_eq!(src.type_(), ::List::static_type()); + + unsafe { + use glib::translate::Uninitialized; + + let mut res = Value::uninitialized(); + ffi::gst_tag_merge_use_first(res.to_glib_none_mut().0, src.to_glib_none().0); + res + } +} + +pub fn merge_strings_with_comma(src: &Value) -> Value { + assert_eq!(src.type_(), ::List::static_type()); + + unsafe { + use glib::translate::Uninitialized; + + let mut res = Value::uninitialized(); + ffi::gst_tag_merge_strings_with_comma(res.to_glib_none_mut().0, src.to_glib_none().0); + res + } +} + #[cfg(test)] mod tests { use super::*; @@ -915,4 +971,48 @@ mod tests { assert_eq!(tag_value.get(), Some(::SECOND * 120)); assert!(tag_iter.next().is_none()); } + + #[test] + fn test_custom_tags() { + ::init().unwrap(); + + struct MyCustomTag; + + impl<'a> Tag<'a> for MyCustomTag { + type TagType = &'a str; + fn tag_name<'b>() -> &'b str { + "my-custom-tag" + } + } + + impl<'a> CustomTag<'a> for MyCustomTag { + const FLAG: ::TagFlag = ::TagFlag::Meta; + const NICK: &'static str = "my custom tag"; + const DESCRIPTION: &'static str = "My own custom tag type for testing"; + + fn merge_func(src: &Value) -> Value { + merge_strings_with_comma(src) + } + } + + register::(); + + let mut tags = TagList::new(); + { + let tags = tags.get_mut().unwrap(); + tags.add::(&"first one", TagMergeMode::Append); + } + + assert_eq!(tags.get::().unwrap().get(), Some("first one")); + + { + let tags = tags.get_mut().unwrap(); + tags.add::(&"second one", TagMergeMode::Append); + } + + assert_eq!( + tags.get::().unwrap().get(), + Some("first one, second one") + ); + } }