Update for Value trait refactoring

This commit is contained in:
Sebastian Dröge 2021-04-20 10:19:02 +03:00
parent 0eb5845934
commit eda1d3d4a7
54 changed files with 1254 additions and 871 deletions

View file

@ -34,7 +34,7 @@ impl ExampleCustomEvent {
_ => return None, // No structure in this event, or the name didn't match _ => return None, // No structure in this event, or the name didn't match
}; };
let send_eos = s.get_some::<bool>("send_eos").unwrap(); let send_eos = s.get::<bool>("send_eos").unwrap();
Some(ExampleCustomEvent { send_eos }) Some(ExampleCustomEvent { send_eos })
} }
_ => None, // Not a custom event _ => None, // Not a custom event

View file

@ -255,7 +255,11 @@ fn example_main() -> Result<(), Error> {
Some(details) if details.name() == "error-details" => details Some(details) if details.name() == "error-details" => details
.get::<&ErrorValue>("error") .get::<&ErrorValue>("error")
.unwrap() .unwrap()
.and_then(|v| v.0.lock().unwrap().take()) .clone()
.0
.lock()
.unwrap()
.take()
.map(Result::Err) .map(Result::Err)
.expect("error-details message without actual error"), .expect("error-details message without actual error"),
_ => Err(ErrorMessage { _ => Err(ErrorMessage {

View file

@ -276,8 +276,11 @@ fn example_main() -> Result<(), Error> {
Some(details) if details.name() == "error-details" => details Some(details) if details.name() == "error-details" => details
.get::<&ErrorValue>("error") .get::<&ErrorValue>("error")
.unwrap() .unwrap()
.cloned() .clone()
.and_then(|v| v.0.lock().unwrap().take()) .0
.lock()
.unwrap()
.take()
.map(Result::Err) .map(Result::Err)
.expect("error-details message without actual error"), .expect("error-details message without actual error"),
_ => Err(ErrorMessage { _ => Err(ErrorMessage {

View file

@ -37,7 +37,7 @@ fn create_ui(app: &gtk::Application) {
// The gtkglsink creates the gtk widget for us. This is accessible through a property. // The gtkglsink creates the gtk widget for us. This is accessible through a property.
// So we get it and use it later to add it to our gui. // So we get it and use it later to add it to our gui.
let widget = gtkglsink.property("widget").unwrap(); let widget = gtkglsink.property("widget").unwrap();
(glsinkbin, widget.get::<gtk::Widget>().unwrap().unwrap()) (glsinkbin, widget.get::<gtk::Widget>().unwrap())
} else { } else {
// Unfortunately, using the OpenGL widget didn't work out, so we will have to render // Unfortunately, using the OpenGL widget didn't work out, so we will have to render
// our frames manually, using the CPU. An example why this may fail is, when // our frames manually, using the CPU. An example why this may fail is, when
@ -46,7 +46,7 @@ fn create_ui(app: &gtk::Application) {
// The gtksink creates the gtk widget for us. This is accessible through a property. // The gtksink creates the gtk widget for us. This is accessible through a property.
// So we get it and use it later to add it to our gui. // So we get it and use it later to add it to our gui.
let widget = sink.property("widget").unwrap(); let widget = sink.property("widget").unwrap();
(sink, widget.get::<gtk::Widget>().unwrap().unwrap()) (sink, widget.get::<gtk::Widget>().unwrap())
}; };
pipeline.add_many(&[&src, &sink]).unwrap(); pipeline.add_many(&[&src, &sink]).unwrap();

View file

@ -139,8 +139,8 @@ fn create_pipeline() -> Result<gst::Pipeline, Error> {
let drawer = drawer.lock().unwrap(); let drawer = drawer.lock().unwrap();
// Get the signal's arguments // Get the signal's arguments
let _overlay = args[0].get::<gst::Element>().unwrap().unwrap(); let _overlay = args[0].get::<gst::Element>().unwrap();
let sample = args[1].get::<gst::Sample>().unwrap().unwrap(); let sample = args[1].get::<gst::Sample>().unwrap();
let buffer = sample.buffer().unwrap(); let buffer = sample.buffer().unwrap();
let timestamp = buffer.pts(); let timestamp = buffer.pts();
@ -276,8 +276,8 @@ fn create_pipeline() -> Result<gst::Pipeline, Error> {
// stream that dynamically changes resolution when enough bandwith is available. // stream that dynamically changes resolution when enough bandwith is available.
overlay overlay
.connect("caps-changed", false, move |args| { .connect("caps-changed", false, move |args| {
let _overlay = args[0].get::<gst::Element>().unwrap().unwrap(); let _overlay = args[0].get::<gst::Element>().unwrap();
let caps = args[1].get::<gst::Caps>().unwrap().unwrap(); let caps = args[1].get::<gst::Caps>().unwrap();
let mut drawer = drawer.lock().unwrap(); let mut drawer = drawer.lock().unwrap();
drawer.info = Some(gst_video::VideoInfo::from_caps(&caps).unwrap()); drawer.info = Some(gst_video::VideoInfo::from_caps(&caps).unwrap());

View file

@ -133,12 +133,12 @@ fn create_pipeline() -> Result<gst::Pipeline, Error> {
let drawer = drawer.lock().unwrap(); let drawer = drawer.lock().unwrap();
// Get the signal's arguments // Get the signal's arguments
let _overlay = args[0].get::<gst::Element>().unwrap().unwrap(); let _overlay = args[0].get::<gst::Element>().unwrap();
// This is the cairo context. This is the root of all of cairo's // This is the cairo context. This is the root of all of cairo's
// drawing functionality. // drawing functionality.
let cr = args[1].get::<cairo::Context>().unwrap().unwrap(); let cr = args[1].get::<cairo::Context>().unwrap();
let timestamp = args[2].get_some::<gst::ClockTime>().unwrap(); let timestamp = args[2].get::<gst::ClockTime>().unwrap();
let _duration = args[3].get_some::<gst::ClockTime>().unwrap(); let _duration = args[3].get::<gst::ClockTime>().unwrap();
let info = drawer.info.as_ref().unwrap(); let info = drawer.info.as_ref().unwrap();
let layout = drawer.layout.borrow(); let layout = drawer.layout.borrow();
@ -207,8 +207,8 @@ fn create_pipeline() -> Result<gst::Pipeline, Error> {
// stream that dynamically changes resolution when enough bandwith is available. // stream that dynamically changes resolution when enough bandwith is available.
overlay overlay
.connect("caps-changed", false, move |args| { .connect("caps-changed", false, move |args| {
let _overlay = args[0].get::<gst::Element>().unwrap().unwrap(); let _overlay = args[0].get::<gst::Element>().unwrap();
let caps = args[1].get::<gst::Caps>().unwrap().unwrap(); let caps = args[1].get::<gst::Caps>().unwrap();
let mut drawer = drawer.lock().unwrap(); let mut drawer = drawer.lock().unwrap();
drawer.info = Some(gst_video::VideoInfo::from_caps(&caps).unwrap()); drawer.info = Some(gst_video::VideoInfo::from_caps(&caps).unwrap());

View file

@ -57,12 +57,11 @@ fn example_main() {
// mark the beginning of a new track, or a new DJ. // mark the beginning of a new track, or a new DJ.
let playbin = values[0] let playbin = values[0]
.get::<glib::Object>() .get::<glib::Object>()
.expect("playbin \"audio-tags-changed\" signal values[1]") .expect("playbin \"audio-tags-changed\" signal values[1]");
.unwrap();
// This gets the index of the stream that changed. This is neccessary, since // This gets the index of the stream that changed. This is neccessary, since
// there could e.g. be multiple audio streams (english, spanish, ...). // there could e.g. be multiple audio streams (english, spanish, ...).
let idx = values[1] let idx = values[1]
.get_some::<i32>() .get::<i32>()
.expect("playbin \"audio-tags-changed\" signal values[1]"); .expect("playbin \"audio-tags-changed\" signal values[1]");
println!("audio tags of audio stream {} changed:", idx); println!("audio tags of audio stream {} changed:", idx);
@ -81,18 +80,18 @@ fn example_main() {
.emit_by_name("get-audio-tags", &[&idx]) .emit_by_name("get-audio-tags", &[&idx])
.unwrap() .unwrap()
.unwrap(); .unwrap();
let tags = tags.get::<gst::TagList>().expect("tags").unwrap(); let tags = tags.get::<gst::TagList>().expect("tags");
if let Some(artist) = tags.get::<gst::tags::Artist>() { if let Some(artist) = tags.get::<gst::tags::Artist>() {
println!(" Artist: {}", artist.get().unwrap()); println!(" Artist: {}", artist.get());
} }
if let Some(title) = tags.get::<gst::tags::Title>() { if let Some(title) = tags.get::<gst::tags::Title>() {
println!(" Title: {}", title.get().unwrap()); println!(" Title: {}", title.get());
} }
if let Some(album) = tags.get::<gst::tags::Album>() { if let Some(album) = tags.get::<gst::tags::Album>() {
println!(" Album: {}", album.get().unwrap()); println!(" Album: {}", album.get());
} }
None None

View file

@ -87,8 +87,7 @@ fn make_fec_decoder(rtpbin: &gst::Element, sess_id: u32) -> Result<gst::Element,
.unwrap() .unwrap()
.unwrap() .unwrap()
.get::<glib::Object>() .get::<glib::Object>()
.unwrap() .unwrap();
.expect("No internal-storage");
fecdec.set_property("storage", &internal_storage)?; fecdec.set_property("storage", &internal_storage)?;
fecdec.set_property("pt", &100u32)?; fecdec.set_property("pt", &100u32)?;
@ -145,8 +144,7 @@ fn example_main() -> Result<(), Error> {
rtpbin.connect("new-storage", false, |values| { rtpbin.connect("new-storage", false, |values| {
let storage = values[1] let storage = values[1]
.get::<gst::Element>() .get::<gst::Element>()
.expect("rtpbin \"new-storage\" signal values[1]") .expect("rtpbin \"new-storage\" signal values[1]");
.expect("rtpbin \"new-storage\" signal values[1]: no `Element`");
storage.set_property("size-time", &250_000_000u64).unwrap(); storage.set_property("size-time", &250_000_000u64).unwrap();
None None
@ -154,7 +152,7 @@ fn example_main() -> Result<(), Error> {
rtpbin.connect("request-pt-map", false, |values| { rtpbin.connect("request-pt-map", false, |values| {
let pt = values[2] let pt = values[2]
.get_some::<u32>() .get::<u32>()
.expect("rtpbin \"new-storage\" signal values[2]"); .expect("rtpbin \"new-storage\" signal values[2]");
match pt { match pt {
100 => Some( 100 => Some(
@ -186,10 +184,9 @@ fn example_main() -> Result<(), Error> {
rtpbin.connect("request-fec-decoder", false, |values| { rtpbin.connect("request-fec-decoder", false, |values| {
let rtpbin = values[0] let rtpbin = values[0]
.get::<gst::Element>() .get::<gst::Element>()
.expect("rtpbin \"request-fec-decoder\" signal values[0]") .expect("rtpbin \"request-fec-decoder\" signal values[0]");
.expect("rtpbin \"request-fec-decoder\" signal values[0]: no `Element`");
let sess_id = values[1] let sess_id = values[1]
.get_some::<u32>() .get::<u32>()
.expect("rtpbin \"request-fec-decoder\" signal values[1]"); .expect("rtpbin \"request-fec-decoder\" signal values[1]");
match make_fec_decoder(&rtpbin, sess_id) { match make_fec_decoder(&rtpbin, sess_id) {

View file

@ -109,8 +109,7 @@ fn example_main() -> Result<(), Error> {
rtpbin.connect("request-fec-encoder", false, move |values| { rtpbin.connect("request-fec-encoder", false, move |values| {
let rtpbin = values[0] let rtpbin = values[0]
.get::<gst::Element>() .get::<gst::Element>()
.expect("rtpbin \"request-fec-encoder\" signal values[0]") .expect("rtpbin \"request-fec-encoder\" signal values[0]");
.expect("rtpbin \"request-fec-encoder\" signal values[0]: no `Element`");
match make_fec_encoder(fec_percentage) { match make_fec_encoder(fec_percentage) {
Ok(elem) => Some(elem.to_value()), Ok(elem) => Some(elem.to_value()),

View file

@ -100,8 +100,7 @@ fn example_main() -> Result<(), Error> {
// much more corner-cases. This is just for the sake of being an example. // much more corner-cases. This is just for the sake of being an example.
let caps = values[2] let caps = values[2]
.get::<gst::Caps>() .get::<gst::Caps>()
.expect("typefinder \"have-type\" signal values[2]") .expect("typefinder \"have-type\" signal values[2]");
.expect("typefinder \"have-type\" signal values[2]: no `caps`");
let format_name = caps.structure(0).expect("Failed to get format name").name(); let format_name = caps.structure(0).expect("Failed to get format name").name();
let demuxer = match format_name { let demuxer = match format_name {

View file

@ -683,7 +683,7 @@ pub(crate) fn main_loop(app: App) -> Result<(), Error> {
gst_gl_context = glupload gst_gl_context = glupload
.property("context") .property("context")
.unwrap() .unwrap()
.get::<gst_gl::GLContext>() .get::<Option<gst_gl::GLContext>>()
.unwrap(); .unwrap();
} }

View file

@ -150,15 +150,12 @@ impl AudioConverterConfig {
.as_slice() .as_slice()
.iter() .iter()
.map(|val| { .map(|val| {
let array = val let array = val.get::<gst::Array>().expect("Wrong type");
.get::<gst::Array>()
.expect("Wrong type")
.unwrap_or_else(|| gst::Array::from_owned(Vec::new()));
array array
.as_slice() .as_slice()
.iter() .iter()
.map(|val| val.get_some::<f32>().expect("Wrong type")) .map(|val| val.get::<f32>().expect("Wrong type"))
.collect::<Vec<_>>() .collect::<Vec<_>>()
}) })
.collect::<Vec<_>>() .collect::<Vec<_>>()

View file

@ -5,7 +5,8 @@ use std::ffi::CStr;
use std::fmt; use std::fmt;
use std::str; use std::str;
use glib::translate::{from_glib, FromGlib, FromGlibPtrNone, ToGlib, ToGlibPtr, ToGlibPtrMut}; use glib::translate::{from_glib, from_glib_none, FromGlib, ToGlib, ToGlibPtr, ToGlibPtrMut};
use glib::StaticType;
#[derive(PartialEq, Eq, Copy, Clone, Debug, Hash)] #[derive(PartialEq, Eq, Copy, Clone, Debug, Hash)]
pub enum AudioEndianness { pub enum AudioEndianness {
@ -313,35 +314,52 @@ impl glib::types::StaticType for AudioFormatInfo {
} }
} }
impl glib::value::ValueType for AudioFormatInfo {
type Type = Self;
}
#[doc(hidden)] #[doc(hidden)]
impl<'a> glib::value::FromValueOptional<'a> for AudioFormatInfo { unsafe impl<'a> glib::value::FromValue<'a> for AudioFormatInfo {
unsafe fn from_value_optional(value: &glib::Value) -> Option<Self> { type Checker = glib::value::GenericValueTypeOrNoneChecker<Self>;
Option::<AudioFormatInfo>::from_glib_none(glib::gobject_ffi::g_value_get_boxed(
value.to_glib_none().0, unsafe fn from_value(value: &'a glib::Value) -> Self {
) as *mut ffi::GstAudioFormatInfo) skip_assert_initialized!();
from_glib_none(glib::gobject_ffi::g_value_get_boxed(value.to_glib_none().0)
as *mut ffi::GstAudioFormatInfo)
} }
} }
#[doc(hidden)] #[doc(hidden)]
impl glib::value::SetValue for AudioFormatInfo { impl glib::value::ToValue for AudioFormatInfo {
unsafe fn set_value(value: &mut glib::Value, this: &Self) { fn to_value(&self) -> glib::Value {
let mut value = glib::Value::for_value_type::<AudioFormatInfo>();
unsafe {
glib::gobject_ffi::g_value_set_boxed( glib::gobject_ffi::g_value_set_boxed(
value.to_glib_none_mut().0, value.to_glib_none_mut().0,
glib::translate::ToGlibPtr::<*const ffi::GstAudioFormatInfo>::to_glib_none(this).0 self.to_glib_none().0 as *mut _,
as glib::ffi::gpointer,
) )
} }
value
}
fn value_type(&self) -> glib::Type {
Self::static_type()
}
} }
#[doc(hidden)] #[doc(hidden)]
impl glib::value::SetValueOptional for AudioFormatInfo { impl glib::value::ToValueOptional for AudioFormatInfo {
unsafe fn set_value_optional(value: &mut glib::Value, this: Option<&Self>) { fn to_value_optional(s: Option<&Self>) -> glib::Value {
skip_assert_initialized!();
let mut value = glib::Value::for_value_type::<AudioFormatInfo>();
unsafe {
glib::gobject_ffi::g_value_set_boxed( glib::gobject_ffi::g_value_set_boxed(
value.to_glib_none_mut().0, value.to_glib_none_mut().0,
glib::translate::ToGlibPtr::<*const ffi::GstAudioFormatInfo>::to_glib_none(&this).0 s.to_glib_none().0 as *mut _,
as glib::ffi::gpointer,
) )
} }
value
}
} }
#[doc(hidden)] #[doc(hidden)]

View file

@ -1,8 +1,6 @@
// Take a look at the license at the top of the repository in the LICENSE file. // Take a look at the license at the top of the repository in the LICENSE file.
use glib::translate::{ use glib::translate::{from_glib, from_glib_full, from_glib_none, ToGlib, ToGlibPtr, ToGlibPtrMut};
from_glib, from_glib_full, from_glib_none, FromGlibPtrNone, ToGlib, ToGlibPtr, ToGlibPtrMut,
};
use gst::prelude::*; use gst::prelude::*;
use std::fmt; use std::fmt;
@ -324,35 +322,53 @@ impl glib::types::StaticType for AudioInfo {
} }
} }
#[doc(hidden)] impl glib::value::ValueType for AudioInfo {
impl<'a> glib::value::FromValueOptional<'a> for AudioInfo { type Type = Self;
unsafe fn from_value_optional(value: &glib::Value) -> Option<Self> {
Option::<AudioInfo>::from_glib_none(glib::gobject_ffi::g_value_get_boxed(
value.to_glib_none().0,
) as *mut ffi::GstAudioInfo)
}
} }
#[doc(hidden)] #[doc(hidden)]
impl glib::value::SetValue for AudioInfo { unsafe impl<'a> glib::value::FromValue<'a> for AudioInfo {
unsafe fn set_value(value: &mut glib::Value, this: &Self) { type Checker = glib::value::GenericValueTypeOrNoneChecker<Self>;
glib::gobject_ffi::g_value_set_boxed(
value.to_glib_none_mut().0, unsafe fn from_value(value: &'a glib::Value) -> Self {
glib::translate::ToGlibPtr::<*const ffi::GstAudioInfo>::to_glib_none(this).0 skip_assert_initialized!();
as glib::ffi::gpointer, from_glib_none(
glib::gobject_ffi::g_value_get_boxed(value.to_glib_none().0) as *mut ffi::GstAudioInfo
) )
} }
} }
#[doc(hidden)] #[doc(hidden)]
impl glib::value::SetValueOptional for AudioInfo { impl glib::value::ToValue for AudioInfo {
unsafe fn set_value_optional(value: &mut glib::Value, this: Option<&Self>) { fn to_value(&self) -> glib::Value {
let mut value = glib::Value::for_value_type::<AudioInfo>();
unsafe {
glib::gobject_ffi::g_value_set_boxed( glib::gobject_ffi::g_value_set_boxed(
value.to_glib_none_mut().0, value.to_glib_none_mut().0,
glib::translate::ToGlibPtr::<*const ffi::GstAudioInfo>::to_glib_none(&this).0 self.to_glib_none().0 as *mut _,
as glib::ffi::gpointer,
) )
} }
value
}
fn value_type(&self) -> glib::Type {
Self::static_type()
}
}
#[doc(hidden)]
impl glib::value::ToValueOptional for AudioInfo {
fn to_value_optional(s: Option<&Self>) -> glib::Value {
skip_assert_initialized!();
let mut value = glib::Value::for_value_type::<AudioInfo>();
unsafe {
glib::gobject_ffi::g_value_set_boxed(
value.to_glib_none_mut().0,
s.to_glib_none().0 as *mut _,
)
}
value
}
} }
#[doc(hidden)] #[doc(hidden)]

View file

@ -135,7 +135,6 @@ impl<O: IsA<Aggregator>> AggregatorExtManual for O {
value value
.get() .get()
.expect("AggregatorExtManual::min_upstream_latency") .expect("AggregatorExtManual::min_upstream_latency")
.unwrap()
} }
} }

View file

@ -51,6 +51,7 @@ macro_rules! skip_assert_initialized {
#[allow(clippy::unreadable_literal)] #[allow(clippy::unreadable_literal)]
#[allow(clippy::too_many_arguments)] #[allow(clippy::too_many_arguments)]
#[allow(clippy::match_same_arms)] #[allow(clippy::match_same_arms)]
#[allow(unused_imports)]
mod auto; mod auto;
pub use crate::auto::*; pub use crate::auto::*;

View file

@ -22,6 +22,7 @@ macro_rules! skip_assert_initialized {
#[allow(clippy::unreadable_literal)] #[allow(clippy::unreadable_literal)]
#[allow(clippy::too_many_arguments)] #[allow(clippy::too_many_arguments)]
#[allow(clippy::match_same_arms)] #[allow(clippy::match_same_arms)]
#[allow(unused_imports)]
mod auto; mod auto;
pub use crate::auto::*; pub use crate::auto::*;

View file

@ -21,6 +21,7 @@ macro_rules! skip_assert_initialized {
#[allow(clippy::unreadable_literal)] #[allow(clippy::unreadable_literal)]
#[allow(clippy::too_many_arguments)] #[allow(clippy::too_many_arguments)]
#[allow(clippy::match_same_arms)] #[allow(clippy::match_same_arms)]
#[allow(unused_imports)]
mod auto; mod auto;
pub use crate::auto::*; pub use crate::auto::*;
mod net_client_clock; mod net_client_clock;

View file

@ -32,10 +32,7 @@ impl Discoverer {
value.to_glib_none_mut().0, value.to_glib_none_mut().0,
); );
} }
value value.get().expect("Discoverer::get_property_timeout")
.get()
.expect("Discoverer::get_property_timeout")
.unwrap()
} }
pub fn connect_property_timeout_notify<F: Fn(&Self) + Send + Sync + 'static>( pub fn connect_property_timeout_notify<F: Fn(&Self) + Send + Sync + 'static>(

View file

@ -19,6 +19,7 @@ macro_rules! assert_initialized_main_thread {
#[allow(clippy::match_same_arms)] #[allow(clippy::match_same_arms)]
#[allow(clippy::type_complexity)] #[allow(clippy::type_complexity)]
#[allow(clippy::cast_ptr_alignment)] #[allow(clippy::cast_ptr_alignment)]
#[allow(unused_imports)]
mod auto; mod auto;
pub use crate::auto::*; pub use crate::auto::*;

View file

@ -15,7 +15,7 @@ impl RTSPToken {
unsafe { from_glib_full(ffi::gst_rtsp_token_new_empty()) } unsafe { from_glib_full(ffi::gst_rtsp_token_new_empty()) }
} }
pub fn new(values: &[(&str, &dyn ToSendValue)]) -> Self { pub fn new(values: &[(&str, &(dyn ToSendValue + Sync))]) -> Self {
assert_initialized_main_thread!(); assert_initialized_main_thread!();
let mut token = RTSPToken::new_empty(); let mut token = RTSPToken::new_empty();

View file

@ -8,6 +8,7 @@ use std::ops;
use std::ptr; use std::ptr;
use glib::translate::*; use glib::translate::*;
use glib::StaticType;
use crate::sdp_attribute::SDPAttribute; use crate::sdp_attribute::SDPAttribute;
use crate::sdp_bandwidth::SDPBandwidth; use crate::sdp_bandwidth::SDPBandwidth;
@ -882,36 +883,44 @@ impl glib::types::StaticType for SDPMessageRef {
} }
} }
impl<'a> glib::value::FromValueOptional<'a> for &'a SDPMessageRef { unsafe impl<'a> glib::value::FromValue<'a> for &'a SDPMessageRef {
unsafe fn from_value_optional(v: &'a glib::Value) -> Option<Self> { type Checker = glib::value::GenericValueTypeOrNoneChecker<Self>;
let ptr = glib::gobject_ffi::g_value_get_boxed(v.to_glib_none().0);
if ptr.is_null() { unsafe fn from_value(value: &'a glib::Value) -> Self {
None skip_assert_initialized!();
} else { &*(glib::gobject_ffi::g_value_get_boxed(value.to_glib_none().0) as *mut SDPMessageRef)
Some(&*(ptr as *const SDPMessageRef))
}
} }
} }
impl glib::value::SetValue for SDPMessageRef { impl glib::value::ToValue for SDPMessageRef {
unsafe fn set_value(v: &mut glib::Value, s: &Self) { fn to_value(&self) -> glib::Value {
let mut value = glib::Value::for_value_type::<SDPMessage>();
unsafe {
glib::gobject_ffi::g_value_set_boxed( glib::gobject_ffi::g_value_set_boxed(
v.to_glib_none_mut().0, value.to_glib_none_mut().0,
s as *const SDPMessageRef as glib::ffi::gpointer, &self.0 as *const ffi::GstSDPMessage as *mut _,
); )
}
value
}
fn value_type(&self) -> glib::Type {
Self::static_type()
} }
} }
impl glib::value::SetValueOptional for SDPMessageRef { impl glib::value::ToValueOptional for SDPMessageRef {
unsafe fn set_value_optional(v: &mut glib::Value, s: Option<&Self>) { fn to_value_optional(s: Option<&Self>) -> glib::Value {
if let Some(s) = s { skip_assert_initialized!();
let mut value = glib::Value::for_value_type::<SDPMessage>();
unsafe {
glib::gobject_ffi::g_value_set_boxed( glib::gobject_ffi::g_value_set_boxed(
v.to_glib_none_mut().0, value.to_glib_none_mut().0,
s as *const SDPMessageRef as glib::ffi::gpointer, s.map(|s| &s.0 as *const ffi::GstSDPMessage)
); .unwrap_or(ptr::null()) as *mut _,
} else { )
glib::gobject_ffi::g_value_set_boxed(v.to_glib_none_mut().0, ptr::null_mut());
} }
value
} }
} }

View file

@ -21,7 +21,10 @@ macro_rules! event_builder_generic_impl {
} }
} }
pub fn other_fields(self, other_fields: &[(&'a str, &'a dyn ToSendValue)]) -> Self { pub fn other_fields(
self,
other_fields: &[(&'a str, &'a (dyn ToSendValue + Sync))],
) -> Self {
Self { Self {
other_fields: self other_fields: self
.other_fields .other_fields
@ -64,7 +67,7 @@ macro_rules! event_builder_generic_impl {
pub struct DownstreamForceKeyUnitEventBuilder<'a> { pub struct DownstreamForceKeyUnitEventBuilder<'a> {
seqnum: Option<gst::Seqnum>, seqnum: Option<gst::Seqnum>,
running_time_offset: Option<i64>, running_time_offset: Option<i64>,
other_fields: Vec<(&'a str, &'a dyn ToSendValue)>, other_fields: Vec<(&'a str, &'a (dyn ToSendValue + Sync))>,
timestamp: gst::ClockTime, timestamp: gst::ClockTime,
stream_time: gst::ClockTime, stream_time: gst::ClockTime,
running_time: gst::ClockTime, running_time: gst::ClockTime,
@ -178,7 +181,7 @@ impl DownstreamForceKeyUnitEvent {
pub struct UpstreamForceKeyUnitEventBuilder<'a> { pub struct UpstreamForceKeyUnitEventBuilder<'a> {
seqnum: Option<gst::Seqnum>, seqnum: Option<gst::Seqnum>,
running_time_offset: Option<i64>, running_time_offset: Option<i64>,
other_fields: Vec<(&'a str, &'a dyn ToSendValue)>, other_fields: Vec<(&'a str, &'a (dyn ToSendValue + Sync))>,
running_time: gst::ClockTime, running_time: gst::ClockTime,
all_headers: bool, all_headers: bool,
count: u32, count: u32,
@ -289,7 +292,7 @@ impl ForceKeyUnitEvent {
pub struct StillFrameEventBuilder<'a> { pub struct StillFrameEventBuilder<'a> {
seqnum: Option<gst::Seqnum>, seqnum: Option<gst::Seqnum>,
running_time_offset: Option<i64>, running_time_offset: Option<i64>,
other_fields: Vec<(&'a str, &'a dyn ToSendValue)>, other_fields: Vec<(&'a str, &'a (dyn ToSendValue + Sync))>,
in_still: bool, in_still: bool,
} }

View file

@ -1,8 +1,8 @@
// Take a look at the license at the top of the repository in the LICENSE file. // Take a look at the license at the top of the repository in the LICENSE file.
use glib::translate::{ use glib::translate::{
from_glib, from_glib_full, from_glib_none, FromGlib, FromGlibPtrFull, FromGlibPtrNone, ToGlib, from_glib, from_glib_full, from_glib_none, FromGlib, FromGlibPtrFull, ToGlib, ToGlibPtr,
ToGlibPtr, ToGlibPtrMut, ToGlibPtrMut,
}; };
use gst::prelude::*; use gst::prelude::*;
@ -55,21 +55,28 @@ impl glib::StaticType for VideoColorRange {
} }
} }
impl<'a> glib::value::FromValueOptional<'a> for VideoColorRange { impl glib::value::ValueType for VideoColorRange {
unsafe fn from_value_optional(value: &glib::value::Value) -> Option<Self> { type Type = Self;
Some(glib::value::FromValue::from_value(value))
}
} }
impl<'a> glib::value::FromValue<'a> for VideoColorRange { unsafe impl<'a> glib::value::FromValue<'a> for VideoColorRange {
unsafe fn from_value(value: &glib::value::Value) -> Self { type Checker = glib::value::GenericValueTypeChecker<Self>;
unsafe fn from_value(value: &glib::Value) -> Self {
skip_assert_initialized!();
from_glib(glib::gobject_ffi::g_value_get_enum(value.to_glib_none().0)) from_glib(glib::gobject_ffi::g_value_get_enum(value.to_glib_none().0))
} }
} }
impl glib::value::SetValue for VideoColorRange { impl glib::value::ToValue for VideoColorRange {
unsafe fn set_value(value: &mut glib::value::Value, this: &Self) { fn to_value(&self) -> glib::Value {
glib::gobject_ffi::g_value_set_enum(value.to_glib_none_mut().0, this.to_glib() as i32) let mut value = glib::Value::for_value_type::<VideoColorRange>();
unsafe { glib::gobject_ffi::g_value_set_enum(value.to_glib_none_mut().0, self.to_glib()) }
value
}
fn value_type(&self) -> glib::Type {
Self::static_type()
} }
} }
@ -858,35 +865,53 @@ impl glib::types::StaticType for VideoInfo {
} }
} }
#[doc(hidden)] impl glib::value::ValueType for VideoInfo {
impl<'a> glib::value::FromValueOptional<'a> for VideoInfo { type Type = Self;
unsafe fn from_value_optional(value: &glib::Value) -> Option<Self> {
Option::<VideoInfo>::from_glib_none(glib::gobject_ffi::g_value_get_boxed(
value.to_glib_none().0,
) as *mut ffi::GstVideoInfo)
}
} }
#[doc(hidden)] #[doc(hidden)]
impl glib::value::SetValue for VideoInfo { unsafe impl<'a> glib::value::FromValue<'a> for VideoInfo {
unsafe fn set_value(value: &mut glib::Value, this: &Self) { type Checker = glib::value::GenericValueTypeOrNoneChecker<Self>;
glib::gobject_ffi::g_value_set_boxed(
value.to_glib_none_mut().0, unsafe fn from_value(value: &'a glib::Value) -> Self {
glib::translate::ToGlibPtr::<*const ffi::GstVideoInfo>::to_glib_none(this).0 skip_assert_initialized!();
as glib::ffi::gpointer, from_glib_none(
glib::gobject_ffi::g_value_get_boxed(value.to_glib_none().0) as *mut ffi::GstVideoInfo
) )
} }
} }
#[doc(hidden)] #[doc(hidden)]
impl glib::value::SetValueOptional for VideoInfo { impl glib::value::ToValue for VideoInfo {
unsafe fn set_value_optional(value: &mut glib::Value, this: Option<&Self>) { fn to_value(&self) -> glib::Value {
let mut value = glib::Value::for_value_type::<VideoInfo>();
unsafe {
glib::gobject_ffi::g_value_set_boxed( glib::gobject_ffi::g_value_set_boxed(
value.to_glib_none_mut().0, value.to_glib_none_mut().0,
glib::translate::ToGlibPtr::<*const ffi::GstVideoInfo>::to_glib_none(&this).0 self.to_glib_none().0 as *mut _,
as glib::ffi::gpointer,
) )
} }
value
}
fn value_type(&self) -> glib::Type {
Self::static_type()
}
}
#[doc(hidden)]
impl glib::value::ToValueOptional for VideoInfo {
fn to_value_optional(s: Option<&Self>) -> glib::Value {
skip_assert_initialized!();
let mut value = glib::Value::for_value_type::<VideoInfo>();
unsafe {
glib::gobject_ffi::g_value_set_boxed(
value.to_glib_none_mut().0,
s.to_glib_none().0 as *mut _,
)
}
value
}
} }
#[doc(hidden)] #[doc(hidden)]

View file

@ -2,7 +2,6 @@
use glib::prelude::*; use glib::prelude::*;
use glib::translate::*; use glib::translate::*;
use glib::value;
use gst::prelude::*; use gst::prelude::*;
use std::cmp; use std::cmp;
use std::convert::{TryFrom, TryInto}; use std::convert::{TryFrom, TryInto};
@ -429,35 +428,52 @@ macro_rules! generic_impl {
} }
} }
impl glib::value::ValueType for $name {
type Type = Self;
}
#[doc(hidden)] #[doc(hidden)]
impl<'a> value::FromValueOptional<'a> for $name { unsafe impl<'a> glib::value::FromValue<'a> for $name {
unsafe fn from_value_optional(value: &glib::Value) -> Option<Self> { type Checker = glib::value::GenericValueTypeOrNoneChecker<Self>;
Option::<$name>::from_glib_none(glib::gobject_ffi::g_value_get_boxed(
value.to_glib_none().0, unsafe fn from_value(value: &'a glib::Value) -> Self {
) as *mut ffi::GstVideoTimeCode) skip_assert_initialized!();
from_glib_none(glib::gobject_ffi::g_value_get_boxed(value.to_glib_none().0)
as *mut ffi::GstVideoTimeCode)
} }
} }
#[doc(hidden)] #[doc(hidden)]
impl value::SetValue for $name { impl glib::value::ToValue for $name {
unsafe fn set_value(value: &mut glib::Value, this: &Self) { fn to_value(&self) -> glib::Value {
let mut value = glib::Value::for_value_type::<$name>();
unsafe {
glib::gobject_ffi::g_value_set_boxed( glib::gobject_ffi::g_value_set_boxed(
value.to_glib_none_mut().0, value.to_glib_none_mut().0,
ToGlibPtr::<*const ffi::GstVideoTimeCode>::to_glib_none(this).0 self.to_glib_none().0 as *mut _,
as glib::ffi::gpointer,
) )
} }
value
}
fn value_type(&self) -> glib::Type {
Self::static_type()
}
} }
#[doc(hidden)] #[doc(hidden)]
impl value::SetValueOptional for $name { impl glib::value::ToValueOptional for $name {
unsafe fn set_value_optional(value: &mut glib::Value, this: Option<&Self>) { fn to_value_optional(s: Option<&Self>) -> glib::Value {
skip_assert_initialized!();
let mut value = glib::Value::for_value_type::<$name>();
unsafe {
glib::gobject_ffi::g_value_set_boxed( glib::gobject_ffi::g_value_set_boxed(
value.to_glib_none_mut().0, value.to_glib_none_mut().0,
ToGlibPtr::<*const ffi::GstVideoTimeCode>::to_glib_none(&this).0 s.to_glib_none().0 as *mut _,
as glib::ffi::gpointer,
) )
} }
value
}
} }
}; };
} }

View file

@ -2,7 +2,6 @@
use glib::prelude::*; use glib::prelude::*;
use glib::translate::*; use glib::translate::*;
use glib::value;
use std::cmp; use std::cmp;
use std::fmt; use std::fmt;
use std::mem; use std::mem;
@ -201,34 +200,50 @@ impl StaticType for VideoTimeCodeInterval {
} }
} }
impl glib::value::ValueType for VideoTimeCodeInterval {
type Type = Self;
}
#[doc(hidden)] #[doc(hidden)]
impl<'a> value::FromValueOptional<'a> for VideoTimeCodeInterval { unsafe impl<'a> glib::value::FromValue<'a> for VideoTimeCodeInterval {
unsafe fn from_value_optional(value: &glib::Value) -> Option<Self> { type Checker = glib::value::GenericValueTypeOrNoneChecker<Self>;
Option::<VideoTimeCodeInterval>::from_glib_full(glib::gobject_ffi::g_value_dup_boxed(
value.to_glib_none().0, unsafe fn from_value(value: &'a glib::Value) -> Self {
) skip_assert_initialized!();
from_glib_none(glib::gobject_ffi::g_value_get_boxed(value.to_glib_none().0)
as *mut ffi::GstVideoTimeCodeInterval) as *mut ffi::GstVideoTimeCodeInterval)
} }
} }
#[doc(hidden)] #[doc(hidden)]
impl value::SetValue for VideoTimeCodeInterval { impl glib::value::ToValue for VideoTimeCodeInterval {
unsafe fn set_value(value: &mut glib::Value, this: &Self) { fn to_value(&self) -> glib::Value {
let mut value = glib::Value::for_value_type::<VideoTimeCodeInterval>();
unsafe {
glib::gobject_ffi::g_value_set_boxed( glib::gobject_ffi::g_value_set_boxed(
value.to_glib_none_mut().0, value.to_glib_none_mut().0,
ToGlibPtr::<*const ffi::GstVideoTimeCodeInterval>::to_glib_none(this).0 self.to_glib_none().0 as *mut _,
as glib::ffi::gpointer,
) )
} }
value
}
fn value_type(&self) -> glib::Type {
Self::static_type()
}
} }
#[doc(hidden)] #[doc(hidden)]
impl value::SetValueOptional for VideoTimeCodeInterval { impl glib::value::ToValueOptional for VideoTimeCodeInterval {
unsafe fn set_value_optional(value: &mut glib::Value, this: Option<&Self>) { fn to_value_optional(s: Option<&Self>) -> glib::Value {
skip_assert_initialized!();
let mut value = glib::Value::for_value_type::<VideoTimeCodeInterval>();
unsafe {
glib::gobject_ffi::g_value_set_boxed( glib::gobject_ffi::g_value_set_boxed(
value.to_glib_none_mut().0, value.to_glib_none_mut().0,
ToGlibPtr::<*const ffi::GstVideoTimeCodeInterval>::to_glib_none(&this).0 s.to_glib_none().0 as *mut _,
as glib::ffi::gpointer,
) )
} }
value
}
} }

View file

@ -22,6 +22,7 @@ macro_rules! skip_assert_initialized {
#[allow(clippy::unreadable_literal)] #[allow(clippy::unreadable_literal)]
#[allow(clippy::too_many_arguments)] #[allow(clippy::too_many_arguments)]
#[allow(clippy::match_same_arms)] #[allow(clippy::match_same_arms)]
#[allow(unused_imports)]
mod auto; mod auto;
pub use crate::auto::*; pub use crate::auto::*;

View file

@ -45,7 +45,7 @@ impl Caps {
unsafe { from_glib_full(ffi::gst_caps_new_any()) } unsafe { from_glib_full(ffi::gst_caps_new_any()) }
} }
pub fn new_simple(name: &str, values: &[(&str, &dyn ToSendValue)]) -> Self { pub fn new_simple(name: &str, values: &[(&str, &(dyn ToSendValue + Sync))]) -> Self {
assert_initialized_main_thread!(); assert_initialized_main_thread!();
let mut caps = Caps::new_empty(); let mut caps = Caps::new_empty();
@ -165,7 +165,7 @@ impl str::FromStr for Caps {
} }
impl CapsRef { impl CapsRef {
pub fn set_simple(&mut self, values: &[(&str, &dyn ToSendValue)]) { pub fn set_simple(&mut self, values: &[(&str, &(dyn ToSendValue + Sync))]) {
for &(name, value) in values { for &(name, value) in values {
let value = value.to_value(); let value = value.to_value();
@ -610,7 +610,7 @@ impl Builder<NoFeature> {
} }
impl<T> Builder<T> { impl<T> Builder<T> {
pub fn field<'b, V: ToSendValue>(mut self, name: &'b str, value: &'b V) -> Self { pub fn field<V: ToSendValue + Sync>(mut self, name: &str, value: V) -> Self {
self.s.set(name, value); self.s.set(name, value);
self self
} }
@ -777,11 +777,11 @@ mod tests {
crate::init().unwrap(); crate::init().unwrap();
let caps = Caps::builder("foo/bar") let caps = Caps::builder("foo/bar")
.field("int", &12) .field("int", 12)
.field("bool", &true) .field("bool", true)
.field("string", &"bla") .field("string", "bla")
.field("fraction", &Fraction::new(1, 2)) .field("fraction", Fraction::new(1, 2))
.field("array", &Array::new(&[&1, &2])) .field("array", Array::new(&[&1, &2]))
.build(); .build();
assert_eq!( assert_eq!(
caps.to_string(), caps.to_string(),

View file

@ -10,11 +10,8 @@ use std::str;
use once_cell::sync::Lazy; use once_cell::sync::Lazy;
use glib::ffi::gpointer; use glib::translate::*;
use glib::translate::{ use glib::StaticType;
from_glib, from_glib_full, FromGlibPtrFull, FromGlibPtrNone, GlibPtrDefault, Stash, StashMut,
ToGlibPtr, ToGlibPtrMut,
};
pub struct CapsFeatures(ptr::NonNull<ffi::GstCapsFeatures>); pub struct CapsFeatures(ptr::NonNull<ffi::GstCapsFeatures>);
unsafe impl Send for CapsFeatures {} unsafe impl Send for CapsFeatures {}
@ -217,26 +214,49 @@ impl FromGlibPtrFull<*mut ffi::GstCapsFeatures> for CapsFeatures {
} }
} }
impl<'a> glib::value::FromValueOptional<'a> for CapsFeatures { impl glib::value::ValueType for CapsFeatures {
unsafe fn from_value_optional(v: &'a glib::Value) -> Option<Self> { type Type = Self;
<&'a CapsFeaturesRef as glib::value::FromValueOptional<'a>>::from_value_optional(v) }
.map(ToOwned::to_owned)
unsafe impl<'a> glib::value::FromValue<'a> for CapsFeatures {
type Checker = glib::value::GenericValueTypeOrNoneChecker<Self>;
unsafe fn from_value(value: &'a glib::Value) -> Self {
skip_assert_initialized!();
from_glib_none(glib::gobject_ffi::g_value_get_boxed(value.to_glib_none().0)
as *mut ffi::GstCapsFeatures)
} }
} }
impl glib::value::SetValue for CapsFeatures { impl glib::value::ToValue for CapsFeatures {
unsafe fn set_value(v: &mut glib::Value, s: &Self) { fn to_value(&self) -> glib::Value {
<CapsFeaturesRef as glib::value::SetValue>::set_value(v, s.as_ref()) let mut value = glib::Value::for_value_type::<CapsFeatures>();
} unsafe {
} glib::gobject_ffi::g_value_set_boxed(
value.to_glib_none_mut().0,
impl glib::value::SetValueOptional for CapsFeatures { ToGlibPtr::<*mut ffi::GstCapsFeatures>::to_glib_none(self).0 as *mut _,
unsafe fn set_value_optional(v: &mut glib::Value, s: Option<&Self>) {
<CapsFeaturesRef as glib::value::SetValueOptional>::set_value_optional(
v,
s.map(|s| s.as_ref()),
) )
} }
value
}
fn value_type(&self) -> glib::Type {
Self::static_type()
}
}
impl glib::value::ToValueOptional for CapsFeatures {
fn to_value_optional(s: Option<&Self>) -> glib::Value {
skip_assert_initialized!();
let mut value = glib::Value::for_value_type::<CapsFeatures>();
unsafe {
glib::gobject_ffi::g_value_set_boxed(
value.to_glib_none_mut().0,
ToGlibPtr::<*mut ffi::GstCapsFeatures>::to_glib_none(&s).0 as *mut _,
)
}
value
}
} }
impl GlibPtrDefault for CapsFeatures { impl GlibPtrDefault for CapsFeatures {
@ -334,32 +354,43 @@ impl glib::types::StaticType for CapsFeaturesRef {
} }
} }
impl<'a> glib::value::FromValueOptional<'a> for &'a CapsFeaturesRef { unsafe impl<'a> glib::value::FromValue<'a> for &'a CapsFeaturesRef {
unsafe fn from_value_optional(v: &'a glib::Value) -> Option<Self> { type Checker = glib::value::GenericValueTypeOrNoneChecker<Self>;
let ptr = glib::gobject_ffi::g_value_get_boxed(v.to_glib_none().0);
if ptr.is_null() { unsafe fn from_value(value: &'a glib::Value) -> Self {
None skip_assert_initialized!();
} else { &*(glib::gobject_ffi::g_value_get_boxed(value.to_glib_none().0) as *const CapsFeaturesRef)
Some(CapsFeaturesRef::from_glib_borrow(
ptr as *const ffi::GstCapsFeatures,
))
}
} }
} }
impl glib::value::SetValue for CapsFeaturesRef { impl glib::value::ToValue for CapsFeaturesRef {
unsafe fn set_value(v: &mut glib::Value, s: &Self) { fn to_value(&self) -> glib::Value {
glib::gobject_ffi::g_value_set_boxed(v.to_glib_none_mut().0, s.as_ptr() as gpointer); let mut value = glib::Value::for_value_type::<CapsFeatures>();
unsafe {
glib::gobject_ffi::g_value_set_boxed(
value.to_glib_none_mut().0,
self.as_mut_ptr() as *mut _,
)
}
value
}
fn value_type(&self) -> glib::Type {
Self::static_type()
} }
} }
impl glib::value::SetValueOptional for CapsFeaturesRef { impl glib::value::ToValueOptional for CapsFeaturesRef {
unsafe fn set_value_optional(v: &mut glib::Value, s: Option<&Self>) { fn to_value_optional(s: Option<&Self>) -> glib::Value {
if let Some(s) = s { skip_assert_initialized!();
glib::gobject_ffi::g_value_set_boxed(v.to_glib_none_mut().0, s.as_ptr() as gpointer); let mut value = glib::Value::for_value_type::<CapsFeatures>();
} else { unsafe {
glib::gobject_ffi::g_value_set_boxed(v.to_glib_none_mut().0, ptr::null_mut()); glib::gobject_ffi::g_value_set_boxed(
value.to_glib_none_mut().0,
s.map(|s| s.as_mut_ptr()).unwrap_or(ptr::null_mut()) as *mut _,
)
} }
value
} }
} }
@ -478,11 +509,13 @@ mod tests {
#[test] #[test]
fn test_from_value_optional() { fn test_from_value_optional() {
use glib::ToValue;
crate::init().unwrap(); crate::init().unwrap();
let a = glib::value::Value::from(None::<&CapsFeatures>); let a = None::<CapsFeatures>.to_value();
assert!(a.get::<CapsFeatures>().unwrap().is_none()); assert!(a.get::<Option<CapsFeatures>>().unwrap().is_none());
let b = glib::value::Value::from(&CapsFeatures::new_empty()); let b = glib::value::Value::from(&CapsFeatures::new_empty());
assert!(b.get::<CapsFeatures>().unwrap().is_some()); assert!(b.get::<Option<CapsFeatures>>().unwrap().is_some());
} }
} }

View file

@ -233,11 +233,11 @@ mod tests {
crate::init().unwrap(); crate::init().unwrap();
let caps = Caps::builder("foo/bar") let caps = Caps::builder("foo/bar")
.field("int", &12) .field("int", 12)
.field("bool", &true) .field("bool", true)
.field("string", &"bla") .field("string", "bla")
.field("fraction", &Fraction::new(1, 2)) .field("fraction", Fraction::new(1, 2))
.field("array", &Array::new(&[&1, &2])) .field("array", Array::new(&[&1, &2]))
.build(); .build();
let pretty_config = ron::ser::PrettyConfig::new().with_new_line("".to_string()); let pretty_config = ron::ser::PrettyConfig::new().with_new_line("".to_string());
@ -263,11 +263,11 @@ mod tests {
); );
let caps = Caps::builder("foo/bar") let caps = Caps::builder("foo/bar")
.field("int", &12) .field("int", 12)
.field("bool", &true) .field("bool", true)
.field("string", &"bla") .field("string", "bla")
.field("fraction", &Fraction::new(1, 2)) .field("fraction", Fraction::new(1, 2))
.field("array", &Array::new(&[&1, &2])) .field("array", Array::new(&[&1, &2]))
.features(&["foo:bar", "foo:baz"]) .features(&["foo:bar", "foo:baz"])
.build(); .build();
@ -297,11 +297,11 @@ mod tests {
); );
let caps = Caps::builder("foo/bar") let caps = Caps::builder("foo/bar")
.field("int", &12) .field("int", 12)
.field("bool", &true) .field("bool", true)
.field("string", &"bla") .field("string", "bla")
.field("fraction", &Fraction::new(1, 2)) .field("fraction", Fraction::new(1, 2))
.field("array", &Array::new(&[&1, &2])) .field("array", Array::new(&[&1, &2]))
.any_features() .any_features()
.build(); .build();
@ -370,16 +370,13 @@ mod tests {
let s = caps.structure(0).unwrap(); let s = caps.structure(0).unwrap();
assert_eq!( assert_eq!(
s, s,
Structure::new( Structure::builder("foo/bar",)
"foo/bar", .field("int", 12)
&[ .field("bool", true)
("int", &12), .field("string", "bla")
("bool", &true), .field("fraction", Fraction::new(1, 2))
("string", &"bla"), .field("array", Array::new(&[&1, &2]))
("fraction", &Fraction::new(1, 2)), .build()
("array", &Array::new(&[&1, &2])),
],
)
.as_ref() .as_ref()
); );
@ -404,16 +401,13 @@ mod tests {
let str_none: Option<&str> = None; let str_none: Option<&str> = None;
assert_eq!( assert_eq!(
s, s,
Structure::new( Structure::builder("foo/bar",)
"foo/bar", .field("int", 12)
&[ .field("bool", true)
("int", &12), .field("string", str_none)
("bool", &true), .field("fraction", Fraction::new(1, 2))
("string", &str_none), .field("array", Array::new(&[&1, &2]))
("fraction", &Fraction::new(1, 2)), .build()
("array", &Array::new(&[&1, &2])),
],
)
.as_ref() .as_ref()
); );
let f = caps.features(0).unwrap(); let f = caps.features(0).unwrap();
@ -439,16 +433,13 @@ mod tests {
let s = caps.structure(0).unwrap(); let s = caps.structure(0).unwrap();
assert_eq!( assert_eq!(
s, s,
Structure::new( Structure::builder("foo/bar",)
"foo/bar", .field("int", 12)
&[ .field("bool", true)
("int", &12), .field("string", "bla")
("bool", &true), .field("fraction", Fraction::new(1, 2))
("string", &"bla"), .field("array", Array::new(&[&1, &2]))
("fraction", &Fraction::new(1, 2)), .build()
("array", &Array::new(&[&1, &2])),
],
)
.as_ref() .as_ref()
); );
let f = caps.features(0).unwrap(); let f = caps.features(0).unwrap();
@ -470,22 +461,22 @@ mod tests {
assert!(caps_de.is_empty()); assert!(caps_de.is_empty());
let caps = Caps::builder("foo/bar") let caps = Caps::builder("foo/bar")
.field("int", &12) .field("int", 12)
.field("bool", &true) .field("bool", true)
.field("string", &"bla") .field("string", "bla")
.field("fraction", &Fraction::new(1, 2)) .field("fraction", Fraction::new(1, 2))
.field("array", &Array::new(&[&1, &2])) .field("array", Array::new(&[&1, &2]))
.build(); .build();
let caps_ser = ron::ser::to_string(&caps).unwrap(); let caps_ser = ron::ser::to_string(&caps).unwrap();
let caps_de: Caps = ron::de::from_str(caps_ser.as_str()).unwrap(); let caps_de: Caps = ron::de::from_str(caps_ser.as_str()).unwrap();
assert!(caps_de.is_strictly_equal(&caps)); assert!(caps_de.is_strictly_equal(&caps));
let caps = Caps::builder("foo/bar") let caps = Caps::builder("foo/bar")
.field("int", &12) .field("int", 12)
.field("bool", &true) .field("bool", true)
.field("string", &"bla") .field("string", "bla")
.field("fraction", &Fraction::new(1, 2)) .field("fraction", Fraction::new(1, 2))
.field("array", &Array::new(&[&1, &2])) .field("array", Array::new(&[&1, &2]))
.features(&["foo:bar", "foo:baz"]) .features(&["foo:bar", "foo:baz"])
.build(); .build();
let caps_ser = ron::ser::to_string(&caps).unwrap(); let caps_ser = ron::ser::to_string(&caps).unwrap();
@ -493,11 +484,11 @@ mod tests {
assert!(caps_de.is_strictly_equal(&caps)); assert!(caps_de.is_strictly_equal(&caps));
let caps = Caps::builder("foo/bar") let caps = Caps::builder("foo/bar")
.field("int", &12) .field("int", 12)
.field("bool", &true) .field("bool", true)
.field("string", &"bla") .field("string", "bla")
.field("fraction", &Fraction::new(1, 2)) .field("fraction", Fraction::new(1, 2))
.field("array", &Array::new(&[&1, &2])) .field("array", Array::new(&[&1, &2]))
.any_features() .any_features()
.build(); .build();
let caps_ser = ron::ser::to_string(&caps).unwrap(); let caps_ser = ron::ser::to_string(&caps).unwrap();

View file

@ -1,6 +1,7 @@
// Take a look at the license at the top of the repository in the LICENSE file. // Take a look at the license at the top of the repository in the LICENSE file.
use glib::translate::*; use glib::translate::*;
use glib::StaticType;
use num_integer::div_rem; use num_integer::div_rem;
use std::io::{self, prelude::*}; use std::io::{self, prelude::*};
use std::time::Duration; use std::time::Duration;
@ -304,25 +305,32 @@ impl FromGlib<ffi::GstClockTime> for ClockTime {
} }
} }
impl glib::value::ValueType for ClockTime {
type Type = Self;
}
#[doc(hidden)] #[doc(hidden)]
impl<'a> glib::value::FromValueOptional<'a> for ClockTime { unsafe impl<'a> glib::value::FromValue<'a> for ClockTime {
unsafe fn from_value_optional(value: &'a glib::Value) -> Option<Self> { type Checker = glib::value::GenericValueTypeChecker<Self>;
<u64 as glib::value::FromValueOptional>::from_value_optional(value)
.map(|x| ClockTime::from_glib(x)) unsafe fn from_value(value: &glib::Value) -> Self {
skip_assert_initialized!();
from_glib(glib::gobject_ffi::g_value_get_uint64(
value.to_glib_none().0,
))
} }
} }
#[doc(hidden)] #[doc(hidden)]
impl<'a> glib::value::FromValue<'a> for ClockTime { impl glib::value::ToValue for ClockTime {
unsafe fn from_value(value: &'a glib::Value) -> Self { fn to_value(&self) -> glib::Value {
ClockTime::from_glib(<u64 as glib::value::FromValue>::from_value(value)) let mut value = glib::Value::for_value_type::<ClockTime>();
} unsafe { glib::gobject_ffi::g_value_set_uint64(value.to_glib_none_mut().0, self.to_glib()) }
value
} }
#[doc(hidden)] fn value_type(&self) -> glib::Type {
impl glib::value::SetValue for ClockTime { Self::static_type()
unsafe fn set_value(value: &mut glib::Value, this: &Self) {
<u64 as glib::value::SetValue>::set_value(value, &this.to_glib());
} }
} }

View file

@ -3,7 +3,7 @@
use std::convert::{TryFrom, TryInto}; use std::convert::{TryFrom, TryInto};
use glib::translate::{FromGlib, ToGlib}; use glib::translate::{FromGlib, ToGlib};
use glib::value::{SetValue, SetValueOptional}; use glib::value::{ToValue, ToValueOptional};
use glib::StaticType; use glib::StaticType;
use crate::DateTime; use crate::DateTime;
@ -33,15 +33,20 @@ impl From<glib::Date> for Date {
} }
} }
impl SetValue for Date { impl ToValue for Date {
unsafe fn set_value(value: &mut glib::Value, this: &Self) { fn to_value(&self) -> glib::Value {
glib::value::SetValue::set_value(value, &this.0); self.0.to_value()
}
fn value_type(&self) -> glib::Type {
glib::Date::static_type()
} }
} }
impl SetValueOptional for Date { impl ToValueOptional for Date {
unsafe fn set_value_optional(value: &mut glib::Value, this: Option<&Self>) { fn to_value_optional(s: Option<&Self>) -> glib::Value {
glib::value::SetValueOptional::set_value_optional(value, this.map(|this| &this.0)); skip_assert_initialized!();
s.map(|s| &s.0).to_value()
} }
} }

View file

@ -11,8 +11,7 @@ use thiserror::Error;
use glib::translate::*; use glib::translate::*;
use glib::value::FromValue; use glib::value::FromValue;
use glib::value::FromValueOptional; use glib::value::ToValue;
use glib::value::SetValue;
use glib::value::Value; use glib::value::Value;
use glib::StaticType; use glib::StaticType;
use glib::Type; use glib::Type;
@ -610,21 +609,30 @@ impl StaticType for MessageType {
} }
} }
impl<'a> FromValueOptional<'a> for MessageType { impl glib::value::ValueType for MessageType {
unsafe fn from_value_optional(value: &Value) -> Option<Self> { type Type = Self;
Some(FromValue::from_value(value)) }
unsafe impl<'a> FromValue<'a> for MessageType {
type Checker = glib::value::GenericValueTypeChecker<Self>;
unsafe fn from_value(value: &glib::Value) -> Self {
skip_assert_initialized!();
from_glib(glib::gobject_ffi::g_value_get_enum(value.to_glib_none().0) as ffi::GstMessageType)
} }
} }
impl<'a> FromValue<'a> for MessageType { impl ToValue for MessageType {
unsafe fn from_value(value: &Value) -> Self { fn to_value(&self) -> Value {
from_glib(glib::gobject_ffi::g_value_get_flags(value.to_glib_none().0)) let mut value = glib::Value::for_value_type::<MessageType>();
unsafe {
glib::gobject_ffi::g_value_set_enum(value.to_glib_none_mut().0, self.to_glib() as i32)
} }
value
} }
impl SetValue for MessageType { fn value_type(&self) -> Type {
unsafe fn set_value(value: &mut Value, this: &Self) { Self::static_type()
glib::gobject_ffi::g_value_set_flags(value.to_glib_none_mut().0, this.to_glib())
} }
} }

View file

@ -1143,7 +1143,7 @@ impl<'a> CustomBothOob<'a> {
struct EventBuilder<'a> { struct EventBuilder<'a> {
seqnum: Option<Seqnum>, seqnum: Option<Seqnum>,
running_time_offset: Option<i64>, running_time_offset: Option<i64>,
other_fields: Vec<(&'a str, &'a dyn ToSendValue)>, other_fields: Vec<(&'a str, &'a (dyn ToSendValue + Sync))>,
} }
impl<'a> EventBuilder<'a> { impl<'a> EventBuilder<'a> {
@ -1169,7 +1169,7 @@ impl<'a> EventBuilder<'a> {
} }
} }
fn other_fields(self, other_fields: &[(&'a str, &'a dyn ToSendValue)]) -> Self { fn other_fields(self, other_fields: &[(&'a str, &'a (dyn ToSendValue + Sync))]) -> Self {
Self { Self {
other_fields: self other_fields: self
.other_fields .other_fields
@ -1201,7 +1201,10 @@ macro_rules! event_builder_generic_impl {
} }
#[allow(clippy::needless_update)] #[allow(clippy::needless_update)]
pub fn other_fields(self, other_fields: &[(&'a str, &'a dyn ToSendValue)]) -> Self { pub fn other_fields(
self,
other_fields: &[(&'a str, &'a (dyn ToSendValue + Sync))],
) -> Self {
Self { Self {
builder: self.builder.other_fields(other_fields), builder: self.builder.other_fields(other_fields),
..self ..self
@ -1980,6 +1983,6 @@ mod tests {
} }
let structure = flush_start_evt.structure().unwrap(); let structure = flush_start_evt.structure().unwrap();
assert_eq!(structure.get_some("test"), Ok(42u32)); assert_eq!(structure.get("test"), Ok(42u32));
} }
} }

View file

@ -2,7 +2,7 @@
use glib::ffi::{gconstpointer, gpointer}; use glib::ffi::{gconstpointer, gpointer};
use glib::translate::*; use glib::translate::*;
use glib::value::{FromValueOptional, ToValue}; use glib::value::{FromValue, ToValue};
use glib::StaticType; use glib::StaticType;
use glib::Value; use glib::Value;
use std::ffi::CString; use std::ffi::CString;
@ -30,7 +30,7 @@ pub struct Iterator<T> {
impl<T> Iterator<T> impl<T> Iterator<T>
where where
for<'a> T: FromValueOptional<'a> + 'static, for<'a> T: FromValue<'a> + 'static,
{ {
pub unsafe fn into_ptr(self) -> *mut ffi::GstIterator { pub unsafe fn into_ptr(self) -> *mut ffi::GstIterator {
let s = mem::ManuallyDrop::new(self); let s = mem::ManuallyDrop::new(self);
@ -46,9 +46,9 @@ where
#[allow(clippy::wildcard_in_or_patterns)] #[allow(clippy::wildcard_in_or_patterns)]
match res { match res {
ffi::GST_ITERATOR_OK => match value.get::<T>().expect("Iterator::next") { ffi::GST_ITERATOR_OK => match value.get::<T>() {
Some(value) => Ok(Some(value)), Ok(value) => Ok(Some(value)),
None => Err(IteratorError::Error), Err(_) => Err(IteratorError::Error),
}, },
ffi::GST_ITERATOR_DONE => Ok(None), ffi::GST_ITERATOR_DONE => Ok(None),
ffi::GST_ITERATOR_RESYNC => Err(IteratorError::Resync), ffi::GST_ITERATOR_RESYNC => Err(IteratorError::Resync),
@ -66,6 +66,7 @@ where
pub fn filter<F>(self, func: F) -> Self pub fn filter<F>(self, func: F) -> Self
where where
F: Fn(T) -> bool + Send + Sync + 'static, F: Fn(T) -> bool + Send + Sync + 'static,
T: StaticType,
{ {
unsafe { unsafe {
let func_box: Box<dyn Fn(T) -> bool + Send + Sync + 'static> = Box::new(func); let func_box: Box<dyn Fn(T) -> bool + Send + Sync + 'static> = Box::new(func);
@ -100,7 +101,7 @@ where
func_ptr, func_ptr,
)); ));
if res { if res {
elem.get::<T>().expect("Iterator::find") Some(elem.get::<T>().expect("Iterator::find"))
} else { } else {
None None
} }
@ -164,7 +165,7 @@ where
impl<T> Iterator<T> impl<T> Iterator<T>
where where
for<'a> T: FromValueOptional<'a> + StaticType + ToValue + Send + 'static, for<'a> T: FromValue<'a> + StaticType + ToValue + Send + 'static,
{ {
pub fn new<I: IteratorImpl<T>>(imp: I) -> Self { pub fn new<I: IteratorImpl<T>>(imp: I) -> Self {
assert_initialized_main_thread!(); assert_initialized_main_thread!();
@ -195,7 +196,7 @@ where
impl<T> Iterator<T> impl<T> Iterator<T>
where where
for<'a> T: FromValueOptional<'a> + StaticType + ToValue + Clone + Send + 'static, for<'a> T: FromValue<'a> + StaticType + ToValue + Clone + Send + 'static,
{ {
pub fn from_vec(items: Vec<T>) -> Self { pub fn from_vec(items: Vec<T>) -> Self {
skip_assert_initialized!(); skip_assert_initialized!();
@ -206,7 +207,7 @@ where
#[repr(C)] #[repr(C)]
struct RsIterator<T, I: IteratorImpl<T>> struct RsIterator<T, I: IteratorImpl<T>>
where where
for<'a> T: FromValueOptional<'a> + StaticType + ToValue + Send + 'static, for<'a> T: FromValue<'a> + StaticType + ToValue + Send + 'static,
{ {
iter: ffi::GstIterator, iter: ffi::GstIterator,
imp: I, imp: I,
@ -215,7 +216,7 @@ where
pub trait IteratorImpl<T>: Clone + Send + 'static pub trait IteratorImpl<T>: Clone + Send + 'static
where where
for<'a> T: FromValueOptional<'a> + StaticType + ToValue + Send + 'static, for<'a> T: FromValue<'a> + StaticType + ToValue + Send + 'static,
{ {
fn next(&mut self) -> Option<Result<T, IteratorError>>; fn next(&mut self) -> Option<Result<T, IteratorError>>;
fn resync(&mut self); fn resync(&mut self);
@ -225,7 +226,7 @@ unsafe extern "C" fn rs_iterator_copy<T, I: IteratorImpl<T>>(
it: *const ffi::GstIterator, it: *const ffi::GstIterator,
copy: *mut ffi::GstIterator, copy: *mut ffi::GstIterator,
) where ) where
for<'a> T: FromValueOptional<'a> + StaticType + ToValue + Send + 'static, for<'a> T: FromValue<'a> + StaticType + ToValue + Send + 'static,
{ {
let it = it as *const RsIterator<T, I>; let it = it as *const RsIterator<T, I>;
let copy = copy as *mut RsIterator<T, I>; let copy = copy as *mut RsIterator<T, I>;
@ -235,7 +236,7 @@ unsafe extern "C" fn rs_iterator_copy<T, I: IteratorImpl<T>>(
unsafe extern "C" fn rs_iterator_free<T, I: IteratorImpl<T>>(it: *mut ffi::GstIterator) unsafe extern "C" fn rs_iterator_free<T, I: IteratorImpl<T>>(it: *mut ffi::GstIterator)
where where
for<'a> T: FromValueOptional<'a> + StaticType + ToValue + Send + 'static, for<'a> T: FromValue<'a> + StaticType + ToValue + Send + 'static,
{ {
let it = it as *mut RsIterator<T, I>; let it = it as *mut RsIterator<T, I>;
ptr::drop_in_place(&mut (*it).imp); ptr::drop_in_place(&mut (*it).imp);
@ -246,7 +247,7 @@ unsafe extern "C" fn rs_iterator_next<T, I: IteratorImpl<T>>(
result: *mut glib::gobject_ffi::GValue, result: *mut glib::gobject_ffi::GValue,
) -> ffi::GstIteratorResult ) -> ffi::GstIteratorResult
where where
for<'a> T: FromValueOptional<'a> + StaticType + ToValue + Send + 'static, for<'a> T: FromValue<'a> + StaticType + ToValue + Send + 'static,
{ {
let it = it as *mut RsIterator<T, I>; let it = it as *mut RsIterator<T, I>;
match (*it).imp.next() { match (*it).imp.next() {
@ -265,7 +266,7 @@ where
unsafe extern "C" fn rs_iterator_resync<T, I: IteratorImpl<T>>(it: *mut ffi::GstIterator) unsafe extern "C" fn rs_iterator_resync<T, I: IteratorImpl<T>>(it: *mut ffi::GstIterator)
where where
for<'a> T: FromValueOptional<'a> + StaticType + ToValue + Send + 'static, for<'a> T: FromValue<'a> + StaticType + ToValue + Send + 'static,
{ {
let it = it as *mut RsIterator<T, I>; let it = it as *mut RsIterator<T, I>;
(*it).imp.resync(); (*it).imp.resync();
@ -279,7 +280,7 @@ struct VecIteratorImpl<T> {
impl<T> VecIteratorImpl<T> impl<T> VecIteratorImpl<T>
where where
for<'a> T: StaticType + ToValue + FromValueOptional<'a> + Clone + Send + 'static, for<'a> T: StaticType + ToValue + FromValue<'a> + Clone + Send + 'static,
{ {
fn new(items: Vec<T>) -> Self { fn new(items: Vec<T>) -> Self {
skip_assert_initialized!(); skip_assert_initialized!();
@ -289,7 +290,7 @@ where
impl<T> IteratorImpl<T> for VecIteratorImpl<T> impl<T> IteratorImpl<T> for VecIteratorImpl<T>
where where
for<'a> T: StaticType + ToValue + FromValueOptional<'a> + Clone + Send + 'static, for<'a> T: StaticType + ToValue + FromValue<'a> + Clone + Send + 'static,
{ {
fn next(&mut self) -> Option<Result<T, IteratorError>> { fn next(&mut self) -> Option<Result<T, IteratorError>> {
if self.pos < self.items.len() { if self.pos < self.items.len() {
@ -311,7 +312,7 @@ unsafe impl<T> Sync for Iterator<T> {}
unsafe extern "C" fn filter_trampoline<T>(value: gconstpointer, func: gconstpointer) -> i32 unsafe extern "C" fn filter_trampoline<T>(value: gconstpointer, func: gconstpointer) -> i32
where where
for<'a> T: FromValueOptional<'a> + 'static, for<'a> T: FromValue<'a> + 'static,
{ {
let value = value as *const glib::gobject_ffi::GValue; let value = value as *const glib::gobject_ffi::GValue;
@ -320,10 +321,7 @@ where
let func = &*(func as *const &(dyn Fn(T) -> bool + Send + Sync + 'static)); let func = &*(func as *const &(dyn Fn(T) -> bool + Send + Sync + 'static));
let value = &*(value as *const glib::Value); let value = &*(value as *const glib::Value);
let value = value let value = value.get::<T>().expect("Iterator filter_trampoline");
.get::<T>()
.expect("Iterator filter_trampoline")
.unwrap();
if func(value) { if func(value) {
0 0
@ -399,13 +397,13 @@ unsafe extern "C" fn find_trampoline<T, F: FnMut(T) -> bool>(
func: gconstpointer, func: gconstpointer,
) -> i32 ) -> i32
where where
for<'a> T: FromValueOptional<'a> + 'static, for<'a> T: FromValue<'a> + 'static,
{ {
let value = value as *const glib::gobject_ffi::GValue; let value = value as *const glib::gobject_ffi::GValue;
let func = func as *mut F; let func = func as *mut F;
let value = &*(value as *const glib::Value); let value = &*(value as *const glib::Value);
let value = value.get::<T>().expect("Iterator find_trampoline").unwrap(); let value = value.get::<T>().expect("Iterator find_trampoline");
if (*func)(value) { if (*func)(value) {
0 0
@ -418,14 +416,11 @@ unsafe extern "C" fn foreach_trampoline<T, F: FnMut(T)>(
value: *const glib::gobject_ffi::GValue, value: *const glib::gobject_ffi::GValue,
func: gpointer, func: gpointer,
) where ) where
for<'a> T: FromValueOptional<'a> + 'static, for<'a> T: FromValue<'a> + 'static,
{ {
let func = func as *mut F; let func = func as *mut F;
let value = &*(value as *const glib::Value); let value = &*(value as *const glib::Value);
let value = value let value = value.get::<T>().expect("Iterator foreach_trampoline");
.get::<T>()
.expect("Iterator foreach_trampoline")
.unwrap();
(*func)(value); (*func)(value);
} }
@ -436,11 +431,11 @@ unsafe extern "C" fn fold_trampoline<T, U, F: FnMut(U, T) -> Result<U, U>>(
func: gpointer, func: gpointer,
) -> glib::ffi::gboolean ) -> glib::ffi::gboolean
where where
for<'a> T: FromValueOptional<'a> + 'static, for<'a> T: FromValue<'a> + 'static,
{ {
let func = func as *mut F; let func = func as *mut F;
let value = &*(value as *const glib::Value); let value = &*(value as *const glib::Value);
let value = value.get::<T>().expect("Iterator fold_trampoline").unwrap(); let value = value.get::<T>().expect("Iterator fold_trampoline");
let accum = &mut *(glib::gobject_ffi::g_value_get_pointer(ret) as *mut Option<U>); let accum = &mut *(glib::gobject_ffi::g_value_get_pointer(ret) as *mut Option<U>);
@ -480,7 +475,7 @@ impl<T> Drop for Iterator<T> {
impl<T> iter::IntoIterator for Iterator<T> impl<T> iter::IntoIterator for Iterator<T>
where where
for<'a> T: FromValueOptional<'a> + 'static, for<'a> T: FromValue<'a> + 'static,
{ {
type Item = Result<T, IteratorError>; type Item = Result<T, IteratorError>;
type IntoIter = StdIterator<T>; type IntoIter = StdIterator<T>;
@ -496,35 +491,50 @@ impl<T> glib::types::StaticType for Iterator<T> {
} }
} }
#[doc(hidden)] impl<T: StaticType + 'static> glib::value::ValueType for Iterator<T> {
impl<'a, T: StaticType> glib::value::FromValueOptional<'a> for Iterator<T> { type Type = Self;
unsafe fn from_value_optional(value: &glib::Value) -> Option<Self> {
Option::<Iterator<T>>::from_glib_none(glib::gobject_ffi::g_value_get_boxed(
value.to_glib_none().0,
) as *mut ffi::GstIterator)
}
} }
#[doc(hidden)] unsafe impl<'a, T: StaticType + 'static> glib::value::FromValue<'a> for Iterator<T> {
impl<T: 'static> glib::value::SetValue for Iterator<T> { type Checker = glib::value::GenericValueTypeOrNoneChecker<Self>;
unsafe fn set_value(value: &mut glib::Value, this: &Self) {
glib::gobject_ffi::g_value_set_boxed( unsafe fn from_value(value: &'a glib::Value) -> Self {
value.to_glib_none_mut().0, skip_assert_initialized!();
glib::translate::ToGlibPtr::<*const ffi::GstIterator>::to_glib_none(this).0 from_glib_none(
as glib::ffi::gpointer, glib::gobject_ffi::g_value_get_boxed(value.to_glib_none().0) as *mut ffi::GstIterator
) )
} }
} }
#[doc(hidden)] impl<T: StaticType + 'static> glib::value::ToValue for Iterator<T> {
impl<T: 'static> glib::value::SetValueOptional for Iterator<T> { fn to_value(&self) -> glib::Value {
unsafe fn set_value_optional(value: &mut glib::Value, this: Option<&Self>) { let mut value = glib::Value::for_value_type::<Self>();
unsafe {
glib::gobject_ffi::g_value_set_boxed( glib::gobject_ffi::g_value_set_boxed(
value.to_glib_none_mut().0, value.to_glib_none_mut().0,
glib::translate::ToGlibPtr::<*const ffi::GstIterator>::to_glib_none(&this).0 self.to_glib_none().0 as *mut _,
as glib::ffi::gpointer,
) )
} }
value
}
fn value_type(&self) -> glib::Type {
Self::static_type()
}
}
impl<T: StaticType + 'static> glib::value::ToValueOptional for Iterator<T> {
fn to_value_optional(s: Option<&Self>) -> glib::Value {
skip_assert_initialized!();
let mut value = glib::Value::for_value_type::<Self>();
unsafe {
glib::gobject_ffi::g_value_set_boxed(
value.to_glib_none_mut().0,
s.to_glib_none().0 as *mut _,
)
}
value
}
} }
#[doc(hidden)] #[doc(hidden)]
@ -645,7 +655,7 @@ impl<T> fmt::Debug for StdIterator<T> {
impl<T> iter::Iterator for StdIterator<T> impl<T> iter::Iterator for StdIterator<T>
where where
for<'a> T: FromValueOptional<'a> + 'static, for<'a> T: FromValue<'a> + 'static,
{ {
type Item = Result<T, IteratorError>; type Item = Result<T, IteratorError>;

View file

@ -26,6 +26,7 @@ macro_rules! skip_assert_initialized {
#[allow(clippy::too_many_arguments)] #[allow(clippy::too_many_arguments)]
#[allow(clippy::match_same_arms)] #[allow(clippy::match_same_arms)]
#[allow(clippy::type_complexity)] #[allow(clippy::type_complexity)]
#[allow(unused_imports)]
mod auto; mod auto;
pub use crate::auto::functions::*; pub use crate::auto::functions::*;
pub use crate::auto::*; pub use crate::auto::*;

View file

@ -1555,7 +1555,7 @@ struct MessageBuilder<'a> {
src: Option<Object>, src: Option<Object>,
seqnum: Option<Seqnum>, seqnum: Option<Seqnum>,
#[allow(unused)] #[allow(unused)]
other_fields: Vec<(&'a str, &'a dyn ToSendValue)>, other_fields: Vec<(&'a str, &'a (dyn ToSendValue + Sync))>,
} }
impl<'a> MessageBuilder<'a> { impl<'a> MessageBuilder<'a> {
@ -1583,7 +1583,7 @@ impl<'a> MessageBuilder<'a> {
#[cfg(any(feature = "v1_14", feature = "dox"))] #[cfg(any(feature = "v1_14", feature = "dox"))]
#[cfg_attr(feature = "dox", doc(cfg(feature = "v1_14")))] #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_14")))]
fn other_fields(self, other_fields: &[(&'a str, &'a dyn ToSendValue)]) -> Self { fn other_fields(self, other_fields: &[(&'a str, &'a (dyn ToSendValue + Sync))]) -> Self {
Self { Self {
other_fields: self other_fields: self
.other_fields .other_fields
@ -1617,7 +1617,10 @@ macro_rules! message_builder_generic_impl {
#[cfg(any(feature = "v1_14", feature = "dox"))] #[cfg(any(feature = "v1_14", feature = "dox"))]
#[cfg_attr(feature = "dox", doc(cfg(feature = "v1_14")))] #[cfg_attr(feature = "dox", doc(cfg(feature = "v1_14")))]
#[allow(clippy::needless_update)] #[allow(clippy::needless_update)]
pub fn other_fields(self, other_fields: &[(&'a str, &'a dyn ToSendValue)]) -> Self { pub fn other_fields(
self,
other_fields: &[(&'a str, &'a (dyn ToSendValue + Sync))],
) -> Self {
Self { Self {
builder: self.builder.other_fields(other_fields), builder: self.builder.other_fields(other_fields),
..self ..self
@ -2117,7 +2120,7 @@ pub struct StreamStatusBuilder<'a> {
builder: MessageBuilder<'a>, builder: MessageBuilder<'a>,
type_: crate::StreamStatusType, type_: crate::StreamStatusType,
owner: &'a crate::Element, owner: &'a crate::Element,
status_object: Option<&'a dyn glib::ToSendValue>, status_object: Option<&'a (dyn glib::ToSendValue + Sync)>,
} }
impl<'a> StreamStatusBuilder<'a> { impl<'a> StreamStatusBuilder<'a> {
@ -2131,7 +2134,7 @@ impl<'a> StreamStatusBuilder<'a> {
} }
} }
pub fn status_object(self, status_object: &'a dyn glib::ToSendValue) -> Self { pub fn status_object(self, status_object: &'a (dyn glib::ToSendValue + Sync)) -> Self {
Self { Self {
status_object: Some(status_object), status_object: Some(status_object),
..self ..self
@ -2614,7 +2617,7 @@ impl<'a> DeviceRemovedBuilder<'a> {
pub struct PropertyNotifyBuilder<'a> { pub struct PropertyNotifyBuilder<'a> {
builder: MessageBuilder<'a>, builder: MessageBuilder<'a>,
property_name: &'a str, property_name: &'a str,
value: Option<&'a dyn glib::ToSendValue>, value: Option<&'a (dyn glib::ToSendValue + Sync)>,
} }
#[cfg(any(feature = "v1_10", feature = "dox"))] #[cfg(any(feature = "v1_10", feature = "dox"))]
@ -2629,7 +2632,7 @@ impl<'a> PropertyNotifyBuilder<'a> {
} }
} }
pub fn value(self, value: &'a dyn glib::ToSendValue) -> Self { pub fn value(self, value: &'a (dyn glib::ToSendValue + Sync)) -> Self {
Self { Self {
value: Some(value), value: Some(value),
..self ..self

View file

@ -424,41 +424,58 @@ macro_rules! mini_object_wrapper (
} }
} }
impl<'a> $crate::glib::value::FromValueOptional<'a> impl glib::value::ValueType for $name {
for $name type Type = Self;
{ }
unsafe fn from_value_optional(v: &'a glib::Value) -> Option<Self> {
let ptr = $crate::glib::gobject_ffi::g_value_get_boxed($crate::glib::translate::ToGlibPtr::to_glib_none(v).0); unsafe impl<'a> $crate::glib::value::FromValue<'a> for $name {
$crate::glib::translate::from_glib_none(ptr as *const $ffi_name) type Checker = $crate::glib::value::GenericValueTypeOrNoneChecker<Self>;
unsafe fn from_value(value: &'a $crate::glib::Value) -> Self {
skip_assert_initialized!();
$crate::glib::translate::from_glib_none(
$crate::glib::gobject_ffi::g_value_get_boxed($crate::glib::translate::ToGlibPtr::to_glib_none(value).0) as *mut $ffi_name
)
} }
} }
impl $crate::glib::value::SetValue for $name { impl $crate::glib::value::ToValue for $name {
unsafe fn set_value(v: &mut glib::Value, s: &Self) { fn to_value(&self) -> $crate::glib::Value {
$crate::glib::gobject_ffi::g_value_set_boxed($crate::glib::translate::ToGlibPtrMut::to_glib_none_mut(v).0, s.as_ptr() as $crate::glib::ffi::gpointer); let mut value = $crate::glib::Value::for_value_type::<$name>();
unsafe {
$crate::glib::gobject_ffi::g_value_set_boxed(
$crate::glib::translate::ToGlibPtrMut::to_glib_none_mut(&mut value).0,
$crate::glib::translate::ToGlibPtr::<*const $ffi_name>::to_glib_none(self).0 as *mut _,
)
}
value
}
fn value_type(&self) -> $crate::glib::Type {
<Self as $crate::glib::StaticType>::static_type()
} }
} }
impl $crate::glib::value::SetValueOptional for $name { impl $crate::glib::value::ToValueOptional for $name {
unsafe fn set_value_optional(v: &mut glib::Value, s: Option<&Self>) { fn to_value_optional(s: Option<&Self>) -> $crate::glib::Value {
if let Some(s) = s { skip_assert_initialized!();
$crate::glib::gobject_ffi::g_value_set_boxed($crate::glib::translate::ToGlibPtrMut::to_glib_none_mut(v).0, s.as_ptr() as $crate::glib::ffi::gpointer); let mut value = $crate::glib::Value::for_value_type::<$name>();
} else { unsafe {
$crate::glib::gobject_ffi::g_value_set_boxed($crate::glib::translate::ToGlibPtrMut::to_glib_none_mut(v).0, std::ptr::null_mut()); $crate::glib::gobject_ffi::g_value_set_boxed(
$crate::glib::translate::ToGlibPtrMut::to_glib_none_mut(&mut value).0,
$crate::glib::translate::ToGlibPtr::<*const $ffi_name>::to_glib_none(&s).0 as *mut _,
)
} }
value
} }
} }
impl<'a> $crate::glib::value::FromValueOptional<'a> unsafe impl<'a> $crate::glib::value::FromValue<'a> for &'a $ref_name {
for &'a $ref_name type Checker = $crate::glib::value::GenericValueTypeOrNoneChecker<Self>;
{
unsafe fn from_value_optional(v: &'a glib::Value) -> Option<Self> { unsafe fn from_value(value: &'a $crate::glib::Value) -> Self {
let ptr = glib::gobject_ffi::g_value_get_boxed($crate::glib::translate::ToGlibPtr::to_glib_none(v).0); skip_assert_initialized!();
if ptr.is_null() { &*($crate::glib::gobject_ffi::g_value_get_boxed($crate::glib::translate::ToGlibPtr::to_glib_none(value).0) as *const $ref_name)
None
} else {
Some(&*(ptr as *const $ref_name))
}
} }
} }

View file

@ -57,13 +57,11 @@ impl<O: IsA<crate::Object>> GstObjectExtManual for O {
.unwrap_or_else(|err| { .unwrap_or_else(|err| {
panic!("Object signal \"deep-notify\": values[0]: {}", err) panic!("Object signal \"deep-notify\": values[0]: {}", err)
}) })
.expect("Object signal \"deep-notify\": values[0] not defined")
.unsafe_cast() .unsafe_cast()
}; };
let prop_obj: crate::Object = values[1] let prop_obj: crate::Object = values[1]
.get() .get()
.unwrap_or_else(|err| panic!("Object signal \"deep-notify\": values[1]: {}", err)) .unwrap_or_else(|err| panic!("Object signal \"deep-notify\": values[1]: {}", err));
.expect("Object signal \"deep-notify\": values[1] not defined");
let pspec = unsafe { let pspec = unsafe {
let pspec = glib::gobject_ffi::g_value_get_param(values[2].to_glib_none().0); let pspec = glib::gobject_ffi::g_value_get_param(values[2].to_glib_none().0);

View file

@ -1663,7 +1663,7 @@ impl<T: IsA<Pad> + IsA<glib::Object> + glib::object::IsClass> PadBuilder<T> {
let gtype = templ let gtype = templ
.property("gtype") .property("gtype")
.unwrap() .unwrap()
.get_some::<glib::Type>() .get::<glib::Type>()
.unwrap(); .unwrap();
if gtype == glib::Type::UNIT { if gtype == glib::Type::UNIT {

View file

@ -6,6 +6,7 @@ use crate::GenericFormattedValue;
use crate::SeekFlags; use crate::SeekFlags;
use crate::SeekType; use crate::SeekType;
use glib::translate::*; use glib::translate::*;
use glib::StaticType;
use std::fmt; use std::fmt;
use std::marker::PhantomData; use std::marker::PhantomData;
use std::mem; use std::mem;
@ -558,37 +559,55 @@ impl<T: FormattedValue> glib::types::StaticType for FormattedSegment<T> {
} }
} }
#[doc(hidden)] impl glib::value::ValueType for Segment {
impl<'a> glib::value::FromValueOptional<'a> for Segment { type Type = Self;
unsafe fn from_value_optional(value: &glib::Value) -> Option<Self> {
Option::<Segment>::from_glib_none(glib::gobject_ffi::g_value_get_boxed(
value.to_glib_none().0,
) as *mut ffi::GstSegment)
}
} }
#[doc(hidden)] #[doc(hidden)]
impl<T: FormattedValue> glib::value::SetValue for FormattedSegment<T> { unsafe impl<'a> glib::value::FromValue<'a> for Segment {
unsafe fn set_value(value: &mut glib::Value, this: &Self) { type Checker = glib::value::GenericValueTypeOrNoneChecker<Self>;
glib::gobject_ffi::g_value_set_boxed(
value.to_glib_none_mut().0, unsafe fn from_value(value: &'a glib::Value) -> Self {
glib::translate::ToGlibPtr::<*const ffi::GstSegment>::to_glib_none(this).0 skip_assert_initialized!();
as glib::ffi::gpointer, from_glib_none(
glib::gobject_ffi::g_value_get_boxed(value.to_glib_none().0) as *mut ffi::GstSegment
) )
} }
} }
#[doc(hidden)] #[doc(hidden)]
impl<T: FormattedValue> glib::value::SetValueOptional for FormattedSegment<T> { impl<T: FormattedValue> glib::value::ToValue for FormattedSegment<T> {
unsafe fn set_value_optional(value: &mut glib::Value, this: Option<&Self>) { fn to_value(&self) -> glib::Value {
let mut value = glib::Value::for_value_type::<Segment>();
unsafe {
glib::gobject_ffi::g_value_set_boxed( glib::gobject_ffi::g_value_set_boxed(
value.to_glib_none_mut().0, value.to_glib_none_mut().0,
glib::translate::ToGlibPtr::<*const ffi::GstSegment>::to_glib_none(&this).0 self.to_glib_none().0 as *mut _,
as glib::ffi::gpointer,
) )
} }
value
}
fn value_type(&self) -> glib::Type {
Self::static_type()
}
} }
#[doc(hidden)]
impl<T: FormattedValue> glib::value::ToValueOptional for FormattedSegment<T> {
fn to_value_optional(s: Option<&Self>) -> glib::Value {
skip_assert_initialized!();
let mut value = glib::Value::for_value_type::<Segment>();
unsafe {
glib::gobject_ffi::g_value_set_boxed(
value.to_glib_none_mut().0,
s.to_glib_none().0 as *mut _,
)
}
value
}
}
#[doc(hidden)]
#[doc(hidden)] #[doc(hidden)]
impl<T: FormattedValue> glib::translate::GlibPtrDefault for FormattedSegment<T> { impl<T: FormattedValue> glib::translate::GlibPtrDefault for FormattedSegment<T> {
type GlibType = *mut ffi::GstSegment; type GlibType = *mut ffi::GstSegment;

View file

@ -3,6 +3,7 @@
use crate::Caps; use crate::Caps;
use glib::translate::*; use glib::translate::*;
use glib::StaticType;
use std::ffi::CStr; use std::ffi::CStr;
use std::fmt; use std::fmt;
@ -35,35 +36,53 @@ impl glib::types::StaticType for StaticCaps {
} }
} }
#[doc(hidden)] impl glib::value::ValueType for StaticCaps {
impl<'a> glib::value::FromValueOptional<'a> for StaticCaps { type Type = Self;
unsafe fn from_value_optional(value: &glib::Value) -> Option<Self> {
Option::<StaticCaps>::from_glib_none(glib::gobject_ffi::g_value_get_boxed(
value.to_glib_none().0,
) as *mut ffi::GstStaticCaps)
}
} }
#[doc(hidden)] #[doc(hidden)]
impl glib::value::SetValue for StaticCaps { unsafe impl<'a> glib::value::FromValue<'a> for StaticCaps {
unsafe fn set_value(value: &mut glib::Value, this: &Self) { type Checker = glib::value::GenericValueTypeOrNoneChecker<Self>;
glib::gobject_ffi::g_value_set_boxed(
value.to_glib_none_mut().0, unsafe fn from_value(value: &'a glib::Value) -> Self {
glib::translate::ToGlibPtr::<*const ffi::GstStaticCaps>::to_glib_none(this).0 skip_assert_initialized!();
as glib::ffi::gpointer, from_glib_none(
glib::gobject_ffi::g_value_get_boxed(value.to_glib_none().0) as *mut ffi::GstStaticCaps
) )
} }
} }
#[doc(hidden)] #[doc(hidden)]
impl glib::value::SetValueOptional for StaticCaps { impl glib::value::ToValue for StaticCaps {
unsafe fn set_value_optional(value: &mut glib::Value, this: Option<&Self>) { fn to_value(&self) -> glib::Value {
let mut value = glib::Value::for_value_type::<StaticCaps>();
unsafe {
glib::gobject_ffi::g_value_set_boxed( glib::gobject_ffi::g_value_set_boxed(
value.to_glib_none_mut().0, value.to_glib_none_mut().0,
glib::translate::ToGlibPtr::<*const ffi::GstStaticCaps>::to_glib_none(&this).0 self.to_glib_none().0 as *mut _,
as glib::ffi::gpointer,
) )
} }
value
}
fn value_type(&self) -> glib::Type {
Self::static_type()
}
}
#[doc(hidden)]
impl glib::value::ToValueOptional for StaticCaps {
fn to_value_optional(s: Option<&Self>) -> glib::Value {
skip_assert_initialized!();
let mut value = glib::Value::for_value_type::<StaticCaps>();
unsafe {
glib::gobject_ffi::g_value_set_boxed(
value.to_glib_none_mut().0,
s.to_glib_none().0 as *mut _,
)
}
value
}
} }
#[doc(hidden)] #[doc(hidden)]

View file

@ -4,6 +4,7 @@ use crate::Caps;
use crate::PadTemplate; use crate::PadTemplate;
use glib::translate::*; use glib::translate::*;
use glib::StaticType;
use std::ffi::CStr; use std::ffi::CStr;
use std::fmt; use std::fmt;
@ -65,35 +66,52 @@ impl glib::types::StaticType for StaticPadTemplate {
} }
} }
impl glib::value::ValueType for StaticPadTemplate {
type Type = Self;
}
#[doc(hidden)] #[doc(hidden)]
impl<'a> glib::value::FromValueOptional<'a> for StaticPadTemplate { unsafe impl<'a> glib::value::FromValue<'a> for StaticPadTemplate {
unsafe fn from_value_optional(value: &glib::Value) -> Option<Self> { type Checker = glib::value::GenericValueTypeOrNoneChecker<Self>;
Option::<StaticPadTemplate>::from_glib_none(glib::gobject_ffi::g_value_get_boxed(
value.to_glib_none().0, unsafe fn from_value(value: &'a glib::Value) -> Self {
) as *mut ffi::GstStaticPadTemplate) skip_assert_initialized!();
from_glib_none(glib::gobject_ffi::g_value_get_boxed(value.to_glib_none().0)
as *mut ffi::GstStaticPadTemplate)
} }
} }
#[doc(hidden)] #[doc(hidden)]
impl glib::value::SetValue for StaticPadTemplate { impl glib::value::ToValue for StaticPadTemplate {
unsafe fn set_value(value: &mut glib::Value, this: &Self) { fn to_value(&self) -> glib::Value {
let mut value = glib::Value::for_value_type::<StaticPadTemplate>();
unsafe {
glib::gobject_ffi::g_value_set_boxed( glib::gobject_ffi::g_value_set_boxed(
value.to_glib_none_mut().0, value.to_glib_none_mut().0,
glib::translate::ToGlibPtr::<*const ffi::GstStaticPadTemplate>::to_glib_none(this).0 self.to_glib_none().0 as *mut _,
as glib::ffi::gpointer,
) )
} }
value
}
fn value_type(&self) -> glib::Type {
Self::static_type()
}
} }
#[doc(hidden)] #[doc(hidden)]
impl glib::value::SetValueOptional for StaticPadTemplate { impl glib::value::ToValueOptional for StaticPadTemplate {
unsafe fn set_value_optional(value: &mut glib::Value, this: Option<&Self>) { fn to_value_optional(s: Option<&Self>) -> glib::Value {
skip_assert_initialized!();
let mut value = glib::Value::for_value_type::<StaticPadTemplate>();
unsafe {
glib::gobject_ffi::g_value_set_boxed( glib::gobject_ffi::g_value_set_boxed(
value.to_glib_none_mut().0, value.to_glib_none_mut().0,
glib::translate::ToGlibPtr::<*const ffi::GstStaticPadTemplate>::to_glib_none(&this).0 s.to_glib_none().0 as *mut _,
as glib::ffi::gpointer,
) )
} }
value
}
} }
#[doc(hidden)] #[doc(hidden)]

View file

@ -8,40 +8,56 @@ use std::ops::{Deref, DerefMut};
use std::ptr; use std::ptr;
use std::str; use std::str;
use thiserror::Error;
use crate::Fraction; use crate::Fraction;
use glib::ffi::gpointer; use glib::translate::*;
use glib::translate::{ use glib::value::{FromValue, SendValue, ToSendValue};
from_glib, from_glib_full, FromGlibPtrFull, FromGlibPtrNone, GlibPtrDefault, Stash, StashMut, use glib::StaticType;
ToGlib, ToGlibPtr, ToGlibPtrMut,
};
use glib::value::{FromValue, FromValueOptional, SendValue, ToSendValue};
#[derive(Clone, Debug, Eq, PartialEq, Error)] #[derive(Clone, Debug, Eq, PartialEq, thiserror::Error)]
pub enum GetError<'name> { pub enum GetError {
#[error("GetError: Structure field with name {name} not found")] #[error("GetError: Structure field with name {name} not found")]
FieldNotFound { name: &'name str }, FieldNotFound { name: &'static str },
#[error("GetError: Structure field with name {name} not retrieved")] #[error("GetError: Structure field with name {name} not retrieved")]
ValueGetError { ValueGetError {
name: &'name str, name: &'static str,
#[source] #[source]
value_get_error: glib::value::GetError, type_mismatch_error: glib::value::ValueTypeMismatchOrNoneError,
}, },
} }
impl<'name> GetError<'name> { impl GetError {
fn new_field_not_found(name: &'name str) -> GetError { fn new_field_not_found(name: &'static str) -> Self {
skip_assert_initialized!(); skip_assert_initialized!();
GetError::FieldNotFound { name } GetError::FieldNotFound { name }
} }
fn from_value_get_error(name: &'name str, value_get_error: glib::value::GetError) -> GetError { fn from_value_get_error<E: GlibValueError>(name: &'static str, err: E) -> Self {
skip_assert_initialized!();
E::from_value_error(name, err)
}
}
pub trait GlibValueError: 'static {
fn from_value_error(name: &'static str, err: Self) -> GetError;
}
impl GlibValueError for glib::value::ValueTypeMismatchError {
fn from_value_error(name: &'static str, err: Self) -> GetError {
skip_assert_initialized!(); skip_assert_initialized!();
GetError::ValueGetError { GetError::ValueGetError {
name, name,
value_get_error, type_mismatch_error: glib::value::ValueTypeMismatchOrNoneError::from(err),
}
}
}
impl GlibValueError for glib::value::ValueTypeMismatchOrNoneError {
fn from_value_error(name: &'static str, err: Self) -> GetError {
skip_assert_initialized!();
GetError::ValueGetError {
name,
type_mismatch_error: err,
} }
} }
} }
@ -65,7 +81,7 @@ impl Structure {
} }
} }
pub fn new(name: &str, values: &[(&str, &dyn ToSendValue)]) -> Structure { pub fn new(name: &str, values: &[(&str, &(dyn ToSendValue + Sync))]) -> Structure {
assert_initialized_main_thread!(); assert_initialized_main_thread!();
let mut structure = Structure::new_empty(name); let mut structure = Structure::new_empty(name);
@ -283,28 +299,54 @@ impl FromGlibPtrFull<*mut ffi::GstStructure> for Structure {
} }
} }
impl<'a> glib::value::FromValueOptional<'a> for Structure { impl glib::value::ValueType for Structure {
unsafe fn from_value_optional(v: &'a glib::Value) -> Option<Self> { type Type = Self;
<&'a StructureRef as glib::value::FromValueOptional<'a>>::from_value_optional(v)
.map(ToOwned::to_owned)
}
} }
impl glib::value::SetValue for Structure { unsafe impl<'a> glib::value::FromValue<'a> for Structure {
unsafe fn set_value(v: &mut glib::Value, s: &Self) { type Checker = glib::value::GenericValueTypeOrNoneChecker<Self>;
<StructureRef as glib::value::SetValue>::set_value(v, s.as_ref())
}
}
impl glib::value::SetValueOptional for Structure { unsafe fn from_value(value: &'a glib::Value) -> Self {
unsafe fn set_value_optional(v: &mut glib::Value, s: Option<&Self>) { skip_assert_initialized!();
<StructureRef as glib::value::SetValueOptional>::set_value_optional( from_glib_none(
v, glib::gobject_ffi::g_value_get_boxed(value.to_glib_none().0) as *mut ffi::GstStructure
s.map(|s| s.as_ref()),
) )
} }
} }
impl glib::value::ToValue for Structure {
fn to_value(&self) -> glib::Value {
let mut value = glib::Value::for_value_type::<Structure>();
unsafe {
glib::gobject_ffi::g_value_set_boxed(
value.to_glib_none_mut().0,
glib::translate::ToGlibPtr::<*const ffi::GstStructure>::to_glib_none(self).0
as *mut _,
)
}
value
}
fn value_type(&self) -> glib::Type {
Self::static_type()
}
}
impl glib::value::ToValueOptional for Structure {
fn to_value_optional(s: Option<&Self>) -> glib::Value {
skip_assert_initialized!();
let mut value = glib::Value::for_value_type::<Structure>();
unsafe {
glib::gobject_ffi::g_value_set_boxed(
value.to_glib_none_mut().0,
glib::translate::ToGlibPtr::<*const ffi::GstStructure>::to_glib_none(&s).0
as *mut _,
)
}
value
}
}
impl GlibPtrDefault for Structure { impl GlibPtrDefault for Structure {
type GlibType = *mut ffi::GstStructure; type GlibType = *mut ffi::GstStructure;
} }
@ -336,54 +378,63 @@ impl StructureRef {
self as *const Self as *mut ffi::GstStructure self as *const Self as *mut ffi::GstStructure
} }
pub fn get<'structure, 'name, T: FromValueOptional<'structure>>( pub fn get<'a, T: FromValue<'a>>(&'a self, name: &str) -> Result<T, GetError>
&'structure self, where
name: &'name str, <<T as FromValue<'a>>::Checker as glib::value::ValueTypeChecker>::Error: GlibValueError,
) -> Result<Option<T>, GetError<'name>> { {
self.value(name)? let name = glib::Quark::from_string(name);
self.get_by_quark(name)
}
pub fn get_optional<'a, T: FromValue<'a>>(&'a self, name: &str) -> Result<Option<T>, GetError>
where
<<T as FromValue<'a>>::Checker as glib::value::ValueTypeChecker>::Error: GlibValueError,
{
let name = glib::Quark::from_string(name);
self.get_optional_by_quark(name)
}
pub fn value(&self, name: &str) -> Result<&SendValue, GetError> {
let name = glib::Quark::from_string(name);
self.value_by_quark(name)
}
pub fn get_by_quark<'a, T: FromValue<'a>>(&'a self, name: glib::Quark) -> Result<T, GetError>
where
<<T as FromValue<'a>>::Checker as glib::value::ValueTypeChecker>::Error: GlibValueError,
{
self.value_by_quark(name)?
.get() .get()
.map_err(|err| GetError::from_value_get_error(name, err)) .map_err(|err| GetError::from_value_get_error(name.to_string(), err))
} }
pub fn get_optional<'structure, 'name, T: FromValueOptional<'structure>>( pub fn get_optional_by_quark<'a, T: FromValue<'a>>(
&'structure self, &'a self,
name: &'name str, name: glib::Quark,
) -> Result<Option<T>, GetError<'name>> { ) -> Result<Option<T>, GetError>
let value = self.value(name); where
if let Ok(value) = value { <<T as FromValue<'a>>::Checker as glib::value::ValueTypeChecker>::Error: GlibValueError,
value {
.get() self.value_by_quark(name)
.map_err(|err| GetError::from_value_get_error(name, err)) .ok()
} else { .map(|v| v.get())
Ok(None) .transpose()
} .map_err(|err| GetError::from_value_get_error(name.to_string(), err))
} }
pub fn get_some<'structure, 'name, T: FromValue<'structure>>( pub fn value_by_quark(&self, name: glib::Quark) -> Result<&SendValue, GetError> {
&'structure self,
name: &'name str,
) -> Result<T, GetError<'name>> {
self.value(name)?
.get_some()
.map_err(|err| GetError::from_value_get_error(name, err))
}
pub fn value<'structure, 'name>(
&'structure self,
name: &'name str,
) -> Result<&SendValue, GetError<'name>> {
unsafe { unsafe {
let value = ffi::gst_structure_get_value(&self.0, name.to_glib_none().0); let value = ffi::gst_structure_id_get_value(&self.0, name.to_glib());
if value.is_null() { if value.is_null() {
return Err(GetError::new_field_not_found(name)); return Err(GetError::new_field_not_found(name.to_string()));
} }
Ok(&*(value as *const SendValue)) Ok(&*(value as *const SendValue))
} }
} }
pub fn set<T: ToSendValue>(&mut self, name: &str, value: &T) { pub fn set<T: ToSendValue + Sync>(&mut self, name: &str, value: T) {
let value = value.to_send_value(); let value = value.to_send_value();
self.set_value(name, value); self.set_value(name, value);
} }
@ -395,6 +446,18 @@ impl StructureRef {
} }
} }
pub fn set_by_quark<T: ToSendValue + Sync>(&mut self, name: glib::Quark, value: T) {
let value = value.to_send_value();
self.set_value_by_quark(name, value);
}
pub fn set_value_by_quark(&mut self, name: glib::Quark, value: SendValue) {
unsafe {
let mut value = value.into_raw();
ffi::gst_structure_id_take_value(&mut self.0, name.to_glib(), &mut value);
}
}
pub fn name<'a>(&self) -> &'a str { pub fn name<'a>(&self) -> &'a str {
unsafe { unsafe {
CStr::from_ptr(ffi::gst_structure_get_name(&self.0)) CStr::from_ptr(ffi::gst_structure_get_name(&self.0))
@ -403,6 +466,10 @@ impl StructureRef {
} }
} }
pub fn name_quark(&self) -> glib::Quark {
unsafe { from_glib(ffi::gst_structure_get_name_id(&self.0)) }
}
pub fn set_name(&mut self, name: &str) { pub fn set_name(&mut self, name: &str) {
unsafe { ffi::gst_structure_set_name(&mut self.0, name.to_glib_none().0) } unsafe { ffi::gst_structure_set_name(&mut self.0, name.to_glib_none().0) }
} }
@ -426,6 +493,20 @@ impl StructureRef {
} }
} }
pub fn has_field_by_quark(&self, field: glib::Quark) -> bool {
unsafe { from_glib(ffi::gst_structure_id_has_field(&self.0, field.to_glib())) }
}
pub fn has_field_with_type_by_quark(&self, field: glib::Quark, type_: glib::Type) -> bool {
unsafe {
from_glib(ffi::gst_structure_id_has_field_typed(
&self.0,
field.to_glib(),
type_.to_glib(),
))
}
}
pub fn remove_field(&mut self, field: &str) { pub fn remove_field(&mut self, field: &str) {
unsafe { unsafe {
ffi::gst_structure_remove_field(&mut self.0, field.to_glib_none().0); ffi::gst_structure_remove_field(&mut self.0, field.to_glib_none().0);
@ -578,32 +659,43 @@ impl glib::types::StaticType for StructureRef {
} }
} }
impl<'a> glib::value::FromValueOptional<'a> for &'a StructureRef { unsafe impl<'a> glib::value::FromValue<'a> for &'a StructureRef {
unsafe fn from_value_optional(v: &'a glib::Value) -> Option<Self> { type Checker = glib::value::GenericValueTypeOrNoneChecker<Self>;
let ptr = glib::gobject_ffi::g_value_get_boxed(v.to_glib_none().0);
if ptr.is_null() { unsafe fn from_value(value: &'a glib::Value) -> Self {
None skip_assert_initialized!();
} else { &*(glib::gobject_ffi::g_value_get_boxed(value.to_glib_none().0) as *const StructureRef)
Some(StructureRef::from_glib_borrow(
ptr as *const ffi::GstStructure,
))
}
} }
} }
impl glib::value::SetValue for StructureRef { impl glib::value::ToValue for StructureRef {
unsafe fn set_value(v: &mut glib::Value, s: &Self) { fn to_value(&self) -> glib::Value {
glib::gobject_ffi::g_value_set_boxed(v.to_glib_none_mut().0, s.as_ptr() as gpointer); let mut value = glib::Value::for_value_type::<Structure>();
unsafe {
glib::gobject_ffi::g_value_set_boxed(
value.to_glib_none_mut().0,
self.as_ptr() as *mut _,
)
}
value
}
fn value_type(&self) -> glib::Type {
Self::static_type()
} }
} }
impl glib::value::SetValueOptional for StructureRef { impl glib::value::ToValueOptional for StructureRef {
unsafe fn set_value_optional(v: &mut glib::Value, s: Option<&Self>) { fn to_value_optional(s: Option<&Self>) -> glib::Value {
if let Some(s) = s { skip_assert_initialized!();
glib::gobject_ffi::g_value_set_boxed(v.to_glib_none_mut().0, s.as_ptr() as gpointer); let mut value = glib::Value::for_value_type::<Structure>();
} else { unsafe {
glib::gobject_ffi::g_value_set_boxed(v.to_glib_none_mut().0, ptr::null_mut()); glib::gobject_ffi::g_value_set_boxed(
value.to_glib_none_mut().0,
s.map(|s| s.as_ptr()).unwrap_or(ptr::null()) as *mut _,
)
} }
value
} }
} }
@ -728,7 +820,7 @@ impl Builder {
} }
} }
pub fn field<V: ToSendValue>(mut self, name: &str, value: &V) -> Self { pub fn field<V: ToSendValue + Sync>(mut self, name: &str, value: V) -> Self {
self.s.set(name, value); self.s.set(name, value);
self self
} }
@ -756,9 +848,9 @@ mod tests {
s.set("f2", &String::from("bcd")); s.set("f2", &String::from("bcd"));
s.set("f3", &123i32); s.set("f3", &123i32);
assert_eq!(s.get::<&str>("f1"), Ok(Some("abc"))); assert_eq!(s.get::<&str>("f1"), Ok("abc"));
assert_eq!(s.get::<&str>("f2"), Ok(Some("bcd"))); assert_eq!(s.get::<Option<&str>>("f2"), Ok(Some("bcd")));
assert_eq!(s.get_some::<i32>("f3"), Ok(123i32)); assert_eq!(s.get::<i32>("f3"), Ok(123i32));
assert_eq!(s.get_optional::<&str>("f1"), Ok(Some("abc"))); assert_eq!(s.get_optional::<&str>("f1"), Ok(Some("abc")));
assert_eq!(s.get_optional::<&str>("f4"), Ok(None)); assert_eq!(s.get_optional::<&str>("f4"), Ok(None));
assert_eq!(s.get_optional::<i32>("f3"), Ok(Some(123i32))); assert_eq!(s.get_optional::<i32>("f3"), Ok(Some(123i32)));
@ -768,35 +860,32 @@ mod tests {
s.get::<i32>("f2"), s.get::<i32>("f2"),
Err(GetError::from_value_get_error( Err(GetError::from_value_get_error(
"f2", "f2",
value::GetError::new_type_mismatch(Type::STRING, Type::I32), value::ValueTypeMismatchError::new(Type::STRING, Type::I32),
)) ))
); );
assert_eq!( assert_eq!(
s.get_some::<bool>("f3"), s.get::<bool>("f3"),
Err(GetError::from_value_get_error( Err(GetError::from_value_get_error(
"f3", "f3",
value::GetError::new_type_mismatch(Type::I32, Type::BOOL), value::ValueTypeMismatchError::new(Type::I32, Type::BOOL),
)) ))
); );
assert_eq!( assert_eq!(
s.get::<&str>("f4"), s.get::<&str>("f4"),
Err(GetError::new_field_not_found("f4")) Err(GetError::new_field_not_found("f4"))
); );
assert_eq!( assert_eq!(s.get::<i32>("f4"), Err(GetError::new_field_not_found("f4")));
s.get_some::<i32>("f4"),
Err(GetError::new_field_not_found("f4"))
);
assert_eq!(s.fields().collect::<Vec<_>>(), vec!["f1", "f2", "f3"]); assert_eq!(s.fields().collect::<Vec<_>>(), vec!["f1", "f2", "f3"]);
let v = s.iter().map(|(f, v)| (f, v.clone())).collect::<Vec<_>>(); let v = s.iter().map(|(f, v)| (f, v.clone())).collect::<Vec<_>>();
assert_eq!(v.len(), 3); assert_eq!(v.len(), 3);
assert_eq!(v[0].0, "f1"); assert_eq!(v[0].0, "f1");
assert_eq!(v[0].1.get::<&str>(), Ok(Some("abc"))); assert_eq!(v[0].1.get::<&str>(), Ok("abc"));
assert_eq!(v[1].0, "f2"); assert_eq!(v[1].0, "f2");
assert_eq!(v[1].1.get::<&str>(), Ok(Some("bcd"))); assert_eq!(v[1].1.get::<&str>(), Ok("bcd"));
assert_eq!(v[2].0, "f3"); assert_eq!(v[2].0, "f3");
assert_eq!(v[2].1.get_some::<i32>(), Ok(123i32)); assert_eq!(v[2].1.get::<i32>(), Ok(123i32));
let s2 = Structure::new("test", &[("f1", &"abc"), ("f2", &"bcd"), ("f3", &123i32)]); let s2 = Structure::new("test", &[("f1", &"abc"), ("f2", &"bcd"), ("f3", &123i32)]);
assert_eq!(s, s2); assert_eq!(s, s2);
@ -813,9 +902,9 @@ mod tests {
.build(); .build();
assert_eq!(s.name(), "test"); assert_eq!(s.name(), "test");
assert_eq!(s.get::<&str>("f1"), Ok(Some("abc"))); assert_eq!(s.get::<&str>("f1"), Ok("abc"));
assert_eq!(s.get::<&str>("f2"), Ok(Some("bcd"))); assert_eq!(s.get::<&str>("f2"), Ok("bcd"));
assert_eq!(s.get_some::<i32>("f3"), Ok(123i32)); assert_eq!(s.get::<i32>("f3"), Ok(123i32));
} }
#[test] #[test]
@ -825,20 +914,22 @@ mod tests {
let a = "Test, f1=(string)abc, f2=(uint)123;"; let a = "Test, f1=(string)abc, f2=(uint)123;";
let s = Structure::from_str(&a).unwrap(); let s = Structure::from_str(&a).unwrap();
assert_eq!(s.get::<&str>("f1"), Ok(Some("abc"))); assert_eq!(s.get::<&str>("f1"), Ok("abc"));
assert_eq!(s.get_some::<u32>("f2"), Ok(123)); assert_eq!(s.get::<u32>("f2"), Ok(123));
assert_eq!(a, s.to_string()); assert_eq!(a, s.to_string());
} }
#[test] #[test]
fn test_from_value_optional() { fn test_from_value_optional() {
use glib::ToValue;
crate::init().unwrap(); crate::init().unwrap();
let a = glib::value::Value::from(None::<&Structure>); let a = None::<&Structure>.to_value();
assert!(a.get::<Structure>().unwrap().is_none()); assert!(a.get::<Option<Structure>>().unwrap().is_none());
let b = glib::value::Value::from(&Structure::from_str(&"foo").unwrap()); let b = Structure::from_str(&"foo").unwrap().to_value();
assert!(b.get::<Structure>().unwrap().is_some()); assert!(b.get::<Option<Structure>>().unwrap().is_some());
} }
#[test] #[test]
@ -854,7 +945,7 @@ mod tests {
let s2 = Structure::from_iter(s.name(), s.iter().filter(|(f, _)| *f == "f1")); let s2 = Structure::from_iter(s.name(), s.iter().filter(|(f, _)| *f == "f1"));
assert_eq!(s2.name(), "test"); assert_eq!(s2.name(), "test");
assert_eq!(s2.get::<&str>("f1"), Ok(Some("abc"))); assert_eq!(s2.get::<&str>("f1"), Ok("abc"));
assert!(s2.get::<&str>("f2").is_err()); assert!(s2.get::<&str>("f2").is_err());
assert!(s2.get::<&str>("f3").is_err()); assert!(s2.get::<&str>("f3").is_err());
} }

View file

@ -5,19 +5,14 @@ use crate::TagMergeMode;
use crate::TagSetter; use crate::TagSetter;
use glib::object::IsA; use glib::object::IsA;
use glib::translate::*; use glib::translate::*;
use glib::value::ToSendValue; use glib::ToSendValue;
pub trait TagSetterExtManual: 'static { pub trait TagSetterExtManual: 'static {
fn add<'a, T: Tag<'a>>(&self, value: T::TagType, mode: TagMergeMode) fn add<'a, T: Tag<'a>>(&self, value: &T::TagType, mode: TagMergeMode);
where
T::TagType: ToSendValue;
} }
impl<O: IsA<TagSetter>> TagSetterExtManual for O { impl<O: IsA<TagSetter>> TagSetterExtManual for O {
fn add<'a, T: Tag<'a>>(&self, value: T::TagType, mode: TagMergeMode) fn add<'a, T: Tag<'a>>(&self, value: &T::TagType, mode: TagMergeMode) {
where
T::TagType: ToSendValue,
{
unsafe { unsafe {
let v = value.to_send_value(); let v = value.to_send_value();

View file

@ -10,7 +10,7 @@ use once_cell::sync::Lazy;
use glib::translate::{ use glib::translate::{
from_glib, from_glib_full, FromGlibPtrFull, ToGlib, ToGlibPtr, ToGlibPtrMut, from_glib, from_glib_full, FromGlibPtrFull, ToGlib, ToGlibPtr, ToGlibPtrMut,
}; };
use glib::value::{FromValue, FromValueOptional, SendValue, SetValue, ToSendValue, Value}; use glib::value::{FromValue, SendValue, ToSendValue, Value};
use glib::StaticType; use glib::StaticType;
use crate::Sample; use crate::Sample;
@ -19,7 +19,7 @@ use crate::TagMergeMode;
use crate::TagScope; use crate::TagScope;
pub trait Tag<'a> { pub trait Tag<'a> {
type TagType: FromValueOptional<'a> + SetValue + Send; type TagType: StaticType + FromValue<'a> + ToSendValue + Send + Sync;
fn tag_name<'b>() -> &'b str; fn tag_name<'b>() -> &'b str;
} }
@ -28,6 +28,7 @@ macro_rules! impl_tag(
pub enum $name {} pub enum $name {}
impl<'a> Tag<'a> for $name { impl<'a> Tag<'a> for $name {
type TagType = $t; type TagType = $t;
fn tag_name<'b>() -> &'b str { fn tag_name<'b>() -> &'b str {
*$rust_tag *$rust_tag
} }
@ -357,39 +358,27 @@ impl Default for TagList {
pub struct TagValue<T>(SendValue, PhantomData<T>); pub struct TagValue<T>(SendValue, PhantomData<T>);
impl<T> TagValue<T> { impl<T> TagValue<T> {
pub fn get<'a>(&'a self) -> Option<T> pub fn get<'a>(&'a self) -> T
where where
T: FromValueOptional<'a>, T: StaticType + FromValue<'a>,
{ {
self.0.get().expect("Invalid tag type") self.0.get().expect("Invalid tag type")
} }
pub fn get_some<'a>(&'a self) -> T
where
T: FromValue<'a>,
{
self.0.get_some().expect("Invalid tag type")
}
} }
impl TagListRef { impl TagListRef {
pub fn add<'a, T: Tag<'a>>(&mut self, value: &T::TagType, mode: TagMergeMode) pub fn add<'a, T: Tag<'a>>(&mut self, value: &T::TagType, mode: TagMergeMode) {
where
T::TagType: ToSendValue,
{
// result can be safely ignored here as `value`'s type is tied to `T::tag_name()` // result can be safely ignored here as `value`'s type is tied to `T::tag_name()`
let _res = self.add_generic(T::tag_name(), value, mode); let v = <T::TagType as ToSendValue>::to_send_value(value);
let _res = self.add_value(T::tag_name(), &v, mode);
} }
pub fn add_generic<T>( pub fn add_generic<T: ToSendValue + Sync>(
&mut self, &mut self,
tag_name: &str, tag_name: &str,
value: &T, value: T,
mode: TagMergeMode, mode: TagMergeMode,
) -> Result<(), TagError> ) -> Result<(), TagError> {
where
T: ToSendValue,
{
let v = value.to_send_value(); let v = value.to_send_value();
self.add_value(tag_name, &v, mode) self.add_value(tag_name, &v, mode)
} }
@ -969,15 +958,12 @@ mod tests {
tags.add::<Duration>(&(crate::SECOND * 120), TagMergeMode::Append); tags.add::<Duration>(&(crate::SECOND * 120), TagMergeMode::Append);
} }
assert_eq!(tags.get::<Title>().unwrap().get(), Some("some title")); assert_eq!(tags.get::<Title>().unwrap().get(), "some title");
assert_eq!(tags.get::<Duration>().unwrap().get(), crate::SECOND * 120);
assert_eq!(tags.index::<Title>(0).unwrap().get(), "some title");
assert_eq!( assert_eq!(
tags.get::<Duration>().unwrap().get_some(), tags.index::<Duration>(0).unwrap().get(),
(crate::SECOND * 120) crate::SECOND * 120
);
assert_eq!(tags.index::<Title>(0).unwrap().get(), Some("some title"));
assert_eq!(
tags.index::<Duration>(0).unwrap().get_some(),
(crate::SECOND * 120)
); );
} }
@ -1003,22 +989,22 @@ mod tests {
{ {
let tags = tags.get_mut().unwrap(); let tags = tags.get_mut().unwrap();
assert!(tags assert!(tags
.add_generic(&TAG_TITLE, &"some title", TagMergeMode::Append) .add_generic(&TAG_TITLE, "some title", TagMergeMode::Append)
.is_ok()); .is_ok());
assert!(tags assert!(tags
.add_generic(&TAG_TITLE, &"second title", TagMergeMode::Append) .add_generic(&TAG_TITLE, "second title", TagMergeMode::Append)
.is_ok()); .is_ok());
assert!(tags assert!(tags
.add_generic(&TAG_DURATION, &(crate::SECOND * 120), TagMergeMode::Append) .add_generic(&TAG_DURATION, crate::SECOND * 120, TagMergeMode::Append)
.is_ok()); .is_ok());
assert!(tags assert!(tags
.add_generic(&TAG_TITLE, &"third title", TagMergeMode::Append) .add_generic(&TAG_TITLE, "third title", TagMergeMode::Append)
.is_ok()); .is_ok());
assert_eq!( assert_eq!(
tags.add_generic( tags.add_generic(
&TAG_IMAGE, &TAG_IMAGE,
&"`&[str] instead of `Sample`", "`&[str] instead of `Sample`",
TagMergeMode::Append TagMergeMode::Append
), ),
Err(TagError::TypeMismatch), Err(TagError::TypeMismatch),
@ -1035,7 +1021,7 @@ mod tests {
); );
assert_eq!( assert_eq!(
tags.index_generic(&TAG_DURATION, 0).unwrap().get(), tags.index_generic(&TAG_DURATION, 0).unwrap().get(),
Ok(Some(crate::SECOND * 120)) Ok(crate::SECOND * 120)
); );
assert_eq!( assert_eq!(
tags.index_generic(&TAG_TITLE, 2).unwrap().get(), tags.index_generic(&TAG_TITLE, 2).unwrap().get(),
@ -1081,7 +1067,7 @@ mod tests {
let (tag_name, mut tag_iter) = tag_list_iter.next().unwrap(); let (tag_name, mut tag_iter) = tag_list_iter.next().unwrap();
assert_eq!(tag_name, *TAG_DURATION); assert_eq!(tag_name, *TAG_DURATION);
let first_duration = tag_iter.next().unwrap(); let first_duration = tag_iter.next().unwrap();
assert_eq!(first_duration.get_some(), Ok(crate::SECOND * 120)); assert_eq!(first_duration.get(), Ok(crate::SECOND * 120));
assert!(tag_iter.next().is_none()); assert!(tag_iter.next().is_none());
// Iter // Iter
@ -1097,7 +1083,7 @@ mod tests {
let (tag_name, tag_value) = tag_list_iter.next().unwrap(); let (tag_name, tag_value) = tag_list_iter.next().unwrap();
assert_eq!(tag_name, *TAG_DURATION); assert_eq!(tag_name, *TAG_DURATION);
assert_eq!(tag_value.get_some(), Ok(crate::SECOND * 120)); assert_eq!(tag_value.get(), Ok(crate::SECOND * 120));
assert!(tag_iter.next().is_none()); assert!(tag_iter.next().is_none());
} }
@ -1148,7 +1134,7 @@ mod tests {
tags.add::<MyCustomTag>(&"first one", TagMergeMode::Append); tags.add::<MyCustomTag>(&"first one", TagMergeMode::Append);
} }
assert_eq!(tags.get::<MyCustomTag>().unwrap().get(), Some("first one")); assert_eq!(tags.get::<MyCustomTag>().unwrap().get(), "first one");
{ {
let tags = tags.get_mut().unwrap(); let tags = tags.get_mut().unwrap();
@ -1157,7 +1143,7 @@ mod tests {
assert_eq!( assert_eq!(
tags.get::<MyCustomTag>().unwrap().get(), tags.get::<MyCustomTag>().unwrap().get(),
Some("first one, second one") "first one, second one"
); );
} }

View file

@ -21,13 +21,14 @@ use crate::Sample;
use crate::TagMergeMode; use crate::TagMergeMode;
use crate::TagScope; use crate::TagScope;
macro_rules! ser_some_tag ( macro_rules! ser_tag (
($value:ident, $seq:ident, $t:ty) => ( ($value:ident, $seq:ident, $t:ty) => (
ser_some_value!($value, $t, |_, value| { ser_some_value!($value, $t, |_, value| {
$seq.serialize_element(&value) $seq.serialize_element(&value)
}) })
); );
); );
macro_rules! ser_opt_tag ( macro_rules! ser_opt_tag (
($value:ident, $seq:ident, $t:ty) => ( ($value:ident, $seq:ident, $t:ty) => (
ser_opt_value!($value, $t, |_, value| { ser_opt_value!($value, $t, |_, value| {
@ -57,24 +58,22 @@ impl<'a> Serialize for TagValuesSer<'a> {
let mut seq = serializer.serialize_seq(tag_iter.size_hint().1)?; let mut seq = serializer.serialize_seq(tag_iter.size_hint().1)?;
for value in tag_iter.deref_mut() { for value in tag_iter.deref_mut() {
match value.type_() { match value.type_() {
glib::Type::F64 => ser_some_tag!(value, seq, f64), glib::Type::F64 => ser_tag!(value, seq, f64),
glib::Type::STRING => { glib::Type::STRING => {
// See above comment about `Tag`s with `String` values // See above comment about `Tag`s with `String` values
ser_opt_value!(value, String, |_, value: Option<String>| { ser_some_value!(value, String, |_, value: String| {
seq.serialize_element(&value.expect("String tag ser")) seq.serialize_element(&value)
}) })
} }
glib::Type::U32 => ser_some_tag!(value, seq, u32), glib::Type::U32 => ser_tag!(value, seq, u32),
glib::Type::U64 => ser_some_tag!(value, seq, u64), glib::Type::U64 => ser_tag!(value, seq, u64),
type_id => { type_id => {
if *DATE_OTHER_TYPE_ID == type_id { if *DATE_OTHER_TYPE_ID == type_id {
// See above comment about `Tag`s with `Date` values // See above comment about `Tag`s with `Date` values
ser_opt_value!(value, Date, |_, value: Option<Date>| { ser_some_value!(value, Date, |_, value: Date| {
// Need to wrap the `glib::Date` in new type `date_time_serde::Date` first // Need to wrap the `glib::Date` in new type `date_time_serde::Date` first
// See comment in `date_time_serde.rs` // See comment in `date_time_serde.rs`
seq.serialize_element(&date_time_serde::Date::from( seq.serialize_element(&date_time_serde::Date::from(value))
value.expect("Date tag ser"),
))
}) })
} else if *DATE_TIME_OTHER_TYPE_ID == type_id { } else if *DATE_TIME_OTHER_TYPE_ID == type_id {
ser_opt_tag!(value, seq, DateTime) ser_opt_tag!(value, seq, DateTime)
@ -147,7 +146,7 @@ impl Serialize for TagList {
} }
} }
macro_rules! de_some_tag( macro_rules! de_tag(
($tag_name:expr, $seq:expr, $t:ty) => ( ($tag_name:expr, $seq:expr, $t:ty) => (
de_some_send_value!("Tag", $tag_name, $seq, $t) de_some_send_value!("Tag", $tag_name, $seq, $t)
); );
@ -176,13 +175,13 @@ impl<'de, 'a> Visitor<'de> for TagValuesVisitor<'a> {
loop { loop {
let tag_value = match tag_type { let tag_value = match tag_type {
glib::Type::F64 => de_some_tag!(self.0, seq, f64), glib::Type::F64 => de_tag!(self.0, seq, f64),
glib::Type::STRING => { glib::Type::STRING => {
// See comment above `TagValuesSer` definition about `Tag`s with `String` values // See comment above `TagValuesSer` definition about `Tag`s with `String` values
de_some_tag!(self.0, seq, String) de_tag!(self.0, seq, String)
} }
glib::Type::U32 => de_some_tag!(self.0, seq, u32), glib::Type::U32 => de_tag!(self.0, seq, u32),
glib::Type::U64 => de_some_tag!(self.0, seq, u64), glib::Type::U64 => de_tag!(self.0, seq, u64),
type_id => { type_id => {
if *DATE_OTHER_TYPE_ID == type_id { if *DATE_OTHER_TYPE_ID == type_id {
// See comment above `TagValuesSer` definition about `Tag`s with `Date` values // See comment above `TagValuesSer` definition about `Tag`s with `Date` values
@ -464,23 +463,23 @@ mod tests {
let tags: TagList = ron::de::from_str(tag_list_ron).unwrap(); let tags: TagList = ron::de::from_str(tag_list_ron).unwrap();
assert_eq!(tags.scope(), TagScope::Global); assert_eq!(tags.scope(), TagScope::Global);
assert_eq!(tags.index::<Title>(0).unwrap().get(), Some("a title")); assert_eq!(tags.index::<Title>(0).unwrap().get(), "a title");
assert_eq!(tags.index::<Title>(1).unwrap().get(), Some("another title")); assert_eq!(tags.index::<Title>(1).unwrap().get(), "another title");
assert_eq!( assert_eq!(
tags.index::<Duration>(0).unwrap().get_some(), tags.index::<Duration>(0).unwrap().get(),
crate::SECOND * 120 crate::SECOND * 120
); );
assert_eq!(tags.index::<Bitrate>(0).unwrap().get_some(), 96_000); assert_eq!(tags.index::<Bitrate>(0).unwrap().get(), 96_000);
assert!((tags.index::<TrackGain>(0).unwrap().get_some() - 1f64).abs() < std::f64::EPSILON); assert!((tags.index::<TrackGain>(0).unwrap().get() - 1f64).abs() < std::f64::EPSILON);
assert_eq!( assert_eq!(
tags.index::<Date>(0).unwrap().get().unwrap(), tags.index::<Date>(0).unwrap().get(),
glib::Date::new_dmy(28, glib::DateMonth::May, 2018).unwrap() glib::Date::new_dmy(28, glib::DateMonth::May, 2018).unwrap()
); );
assert_eq!( assert_eq!(
tags.index::<DateTime>(0).unwrap().get().unwrap(), tags.index::<DateTime>(0).unwrap().get(),
crate::DateTime::new_ymd(2018, 5, 28).unwrap() crate::DateTime::new_ymd(2018, 5, 28).unwrap()
); );
let sample = tags.index::<Image>(0).unwrap().get().unwrap(); let sample = tags.index::<Image>(0).unwrap().get();
let buffer = sample.buffer().unwrap(); let buffer = sample.buffer().unwrap();
{ {
let data = buffer.map_readable().unwrap(); let data = buffer.map_readable().unwrap();
@ -504,19 +503,19 @@ mod tests {
let tags: TagList = serde_json::from_str(tag_json).unwrap(); let tags: TagList = serde_json::from_str(tag_json).unwrap();
assert_eq!(tags.scope(), TagScope::Global); assert_eq!(tags.scope(), TagScope::Global);
assert_eq!(tags.index::<Title>(0).unwrap().get(), Some("a title")); assert_eq!(tags.index::<Title>(0).unwrap().get(), "a title");
assert_eq!(tags.index::<Title>(1).unwrap().get(), Some("another title")); assert_eq!(tags.index::<Title>(1).unwrap().get(), "another title");
assert_eq!(tags.index::<Bitrate>(0).unwrap().get_some(), 96_000); assert_eq!(tags.index::<Bitrate>(0).unwrap().get(), 96_000);
assert!((tags.index::<TrackGain>(0).unwrap().get_some() - 1f64).abs() < std::f64::EPSILON); assert!((tags.index::<TrackGain>(0).unwrap().get() - 1f64).abs() < std::f64::EPSILON);
assert_eq!( assert_eq!(
tags.index::<Date>(0).unwrap().get().unwrap(), tags.index::<Date>(0).unwrap().get(),
glib::Date::new_dmy(28, glib::DateMonth::May, 2018).unwrap() glib::Date::new_dmy(28, glib::DateMonth::May, 2018).unwrap()
); );
assert_eq!( assert_eq!(
tags.index::<DateTime>(0).unwrap().get().unwrap(), tags.index::<DateTime>(0).unwrap().get(),
crate::DateTime::new_ymd(2018, 5, 28).unwrap() crate::DateTime::new_ymd(2018, 5, 28).unwrap()
); );
let sample = tags.index::<Image>(0).unwrap().get().unwrap(); let sample = tags.index::<Image>(0).unwrap().get();
let buffer = sample.buffer().unwrap(); let buffer = sample.buffer().unwrap();
{ {
let data = buffer.map_readable().unwrap(); let data = buffer.map_readable().unwrap();
@ -572,16 +571,16 @@ mod tests {
tags.index::<Title>(1).unwrap().get(), tags.index::<Title>(1).unwrap().get(),
); );
assert_eq!( assert_eq!(
tags_de.index::<Duration>(0).unwrap().get_some(), tags_de.index::<Duration>(0).unwrap().get(),
tags.index::<Duration>(0).unwrap().get_some(), tags.index::<Duration>(0).unwrap().get(),
); );
assert_eq!( assert_eq!(
tags_de.index::<Bitrate>(0).unwrap().get_some(), tags_de.index::<Bitrate>(0).unwrap().get(),
tags.index::<Bitrate>(0).unwrap().get_some(), tags.index::<Bitrate>(0).unwrap().get(),
); );
assert!( assert!(
(tags_de.index::<TrackGain>(0).unwrap().get_some() (tags_de.index::<TrackGain>(0).unwrap().get()
- tags.index::<TrackGain>(0).unwrap().get_some()) - tags.index::<TrackGain>(0).unwrap().get())
.abs() .abs()
< std::f64::EPSILON < std::f64::EPSILON
); );
@ -590,10 +589,10 @@ mod tests {
tags.index::<Date>(0).unwrap().get(), tags.index::<Date>(0).unwrap().get(),
); );
assert_eq!( assert_eq!(
tags.index::<DateTime>(0).unwrap().get().unwrap(), tags.index::<DateTime>(0).unwrap().get(),
crate::DateTime::new_ymd(2018, 5, 28).unwrap() crate::DateTime::new_ymd(2018, 5, 28).unwrap()
); );
let sample = tags.index::<Image>(0).unwrap().get().unwrap(); let sample = tags.index::<Image>(0).unwrap().get();
let buffer = sample.buffer().unwrap(); let buffer = sample.buffer().unwrap();
{ {
let data = buffer.map_readable().unwrap(); let data = buffer.map_readable().unwrap();

View file

@ -387,7 +387,7 @@ mod tests {
assert_eq!("chapter1.1", chapter1_1.uid()); assert_eq!("chapter1.1", chapter1_1.uid());
assert_eq!(Some((0, 4)), chapter1_1.start_stop_times()); assert_eq!(Some((0, 4)), chapter1_1.start_stop_times());
let tags = chapter1_1.tags().unwrap(); let tags = chapter1_1.tags().unwrap();
assert_eq!(Some("chapter 1.1"), tags.index::<Title>(0).unwrap().get()); assert_eq!("chapter 1.1", tags.index::<Title>(0).unwrap().get());
assert_eq!(0, chapter1_1.sub_entries().len()); assert_eq!(0, chapter1_1.sub_entries().len());
let chapter1_2 = &chap1_sub_entries[1]; let chapter1_2 = &chap1_sub_entries[1];
@ -395,14 +395,14 @@ mod tests {
assert_eq!("chapter1.2", chapter1_2.uid()); assert_eq!("chapter1.2", chapter1_2.uid());
assert_eq!(Some((4, 10)), chapter1_2.start_stop_times()); assert_eq!(Some((4, 10)), chapter1_2.start_stop_times());
let tags = chapter1_2.tags().unwrap(); let tags = chapter1_2.tags().unwrap();
assert_eq!(Some("chapter 1.2"), tags.index::<Title>(0).unwrap().get()); assert_eq!("chapter 1.2", tags.index::<Title>(0).unwrap().get());
assert_eq!(0, chapter1_2.sub_entries().len()); assert_eq!(0, chapter1_2.sub_entries().len());
let chapter2 = &sub_entries[1]; let chapter2 = &sub_entries[1];
assert_eq!(TocEntryType::Chapter, chapter2.entry_type()); assert_eq!(TocEntryType::Chapter, chapter2.entry_type());
assert_eq!("chapter2", chapter2.uid()); assert_eq!("chapter2", chapter2.uid());
let tags = chapter2.tags().unwrap(); let tags = chapter2.tags().unwrap();
assert_eq!(Some("chapter 2"), tags.index::<Title>(0).unwrap().get()); assert_eq!("chapter 2", tags.index::<Title>(0).unwrap().get());
assert_eq!(Some((10, 15)), chapter2.start_stop_times()); assert_eq!(Some((10, 15)), chapter2.start_stop_times());
assert_eq!(0, chapter2.sub_entries().len()); assert_eq!(0, chapter2.sub_entries().len());
} }

View file

@ -8,7 +8,8 @@ use std::ops;
use std::slice; use std::slice;
use glib::translate::{from_glib, FromGlibPtrFull, ToGlibPtr, ToGlibPtrMut, Uninitialized}; use glib::translate::{from_glib, FromGlibPtrFull, ToGlibPtr, ToGlibPtrMut, Uninitialized};
use glib::value::{FromValue, FromValueOptional, SetValue, ToSendValue, Value}; use glib::value::ToSendValue;
use glib::StaticType;
#[derive(Copy, Clone, Debug, Ord, PartialOrd, Eq, PartialEq, Hash)] #[derive(Copy, Clone, Debug, Ord, PartialOrd, Eq, PartialEq, Hash)]
pub struct Fraction(pub Rational32); pub struct Fraction(pub Rational32);
@ -243,24 +244,33 @@ impl glib::types::StaticType for Fraction {
} }
} }
impl<'a> FromValue<'a> for Fraction { impl glib::value::ValueType for Fraction {
unsafe fn from_value(v: &'a Value) -> Self { type Type = Self;
let n = ffi::gst_value_get_fraction_numerator(v.to_glib_none().0); }
let d = ffi::gst_value_get_fraction_denominator(v.to_glib_none().0);
unsafe impl<'a> glib::value::FromValue<'a> for Fraction {
type Checker = glib::value::GenericValueTypeChecker<Self>;
unsafe fn from_value(value: &'a glib::Value) -> Self {
skip_assert_initialized!();
let n = ffi::gst_value_get_fraction_numerator(value.to_glib_none().0);
let d = ffi::gst_value_get_fraction_denominator(value.to_glib_none().0);
Fraction::new(n, d) Fraction::new(n, d)
} }
} }
impl<'a> FromValueOptional<'a> for Fraction { impl glib::value::ToValue for Fraction {
unsafe fn from_value_optional(v: &'a Value) -> Option<Self> { fn to_value(&self) -> glib::Value {
Some(Fraction::from_value(v)) let mut value = glib::Value::for_value_type::<Fraction>();
unsafe {
ffi::gst_value_set_fraction(value.to_glib_none_mut().0, *self.numer(), *self.denom());
} }
value
} }
impl SetValue for Fraction { fn value_type(&self) -> glib::Type {
unsafe fn set_value(v: &mut Value, f: &Self) { Self::static_type()
ffi::gst_value_set_fraction(v.to_glib_none_mut().0, *f.numer(), *f.denom());
} }
} }
@ -352,25 +362,39 @@ impl glib::types::StaticType for IntRange<i32> {
} }
} }
impl<'a> FromValue<'a> for IntRange<i32> { impl glib::value::ValueType for IntRange<i32> {
unsafe fn from_value(v: &'a Value) -> Self { type Type = Self;
let min = ffi::gst_value_get_int_range_min(v.to_glib_none().0); }
let max = ffi::gst_value_get_int_range_max(v.to_glib_none().0);
let step = ffi::gst_value_get_int_range_step(v.to_glib_none().0); unsafe impl<'a> glib::value::FromValue<'a> for IntRange<i32> {
type Checker = glib::value::GenericValueTypeChecker<Self>;
unsafe fn from_value(value: &'a glib::Value) -> Self {
skip_assert_initialized!();
let min = ffi::gst_value_get_int_range_min(value.to_glib_none().0);
let max = ffi::gst_value_get_int_range_max(value.to_glib_none().0);
let step = ffi::gst_value_get_int_range_step(value.to_glib_none().0);
Self::with_step(min, max, step) Self::with_step(min, max, step)
} }
} }
impl<'a> FromValueOptional<'a> for IntRange<i32> { impl glib::value::ToValue for IntRange<i32> {
unsafe fn from_value_optional(v: &'a Value) -> Option<Self> { fn to_value(&self) -> glib::Value {
Some(Self::from_value(v)) let mut value = glib::Value::for_value_type::<IntRange<i32>>();
unsafe {
ffi::gst_value_set_int_range_step(
value.to_glib_none_mut().0,
self.min(),
self.max(),
self.step(),
);
} }
value
} }
impl SetValue for IntRange<i32> { fn value_type(&self) -> glib::Type {
unsafe fn set_value(v: &mut Value, r: &Self) { Self::static_type()
ffi::gst_value_set_int_range_step(v.to_glib_none_mut().0, r.min(), r.max(), r.step());
} }
} }
@ -380,25 +404,39 @@ impl glib::types::StaticType for IntRange<i64> {
} }
} }
impl<'a> FromValue<'a> for IntRange<i64> { impl glib::value::ValueType for IntRange<i64> {
unsafe fn from_value(v: &'a Value) -> Self { type Type = Self;
let min = ffi::gst_value_get_int64_range_min(v.to_glib_none().0); }
let max = ffi::gst_value_get_int64_range_max(v.to_glib_none().0);
let step = ffi::gst_value_get_int64_range_step(v.to_glib_none().0); unsafe impl<'a> glib::value::FromValue<'a> for IntRange<i64> {
type Checker = glib::value::GenericValueTypeChecker<Self>;
unsafe fn from_value(value: &'a glib::Value) -> Self {
skip_assert_initialized!();
let min = ffi::gst_value_get_int64_range_min(value.to_glib_none().0);
let max = ffi::gst_value_get_int64_range_max(value.to_glib_none().0);
let step = ffi::gst_value_get_int64_range_step(value.to_glib_none().0);
Self::with_step(min, max, step) Self::with_step(min, max, step)
} }
} }
impl<'a> FromValueOptional<'a> for IntRange<i64> { impl glib::value::ToValue for IntRange<i64> {
unsafe fn from_value_optional(v: &'a Value) -> Option<Self> { fn to_value(&self) -> glib::Value {
Some(Self::from_value(v)) let mut value = glib::Value::for_value_type::<IntRange<i64>>();
unsafe {
ffi::gst_value_set_int64_range_step(
value.to_glib_none_mut().0,
self.min(),
self.max(),
self.step(),
);
} }
value
} }
impl SetValue for IntRange<i64> { fn value_type(&self) -> glib::Type {
unsafe fn set_value(v: &mut Value, r: &Self) { Self::static_type()
ffi::gst_value_set_int64_range_step(v.to_glib_none_mut().0, r.min(), r.max(), r.step());
} }
} }
@ -444,10 +482,17 @@ impl glib::types::StaticType for FractionRange {
} }
} }
impl<'a> FromValue<'a> for FractionRange { impl glib::value::ValueType for FractionRange {
unsafe fn from_value(v: &'a Value) -> Self { type Type = Self;
let min = ffi::gst_value_get_fraction_range_min(v.to_glib_none().0); }
let max = ffi::gst_value_get_fraction_range_max(v.to_glib_none().0);
unsafe impl<'a> glib::value::FromValue<'a> for FractionRange {
type Checker = glib::value::GenericValueTypeChecker<Self>;
unsafe fn from_value(value: &'a glib::Value) -> Self {
skip_assert_initialized!();
let min = ffi::gst_value_get_fraction_range_min(value.to_glib_none().0);
let max = ffi::gst_value_get_fraction_range_max(value.to_glib_none().0);
let min_n = ffi::gst_value_get_fraction_numerator(min); let min_n = ffi::gst_value_get_fraction_numerator(min);
let min_d = ffi::gst_value_get_fraction_denominator(min); let min_d = ffi::gst_value_get_fraction_denominator(min);
@ -458,21 +503,23 @@ impl<'a> FromValue<'a> for FractionRange {
} }
} }
impl<'a> FromValueOptional<'a> for FractionRange { impl glib::value::ToValue for FractionRange {
unsafe fn from_value_optional(v: &'a Value) -> Option<Self> { fn to_value(&self) -> glib::Value {
Some(Self::from_value(v)) let mut value = glib::Value::for_value_type::<FractionRange>();
unsafe {
ffi::gst_value_set_fraction_range_full(
value.to_glib_none_mut().0,
*self.min().numer(),
*self.min().denom(),
*self.max().numer(),
*self.max().denom(),
);
} }
value
} }
impl SetValue for FractionRange { fn value_type(&self) -> glib::Type {
unsafe fn set_value(v: &mut Value, r: &Self) { Self::static_type()
ffi::gst_value_set_fraction_range_full(
v.to_glib_none_mut().0,
*r.min().numer(),
*r.min().denom(),
*r.max().numer(),
*r.max().denom(),
);
} }
} }
@ -546,22 +593,31 @@ impl glib::types::StaticType for Bitmask {
} }
} }
impl<'a> FromValue<'a> for Bitmask { impl glib::value::ValueType for Bitmask {
unsafe fn from_value(v: &'a Value) -> Self { type Type = Self;
let v = ffi::gst_value_get_bitmask(v.to_glib_none().0); }
unsafe impl<'a> glib::value::FromValue<'a> for Bitmask {
type Checker = glib::value::GenericValueTypeChecker<Self>;
unsafe fn from_value(value: &'a glib::Value) -> Self {
skip_assert_initialized!();
let v = ffi::gst_value_get_bitmask(value.to_glib_none().0);
Self::new(v) Self::new(v)
} }
} }
impl<'a> FromValueOptional<'a> for Bitmask { impl glib::value::ToValue for Bitmask {
unsafe fn from_value_optional(v: &'a Value) -> Option<Self> { fn to_value(&self) -> glib::Value {
Some(Self::from_value(v)) let mut value = glib::Value::for_value_type::<Bitmask>();
unsafe {
ffi::gst_value_set_bitmask(value.to_glib_none_mut().0, self.0);
} }
value
} }
impl SetValue for Bitmask { fn value_type(&self) -> glib::Type {
unsafe fn set_value(v: &mut Value, r: &Self) { Self::static_type()
ffi::gst_value_set_bitmask(v.to_glib_none_mut().0, r.0);
} }
} }
@ -569,9 +625,10 @@ impl SetValue for Bitmask {
pub struct Array<'a>(Cow<'a, [glib::SendValue]>); pub struct Array<'a>(Cow<'a, [glib::SendValue]>);
unsafe impl<'a> Send for Array<'a> {} unsafe impl<'a> Send for Array<'a> {}
unsafe impl<'a> Sync for Array<'a> {}
impl<'a> Array<'a> { impl<'a> Array<'a> {
pub fn new(values: &[&dyn ToSendValue]) -> Self { pub fn new(values: &[&(dyn ToSendValue + Sync)]) -> Self {
assert_initialized_main_thread!(); assert_initialized_main_thread!();
Array(values.iter().map(|v| v.to_send_value()).collect()) Array(values.iter().map(|v| v.to_send_value()).collect())
@ -598,8 +655,8 @@ impl<'a> Array<'a> {
} }
} }
impl<'a> From<&'a [&'a dyn ToSendValue]> for Array<'a> { impl<'a> From<&'a [&'a (dyn ToSendValue + Sync)]> for Array<'a> {
fn from(values: &'a [&'a dyn ToSendValue]) -> Self { fn from(values: &'a [&'a (dyn ToSendValue + Sync)]) -> Self {
skip_assert_initialized!(); skip_assert_initialized!();
Self::new(values) Self::new(values)
@ -614,9 +671,16 @@ impl<'a> From<&'a [glib::SendValue]> for Array<'a> {
} }
} }
impl<'a> FromValue<'a> for Array<'a> { impl<'a> glib::value::ValueType for Array<'static> {
unsafe fn from_value(v: &'a Value) -> Self { type Type = Self;
let arr = (*v.to_glib_none().0).data[0].v_pointer as *const glib::ffi::GArray; }
unsafe impl<'a> glib::value::FromValue<'a> for Array<'a> {
type Checker = glib::value::GenericValueTypeChecker<Self>;
unsafe fn from_value(value: &'a glib::Value) -> Self {
skip_assert_initialized!();
let arr = (*value.to_glib_none().0).data[0].v_pointer as *const glib::ffi::GArray;
if arr.is_null() { if arr.is_null() {
Array(Cow::Borrowed(&[])) Array(Cow::Borrowed(&[]))
} else { } else {
@ -629,17 +693,19 @@ impl<'a> FromValue<'a> for Array<'a> {
} }
} }
impl<'a> FromValueOptional<'a> for Array<'a> { impl<'a> glib::value::ToValue for Array<'a> {
unsafe fn from_value_optional(v: &'a Value) -> Option<Self> { fn to_value(&self) -> glib::Value {
Some(Array::from_value(v)) let mut value = glib::Value::for_value_type::<Array<'static>>();
unsafe {
for v in self.as_slice() {
ffi::gst_value_array_append_value(value.to_glib_none_mut().0, v.to_glib_none().0);
} }
} }
value
}
impl<'a> SetValue for Array<'a> { fn value_type(&self) -> glib::Type {
unsafe fn set_value(v: &mut Value, a: &Self) { Self::static_type()
for value in a.as_slice() {
ffi::gst_value_array_append_value(v.to_glib_none_mut().0, value.to_glib_none().0);
}
} }
} }
@ -653,9 +719,10 @@ impl<'a> glib::types::StaticType for Array<'a> {
pub struct List<'a>(Cow<'a, [glib::SendValue]>); pub struct List<'a>(Cow<'a, [glib::SendValue]>);
unsafe impl<'a> Send for List<'a> {} unsafe impl<'a> Send for List<'a> {}
unsafe impl<'a> Sync for List<'a> {}
impl<'a> List<'a> { impl<'a> List<'a> {
pub fn new(values: &[&dyn ToSendValue]) -> Self { pub fn new(values: &[&(dyn ToSendValue + Sync)]) -> Self {
assert_initialized_main_thread!(); assert_initialized_main_thread!();
List(values.iter().map(|v| v.to_send_value()).collect()) List(values.iter().map(|v| v.to_send_value()).collect())
@ -682,8 +749,8 @@ impl<'a> List<'a> {
} }
} }
impl<'a> From<&'a [&'a dyn ToSendValue]> for List<'a> { impl<'a> From<&'a [&'a (dyn ToSendValue + Sync)]> for List<'a> {
fn from(values: &'a [&'a dyn ToSendValue]) -> Self { fn from(values: &'a [&'a (dyn ToSendValue + Sync)]) -> Self {
skip_assert_initialized!(); skip_assert_initialized!();
Self::new(values) Self::new(values)
@ -698,9 +765,16 @@ impl<'a> From<&'a [glib::SendValue]> for List<'a> {
} }
} }
impl<'a> FromValue<'a> for List<'a> { impl glib::value::ValueType for List<'static> {
unsafe fn from_value(v: &'a Value) -> Self { type Type = Self;
let arr = (*v.to_glib_none().0).data[0].v_pointer as *const glib::ffi::GArray; }
unsafe impl<'a> glib::value::FromValue<'a> for List<'a> {
type Checker = glib::value::GenericValueTypeChecker<Self>;
unsafe fn from_value(value: &'a glib::Value) -> Self {
skip_assert_initialized!();
let arr = (*value.to_glib_none().0).data[0].v_pointer as *const glib::ffi::GArray;
if arr.is_null() { if arr.is_null() {
List(Cow::Borrowed(&[])) List(Cow::Borrowed(&[]))
} else { } else {
@ -713,17 +787,19 @@ impl<'a> FromValue<'a> for List<'a> {
} }
} }
impl<'a> FromValueOptional<'a> for List<'a> { impl<'a> glib::value::ToValue for List<'a> {
unsafe fn from_value_optional(v: &'a Value) -> Option<Self> { fn to_value(&self) -> glib::Value {
Some(List::from_value(v)) let mut value = glib::Value::for_value_type::<List<'static>>();
unsafe {
for v in self.as_slice() {
ffi::gst_value_list_append_value(value.to_glib_none_mut().0, v.to_glib_none().0);
} }
} }
value
}
impl<'a> SetValue for List<'a> { fn value_type(&self) -> glib::Type {
unsafe fn set_value(v: &mut Value, a: &Self) { Self::static_type()
for value in a.as_slice() {
ffi::gst_value_list_append_value(v.to_glib_none_mut().0, value.to_glib_none().0);
}
} }
} }

View file

@ -52,7 +52,7 @@ impl<'de> Deserialize<'de> for Fraction {
macro_rules! ser_some_value ( macro_rules! ser_some_value (
($value:expr, $t:ty, $ser_closure:expr) => ( ($value:expr, $t:ty, $ser_closure:expr) => (
{ {
let value = $value.get_some::<$t>().expect("ser_some_value macro"); let value = $value.get::<$t>().expect("ser_some_value macro");
$ser_closure(stringify!($t), value) $ser_closure(stringify!($t), value)
} }
); );
@ -60,7 +60,7 @@ macro_rules! ser_some_value (
macro_rules! ser_opt_value ( macro_rules! ser_opt_value (
($value:expr, $t:ty, $ser_closure:expr) => ( ($value:expr, $t:ty, $ser_closure:expr) => (
{ {
let value = $value.get::<$t>().expect("ser_opt_value macro"); let value = $value.get::<Option<$t>>().expect("ser_opt_value macro");
$ser_closure(stringify!($t), value) $ser_closure(stringify!($t), value)
} }
); );
@ -523,54 +523,60 @@ mod tests {
let slice = array.as_slice(); let slice = array.as_slice();
assert_eq!(6, slice.len()); assert_eq!(6, slice.len());
let fraction = slice[0].get::<Fraction>().expect("slice[0]").unwrap(); let fraction = slice[0].get::<Fraction>().expect("slice[0]");
assert_eq!(fraction.0.numer(), &1); assert_eq!(fraction.0.numer(), &1);
assert_eq!(fraction.0.denom(), &3); assert_eq!(fraction.0.denom(), &3);
let fraction = slice[1].get::<Fraction>().expect("slice[1]").unwrap(); let fraction = slice[1].get::<Fraction>().expect("slice[1]");
assert_eq!(fraction.0.numer(), &1); assert_eq!(fraction.0.numer(), &1);
assert_eq!(fraction.0.denom(), &2); assert_eq!(fraction.0.denom(), &2);
assert_eq!( assert_eq!(
"test str".to_owned(), "test str".to_owned(),
slice[2].get::<String>().expect("slice[2]").unwrap() slice[2].get::<String>().expect("slice[2]")
); );
assert!(slice[3].get::<String>().expect("slice[3]").is_none()); assert!(slice[3]
.get::<Option<String>>()
.expect("slice[3]")
.is_none());
assert_eq!( assert_eq!(
Date::new_dmy(19, DateMonth::August, 2019).unwrap(), Date::new_dmy(19, DateMonth::August, 2019).unwrap(),
slice[4].get::<Date>().expect("slice[4]").unwrap() slice[4].get::<Date>().expect("slice[4]")
); );
assert!(slice[5].get::<Date>().expect("slice[5]").is_none()); assert!(slice[5].get::<Option<Date>>().expect("slice[5]").is_none());
let array_json = r#"[["Fraction",[1,3]],["Fraction",[1,2]],["String","test str"],["String",null],["Date",{"YMD":[2019,8,19]}],["Date",null]]"#; let array_json = r#"[["Fraction",[1,3]],["Fraction",[1,2]],["String","test str"],["String",null],["Date",{"YMD":[2019,8,19]}],["Date",null]]"#;
let array: Array = serde_json::from_str(array_json).unwrap(); let array: Array = serde_json::from_str(array_json).unwrap();
let slice = array.as_slice(); let slice = array.as_slice();
assert_eq!(6, slice.len()); assert_eq!(6, slice.len());
let fraction = slice[0].get::<Fraction>().expect("slice[0]").unwrap(); let fraction = slice[0].get::<Fraction>().expect("slice[0]");
assert_eq!(fraction.0.numer(), &1); assert_eq!(fraction.0.numer(), &1);
assert_eq!(fraction.0.denom(), &3); assert_eq!(fraction.0.denom(), &3);
let fraction = slice[1].get::<Fraction>().expect("slice[1]").unwrap(); let fraction = slice[1].get::<Fraction>().expect("slice[1]");
assert_eq!(fraction.0.numer(), &1); assert_eq!(fraction.0.numer(), &1);
assert_eq!(fraction.0.denom(), &2); assert_eq!(fraction.0.denom(), &2);
assert_eq!( assert_eq!(
"test str".to_owned(), "test str".to_owned(),
slice[2].get::<String>().expect("slice[2]").unwrap() slice[2].get::<String>().expect("slice[2]")
); );
assert!(slice[3].get::<String>().expect("slice[3]").is_none()); assert!(slice[3]
.get::<Option<String>>()
.expect("slice[3]")
.is_none());
assert_eq!( assert_eq!(
Date::new_dmy(19, DateMonth::August, 2019).unwrap(), Date::new_dmy(19, DateMonth::August, 2019).unwrap(),
slice[4].get::<Date>().expect("slice[4]").unwrap() slice[4].get::<Date>().expect("slice[4]")
); );
assert!(slice[5].get::<Date>().expect("slice[5]").is_none()); assert!(slice[5].get::<Option<Date>>().expect("slice[5]").is_none());
// List // List
let list_ron = r#"[ let list_ron = r#"[
@ -584,23 +590,29 @@ mod tests {
let slice = list.as_slice(); let slice = list.as_slice();
assert_eq!(5, slice.len()); assert_eq!(5, slice.len());
let fraction = slice[0].get::<Fraction>().expect("slice[0]").unwrap(); let fraction = slice[0].get::<Fraction>().expect("slice[0]");
assert_eq!(fraction.0.numer(), &1); assert_eq!(fraction.0.numer(), &1);
assert_eq!(fraction.0.denom(), &2); assert_eq!(fraction.0.denom(), &2);
assert_eq!( assert_eq!(
"test str".to_owned(), "test str".to_owned(),
slice[1].get::<String>().expect("slice[1]").unwrap() slice[1].get::<String>().expect("slice[1]")
); );
assert!(slice[2].get::<String>().expect("slice[2]").is_none()); assert!(slice[2]
.get::<Option<String>>()
.expect("slice[2]")
.is_none());
assert_eq!( assert_eq!(
DateTime::new(2f32, 2019, 8, 19, 13, 34, 42f64).unwrap(), DateTime::new(2f32, 2019, 8, 19, 13, 34, 42f64).unwrap(),
slice[3].get::<DateTime>().expect("slice[3]").unwrap() slice[3].get::<DateTime>().expect("slice[3]")
); );
assert!(slice[4].get::<DateTime>().expect("slice[4]").is_none()); assert!(slice[4]
.get::<Option<DateTime>>()
.expect("slice[4]")
.is_none());
} }
#[test] #[test]
@ -630,29 +642,32 @@ mod tests {
let slice = array.as_slice(); let slice = array.as_slice();
assert_eq!(slice_de.len(), slice.len()); assert_eq!(slice_de.len(), slice.len());
let fraction_de = slice_de[0].get::<Fraction>().expect("slice_de[0]").unwrap(); let fraction_de = slice_de[0].get::<Fraction>().expect("slice_de[0]");
let fraction = slice[0].get::<Fraction>().expect("slice[0]").unwrap(); let fraction = slice[0].get::<Fraction>().expect("slice[0]");
assert_eq!(fraction_de.0.numer(), fraction.0.numer()); assert_eq!(fraction_de.0.numer(), fraction.0.numer());
assert_eq!(fraction_de.0.denom(), fraction.0.denom()); assert_eq!(fraction_de.0.denom(), fraction.0.denom());
let fraction_de = slice_de[1].get::<Fraction>().expect("slice_de[1]").unwrap(); let fraction_de = slice_de[1].get::<Fraction>().expect("slice_de[1]");
let fraction = slice[1].get::<Fraction>().expect("slice[1]").unwrap(); let fraction = slice[1].get::<Fraction>().expect("slice[1]");
assert_eq!(fraction_de.0.numer(), fraction.0.numer()); assert_eq!(fraction_de.0.numer(), fraction.0.numer());
assert_eq!(fraction.0.denom(), fraction.0.denom()); assert_eq!(fraction.0.denom(), fraction.0.denom());
assert_eq!( assert_eq!(
slice_de[2].get::<String>().expect("slice_de[2]").unwrap(), slice_de[2].get::<String>().expect("slice_de[2]"),
slice[2].get::<String>().expect("slice[2]").unwrap() slice[2].get::<String>().expect("slice[2]")
); );
assert!(slice[3].get::<String>().expect("slice[3]").is_none()); assert!(slice[3]
.get::<Option<String>>()
.expect("slice[3]")
.is_none());
assert_eq!( assert_eq!(
slice_de[4].get::<Date>().expect("slice_de[4]").unwrap(), slice_de[4].get::<Date>().expect("slice_de[4]"),
slice[4].get::<Date>().expect("slice[4]").unwrap() slice[4].get::<Date>().expect("slice[4]")
); );
assert!(slice[5].get::<Date>().expect("slice[5]").is_none()); assert!(slice[5].get::<Option<Date>>().expect("slice[5]").is_none());
// List // List
let value_12 = Fraction::new(1, 2); let value_12 = Fraction::new(1, 2);
@ -675,23 +690,29 @@ mod tests {
let slice = list.as_slice(); let slice = list.as_slice();
assert_eq!(slice_de.len(), slice.len()); assert_eq!(slice_de.len(), slice.len());
let fraction_de = slice_de[0].get::<Fraction>().expect("slice_de[0]").unwrap(); let fraction_de = slice_de[0].get::<Fraction>().expect("slice_de[0]");
let fraction = slice[0].get::<Fraction>().expect("slice[0]").unwrap(); let fraction = slice[0].get::<Fraction>().expect("slice[0]");
assert_eq!(fraction_de.0.numer(), fraction.0.numer()); assert_eq!(fraction_de.0.numer(), fraction.0.numer());
assert_eq!(fraction_de.0.denom(), fraction.0.denom()); assert_eq!(fraction_de.0.denom(), fraction.0.denom());
assert_eq!( assert_eq!(
slice_de[1].get::<String>().expect("slice_de[1]").unwrap(), slice_de[1].get::<String>().expect("slice_de[1]"),
slice[1].get::<String>().expect("slice[1]").unwrap() slice[1].get::<String>().expect("slice[1]")
); );
assert!(slice[2].get::<String>().expect("slice[2]").is_none()); assert!(slice[2]
.get::<Option<String>>()
.expect("slice[2]")
.is_none());
assert_eq!( assert_eq!(
slice_de[3].get::<DateTime>().expect("slice_de[3]").unwrap(), slice_de[3].get::<DateTime>().expect("slice_de[3]"),
slice[3].get::<DateTime>().expect("slice[3]").unwrap() slice[3].get::<DateTime>().expect("slice[3]")
); );
assert!(slice[4].get::<DateTime>().expect("slice[4]").is_none()); assert!(slice[4]
.get::<Option<DateTime>>()
.expect("slice[4]")
.is_none());
} }
} }

View file

@ -56,7 +56,11 @@ fn send_seek_event(pipeline: &Element, rate: f64) -> bool {
}; };
// If we have not done so, obtain the sink through which we will send the seek events // If we have not done so, obtain the sink through which we will send the seek events
if let Ok(Some(video_sink)) = pipeline.property("video-sink").unwrap().get::<Element>() { if let Ok(Some(video_sink)) = pipeline
.property("video-sink")
.unwrap()
.get::<Option<Element>>()
{
println!("Current rate: {}\r", rate); println!("Current rate: {}\r", rate);
// Send the event // Send the event
video_sink.send_event(seek_event) video_sink.send_event(seek_event)
@ -171,8 +175,10 @@ USAGE: Choose one of the following options, then press enter:
} }
} }
Command::NextFrame => { Command::NextFrame => {
if let Ok(Some(video_sink)) = if let Ok(Some(video_sink)) = pipeline
pipeline.property("video-sink").unwrap().get::<Element>() .property("video-sink")
.unwrap()
.get::<Option<Element>>()
{ {
// Send the event // Send the event
let step = Step::new(gst::format::Buffers(Some(1)), rate.abs(), true, false); let step = Step::new(gst::format::Buffers(Some(1)), rate.abs(), true, false);

View file

@ -41,49 +41,31 @@ mod tutorial5 {
let propname: &str = &format!("n-{}", stype); let propname: &str = &format!("n-{}", stype);
let signame: &str = &format!("get-{}-tags", stype); let signame: &str = &format!("get-{}-tags", stype);
match playbin.property(propname).unwrap().get() { let x = playbin.property(propname).unwrap().get::<i32>().unwrap();
Ok(Some(x)) => {
for i in 0..x { for i in 0..x {
let tags = playbin.emit_by_name(signame, &[&i]).unwrap().unwrap(); let tags = playbin.emit_by_name(signame, &[&i]).unwrap().unwrap();
if let Ok(Some(tags)) = tags.get::<gst::TagList>() { if let Ok(Some(tags)) = tags.get::<Option<gst::TagList>>() {
textbuf.insert_at_cursor(&format!("{} stream {}:\n ", stype, i)); textbuf.insert_at_cursor(&format!("{} stream {}:\n ", stype, i));
if let Some(codec) = tags.get::<gst::tags::VideoCodec>() { if let Some(codec) = tags.get::<gst::tags::VideoCodec>() {
textbuf.insert_at_cursor(&format!( textbuf.insert_at_cursor(&format!(" codec: {} \n", codec.get()));
" codec: {} \n",
codec.get().unwrap()
));
} }
if let Some(codec) = tags.get::<gst::tags::AudioCodec>() { if let Some(codec) = tags.get::<gst::tags::AudioCodec>() {
textbuf.insert_at_cursor(&format!( textbuf.insert_at_cursor(&format!(" codec: {} \n", codec.get()));
" codec: {} \n",
codec.get().unwrap()
));
} }
if let Some(lang) = tags.get::<gst::tags::LanguageCode>() { if let Some(lang) = tags.get::<gst::tags::LanguageCode>() {
textbuf.insert_at_cursor(&format!( textbuf.insert_at_cursor(&format!(" language: {} \n", lang.get()));
" language: {} \n",
lang.get().unwrap()
));
} }
if let Some(bitrate) = tags.get::<gst::tags::Bitrate>() { if let Some(bitrate) = tags.get::<gst::tags::Bitrate>() {
textbuf.insert_at_cursor(&format!( textbuf.insert_at_cursor(&format!(" bitrate: {} \n", bitrate.get()));
" bitrate: {} \n",
bitrate.get().unwrap()
));
} }
} }
} }
} }
_ => {
eprintln!("Could not get {}!", propname);
}
}
}
// Extract metadata from all the streams and write it to the text widget in the GUI // Extract metadata from all the streams and write it to the text widget in the GUI
fn analyze_streams(playbin: &gst::Element, textbuf: &gtk::TextBuffer) { fn analyze_streams(playbin: &gst::Element, textbuf: &gtk::TextBuffer) {
@ -329,8 +311,7 @@ mod tutorial5 {
.connect("video-tags-changed", false, |args| { .connect("video-tags-changed", false, |args| {
let pipeline = args[0] let pipeline = args[0]
.get::<gst::Element>() .get::<gst::Element>()
.expect("playbin \"video-tags-changed\" args[0]") .expect("playbin \"video-tags-changed\" args[0]");
.unwrap();
post_app_message(&pipeline); post_app_message(&pipeline);
None None
}) })
@ -340,8 +321,7 @@ mod tutorial5 {
.connect("audio-tags-changed", false, |args| { .connect("audio-tags-changed", false, |args| {
let pipeline = args[0] let pipeline = args[0]
.get::<gst::Element>() .get::<gst::Element>()
.expect("playbin \"audio-tags-changed\" args[0]") .expect("playbin \"audio-tags-changed\" args[0]");
.unwrap();
post_app_message(&pipeline); post_app_message(&pipeline);
None None
}) })
@ -351,8 +331,7 @@ mod tutorial5 {
.connect("text-tags-changed", false, move |args| { .connect("text-tags-changed", false, move |args| {
let pipeline = args[0] let pipeline = args[0]
.get::<gst::Element>() .get::<gst::Element>()
.expect("playbin \"text-tags-changed\" args[0]") .expect("playbin \"text-tags-changed\" args[0]");
.unwrap();
post_app_message(&pipeline); post_app_message(&pipeline);
None None
}) })

View file

@ -11,7 +11,7 @@ use std::env;
mod tutorials_common; mod tutorials_common;
fn send_value_as_str(v: &glib::SendValue) -> Option<String> { fn send_value_as_str(v: &glib::SendValue) -> Option<String> {
if let Ok(Some(s)) = v.get::<&str>() { if let Ok(s) = v.get::<&str>() {
Some(s.to_string()) Some(s.to_string())
} else if let Ok(serialized) = v.serialize() { } else if let Ok(serialized) = v.serialize() {
Some(serialized.into()) Some(serialized.into())

View file

@ -100,18 +100,14 @@ fn tutorial_main() -> Result<(), Error> {
.expect("Failed to add bus watch"); .expect("Failed to add bus watch");
pipeline.connect("deep-notify::temp-location", false, |args| { pipeline.connect("deep-notify::temp-location", false, |args| {
let download_buffer = args[1] let download_buffer = args[1].get::<gst::Object>().unwrap();
.get::<gst::Object>()
.unwrap()
.expect("download buffer");
println!( println!(
"Temporary file: {:?}", "Temporary file: {:?}",
download_buffer download_buffer
.property("temp-location") .property("temp-location")
.unwrap() .unwrap()
.get::<String>() .get::<Option<String>>()
.unwrap() .unwrap()
.as_deref()
); );
// Uncomment this line to keep the temporary file after the program exists. // Uncomment this line to keep the temporary file after the program exists.
// download_buffer.set_property("temp-remove", &false).ok(); // download_buffer.set_property("temp-remove", &false).ok();