Query: allow concrete query instantiation

Allow instantiating and dereferencing concrete queries. The motivation
for this proposal is to allow the following usability enhancements:

- Concrete queries mutability guaranteed by the borrow checker,
including for generic functions:
``` rust
    let mut p = Query::new_position(::Format::Time);
    p.get_mut_structure().set("check_mut", &true);
```

- Concrete queries functions available in place:
``` rust
    let mut q = gst::Query::new_duration(gst::Format::Time);
    let duration = if pipeline.query(&mut q) {
        Some(q.get_result())
    } else {
        None
    };
```
This commit is contained in:
François Laignel 2018-02-15 15:05:51 +01:00 committed by Sebastian Dröge
parent b4d5c98834
commit c971727193
3 changed files with 330 additions and 185 deletions

View file

@ -25,19 +25,14 @@ fn example_main() {
let pipeline_clone = pipeline.clone(); let pipeline_clone = pipeline.clone();
glib::timeout_add_seconds(1, move || { glib::timeout_add_seconds(1, move || {
use gst::QueryView;
let pipeline = &pipeline_clone; let pipeline = &pipeline_clone;
//let pos = pipeline.query_position(gst::Format::Time).unwrap_or(-1); //let pos = pipeline.query_position(gst::Format::Time).unwrap_or(-1);
//let dur = pipeline.query_duration(gst::Format::Time).unwrap_or(-1); //let dur = pipeline.query_duration(gst::Format::Time).unwrap_or(-1);
let pos = { let pos = {
let mut q = gst::Query::new_position(gst::Format::Time); let mut q = gst::Query::new_position(gst::Format::Time);
if pipeline.query(q.get_mut().unwrap()) { if pipeline.query(&mut q) {
match q.view() { Some(q.get_result())
QueryView::Position(ref p) => Some(p.get_result()),
_ => None,
}
} else { } else {
None None
} }
@ -46,11 +41,8 @@ fn example_main() {
let dur = { let dur = {
let mut q = gst::Query::new_duration(gst::Format::Time); let mut q = gst::Query::new_duration(gst::Format::Time);
if pipeline.query(q.get_mut().unwrap()) { if pipeline.query(&mut q) {
match q.view() { Some(q.get_result())
QueryView::Duration(ref p) => Some(p.get_result()),
_ => None,
}
} else { } else {
None None
} }

View file

@ -15,10 +15,10 @@ use std::ptr;
use std::mem; use std::mem;
use std::fmt; use std::fmt;
use std::ffi::CStr; use std::ffi::CStr;
use std::ops::Deref; use std::ops::{Deref, DerefMut};
use glib; use glib;
use glib::translate::{from_glib, from_glib_full, ToGlib, ToGlibPtr}; use glib::translate::*;
#[repr(C)] #[repr(C)]
pub struct QueryRef(ffi::GstQuery); pub struct QueryRef(ffi::GstQuery);
@ -33,92 +33,151 @@ unsafe impl MiniObject for QueryRef {
} }
impl GstRc<QueryRef> { impl GstRc<QueryRef> {
pub fn new_position(fmt: ::Format) -> Self { pub fn new_position(fmt: ::Format) -> Position<Self> {
assert_initialized_main_thread!(); assert_initialized_main_thread!();
unsafe { from_glib_full(ffi::gst_query_new_position(fmt.to_glib())) } unsafe {
Position::<Self>(
from_glib_full(ffi::gst_query_new_position(fmt.to_glib()))
)
}
} }
pub fn new_duration(fmt: ::Format) -> Self { pub fn new_duration(fmt: ::Format) -> Duration<Self> {
assert_initialized_main_thread!(); assert_initialized_main_thread!();
unsafe { from_glib_full(ffi::gst_query_new_duration(fmt.to_glib())) } unsafe {
Duration::<Self>(
from_glib_full(ffi::gst_query_new_duration(fmt.to_glib()))
)
}
} }
pub fn new_latency() -> Self { pub fn new_latency() -> Latency<Self> {
assert_initialized_main_thread!(); assert_initialized_main_thread!();
unsafe { from_glib_full(ffi::gst_query_new_latency()) } unsafe {
Latency::<Self>(
from_glib_full(ffi::gst_query_new_latency())
)
}
} }
pub fn new_seeking(fmt: ::Format) -> Self { pub fn new_seeking(fmt: ::Format) -> Seeking<Self> {
assert_initialized_main_thread!(); assert_initialized_main_thread!();
unsafe { from_glib_full(ffi::gst_query_new_seeking(fmt.to_glib())) } unsafe {
Seeking::<Self>(
from_glib_full(ffi::gst_query_new_seeking(fmt.to_glib()))
)
}
} }
pub fn new_segment(fmt: ::Format) -> Self { pub fn new_segment(fmt: ::Format) -> Segment<Self> {
assert_initialized_main_thread!(); assert_initialized_main_thread!();
unsafe { from_glib_full(ffi::gst_query_new_segment(fmt.to_glib())) } unsafe {
Segment::<Self>(
from_glib_full(ffi::gst_query_new_segment(fmt.to_glib()))
)
}
} }
pub fn new_convert<V: Into<GenericFormattedValue>>(value: V, dest_fmt: ::Format) -> Self { pub fn new_convert<V: Into<GenericFormattedValue>>(
value: V,
dest_fmt: ::Format
) -> Convert<Self> {
assert_initialized_main_thread!(); assert_initialized_main_thread!();
let value = value.into(); let value = value.into();
unsafe { unsafe {
from_glib_full(ffi::gst_query_new_convert( Convert::<Self>(
value.get_format().to_glib(), from_glib_full(ffi::gst_query_new_convert(
value.get_value(), value.get_format().to_glib(),
dest_fmt.to_glib(), value.get_value(),
)) dest_fmt.to_glib(),
))
)
} }
} }
pub fn new_formats() -> Self { pub fn new_formats() -> Formats<Self> {
assert_initialized_main_thread!();
unsafe { from_glib_full(ffi::gst_query_new_formats()) }
}
pub fn new_buffering(fmt: ::Format) -> Self {
assert_initialized_main_thread!();
unsafe { from_glib_full(ffi::gst_query_new_buffering(fmt.to_glib())) }
}
pub fn new_custom(structure: ::Structure) -> Self {
assert_initialized_main_thread!(); assert_initialized_main_thread!();
unsafe { unsafe {
from_glib_full(ffi::gst_query_new_custom( Formats::<Self>(
ffi::GST_QUERY_CUSTOM, from_glib_full(ffi::gst_query_new_formats())
structure.into_ptr(), )
))
} }
} }
pub fn new_uri() -> Self { pub fn new_buffering(fmt: ::Format) -> Buffering<Self> {
assert_initialized_main_thread!(); assert_initialized_main_thread!();
unsafe { from_glib_full(ffi::gst_query_new_uri()) } unsafe {
Buffering::<Self>(
from_glib_full(ffi::gst_query_new_buffering(fmt.to_glib()))
)
}
} }
pub fn new_scheduling() -> Self { pub fn new_custom(structure: ::Structure) -> Custom<Self> {
assert_initialized_main_thread!(); assert_initialized_main_thread!();
unsafe { from_glib_full(ffi::gst_query_new_scheduling()) } unsafe {
Custom::<Self>(
from_glib_full(ffi::gst_query_new_custom(
ffi::GST_QUERY_CUSTOM,
structure.into_ptr(),
))
)
}
} }
pub fn new_accept_caps(caps: &::Caps) -> Self { pub fn new_uri() -> Uri<Self> {
assert_initialized_main_thread!(); assert_initialized_main_thread!();
unsafe { from_glib_full(ffi::gst_query_new_accept_caps(caps.as_mut_ptr())) } unsafe {
Uri::<Self>(
from_glib_full(ffi::gst_query_new_uri())
)
}
} }
pub fn new_caps<'a, P: Into<Option<&'a ::Caps>>>(filter: P) -> Self { pub fn new_scheduling() -> Scheduling<Self> {
assert_initialized_main_thread!();
unsafe {
Scheduling::<Self>(
from_glib_full(ffi::gst_query_new_scheduling())
)
}
}
pub fn new_accept_caps(caps: &::Caps) -> AcceptCaps<Self> {
assert_initialized_main_thread!();
unsafe {
AcceptCaps::<Self>(
from_glib_full(ffi::gst_query_new_accept_caps(caps.as_mut_ptr()))
)
}
}
pub fn new_caps<'a, P: Into<Option<&'a ::Caps>>>(filter: P) -> Caps<Self> {
assert_initialized_main_thread!(); assert_initialized_main_thread!();
let filter = filter.into(); let filter = filter.into();
unsafe { from_glib_full(ffi::gst_query_new_caps(filter.to_glib_none().0)) } unsafe {
Caps::<Self>(
from_glib_full(ffi::gst_query_new_caps(filter.to_glib_none().0))
)
}
} }
pub fn new_drain() -> Self { pub fn new_drain() -> Drain<Self> {
assert_initialized_main_thread!(); assert_initialized_main_thread!();
unsafe { from_glib_full(ffi::gst_query_new_drain()) } unsafe {
Drain::<Self>(
from_glib_full(ffi::gst_query_new_drain())
)
}
} }
pub fn new_context(context_type: &str) -> Self { pub fn new_context(context_type: &str) -> Context<Self> {
assert_initialized_main_thread!(); assert_initialized_main_thread!();
unsafe { from_glib_full(ffi::gst_query_new_context(context_type.to_glib_none().0)) } unsafe {
Context::<Self>(
from_glib_full(ffi::gst_query_new_context(context_type.to_glib_none().0))
)
}
} }
} }
@ -208,17 +267,45 @@ impl fmt::Debug for QueryRef {
} }
} }
impl ToOwned for QueryRef { pub unsafe trait AsPtr {
type Owned = GstRc<QueryRef>; unsafe fn as_ptr(&self) -> *mut ffi::GstQuery;
}
fn to_owned(&self) -> GstRc<QueryRef> { pub unsafe trait AsMutPtr: AsPtr {
unsafe { unsafe fn as_mut_ptr(&self) -> *mut ffi::GstQuery;
from_glib_full(ffi::gst_mini_object_copy(self.as_ptr() as *const _) }
as *mut _)
} unsafe impl AsPtr for Query {
unsafe fn as_ptr(&self) -> *mut ffi::GstQuery {
self.as_ref().as_ptr() as *mut ffi::GstQuery
} }
} }
unsafe impl AsMutPtr for Query {
unsafe fn as_mut_ptr(&self) -> *mut ffi::GstQuery {
self.as_ref().as_mut_ptr()
}
}
unsafe impl<'a> AsPtr for &'a QueryRef {
unsafe fn as_ptr(&self) -> *mut ffi::GstQuery {
MiniObject::as_ptr(self as &QueryRef) as *mut ffi::GstQuery
}
}
unsafe impl<'a> AsPtr for &'a mut QueryRef {
unsafe fn as_ptr(&self) -> *mut ffi::GstQuery {
MiniObject::as_ptr(self as &QueryRef) as *mut ffi::GstQuery
}
}
unsafe impl<'a> AsMutPtr for &'a mut QueryRef {
unsafe fn as_mut_ptr(&self) -> *mut ffi::GstQuery {
MiniObject::as_mut_ptr(self as &QueryRef) as *mut ffi::GstQuery
}
}
#[derive(Debug)]
pub enum QueryView<T> { pub enum QueryView<T> {
Position(Position<T>), Position(Position<T>),
Duration(Duration<T>), Duration(Duration<T>),
@ -244,6 +331,7 @@ pub enum QueryView<T> {
macro_rules! declare_concrete_query( macro_rules! declare_concrete_query(
($name:ident, $param:ident) => { ($name:ident, $param:ident) => {
#[derive(Debug)]
pub struct $name<$param>($param); pub struct $name<$param>($param);
impl<'a> $name<&'a QueryRef> { impl<'a> $name<&'a QueryRef> {
@ -260,12 +348,6 @@ macro_rules! declare_concrete_query(
} }
} }
impl<'a> $name<&'a mut QueryRef> {
pub fn get_mut_query(&mut self) -> &mut QueryRef {
self.0
}
}
impl<'a> Deref for $name<&'a mut QueryRef> { impl<'a> Deref for $name<&'a mut QueryRef> {
type Target = $name<&'a QueryRef>; type Target = $name<&'a QueryRef>;
@ -275,17 +357,43 @@ macro_rules! declare_concrete_query(
} }
} }
} }
impl<'a> $name<&'a mut QueryRef> {
pub fn get_mut_query(&mut self) -> &mut QueryRef {
self.0
}
}
impl Deref for $name<Query> {
type Target = QueryRef;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl DerefMut for $name<Query> {
fn deref_mut(&mut self) -> &mut Self::Target {
self.0.get_mut().unwrap()
}
}
impl From<$name<Query>> for Query {
fn from(concrete: $name<Query>) -> Self {
unsafe { from_glib_none(concrete.0.as_mut_ptr()) }
}
}
} }
); );
declare_concrete_query!(Position, T); declare_concrete_query!(Position, T);
impl<'a> Position<&'a QueryRef> { impl<T: AsPtr> Position<T> {
pub fn get_result(&self) -> GenericFormattedValue { pub fn get_result(&self) -> GenericFormattedValue {
unsafe { unsafe {
let mut fmt = mem::uninitialized(); let mut fmt = mem::uninitialized();
let mut pos = mem::uninitialized(); let mut pos = mem::uninitialized();
ffi::gst_query_parse_position(self.as_mut_ptr(), &mut fmt, &mut pos); ffi::gst_query_parse_position(self.0.as_ptr(), &mut fmt, &mut pos);
GenericFormattedValue::new(from_glib(fmt), pos) GenericFormattedValue::new(from_glib(fmt), pos)
} }
@ -295,20 +403,20 @@ impl<'a> Position<&'a QueryRef> {
unsafe { unsafe {
let mut fmt = mem::uninitialized(); let mut fmt = mem::uninitialized();
ffi::gst_query_parse_position(self.as_mut_ptr(), &mut fmt, ptr::null_mut()); ffi::gst_query_parse_position(self.0.as_ptr(), &mut fmt, ptr::null_mut());
from_glib(fmt) from_glib(fmt)
} }
} }
} }
impl<'a> Position<&'a mut QueryRef> { impl<T: AsMutPtr> Position<T> {
pub fn set<V: Into<GenericFormattedValue>>(&mut self, pos: V) { pub fn set<V: Into<GenericFormattedValue>>(&mut self, pos: V) {
let pos = pos.into(); let pos = pos.into();
assert_eq!(pos.get_format(), self.get_format()); assert_eq!(pos.get_format(), self.get_format());
unsafe { unsafe {
ffi::gst_query_set_position( ffi::gst_query_set_position(
self.as_mut_ptr(), self.0.as_mut_ptr(),
pos.get_format().to_glib(), pos.get_format().to_glib(),
pos.get_value(), pos.get_value(),
); );
@ -317,13 +425,13 @@ impl<'a> Position<&'a mut QueryRef> {
} }
declare_concrete_query!(Duration, T); declare_concrete_query!(Duration, T);
impl<'a> Duration<&'a QueryRef> { impl<T: AsPtr> Duration<T> {
pub fn get_result(&self) -> GenericFormattedValue { pub fn get_result(&self) -> GenericFormattedValue {
unsafe { unsafe {
let mut fmt = mem::uninitialized(); let mut fmt = mem::uninitialized();
let mut pos = mem::uninitialized(); let mut pos = mem::uninitialized();
ffi::gst_query_parse_duration(self.as_mut_ptr(), &mut fmt, &mut pos); ffi::gst_query_parse_duration(self.0.as_ptr(), &mut fmt, &mut pos);
GenericFormattedValue::new(from_glib(fmt), pos) GenericFormattedValue::new(from_glib(fmt), pos)
} }
@ -333,20 +441,20 @@ impl<'a> Duration<&'a QueryRef> {
unsafe { unsafe {
let mut fmt = mem::uninitialized(); let mut fmt = mem::uninitialized();
ffi::gst_query_parse_duration(self.as_mut_ptr(), &mut fmt, ptr::null_mut()); ffi::gst_query_parse_duration(self.0.as_ptr(), &mut fmt, ptr::null_mut());
from_glib(fmt) from_glib(fmt)
} }
} }
} }
impl<'a> Duration<&'a mut QueryRef> { impl<T: AsMutPtr> Duration<T> {
pub fn set<V: Into<GenericFormattedValue>>(&mut self, dur: V) { pub fn set<V: Into<GenericFormattedValue>>(&mut self, dur: V) {
let dur = dur.into(); let dur = dur.into();
assert_eq!(dur.get_format(), self.get_format()); assert_eq!(dur.get_format(), self.get_format());
unsafe { unsafe {
ffi::gst_query_set_duration( ffi::gst_query_set_duration(
self.as_mut_ptr(), self.0.as_mut_ptr(),
dur.get_format().to_glib(), dur.get_format().to_glib(),
dur.get_value(), dur.get_value(),
); );
@ -355,25 +463,25 @@ impl<'a> Duration<&'a mut QueryRef> {
} }
declare_concrete_query!(Latency, T); declare_concrete_query!(Latency, T);
impl<'a> Latency<&'a QueryRef> { impl<T: AsPtr> Latency<T> {
pub fn get_result(&self) -> (bool, ::ClockTime, ::ClockTime) { pub fn get_result(&self) -> (bool, ::ClockTime, ::ClockTime) {
unsafe { unsafe {
let mut live = mem::uninitialized(); let mut live = mem::uninitialized();
let mut min = mem::uninitialized(); let mut min = mem::uninitialized();
let mut max = mem::uninitialized(); let mut max = mem::uninitialized();
ffi::gst_query_parse_latency(self.as_mut_ptr(), &mut live, &mut min, &mut max); ffi::gst_query_parse_latency(self.0.as_ptr(), &mut live, &mut min, &mut max);
(from_glib(live), from_glib(min), from_glib(max)) (from_glib(live), from_glib(min), from_glib(max))
} }
} }
} }
impl<'a> Latency<&'a mut QueryRef> { impl<T: AsMutPtr> Latency<T> {
pub fn set(&mut self, live: bool, min: ::ClockTime, max: ::ClockTime) { pub fn set(&mut self, live: bool, min: ::ClockTime, max: ::ClockTime) {
unsafe { unsafe {
ffi::gst_query_set_latency( ffi::gst_query_set_latency(
self.as_mut_ptr(), self.0.as_mut_ptr(),
live.to_glib(), live.to_glib(),
min.to_glib(), min.to_glib(),
max.to_glib(), max.to_glib(),
@ -386,7 +494,7 @@ declare_concrete_query!(Jitter, T);
declare_concrete_query!(Rate, T); declare_concrete_query!(Rate, T);
declare_concrete_query!(Seeking, T); declare_concrete_query!(Seeking, T);
impl<'a> Seeking<&'a QueryRef> { impl<T: AsPtr> Seeking<T> {
pub fn get_result(&self) -> (bool, GenericFormattedValue, GenericFormattedValue) { pub fn get_result(&self) -> (bool, GenericFormattedValue, GenericFormattedValue) {
unsafe { unsafe {
let mut fmt = mem::uninitialized(); let mut fmt = mem::uninitialized();
@ -394,7 +502,7 @@ impl<'a> Seeking<&'a QueryRef> {
let mut start = mem::uninitialized(); let mut start = mem::uninitialized();
let mut end = mem::uninitialized(); let mut end = mem::uninitialized();
ffi::gst_query_parse_seeking( ffi::gst_query_parse_seeking(
self.as_mut_ptr(), self.0.as_ptr(),
&mut fmt, &mut fmt,
&mut seekable, &mut seekable,
&mut start, &mut start,
@ -413,7 +521,7 @@ impl<'a> Seeking<&'a QueryRef> {
unsafe { unsafe {
let mut fmt = mem::uninitialized(); let mut fmt = mem::uninitialized();
ffi::gst_query_parse_seeking( ffi::gst_query_parse_seeking(
self.as_mut_ptr(), self.0.as_ptr(),
&mut fmt, &mut fmt,
ptr::null_mut(), ptr::null_mut(),
ptr::null_mut(), ptr::null_mut(),
@ -425,7 +533,7 @@ impl<'a> Seeking<&'a QueryRef> {
} }
} }
impl<'a> Seeking<&'a mut QueryRef> { impl<T: AsMutPtr> Seeking<T> {
pub fn set<V: Into<GenericFormattedValue>>(&mut self, seekable: bool, start: V, end: V) { pub fn set<V: Into<GenericFormattedValue>>(&mut self, seekable: bool, start: V, end: V) {
let start = start.into(); let start = start.into();
let end = end.into(); let end = end.into();
@ -435,7 +543,7 @@ impl<'a> Seeking<&'a mut QueryRef> {
unsafe { unsafe {
ffi::gst_query_set_seeking( ffi::gst_query_set_seeking(
self.as_mut_ptr(), self.0.as_mut_ptr(),
start.get_format().to_glib(), start.get_format().to_glib(),
seekable.to_glib(), seekable.to_glib(),
start.get_value(), start.get_value(),
@ -446,7 +554,7 @@ impl<'a> Seeking<&'a mut QueryRef> {
} }
declare_concrete_query!(Segment, T); declare_concrete_query!(Segment, T);
impl<'a> Segment<&'a QueryRef> { impl<T: AsPtr> Segment<T> {
pub fn get_result(&self) -> (f64, GenericFormattedValue, GenericFormattedValue) { pub fn get_result(&self) -> (f64, GenericFormattedValue, GenericFormattedValue) {
unsafe { unsafe {
let mut rate = mem::uninitialized(); let mut rate = mem::uninitialized();
@ -455,7 +563,7 @@ impl<'a> Segment<&'a QueryRef> {
let mut stop = mem::uninitialized(); let mut stop = mem::uninitialized();
ffi::gst_query_parse_segment( ffi::gst_query_parse_segment(
self.as_mut_ptr(), self.0.as_ptr(),
&mut rate, &mut rate,
&mut fmt, &mut fmt,
&mut start, &mut start,
@ -474,7 +582,7 @@ impl<'a> Segment<&'a QueryRef> {
let mut fmt = mem::uninitialized(); let mut fmt = mem::uninitialized();
ffi::gst_query_parse_segment( ffi::gst_query_parse_segment(
self.as_mut_ptr(), self.0.as_ptr(),
ptr::null_mut(), ptr::null_mut(),
&mut fmt, &mut fmt,
ptr::null_mut(), ptr::null_mut(),
@ -485,7 +593,7 @@ impl<'a> Segment<&'a QueryRef> {
} }
} }
impl<'a> Segment<&'a mut QueryRef> { impl<T: AsMutPtr> Segment<T> {
pub fn set<V: Into<GenericFormattedValue>>(&mut self, rate: f64, start: V, stop: V) { pub fn set<V: Into<GenericFormattedValue>>(&mut self, rate: f64, start: V, stop: V) {
let start = start.into(); let start = start.into();
let stop = stop.into(); let stop = stop.into();
@ -494,7 +602,7 @@ impl<'a> Segment<&'a mut QueryRef> {
unsafe { unsafe {
ffi::gst_query_set_segment( ffi::gst_query_set_segment(
self.as_mut_ptr(), self.0.as_mut_ptr(),
rate, rate,
start.get_format().to_glib(), start.get_format().to_glib(),
start.get_value(), start.get_value(),
@ -505,7 +613,7 @@ impl<'a> Segment<&'a mut QueryRef> {
} }
declare_concrete_query!(Convert, T); declare_concrete_query!(Convert, T);
impl<'a> Convert<&'a QueryRef> { impl<T: AsPtr> Convert<T> {
pub fn get_result(&self) -> (GenericFormattedValue, GenericFormattedValue) { pub fn get_result(&self) -> (GenericFormattedValue, GenericFormattedValue) {
unsafe { unsafe {
let mut src_fmt = mem::uninitialized(); let mut src_fmt = mem::uninitialized();
@ -514,7 +622,7 @@ impl<'a> Convert<&'a QueryRef> {
let mut dest = mem::uninitialized(); let mut dest = mem::uninitialized();
ffi::gst_query_parse_convert( ffi::gst_query_parse_convert(
self.as_mut_ptr(), self.0.as_ptr(),
&mut src_fmt, &mut src_fmt,
&mut src, &mut src,
&mut dest_fmt, &mut dest_fmt,
@ -534,7 +642,7 @@ impl<'a> Convert<&'a QueryRef> {
let mut dest_fmt = mem::uninitialized(); let mut dest_fmt = mem::uninitialized();
ffi::gst_query_parse_convert( ffi::gst_query_parse_convert(
self.as_mut_ptr(), self.0.as_ptr(),
&mut src_fmt, &mut src_fmt,
&mut src, &mut src,
&mut dest_fmt, &mut dest_fmt,
@ -548,14 +656,14 @@ impl<'a> Convert<&'a QueryRef> {
} }
} }
impl<'a> Convert<&'a mut QueryRef> { impl<T: AsMutPtr> Convert<T> {
pub fn set<V: Into<GenericFormattedValue>>(&mut self, src: V, dest: V) { pub fn set<V: Into<GenericFormattedValue>>(&mut self, src: V, dest: V) {
let src = src.into(); let src = src.into();
let dest = dest.into(); let dest = dest.into();
unsafe { unsafe {
ffi::gst_query_set_convert( ffi::gst_query_set_convert(
self.as_mut_ptr(), self.0.as_mut_ptr(),
src.get_format().to_glib(), src.get_format().to_glib(),
src.get_value(), src.get_value(),
dest.get_format().to_glib(), dest.get_format().to_glib(),
@ -566,16 +674,16 @@ impl<'a> Convert<&'a mut QueryRef> {
} }
declare_concrete_query!(Formats, T); declare_concrete_query!(Formats, T);
impl<'a> Formats<&'a QueryRef> { impl<T: AsPtr> Formats<T> {
pub fn get_result(&self) -> Vec<::Format> { pub fn get_result(&self) -> Vec<::Format> {
unsafe { unsafe {
let mut n = mem::uninitialized(); let mut n = mem::uninitialized();
ffi::gst_query_parse_n_formats(self.as_mut_ptr(), &mut n); ffi::gst_query_parse_n_formats(self.0.as_ptr(), &mut n);
let mut res = Vec::with_capacity(n as usize); let mut res = Vec::with_capacity(n as usize);
for i in 0..n { for i in 0..n {
let mut fmt = mem::uninitialized(); let mut fmt = mem::uninitialized();
ffi::gst_query_parse_nth_format(self.as_mut_ptr(), i, &mut fmt); ffi::gst_query_parse_nth_format(self.0.as_ptr(), i, &mut fmt);
res.push(from_glib(fmt)); res.push(from_glib(fmt));
} }
@ -584,23 +692,23 @@ impl<'a> Formats<&'a QueryRef> {
} }
} }
impl<'a> Formats<&'a mut QueryRef> { impl<T: AsMutPtr> Formats<T> {
pub fn set(&mut self, formats: &[::Format]) { pub fn set(&mut self, formats: &[::Format]) {
unsafe { unsafe {
let v: Vec<_> = formats.iter().map(|f| f.to_glib()).collect(); let v: Vec<_> = formats.iter().map(|f| f.to_glib()).collect();
ffi::gst_query_set_formatsv(self.as_mut_ptr(), v.len() as i32, v.as_ptr() as *mut _); ffi::gst_query_set_formatsv(self.0.as_mut_ptr(), v.len() as i32, v.as_ptr() as *mut _);
} }
} }
} }
declare_concrete_query!(Buffering, T); declare_concrete_query!(Buffering, T);
impl<'a> Buffering<&'a QueryRef> { impl<T: AsPtr> Buffering<T> {
pub fn get_format(&self) -> ::Format { pub fn get_format(&self) -> ::Format {
unsafe { unsafe {
let mut fmt = mem::uninitialized(); let mut fmt = mem::uninitialized();
ffi::gst_query_parse_buffering_range( ffi::gst_query_parse_buffering_range(
self.as_mut_ptr(), self.0.as_ptr(),
&mut fmt, &mut fmt,
ptr::null_mut(), ptr::null_mut(),
ptr::null_mut(), ptr::null_mut(),
@ -616,7 +724,7 @@ impl<'a> Buffering<&'a QueryRef> {
let mut busy = mem::uninitialized(); let mut busy = mem::uninitialized();
let mut percent = mem::uninitialized(); let mut percent = mem::uninitialized();
ffi::gst_query_parse_buffering_percent(self.as_mut_ptr(), &mut busy, &mut percent); ffi::gst_query_parse_buffering_percent(self.0.as_ptr(), &mut busy, &mut percent);
(from_glib(busy), percent) (from_glib(busy), percent)
} }
@ -630,7 +738,7 @@ impl<'a> Buffering<&'a QueryRef> {
let mut estimated_total = mem::uninitialized(); let mut estimated_total = mem::uninitialized();
ffi::gst_query_parse_buffering_range( ffi::gst_query_parse_buffering_range(
self.as_mut_ptr(), self.0.as_ptr(),
&mut fmt, &mut fmt,
&mut start, &mut start,
&mut stop, &mut stop,
@ -652,7 +760,7 @@ impl<'a> Buffering<&'a QueryRef> {
let mut buffering_left = mem::uninitialized(); let mut buffering_left = mem::uninitialized();
ffi::gst_query_parse_buffering_stats( ffi::gst_query_parse_buffering_stats(
self.as_mut_ptr(), self.0.as_ptr(),
&mut mode, &mut mode,
&mut avg_in, &mut avg_in,
&mut avg_out, &mut avg_out,
@ -667,7 +775,7 @@ impl<'a> Buffering<&'a QueryRef> {
unsafe { unsafe {
let mut fmt = mem::uninitialized(); let mut fmt = mem::uninitialized();
ffi::gst_query_parse_buffering_range( ffi::gst_query_parse_buffering_range(
self.as_mut_ptr(), self.0.as_ptr(),
&mut fmt, &mut fmt,
ptr::null_mut(), ptr::null_mut(),
ptr::null_mut(), ptr::null_mut(),
@ -675,13 +783,13 @@ impl<'a> Buffering<&'a QueryRef> {
); );
let fmt = from_glib(fmt); let fmt = from_glib(fmt);
let n = ffi::gst_query_get_n_buffering_ranges(self.as_mut_ptr()); let n = ffi::gst_query_get_n_buffering_ranges(self.0.as_ptr());
let mut res = Vec::with_capacity(n as usize); let mut res = Vec::with_capacity(n as usize);
for i in 0..n { for i in 0..n {
let mut start = mem::uninitialized(); let mut start = mem::uninitialized();
let mut stop = mem::uninitialized(); let mut stop = mem::uninitialized();
let s: bool = from_glib(ffi::gst_query_parse_nth_buffering_range( let s: bool = from_glib(ffi::gst_query_parse_nth_buffering_range(
self.as_mut_ptr(), self.0.as_ptr(),
i, i,
&mut start, &mut start,
&mut stop, &mut stop,
@ -699,10 +807,10 @@ impl<'a> Buffering<&'a QueryRef> {
} }
} }
impl<'a> Buffering<&'a mut QueryRef> { impl<T: AsMutPtr> Buffering<T> {
pub fn set_percent(&mut self, busy: bool, percent: i32) { pub fn set_percent(&mut self, busy: bool, percent: i32) {
unsafe { unsafe {
ffi::gst_query_set_buffering_percent(self.as_mut_ptr(), busy.to_glib(), percent); ffi::gst_query_set_buffering_percent(self.0.as_mut_ptr(), busy.to_glib(), percent);
} }
} }
@ -720,7 +828,7 @@ impl<'a> Buffering<&'a mut QueryRef> {
unsafe { unsafe {
ffi::gst_query_set_buffering_range( ffi::gst_query_set_buffering_range(
self.as_mut_ptr(), self.0.as_mut_ptr(),
start.get_format().to_glib(), start.get_format().to_glib(),
start.get_value(), start.get_value(),
stop.get_value(), stop.get_value(),
@ -739,7 +847,7 @@ impl<'a> Buffering<&'a mut QueryRef> {
skip_assert_initialized!(); skip_assert_initialized!();
unsafe { unsafe {
ffi::gst_query_set_buffering_stats( ffi::gst_query_set_buffering_stats(
self.as_mut_ptr(), self.0.as_mut_ptr(),
mode.to_glib(), mode.to_glib(),
avg_in, avg_in,
avg_out, avg_out,
@ -761,7 +869,7 @@ impl<'a> Buffering<&'a mut QueryRef> {
assert_eq!(start.get_format(), fmt); assert_eq!(start.get_format(), fmt);
assert_eq!(stop.get_format(), fmt); assert_eq!(stop.get_format(), fmt);
ffi::gst_query_add_buffering_range( ffi::gst_query_add_buffering_range(
self.as_mut_ptr(), self.0.as_mut_ptr(),
start.get_value(), start.get_value(),
stop.get_value(), stop.get_value(),
); );
@ -773,11 +881,11 @@ impl<'a> Buffering<&'a mut QueryRef> {
declare_concrete_query!(Custom, T); declare_concrete_query!(Custom, T);
declare_concrete_query!(Uri, T); declare_concrete_query!(Uri, T);
impl<'a> Uri<&'a QueryRef> { impl<T: AsPtr> Uri<T> {
pub fn get_uri(&self) -> Option<String> { pub fn get_uri(&self) -> Option<String> {
unsafe { unsafe {
let mut uri = ptr::null_mut(); let mut uri = ptr::null_mut();
ffi::gst_query_parse_uri(self.as_mut_ptr(), &mut uri); ffi::gst_query_parse_uri(self.0.as_ptr(), &mut uri);
from_glib_full(uri) from_glib_full(uri)
} }
} }
@ -785,28 +893,28 @@ impl<'a> Uri<&'a QueryRef> {
pub fn get_redirection(&self) -> (Option<String>, bool) { pub fn get_redirection(&self) -> (Option<String>, bool) {
unsafe { unsafe {
let mut uri = ptr::null_mut(); let mut uri = ptr::null_mut();
ffi::gst_query_parse_uri_redirection(self.as_mut_ptr(), &mut uri); ffi::gst_query_parse_uri_redirection(self.0.as_ptr(), &mut uri);
let mut permanent = mem::uninitialized(); let mut permanent = mem::uninitialized();
ffi::gst_query_parse_uri_redirection_permanent(self.as_mut_ptr(), &mut permanent); ffi::gst_query_parse_uri_redirection_permanent(self.0.as_ptr(), &mut permanent);
(from_glib_full(uri), from_glib(permanent)) (from_glib_full(uri), from_glib(permanent))
} }
} }
} }
impl<'a> Uri<&'a mut QueryRef> { impl<T: AsMutPtr> Uri<T> {
pub fn set_uri<'b, T: Into<&'b str>>(&mut self, uri: T) { pub fn set_uri<'b, U: Into<&'b str>>(&mut self, uri: U) {
let uri = uri.into(); let uri = uri.into();
unsafe { unsafe {
ffi::gst_query_set_uri(self.as_mut_ptr(), uri.to_glib_none().0); ffi::gst_query_set_uri(self.0.as_mut_ptr(), uri.to_glib_none().0);
} }
} }
pub fn set_redirection<'b, T: Into<&'b str>>(&mut self, uri: T, permanent: bool) { pub fn set_redirection<'b, U: Into<&'b str>>(&mut self, uri: U, permanent: bool) {
let uri = uri.into(); let uri = uri.into();
unsafe { unsafe {
ffi::gst_query_set_uri_redirection(self.as_mut_ptr(), uri.to_glib_none().0); ffi::gst_query_set_uri_redirection(self.0.as_mut_ptr(), uri.to_glib_none().0);
ffi::gst_query_set_uri_redirection_permanent(self.as_mut_ptr(), permanent.to_glib()); ffi::gst_query_set_uri_redirection_permanent(self.0.as_mut_ptr(), permanent.to_glib());
} }
} }
} }
@ -815,11 +923,11 @@ impl<'a> Uri<&'a mut QueryRef> {
declare_concrete_query!(Allocation, T); declare_concrete_query!(Allocation, T);
declare_concrete_query!(Scheduling, T); declare_concrete_query!(Scheduling, T);
impl<'a> Scheduling<&'a QueryRef> { impl<T: AsPtr> Scheduling<T> {
pub fn has_scheduling_mode(&self, mode: ::PadMode) -> bool { pub fn has_scheduling_mode(&self, mode: ::PadMode) -> bool {
unsafe { unsafe {
from_glib(ffi::gst_query_has_scheduling_mode( from_glib(ffi::gst_query_has_scheduling_mode(
self.as_mut_ptr(), self.0.as_ptr(),
mode.to_glib(), mode.to_glib(),
)) ))
} }
@ -833,7 +941,7 @@ impl<'a> Scheduling<&'a QueryRef> {
skip_assert_initialized!(); skip_assert_initialized!();
unsafe { unsafe {
from_glib(ffi::gst_query_has_scheduling_mode_with_flags( from_glib(ffi::gst_query_has_scheduling_mode_with_flags(
self.as_mut_ptr(), self.0.as_ptr(),
mode.to_glib(), mode.to_glib(),
flags.to_glib(), flags.to_glib(),
)) ))
@ -842,11 +950,11 @@ impl<'a> Scheduling<&'a QueryRef> {
pub fn get_scheduling_modes(&self) -> Vec<::PadMode> { pub fn get_scheduling_modes(&self) -> Vec<::PadMode> {
unsafe { unsafe {
let n = ffi::gst_query_get_n_scheduling_modes(self.as_mut_ptr()); let n = ffi::gst_query_get_n_scheduling_modes(self.0.as_ptr());
let mut res = Vec::with_capacity(n as usize); let mut res = Vec::with_capacity(n as usize);
for i in 0..n { for i in 0..n {
res.push(from_glib(ffi::gst_query_parse_nth_scheduling_mode( res.push(from_glib(ffi::gst_query_parse_nth_scheduling_mode(
self.as_mut_ptr(), self.0.as_ptr(),
i, i,
))); )));
} }
@ -863,7 +971,7 @@ impl<'a> Scheduling<&'a QueryRef> {
let mut align = mem::uninitialized(); let mut align = mem::uninitialized();
ffi::gst_query_parse_scheduling( ffi::gst_query_parse_scheduling(
self.as_mut_ptr(), self.0.as_ptr(),
&mut flags, &mut flags,
&mut minsize, &mut minsize,
&mut maxsize, &mut maxsize,
@ -875,11 +983,11 @@ impl<'a> Scheduling<&'a QueryRef> {
} }
} }
impl<'a> Scheduling<&'a mut QueryRef> { impl<T: AsMutPtr> Scheduling<T> {
pub fn add_scheduling_modes(&mut self, modes: &[::PadMode]) { pub fn add_scheduling_modes(&mut self, modes: &[::PadMode]) {
unsafe { unsafe {
for mode in modes { for mode in modes {
ffi::gst_query_add_scheduling_mode(self.as_mut_ptr(), mode.to_glib()); ffi::gst_query_add_scheduling_mode(self.0.as_mut_ptr(), mode.to_glib());
} }
} }
} }
@ -887,7 +995,7 @@ impl<'a> Scheduling<&'a mut QueryRef> {
pub fn set(&mut self, flags: ::SchedulingFlags, minsize: i32, maxsize: i32, align: i32) { pub fn set(&mut self, flags: ::SchedulingFlags, minsize: i32, maxsize: i32, align: i32) {
unsafe { unsafe {
ffi::gst_query_set_scheduling( ffi::gst_query_set_scheduling(
self.as_mut_ptr(), self.0.as_mut_ptr(),
flags.to_glib(), flags.to_glib(),
minsize, minsize,
maxsize, maxsize,
@ -898,11 +1006,11 @@ impl<'a> Scheduling<&'a mut QueryRef> {
} }
declare_concrete_query!(AcceptCaps, T); declare_concrete_query!(AcceptCaps, T);
impl<'a> AcceptCaps<&'a QueryRef> { impl<T: AsPtr> AcceptCaps<T> {
pub fn get_caps(&self) -> &::CapsRef { pub fn get_caps(&self) -> &::CapsRef {
unsafe { unsafe {
let mut caps = ptr::null_mut(); let mut caps = ptr::null_mut();
ffi::gst_query_parse_accept_caps(self.as_mut_ptr(), &mut caps); ffi::gst_query_parse_accept_caps(self.0.as_ptr(), &mut caps);
::CapsRef::from_ptr(caps) ::CapsRef::from_ptr(caps)
} }
} }
@ -910,26 +1018,26 @@ impl<'a> AcceptCaps<&'a QueryRef> {
pub fn get_result(&self) -> bool { pub fn get_result(&self) -> bool {
unsafe { unsafe {
let mut accepted = mem::uninitialized(); let mut accepted = mem::uninitialized();
ffi::gst_query_parse_accept_caps_result(self.as_mut_ptr(), &mut accepted); ffi::gst_query_parse_accept_caps_result(self.0.as_ptr(), &mut accepted);
from_glib(accepted) from_glib(accepted)
} }
} }
} }
impl<'a> AcceptCaps<&'a mut QueryRef> { impl<T: AsMutPtr> AcceptCaps<T> {
pub fn set_result(&mut self, accepted: bool) { pub fn set_result(&mut self, accepted: bool) {
unsafe { unsafe {
ffi::gst_query_set_accept_caps_result(self.as_mut_ptr(), accepted.to_glib()); ffi::gst_query_set_accept_caps_result(self.0.as_mut_ptr(), accepted.to_glib());
} }
} }
} }
declare_concrete_query!(Caps, T); declare_concrete_query!(Caps, T);
impl<'a> Caps<&'a QueryRef> { impl<T: AsPtr> Caps<T> {
pub fn get_filter(&self) -> Option<&::CapsRef> { pub fn get_filter(&self) -> Option<&::CapsRef> {
unsafe { unsafe {
let mut caps = ptr::null_mut(); let mut caps = ptr::null_mut();
ffi::gst_query_parse_caps(self.as_mut_ptr(), &mut caps); ffi::gst_query_parse_caps(self.0.as_ptr(), &mut caps);
if caps.is_null() { if caps.is_null() {
None None
} else { } else {
@ -941,7 +1049,7 @@ impl<'a> Caps<&'a QueryRef> {
pub fn get_result(&self) -> Option<&::CapsRef> { pub fn get_result(&self) -> Option<&::CapsRef> {
unsafe { unsafe {
let mut caps = ptr::null_mut(); let mut caps = ptr::null_mut();
ffi::gst_query_parse_caps_result(self.as_mut_ptr(), &mut caps); ffi::gst_query_parse_caps_result(self.0.as_ptr(), &mut caps);
if caps.is_null() { if caps.is_null() {
None None
} else { } else {
@ -951,10 +1059,10 @@ impl<'a> Caps<&'a QueryRef> {
} }
} }
impl<'a> Caps<&'a mut QueryRef> { impl<T: AsMutPtr> Caps<T> {
pub fn set_result(&mut self, caps: &::Caps) { pub fn set_result(&mut self, caps: &::Caps) {
unsafe { unsafe {
ffi::gst_query_set_caps_result(self.as_mut_ptr(), caps.as_mut_ptr()); ffi::gst_query_set_caps_result(self.0.as_mut_ptr(), caps.as_mut_ptr());
} }
} }
} }
@ -962,11 +1070,11 @@ impl<'a> Caps<&'a mut QueryRef> {
declare_concrete_query!(Drain, T); declare_concrete_query!(Drain, T);
declare_concrete_query!(Context, T); declare_concrete_query!(Context, T);
impl<'a> Context<&'a QueryRef> { impl<T: AsPtr> Context<T> {
pub fn get_context(&self) -> Option<&::ContextRef> { pub fn get_context(&self) -> Option<&::ContextRef> {
unsafe { unsafe {
let mut context = ptr::null_mut(); let mut context = ptr::null_mut();
ffi::gst_query_parse_context(self.as_mut_ptr(), &mut context); ffi::gst_query_parse_context(self.0.as_ptr(), &mut context);
if context.is_null() { if context.is_null() {
None None
} else { } else {
@ -978,16 +1086,16 @@ impl<'a> Context<&'a QueryRef> {
pub fn get_context_type(&self) -> &str { pub fn get_context_type(&self) -> &str {
unsafe { unsafe {
let mut context_type = ptr::null(); let mut context_type = ptr::null();
ffi::gst_query_parse_context_type(self.as_mut_ptr(), &mut context_type); ffi::gst_query_parse_context_type(self.0.as_ptr(), &mut context_type);
CStr::from_ptr(context_type).to_str().unwrap() CStr::from_ptr(context_type).to_str().unwrap()
} }
} }
} }
impl<'a> Context<&'a mut QueryRef> { impl<T: AsMutPtr> Context<T> {
pub fn set_context(&mut self, context: &::Context) { pub fn set_context(&mut self, context: &::Context) {
unsafe { unsafe {
ffi::gst_query_set_context(self.as_mut_ptr(), context.as_mut_ptr()); ffi::gst_query_set_context(self.0.as_mut_ptr(), context.as_mut_ptr());
} }
} }
} }
@ -1002,32 +1110,82 @@ mod tests {
fn test_writability() { fn test_writability() {
::init().unwrap(); ::init().unwrap();
let mut q = Query::new_position(::Format::Time); fn check_mut(query: &mut QueryRef) {
match query.view_mut() {
match q.view() { QueryView::Position(ref mut p) => {
QueryView::Position(ref p) => { let pos = p.get_result();
let fmt = p.get_format(); assert_eq!(pos.try_into_time(), Ok(::CLOCK_TIME_NONE));
assert_eq!(fmt, ::Format::Time); p.set(3 * ::SECOND);
assert!(!p.is_serialized()); let pos = p.get_result();
assert_eq!(pos.try_into_time(), 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_time(), 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_time(), 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 q.get_mut().unwrap().view_mut() { match query.view() {
QueryView::Position(ref mut p) => { QueryView::Duration(ref d) => {
let pos = p.get_result(); let duration = d.get_result();
assert_eq!(pos.try_into_time(), Ok(::CLOCK_TIME_NONE)); assert_eq!(duration.try_into_time(), Ok(2 * ::SECOND));
p.set(2 * ::SECOND); },
}
_ => (),
}
match q.view() {
QueryView::Position(ref p) => {
let pos = p.get_result();
assert_eq!(pos.try_into_time(), Ok(2 * ::SECOND));
}
_ => (), _ => (),
} }
} }
#[test]
fn test_concrete_to_ffi() {
::init().unwrap();
let p = Query::new_position(::Format::Time);
unsafe { assert!(!p.as_mut_ptr().is_null()); }
}
} }

View file

@ -128,19 +128,14 @@ fn handle_message(custom_data: &mut CustomData, msg: &gst::GstRc<gst::MessageRef
custom_data.playing = new_state == gst::State::Playing; custom_data.playing = new_state == gst::State::Playing;
if custom_data.playing { if custom_data.playing {
let mut query = gst::Query::new_seeking(gst::Format::Time); let mut seeking = gst::Query::new_seeking(gst::Format::Time);
if custom_data.playbin.query(query.get_mut().unwrap()) { if custom_data.playbin.query(&mut seeking) {
match query.view() { let (seekable, start, end) = seeking.get_result();
gst::QueryView::Seeking(seek) => { custom_data.seek_enabled = seekable;
let (seekable, start, end) = seek.get_result(); if seekable {
custom_data.seek_enabled = seekable; println!("Seeking is ENABLED from {:?} to {:?}", start, end)
if seekable { } else {
println!("Seeking is ENABLED from {:?} to {:?}", start, end) println!("Seeking is DISABLED for this stream.")
} else {
println!("Seeking is DISABLED for this stream.")
}
}
_ => unreachable!(),
} }
} else { } else {
eprintln!("Seeking query failed.") eprintln!("Seeking query failed.")