// Copyright (C) 2016-2017 Sebastian Dröge // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. use gst_sys; use miniobject::*; use structure::*; use GenericFormattedValue; use std::ffi::CStr; use std::fmt; use std::mem; use std::ops::{Deref, DerefMut}; use std::ptr; use glib; use glib::translate::*; use glib_sys; gst_define_mini_object_wrapper!(Query, QueryRef, gst_sys::GstQuery, [Debug,], || { gst_sys::gst_query_get_type() }); impl Query { pub fn new_position(fmt: ::Format) -> Position { assert_initialized_main_thread!(); unsafe { Position::(from_glib_full(gst_sys::gst_query_new_position( fmt.to_glib(), ))) } } pub fn new_duration(fmt: ::Format) -> Duration { assert_initialized_main_thread!(); unsafe { Duration::(from_glib_full(gst_sys::gst_query_new_duration( fmt.to_glib(), ))) } } pub fn new_latency() -> Latency { assert_initialized_main_thread!(); unsafe { Latency::(from_glib_full(gst_sys::gst_query_new_latency())) } } pub fn new_seeking(fmt: ::Format) -> Seeking { assert_initialized_main_thread!(); unsafe { Seeking::(from_glib_full(gst_sys::gst_query_new_seeking( fmt.to_glib(), ))) } } pub fn new_segment(fmt: ::Format) -> Segment { assert_initialized_main_thread!(); unsafe { Segment::(from_glib_full(gst_sys::gst_query_new_segment( fmt.to_glib(), ))) } } pub fn new_convert>( value: V, dest_fmt: ::Format, ) -> Convert { assert_initialized_main_thread!(); let value = value.into(); unsafe { Convert::(from_glib_full(gst_sys::gst_query_new_convert( value.get_format().to_glib(), value.get_value(), dest_fmt.to_glib(), ))) } } pub fn new_formats() -> Formats { assert_initialized_main_thread!(); unsafe { Formats::(from_glib_full(gst_sys::gst_query_new_formats())) } } pub fn new_buffering(fmt: ::Format) -> Buffering { assert_initialized_main_thread!(); unsafe { Buffering::(from_glib_full(gst_sys::gst_query_new_buffering( fmt.to_glib(), ))) } } pub fn new_custom(structure: ::Structure) -> Custom { assert_initialized_main_thread!(); unsafe { Custom::(from_glib_full(gst_sys::gst_query_new_custom( gst_sys::GST_QUERY_CUSTOM, structure.into_ptr(), ))) } } pub fn new_uri() -> Uri { assert_initialized_main_thread!(); unsafe { Uri::(from_glib_full(gst_sys::gst_query_new_uri())) } } pub fn new_allocation(caps: &::Caps, need_pool: bool) -> Allocation { assert_initialized_main_thread!(); unsafe { Allocation::(from_glib_full(gst_sys::gst_query_new_allocation( caps.as_mut_ptr(), need_pool.to_glib(), ))) } } pub fn new_scheduling() -> Scheduling { assert_initialized_main_thread!(); unsafe { Scheduling::(from_glib_full(gst_sys::gst_query_new_scheduling())) } } pub fn new_accept_caps(caps: &::Caps) -> AcceptCaps { assert_initialized_main_thread!(); unsafe { AcceptCaps::(from_glib_full(gst_sys::gst_query_new_accept_caps( caps.as_mut_ptr(), ))) } } pub fn new_caps(filter: Option<&::Caps>) -> Caps { assert_initialized_main_thread!(); unsafe { Caps::(from_glib_full(gst_sys::gst_query_new_caps( filter.to_glib_none().0, ))) } } pub fn new_drain() -> Drain { assert_initialized_main_thread!(); unsafe { Drain::(from_glib_full(gst_sys::gst_query_new_drain())) } } pub fn new_context(context_type: &str) -> Context { assert_initialized_main_thread!(); unsafe { Context::(from_glib_full(gst_sys::gst_query_new_context( context_type.to_glib_none().0, ))) } } #[cfg(any(feature = "v1_16", feature = "dox"))] pub fn new_bitrate() -> Bitrate { assert_initialized_main_thread!(); unsafe { Bitrate::(from_glib_full(gst_sys::gst_query_new_bitrate())) } } } impl QueryRef { pub fn get_structure(&self) -> Option<&StructureRef> { unsafe { let structure = gst_sys::gst_query_get_structure(self.as_mut_ptr()); if structure.is_null() { None } else { Some(StructureRef::from_glib_borrow(structure)) } } } pub fn get_mut_structure(&mut self) -> &mut StructureRef { unsafe { let structure = gst_sys::gst_query_writable_structure(self.as_mut_ptr()); StructureRef::from_glib_borrow_mut(structure) } } pub fn is_downstream(&self) -> bool { unsafe { ((*self.as_ptr()).type_ as u32) & gst_sys::GST_QUERY_TYPE_DOWNSTREAM != 0 } } pub fn is_upstream(&self) -> bool { unsafe { ((*self.as_ptr()).type_ as u32) & gst_sys::GST_QUERY_TYPE_UPSTREAM != 0 } } pub fn is_serialized(&self) -> bool { unsafe { ((*self.as_ptr()).type_ as u32) & gst_sys::GST_QUERY_TYPE_SERIALIZED != 0 } } pub fn view(&self) -> QueryView<&Self> { let type_ = unsafe { (*self.as_ptr()).type_ }; match type_ { gst_sys::GST_QUERY_POSITION => QueryView::Position(Position(self)), gst_sys::GST_QUERY_DURATION => QueryView::Duration(Duration(self)), gst_sys::GST_QUERY_LATENCY => QueryView::Latency(Latency(self)), gst_sys::GST_QUERY_JITTER => QueryView::Jitter(Jitter(self)), gst_sys::GST_QUERY_RATE => QueryView::Rate(Rate(self)), gst_sys::GST_QUERY_SEEKING => QueryView::Seeking(Seeking(self)), gst_sys::GST_QUERY_SEGMENT => QueryView::Segment(Segment(self)), gst_sys::GST_QUERY_CONVERT => QueryView::Convert(Convert(self)), gst_sys::GST_QUERY_FORMATS => QueryView::Formats(Formats(self)), gst_sys::GST_QUERY_BUFFERING => QueryView::Buffering(Buffering(self)), gst_sys::GST_QUERY_CUSTOM => QueryView::Custom(Custom(self)), gst_sys::GST_QUERY_URI => QueryView::Uri(Uri(self)), gst_sys::GST_QUERY_ALLOCATION => QueryView::Allocation(Allocation(self)), gst_sys::GST_QUERY_SCHEDULING => QueryView::Scheduling(Scheduling(self)), gst_sys::GST_QUERY_ACCEPT_CAPS => QueryView::AcceptCaps(AcceptCaps(self)), gst_sys::GST_QUERY_CAPS => QueryView::Caps(Caps(self)), gst_sys::GST_QUERY_DRAIN => QueryView::Drain(Drain(self)), gst_sys::GST_QUERY_CONTEXT => QueryView::Context(Context(self)), gst_sys::GST_QUERY_BITRATE => QueryView::Bitrate(Bitrate(self)), _ => QueryView::Other(Other(self)), } } pub fn view_mut(&mut self) -> QueryView<&mut Self> { unsafe { mem::transmute(self.view()) } } } impl fmt::Debug for QueryRef { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("Query") .field("ptr", unsafe { &self.as_ptr() }) .field("type", &unsafe { let type_ = gst_sys::gst_query_type_get_name((*self.as_ptr()).type_); CStr::from_ptr(type_).to_str().unwrap() }) .field("structure", &self.get_structure()) .finish() } } pub unsafe trait AsPtr { unsafe fn as_ptr(&self) -> *mut gst_sys::GstQuery; } pub unsafe trait AsMutPtr: AsPtr { unsafe fn as_mut_ptr(&self) -> *mut gst_sys::GstQuery; } unsafe impl AsPtr for Query { unsafe fn as_ptr(&self) -> *mut gst_sys::GstQuery { self.as_ref().as_ptr() as *mut gst_sys::GstQuery } } unsafe impl AsMutPtr for Query { unsafe fn as_mut_ptr(&self) -> *mut gst_sys::GstQuery { self.as_ref().as_mut_ptr() } } unsafe impl<'a> AsPtr for &'a QueryRef { unsafe fn as_ptr(&self) -> *mut gst_sys::GstQuery { MiniObject::as_ptr(self as &QueryRef) as *mut gst_sys::GstQuery } } unsafe impl<'a> AsPtr for &'a mut QueryRef { unsafe fn as_ptr(&self) -> *mut gst_sys::GstQuery { MiniObject::as_ptr(self as &QueryRef) as *mut gst_sys::GstQuery } } unsafe impl<'a> AsMutPtr for &'a mut QueryRef { unsafe fn as_mut_ptr(&self) -> *mut gst_sys::GstQuery { MiniObject::as_mut_ptr(self as &QueryRef) as *mut gst_sys::GstQuery } } #[derive(Debug)] pub enum QueryView { Position(Position), Duration(Duration), Latency(Latency), Jitter(Jitter), Rate(Rate), Seeking(Seeking), Segment(Segment), Convert(Convert), Formats(Formats), Buffering(Buffering), Custom(Custom), Uri(Uri), Allocation(Allocation), Scheduling(Scheduling), AcceptCaps(AcceptCaps), Caps(Caps), Drain(Drain), Context(Context), Bitrate(Bitrate), Other(Other), __NonExhaustive, } macro_rules! declare_concrete_query( ($name:ident, $param:ident) => { #[derive(Debug)] pub struct $name<$param>($param); impl<'a> $name<&'a QueryRef> { pub fn get_query(&self) -> &QueryRef { self.0 } } impl<'a> Deref for $name<&'a QueryRef> { type Target = QueryRef; fn deref(&self) -> &Self::Target { self.0 } } impl<'a> Deref for $name<&'a mut QueryRef> { type Target = $name<&'a QueryRef>; fn deref(&self) -> &Self::Target { unsafe { &*(self as *const $name<&'a mut QueryRef> as *const $name<&'a QueryRef>) } } } impl<'a> $name<&'a mut QueryRef> { pub fn get_mut_query(&mut self) -> &mut QueryRef { self.0 } } impl Deref for $name { type Target = QueryRef; fn deref(&self) -> &Self::Target { &self.0 } } impl DerefMut for $name { fn deref_mut(&mut self) -> &mut Self::Target { self.0.get_mut().unwrap() } } impl From<$name> for Query { fn from(concrete: $name) -> Self { unsafe { from_glib_none(concrete.0.as_mut_ptr()) } } } } ); declare_concrete_query!(Position, T); impl Position { pub fn get_result(&self) -> GenericFormattedValue { unsafe { let mut fmt = mem::uninitialized(); let mut pos = mem::uninitialized(); gst_sys::gst_query_parse_position(self.0.as_ptr(), &mut fmt, &mut pos); GenericFormattedValue::new(from_glib(fmt), pos) } } pub fn get_format(&self) -> ::Format { unsafe { let mut fmt = mem::uninitialized(); gst_sys::gst_query_parse_position(self.0.as_ptr(), &mut fmt, ptr::null_mut()); from_glib(fmt) } } } impl Position { pub fn set>(&mut self, pos: V) { let pos = pos.into(); assert_eq!(pos.get_format(), self.get_format()); unsafe { gst_sys::gst_query_set_position( self.0.as_mut_ptr(), pos.get_format().to_glib(), pos.get_value(), ); } } } declare_concrete_query!(Duration, T); impl Duration { pub fn get_result(&self) -> GenericFormattedValue { unsafe { let mut fmt = mem::uninitialized(); let mut pos = mem::uninitialized(); gst_sys::gst_query_parse_duration(self.0.as_ptr(), &mut fmt, &mut pos); GenericFormattedValue::new(from_glib(fmt), pos) } } pub fn get_format(&self) -> ::Format { unsafe { let mut fmt = mem::uninitialized(); gst_sys::gst_query_parse_duration(self.0.as_ptr(), &mut fmt, ptr::null_mut()); from_glib(fmt) } } } impl Duration { pub fn set>(&mut self, dur: V) { let dur = dur.into(); assert_eq!(dur.get_format(), self.get_format()); unsafe { gst_sys::gst_query_set_duration( self.0.as_mut_ptr(), dur.get_format().to_glib(), dur.get_value(), ); } } } declare_concrete_query!(Latency, T); impl Latency { pub fn get_result(&self) -> (bool, ::ClockTime, ::ClockTime) { unsafe { let mut live = mem::uninitialized(); let mut min = mem::uninitialized(); let mut max = mem::uninitialized(); gst_sys::gst_query_parse_latency(self.0.as_ptr(), &mut live, &mut min, &mut max); (from_glib(live), from_glib(min), from_glib(max)) } } } impl Latency { pub fn set(&mut self, live: bool, min: ::ClockTime, max: ::ClockTime) { unsafe { gst_sys::gst_query_set_latency( self.0.as_mut_ptr(), live.to_glib(), min.to_glib(), max.to_glib(), ); } } } declare_concrete_query!(Jitter, T); declare_concrete_query!(Rate, T); declare_concrete_query!(Seeking, T); impl Seeking { pub fn get_result(&self) -> (bool, GenericFormattedValue, GenericFormattedValue) { unsafe { let mut fmt = mem::uninitialized(); let mut seekable = mem::uninitialized(); let mut start = mem::uninitialized(); let mut end = mem::uninitialized(); gst_sys::gst_query_parse_seeking( self.0.as_ptr(), &mut fmt, &mut seekable, &mut start, &mut end, ); ( from_glib(seekable), GenericFormattedValue::new(from_glib(fmt), start), GenericFormattedValue::new(from_glib(fmt), end), ) } } pub fn get_format(&self) -> ::Format { unsafe { let mut fmt = mem::uninitialized(); gst_sys::gst_query_parse_seeking( self.0.as_ptr(), &mut fmt, ptr::null_mut(), ptr::null_mut(), ptr::null_mut(), ); from_glib(fmt) } } } impl Seeking { pub fn set>(&mut self, seekable: bool, start: V, end: V) { let start = start.into(); let end = end.into(); assert_eq!(self.get_format(), start.get_format()); assert_eq!(start.get_format(), end.get_format()); unsafe { gst_sys::gst_query_set_seeking( self.0.as_mut_ptr(), start.get_format().to_glib(), seekable.to_glib(), start.get_value(), end.get_value(), ); } } } declare_concrete_query!(Segment, T); impl Segment { pub fn get_result(&self) -> (f64, GenericFormattedValue, GenericFormattedValue) { unsafe { let mut rate = mem::uninitialized(); let mut fmt = mem::uninitialized(); let mut start = mem::uninitialized(); let mut stop = mem::uninitialized(); gst_sys::gst_query_parse_segment( self.0.as_ptr(), &mut rate, &mut fmt, &mut start, &mut stop, ); ( rate, GenericFormattedValue::new(from_glib(fmt), start), GenericFormattedValue::new(from_glib(fmt), stop), ) } } pub fn get_format(&self) -> ::Format { unsafe { let mut fmt = mem::uninitialized(); gst_sys::gst_query_parse_segment( self.0.as_ptr(), ptr::null_mut(), &mut fmt, ptr::null_mut(), ptr::null_mut(), ); from_glib(fmt) } } } impl Segment { pub fn set>(&mut self, rate: f64, start: V, stop: V) { let start = start.into(); let stop = stop.into(); assert_eq!(start.get_format(), stop.get_format()); unsafe { gst_sys::gst_query_set_segment( self.0.as_mut_ptr(), rate, start.get_format().to_glib(), start.get_value(), stop.get_value(), ); } } } declare_concrete_query!(Convert, T); impl Convert { pub fn get_result(&self) -> (GenericFormattedValue, GenericFormattedValue) { unsafe { let mut src_fmt = mem::uninitialized(); let mut src = mem::uninitialized(); let mut dest_fmt = mem::uninitialized(); let mut dest = mem::uninitialized(); gst_sys::gst_query_parse_convert( self.0.as_ptr(), &mut src_fmt, &mut src, &mut dest_fmt, &mut dest, ); ( GenericFormattedValue::new(from_glib(src_fmt), src), GenericFormattedValue::new(from_glib(dest_fmt), dest), ) } } pub fn get(&self) -> (GenericFormattedValue, ::Format) { unsafe { let mut src_fmt = mem::uninitialized(); let mut src = mem::uninitialized(); let mut dest_fmt = mem::uninitialized(); gst_sys::gst_query_parse_convert( self.0.as_ptr(), &mut src_fmt, &mut src, &mut dest_fmt, ptr::null_mut(), ); ( GenericFormattedValue::new(from_glib(src_fmt), src), from_glib(dest_fmt), ) } } } impl Convert { pub fn set>(&mut self, src: V, dest: V) { let src = src.into(); let dest = dest.into(); unsafe { gst_sys::gst_query_set_convert( self.0.as_mut_ptr(), src.get_format().to_glib(), src.get_value(), dest.get_format().to_glib(), dest.get_value(), ); } } } declare_concrete_query!(Formats, T); impl Formats { pub fn get_result(&self) -> Vec<::Format> { unsafe { let mut n = mem::uninitialized(); gst_sys::gst_query_parse_n_formats(self.0.as_ptr(), &mut n); let mut res = Vec::with_capacity(n as usize); for i in 0..n { let mut fmt = mem::uninitialized(); gst_sys::gst_query_parse_nth_format(self.0.as_ptr(), i, &mut fmt); res.push(from_glib(fmt)); } res } } } impl Formats { pub fn set(&mut self, formats: &[::Format]) { unsafe { let v: Vec<_> = formats.iter().map(|f| f.to_glib()).collect(); gst_sys::gst_query_set_formatsv( self.0.as_mut_ptr(), v.len() as i32, v.as_ptr() as *mut _, ); } } } declare_concrete_query!(Buffering, T); impl Buffering { pub fn get_format(&self) -> ::Format { unsafe { let mut fmt = mem::uninitialized(); gst_sys::gst_query_parse_buffering_range( self.0.as_ptr(), &mut fmt, ptr::null_mut(), ptr::null_mut(), ptr::null_mut(), ); from_glib(fmt) } } pub fn get_percent(&self) -> (bool, i32) { unsafe { let mut busy = mem::uninitialized(); let mut percent = mem::uninitialized(); gst_sys::gst_query_parse_buffering_percent(self.0.as_ptr(), &mut busy, &mut percent); (from_glib(busy), percent) } } pub fn get_range(&self) -> (GenericFormattedValue, GenericFormattedValue, i64) { unsafe { let mut fmt = mem::uninitialized(); let mut start = mem::uninitialized(); let mut stop = mem::uninitialized(); let mut estimated_total = mem::uninitialized(); gst_sys::gst_query_parse_buffering_range( self.0.as_ptr(), &mut fmt, &mut start, &mut stop, &mut estimated_total, ); ( GenericFormattedValue::new(from_glib(fmt), start), GenericFormattedValue::new(from_glib(fmt), stop), estimated_total, ) } } pub fn get_stats(&self) -> (::BufferingMode, i32, i32, i64) { unsafe { let mut mode = mem::uninitialized(); let mut avg_in = mem::uninitialized(); let mut avg_out = mem::uninitialized(); let mut buffering_left = mem::uninitialized(); gst_sys::gst_query_parse_buffering_stats( self.0.as_ptr(), &mut mode, &mut avg_in, &mut avg_out, &mut buffering_left, ); (from_glib(mode), avg_in, avg_out, buffering_left) } } pub fn get_ranges(&self) -> Vec<(GenericFormattedValue, GenericFormattedValue)> { unsafe { let mut fmt = mem::uninitialized(); gst_sys::gst_query_parse_buffering_range( self.0.as_ptr(), &mut fmt, ptr::null_mut(), ptr::null_mut(), ptr::null_mut(), ); let fmt = from_glib(fmt); let n = gst_sys::gst_query_get_n_buffering_ranges(self.0.as_ptr()); let mut res = Vec::with_capacity(n as usize); for i in 0..n { let mut start = mem::uninitialized(); let mut stop = mem::uninitialized(); let s: bool = from_glib(gst_sys::gst_query_parse_nth_buffering_range( self.0.as_ptr(), i, &mut start, &mut stop, )); if s { res.push(( GenericFormattedValue::new(fmt, start), GenericFormattedValue::new(fmt, stop), )); } } res } } } impl Buffering { pub fn set_percent(&mut self, busy: bool, percent: i32) { unsafe { gst_sys::gst_query_set_buffering_percent(self.0.as_mut_ptr(), busy.to_glib(), percent); } } pub fn set_range>( &mut self, start: V, stop: V, estimated_total: i64, ) { let start = start.into(); let stop = stop.into(); assert_eq!(self.get_format(), start.get_format()); assert_eq!(start.get_format(), stop.get_format()); unsafe { gst_sys::gst_query_set_buffering_range( self.0.as_mut_ptr(), start.get_format().to_glib(), start.get_value(), stop.get_value(), estimated_total, ); } } pub fn set_stats( &mut self, mode: ::BufferingMode, avg_in: i32, avg_out: i32, buffering_left: i64, ) { skip_assert_initialized!(); unsafe { gst_sys::gst_query_set_buffering_stats( self.0.as_mut_ptr(), mode.to_glib(), avg_in, avg_out, buffering_left, ); } } pub fn add_buffering_ranges + Copy>( &mut self, ranges: &[(V, V)], ) { unsafe { let fmt = self.get_format(); for &(start, stop) in ranges { let start = start.into(); let stop = stop.into(); assert_eq!(start.get_format(), fmt); assert_eq!(stop.get_format(), fmt); gst_sys::gst_query_add_buffering_range( self.0.as_mut_ptr(), start.get_value(), stop.get_value(), ); } } } } declare_concrete_query!(Custom, T); declare_concrete_query!(Uri, T); impl Uri { pub fn get_uri(&self) -> Option { unsafe { let mut uri = ptr::null_mut(); gst_sys::gst_query_parse_uri(self.0.as_ptr(), &mut uri); from_glib_full(uri) } } pub fn get_redirection(&self) -> (Option, bool) { unsafe { let mut uri = ptr::null_mut(); gst_sys::gst_query_parse_uri_redirection(self.0.as_ptr(), &mut uri); let mut permanent = mem::uninitialized(); gst_sys::gst_query_parse_uri_redirection_permanent(self.0.as_ptr(), &mut permanent); (from_glib_full(uri), from_glib(permanent)) } } } impl Uri { pub fn set_uri<'b, U: Into<&'b str>>(&mut self, uri: U) { let uri = uri.into(); unsafe { gst_sys::gst_query_set_uri(self.0.as_mut_ptr(), uri.to_glib_none().0); } } pub fn set_redirection<'b, U: Into<&'b str>>(&mut self, uri: U, permanent: bool) { let uri = uri.into(); unsafe { gst_sys::gst_query_set_uri_redirection(self.0.as_mut_ptr(), uri.to_glib_none().0); gst_sys::gst_query_set_uri_redirection_permanent( self.0.as_mut_ptr(), permanent.to_glib(), ); } } } declare_concrete_query!(Allocation, T); impl Allocation { pub fn get(&self) -> (&::CapsRef, bool) { unsafe { let mut caps = ptr::null_mut(); let mut need_pool = 0; gst_sys::gst_query_parse_allocation(self.0.as_ptr(), &mut caps, &mut need_pool); (::CapsRef::from_ptr(caps), from_glib(need_pool)) } } pub fn get_owned(&self) -> (::Caps, bool) { unsafe { let (caps, need_pool) = self.get(); (from_glib_none(caps.as_ptr()), need_pool) } } pub fn get_allocation_pools(&self) -> Vec<(Option<::BufferPool>, u32, u32, u32)> { unsafe { let n = gst_sys::gst_query_get_n_allocation_pools(self.0.as_ptr()); let mut pools = Vec::with_capacity(n as usize); for i in 0..n { let mut pool = ptr::null_mut(); let mut size = 0; let mut min_buffers = 0; let mut max_buffers = 0; gst_sys::gst_query_parse_nth_allocation_pool( self.0.as_ptr(), i, &mut pool, &mut size, &mut min_buffers, &mut max_buffers, ); pools.push((from_glib_full(pool), size, min_buffers, max_buffers)); } pools } } pub fn get_allocation_metas(&self) -> Vec<(glib::Type, Option<&::StructureRef>)> { unsafe { let n = gst_sys::gst_query_get_n_allocation_metas(self.0.as_ptr()); let mut metas = Vec::with_capacity(n as usize); for i in 0..n { let mut structure = ptr::null(); let api = gst_sys::gst_query_parse_nth_allocation_meta( self.0.as_ptr(), i, &mut structure, ); metas.push(( from_glib(api), if structure.is_null() { None } else { Some(::StructureRef::from_glib_borrow(structure)) }, )); } metas } } pub fn find_allocation_meta(&self) -> Option { unsafe { let mut idx = 0; if gst_sys::gst_query_find_allocation_meta( self.0.as_ptr(), U::get_meta_api().to_glib(), &mut idx, ) != glib_sys::GFALSE { Some(idx) } else { None } } } } impl Allocation { pub fn add_allocation_pool( &mut self, pool: Option<&::BufferPool>, size: u32, min_buffers: u32, max_buffers: u32, ) { unsafe { gst_sys::gst_query_add_allocation_pool( self.0.as_mut_ptr(), pool.to_glib_none().0, size, min_buffers, max_buffers, ); } } pub fn set_nth_allocation_pool( &mut self, idx: u32, pool: Option<&::BufferPool>, size: u32, min_buffers: u32, max_buffers: u32, ) { unsafe { gst_sys::gst_query_set_nth_allocation_pool( self.0.as_mut_ptr(), idx, pool.to_glib_none().0, size, min_buffers, max_buffers, ); } } pub fn remove_nth_allocation_pool(&mut self, idx: u32) { unsafe { gst_sys::gst_query_remove_nth_allocation_pool(self.0.as_mut_ptr(), idx); } } pub fn add_allocation_meta(&mut self, structure: Option<&::StructureRef>) { unsafe { gst_sys::gst_query_add_allocation_meta( self.0.as_mut_ptr(), U::get_meta_api().to_glib(), if let Some(structure) = structure { structure.as_ptr() } else { ptr::null() }, ); } } pub fn remove_nth_allocation_meta(&mut self, idx: u32) { unsafe { gst_sys::gst_query_remove_nth_allocation_meta(self.0.as_mut_ptr(), idx); } } } declare_concrete_query!(Scheduling, T); impl Scheduling { pub fn has_scheduling_mode(&self, mode: ::PadMode) -> bool { unsafe { from_glib(gst_sys::gst_query_has_scheduling_mode( self.0.as_ptr(), mode.to_glib(), )) } } pub fn has_scheduling_mode_with_flags( &self, mode: ::PadMode, flags: ::SchedulingFlags, ) -> bool { skip_assert_initialized!(); unsafe { from_glib(gst_sys::gst_query_has_scheduling_mode_with_flags( self.0.as_ptr(), mode.to_glib(), flags.to_glib(), )) } } pub fn get_scheduling_modes(&self) -> Vec<::PadMode> { unsafe { let n = gst_sys::gst_query_get_n_scheduling_modes(self.0.as_ptr()); let mut res = Vec::with_capacity(n as usize); for i in 0..n { res.push(from_glib(gst_sys::gst_query_parse_nth_scheduling_mode( self.0.as_ptr(), i, ))); } res } } pub fn get_result(&self) -> (::SchedulingFlags, i32, i32, i32) { unsafe { let mut flags = mem::uninitialized(); let mut minsize = mem::uninitialized(); let mut maxsize = mem::uninitialized(); let mut align = mem::uninitialized(); gst_sys::gst_query_parse_scheduling( self.0.as_ptr(), &mut flags, &mut minsize, &mut maxsize, &mut align, ); (from_glib(flags), minsize, maxsize, align) } } } impl Scheduling { pub fn add_scheduling_modes(&mut self, modes: &[::PadMode]) { unsafe { for mode in modes { gst_sys::gst_query_add_scheduling_mode(self.0.as_mut_ptr(), mode.to_glib()); } } } pub fn set(&mut self, flags: ::SchedulingFlags, minsize: i32, maxsize: i32, align: i32) { unsafe { gst_sys::gst_query_set_scheduling( self.0.as_mut_ptr(), flags.to_glib(), minsize, maxsize, align, ); } } } declare_concrete_query!(AcceptCaps, T); impl AcceptCaps { pub fn get_caps(&self) -> &::CapsRef { unsafe { let mut caps = ptr::null_mut(); gst_sys::gst_query_parse_accept_caps(self.0.as_ptr(), &mut caps); ::CapsRef::from_ptr(caps) } } pub fn get_caps_owned(&self) -> ::Caps { unsafe { from_glib_none(self.get_caps().as_ptr()) } } pub fn get_result(&self) -> bool { unsafe { let mut accepted = mem::uninitialized(); gst_sys::gst_query_parse_accept_caps_result(self.0.as_ptr(), &mut accepted); from_glib(accepted) } } } impl AcceptCaps { pub fn set_result(&mut self, accepted: bool) { unsafe { gst_sys::gst_query_set_accept_caps_result(self.0.as_mut_ptr(), accepted.to_glib()); } } } declare_concrete_query!(Caps, T); impl Caps { pub fn get_filter(&self) -> Option<&::CapsRef> { unsafe { let mut caps = ptr::null_mut(); gst_sys::gst_query_parse_caps(self.0.as_ptr(), &mut caps); if caps.is_null() { None } else { Some(::CapsRef::from_ptr(caps)) } } } pub fn get_filter_owned(&self) -> Option<::Caps> { unsafe { self.get_filter().map(|caps| from_glib_none(caps.as_ptr())) } } pub fn get_result(&self) -> Option<&::CapsRef> { unsafe { let mut caps = ptr::null_mut(); gst_sys::gst_query_parse_caps_result(self.0.as_ptr(), &mut caps); if caps.is_null() { None } else { Some(::CapsRef::from_ptr(caps)) } } } pub fn get_result_owned(&self) -> Option<::Caps> { unsafe { self.get_result().map(|caps| from_glib_none(caps.as_ptr())) } } } impl Caps { pub fn set_result(&mut self, caps: &::Caps) { unsafe { gst_sys::gst_query_set_caps_result(self.0.as_mut_ptr(), caps.as_mut_ptr()); } } } declare_concrete_query!(Drain, T); declare_concrete_query!(Context, T); impl Context { pub fn get_context(&self) -> Option<&::ContextRef> { unsafe { let mut context = ptr::null_mut(); gst_sys::gst_query_parse_context(self.0.as_ptr(), &mut context); if context.is_null() { None } else { Some(::ContextRef::from_ptr(context)) } } } pub fn get_context_owned(&self) -> Option<::Context> { unsafe { self.get_context() .map(|context| from_glib_none(context.as_ptr())) } } pub fn get_context_type(&self) -> &str { unsafe { let mut context_type = ptr::null(); gst_sys::gst_query_parse_context_type(self.0.as_ptr(), &mut context_type); CStr::from_ptr(context_type).to_str().unwrap() } } } impl Context { pub fn set_context(&mut self, context: &::Context) { unsafe { gst_sys::gst_query_set_context(self.0.as_mut_ptr(), context.as_mut_ptr()); } } } declare_concrete_query!(Bitrate, T); impl Bitrate { #[cfg(any(feature = "v1_16", feature = "dox"))] pub fn get_bitrate(&self) -> u32 { unsafe { let mut bitrate = 0; gst_sys::gst_query_parse_bitrate(self.0.as_ptr(), &mut bitrate); bitrate } } } impl Bitrate { #[cfg(any(feature = "v1_16", feature = "dox"))] pub fn set_bitrate(&mut self, bitrate: u32) { unsafe { gst_sys::gst_query_set_bitrate(self.0.as_mut_ptr(), bitrate); } } } declare_concrete_query!(Other, T); #[cfg(test)] mod tests { use super::*; use std::convert::TryInto; #[test] fn test_writability() { ::init().unwrap(); fn check_mut(query: &mut QueryRef) { match query.view_mut() { QueryView::Position(ref mut p) => { let pos = p.get_result(); assert_eq!(pos.try_into(), Ok(::CLOCK_TIME_NONE)); p.set(3 * ::SECOND); let pos = p.get_result(); assert_eq!(pos.try_into(), Ok(3 * ::SECOND)); } _ => panic!("Wrong concrete Query in Query"), } } fn check_ref(query: &QueryRef) { match query.view() { QueryView::Position(ref p) => { let pos = p.get_result(); assert_eq!(pos.try_into(), Ok(3 * ::SECOND)); unsafe { assert!(!p.as_mut_ptr().is_null()); } } _ => panic!("Wrong concrete Query in Query"), } } let mut p = Query::new_position(::Format::Time); let pos = p.get_result(); assert_eq!(pos.try_into(), Ok(::CLOCK_TIME_NONE)); p.get_mut_structure().set("check_mut", &true); // deref assert!(!p.is_serialized()); { check_mut(&mut p); let structure = p.get_structure(); structure.unwrap().has_field("check_mut"); // Expected: cannot borrow `p` as mutable because it is also borrowed as immutable //check_mut(&mut p); } check_ref(&p); } #[test] fn test_into_query() { ::init().unwrap(); let d = Query::new_duration(::Format::Time); let mut query: Query = d.into(); assert!(query.is_writable()); let query = query.make_mut(); match query.view_mut() { QueryView::Duration(ref mut d) => { d.set(2 * ::SECOND); } _ => (), } match query.view() { QueryView::Duration(ref d) => { let duration = d.get_result(); assert_eq!(duration.try_into(), Ok(2 * ::SECOND)); } _ => (), } } #[test] fn test_concrete_to_sys() { ::init().unwrap(); let p = Query::new_position(::Format::Time); unsafe { assert!(!p.as_mut_ptr().is_null()); } } }