1// Take a look at the license at the top of the repository in the LICENSE file.
2
3#[cfg(feature = "v1_16")]
4#[cfg_attr(docsrs, doc(cfg(feature = "v1_16")))]
5use std::boxed::Box as Box_;
6#[cfg(feature = "v1_16")]
7#[cfg_attr(docsrs, doc(cfg(feature = "v1_16")))]
8use std::mem::transmute;
9use std::{mem, ptr};
10
11#[cfg(feature = "v1_16")]
12#[cfg_attr(docsrs, doc(cfg(feature = "v1_16")))]
13use glib::signal::{connect_raw, SignalHandlerId};
14use glib::{prelude::*, translate::*};
15use gst::{format::FormattedValue, prelude::*};
16
17use crate::{ffi, Aggregator, AggregatorPad};
18
19mod sealed {
20 pub trait Sealed {}
21 impl<T: super::IsA<super::Aggregator>> Sealed for T {}
22}
23
24pub trait AggregatorExtManual: sealed::Sealed + IsA<Aggregator> + 'static {
25 #[doc(alias = "get_allocator")]
26 #[doc(alias = "gst_aggregator_get_allocator")]
27 fn allocator(&self) -> (Option<gst::Allocator>, gst::AllocationParams) {
28 unsafe {
29 let mut allocator = ptr::null_mut();
30 let mut params = mem::MaybeUninit::uninit();
31 ffi::gst_aggregator_get_allocator(
32 self.as_ref().to_glib_none().0,
33 &mut allocator,
34 params.as_mut_ptr(),
35 );
36 (from_glib_full(allocator), params.assume_init().into())
37 }
38 }
39
40 #[cfg(feature = "v1_16")]
41 #[cfg_attr(docsrs, doc(cfg(feature = "v1_16")))]
42 #[doc(alias = "min-upstream-latency")]
43 fn min_upstream_latency(&self) -> gst::ClockTime {
44 self.as_ref().property("min-upstream-latency")
45 }
46
47 #[cfg(feature = "v1_16")]
48 #[cfg_attr(docsrs, doc(cfg(feature = "v1_16")))]
49 #[doc(alias = "min-upstream-latency")]
50 fn set_min_upstream_latency(&self, min_upstream_latency: gst::ClockTime) {
51 self.as_ref()
52 .set_property("min-upstream-latency", min_upstream_latency);
53 }
54
55 #[cfg(feature = "v1_16")]
56 #[cfg_attr(docsrs, doc(cfg(feature = "v1_16")))]
57 #[doc(alias = "min-upstream-latency")]
58 fn connect_min_upstream_latency_notify<F: Fn(&Self) + Send + Sync + 'static>(
59 &self,
60 f: F,
61 ) -> SignalHandlerId {
62 unsafe {
63 let f: Box_<F> = Box_::new(f);
64 connect_raw(
65 self.as_ptr() as *mut _,
66 b"notify::min-upstream-latency\0".as_ptr() as *const _,
67 Some(transmute::<*const (), unsafe extern "C" fn()>(
68 notify_min_upstream_latency_trampoline::<Self, F> as *const (),
69 )),
70 Box_::into_raw(f),
71 )
72 }
73 }
74
75 #[cfg(feature = "v1_18")]
76 #[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
77 #[doc(alias = "gst_aggregator_update_segment")]
78 fn update_segment<F: gst::format::FormattedValueIntrinsic>(
79 &self,
80 segment: &gst::FormattedSegment<F>,
81 ) {
82 unsafe {
83 ffi::gst_aggregator_update_segment(
84 self.as_ref().to_glib_none().0,
85 mut_override(segment.to_glib_none().0),
86 )
87 }
88 }
89
90 fn set_position(&self, position: impl FormattedValue) {
91 unsafe {
92 let ptr: *mut ffi::GstAggregator = self.as_ref().to_glib_none().0;
93 let ptr = &mut *ptr;
94 let _guard = self.as_ref().object_lock();
95
96 // gstaggregator.c asserts that the src pad is always of type GST_TYPE_AGGREGATOR_PAD,
97 // so the pointer cast here should be safe.
98 let srcpad = &mut *(ptr.srcpad as *mut ffi::GstAggregatorPad);
99
100 assert_eq!(srcpad.segment.format, position.format().into_glib());
101 srcpad.segment.position = position.into_raw_value() as u64;
102 }
103 }
104
105 #[cfg(feature = "v1_18")]
106 #[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
107 #[doc(alias = "gst_aggregator_selected_samples")]
108 fn selected_samples(
109 &self,
110 pts: impl Into<Option<gst::ClockTime>>,
111 dts: impl Into<Option<gst::ClockTime>>,
112 duration: impl Into<Option<gst::ClockTime>>,
113 info: Option<&gst::StructureRef>,
114 ) {
115 unsafe {
116 ffi::gst_aggregator_selected_samples(
117 self.as_ref().to_glib_none().0,
118 pts.into().into_glib(),
119 dts.into().into_glib(),
120 duration.into().into_glib(),
121 info.as_ref()
122 .map(|s| s.as_ptr() as *mut _)
123 .unwrap_or(ptr::null_mut()),
124 );
125 }
126 }
127
128 #[cfg(feature = "v1_18")]
129 #[cfg_attr(docsrs, doc(cfg(feature = "v1_18")))]
130 fn connect_samples_selected<
131 F: Fn(
132 &Self,
133 &gst::Segment,
134 Option<gst::ClockTime>,
135 Option<gst::ClockTime>,
136 Option<gst::ClockTime>,
137 Option<&gst::StructureRef>,
138 ) + Send
139 + 'static,
140 >(
141 &self,
142 f: F,
143 ) -> SignalHandlerId {
144 unsafe extern "C" fn samples_selected_trampoline<
145 P,
146 F: Fn(
147 &P,
148 &gst::Segment,
149 Option<gst::ClockTime>,
150 Option<gst::ClockTime>,
151 Option<gst::ClockTime>,
152 Option<&gst::StructureRef>,
153 ) + Send
154 + 'static,
155 >(
156 this: *mut ffi::GstAggregator,
157 segment: *mut gst::ffi::GstSegment,
158 pts: gst::ffi::GstClockTime,
159 dts: gst::ffi::GstClockTime,
160 duration: gst::ffi::GstClockTime,
161 info: *mut gst::ffi::GstStructure,
162 f: glib::ffi::gpointer,
163 ) where
164 P: IsA<Aggregator>,
165 {
166 let f: &F = &*(f as *const F);
167 f(
168 Aggregator::from_glib_borrow(this).unsafe_cast_ref(),
169 gst::Segment::from_glib_ptr_borrow(segment),
170 from_glib(pts),
171 from_glib(dts),
172 from_glib(duration),
173 if info.is_null() {
174 None
175 } else {
176 Some(gst::StructureRef::from_glib_borrow(info))
177 },
178 )
179 }
180
181 unsafe {
182 let f: Box_<F> = Box_::new(f);
183 connect_raw(
184 self.as_ptr() as *mut _,
185 b"samples-selected\0".as_ptr() as *const _,
186 Some(transmute::<*const (), unsafe extern "C" fn()>(
187 samples_selected_trampoline::<Self, F> as *const (),
188 )),
189 Box_::into_raw(f),
190 )
191 }
192 }
193
194 fn src_pad(&self) -> &AggregatorPad {
195 unsafe {
196 let elt = &*(self.as_ptr() as *const ffi::GstAggregator);
197 &*(&elt.srcpad as *const *mut gst::ffi::GstPad as *const AggregatorPad)
198 }
199 }
200}
201
202impl<O: IsA<Aggregator>> AggregatorExtManual for O {}
203
204#[cfg(feature = "v1_16")]
205#[cfg_attr(docsrs, doc(cfg(feature = "v1_16")))]
206unsafe extern "C" fn notify_min_upstream_latency_trampoline<P, F: Fn(&P) + Send + Sync + 'static>(
207 this: *mut ffi::GstAggregator,
208 _param_spec: glib::ffi::gpointer,
209 f: glib::ffi::gpointer,
210) where
211 P: IsA<Aggregator>,
212{
213 let f: &F = &*(f as *const F);
214 f(Aggregator::from_glib_borrow(this).unsafe_cast_ref())
215}
216