gstreamer_pbutils/
discoverer.rs1use std::{boxed::Box as Box_, fmt, mem::transmute};
4
5use glib::{
6 prelude::*,
7 signal::{SignalHandlerId, connect_raw},
8 translate::*,
9};
10
11use crate::{Discoverer, DiscovererInfo, ffi};
12
13#[cfg(feature = "v1_30")]
14use crate::{DiscovererResult, DiscovererStreamInfo};
15
16impl Discoverer {
17 pub fn set_timeout(&self, timeout: gst::ClockTime) {
18 self.set_property("timeout", timeout);
19 }
20
21 pub fn timeout(&self) -> gst::ClockTime {
22 self.property("timeout")
23 }
24
25 #[doc(alias = "timeout")]
26 pub fn connect_timeout_notify<F: Fn(&Self) + Send + Sync + 'static>(
27 &self,
28 f: F,
29 ) -> SignalHandlerId {
30 unsafe {
31 let f: Box_<F> = Box_::new(f);
32 connect_raw(
33 self.as_ptr() as *mut _,
34 b"notify::timeout\0".as_ptr() as *const _,
35 Some(transmute::<*const (), unsafe extern "C" fn()>(
36 notify_timeout_trampoline::<Self, F> as *const (),
37 )),
38 Box_::into_raw(f),
39 )
40 }
41 }
42}
43
44unsafe extern "C" fn notify_timeout_trampoline<P, F: Fn(&P) + Send + Sync + 'static>(
45 this: *mut ffi::GstDiscoverer,
46 _param_spec: glib::ffi::gpointer,
47 f: glib::ffi::gpointer,
48) where
49 P: IsA<Discoverer>,
50{
51 unsafe {
52 let f: &F = &*(f as *const F);
53 f(Discoverer::from_glib_borrow(this).unsafe_cast_ref())
54 }
55}
56
57pub struct DebugInfo<'a>(&'a DiscovererInfo);
58
59impl fmt::Debug for DebugInfo<'_> {
60 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
61 let stream_info = self.0.stream_info();
62 let stream_list = self.0.stream_list();
63 let container_streams = self.0.container_streams();
64 let audio_streams = self.0.audio_streams();
65 let video_streams = self.0.video_streams();
66 let subtitle_streams = self.0.subtitle_streams();
67
68 f.debug_struct("DiscovererInfo")
69 .field("uri", &self.0.uri())
70 .field("result", &self.0.result())
71 .field("duration", &self.0.duration())
72 .field("is-live", &self.0.is_live())
73 .field("is-seekable", &self.0.is_seekable())
74 .field(
75 "stream-info",
76 &stream_info.as_ref().map(|info| info.debug()),
77 )
78 .field(
79 "stream-list",
80 &stream_list
81 .iter()
82 .map(|info| info.debug())
83 .collect::<Vec<_>>(),
84 )
85 .field(
86 "container-streams",
87 &container_streams
88 .iter()
89 .map(|info| info.debug())
90 .collect::<Vec<_>>(),
91 )
92 .field(
93 "audio-streams",
94 &audio_streams
95 .iter()
96 .map(|info| info.debug())
97 .collect::<Vec<_>>(),
98 )
99 .field(
100 "video-streams",
101 &video_streams
102 .iter()
103 .map(|info| info.debug())
104 .collect::<Vec<_>>(),
105 )
106 .field(
107 "subtitle-streams",
108 &subtitle_streams
109 .iter()
110 .map(|info| info.debug())
111 .collect::<Vec<_>>(),
112 )
113 .field("toc", &self.0.toc())
114 .field("misc", &self.0.misc())
115 .field(
116 "missing-elements-installer-details",
117 &self.0.missing_elements_installer_details(),
118 )
119 .finish()
120 }
121}
122
123impl DiscovererInfo {
124 pub fn debug(&self) -> DebugInfo<'_> {
125 DebugInfo(self)
126 }
127
128 #[cfg(feature = "v1_30")]
129 #[cfg_attr(docsrs, doc(cfg(feature = "v1_30")))]
130 #[doc(alias = "gst_discoverer_info_builder_new")]
131 pub fn builder(
132 uri: &str,
133 stream_info: impl IsA<DiscovererStreamInfo>,
134 ) -> DiscovererInfoBuilder {
135 skip_assert_initialized!();
136
137 DiscovererInfoBuilder::new(uri, stream_info)
138 }
139}
140
141#[cfg(feature = "v1_30")]
142#[cfg_attr(docsrs, doc(cfg(feature = "v1_30")))]
143#[derive(Debug)]
144#[doc(alias = "GstDiscovererInfoBuilder")]
145#[repr(transparent)]
146pub struct DiscovererInfoBuilder(std::ptr::NonNull<ffi::GstDiscovererInfoBuilder>);
147
148#[cfg(feature = "v1_30")]
149#[cfg_attr(docsrs, doc(cfg(feature = "v1_30")))]
150impl DiscovererInfoBuilder {
151 #[doc(alias = "gst_discoverer_info_builder_new")]
152 pub fn new(uri: &str, stream_info: impl IsA<DiscovererStreamInfo>) -> Self {
153 skip_assert_initialized!();
154
155 unsafe {
156 let ptr = ffi::gst_discoverer_info_builder_new(
157 uri.to_glib_none().0,
158 stream_info.upcast().into_glib_ptr(),
159 );
160 DiscovererInfoBuilder(std::ptr::NonNull::new_unchecked(ptr))
161 }
162 }
163
164 #[doc(alias = "gst_discoverer_info_builder_set_duration")]
165 pub fn duration(self, duration: gst::ClockTime) -> Self {
166 unsafe {
167 ffi::gst_discoverer_info_builder_set_duration(self.0.as_ptr(), duration.into_glib());
168 }
169 self
170 }
171
172 #[doc(alias = "gst_discoverer_info_builder_set_live")]
173 pub fn live(self, live: bool) -> Self {
174 unsafe {
175 ffi::gst_discoverer_info_builder_set_live(self.0.as_ptr(), live.into_glib());
176 }
177 self
178 }
179
180 #[doc(alias = "gst_discoverer_info_builder_set_result")]
181 pub fn result(self, result: DiscovererResult) -> Self {
182 unsafe {
183 ffi::gst_discoverer_info_builder_set_result(self.0.as_ptr(), result.into_glib());
184 }
185 self
186 }
187
188 #[doc(alias = "gst_discoverer_info_builder_set_seekable")]
189 pub fn seekable(self, seekable: bool) -> Self {
190 unsafe {
191 ffi::gst_discoverer_info_builder_set_seekable(self.0.as_ptr(), seekable.into_glib());
192 }
193 self
194 }
195
196 #[doc(alias = "gst_discoverer_info_builder_set_tags")]
197 pub fn tags(self, tags: &gst::TagList) -> Self {
198 unsafe {
199 ffi::gst_discoverer_info_builder_set_tags(self.0.as_ptr(), tags.to_glib_none().0);
200 }
201 self
202 }
203
204 #[doc(alias = "gst_discoverer_info_builder_build")]
205 pub fn build(self) -> DiscovererInfo {
206 unsafe {
207 let s = std::mem::ManuallyDrop::new(self);
210
211 from_glib_full(ffi::gst_discoverer_info_builder_build(s.0.as_ptr()))
212 }
213 }
214}
215
216#[cfg(feature = "v1_30")]
217#[cfg_attr(docsrs, doc(cfg(feature = "v1_30")))]
218impl Drop for DiscovererInfoBuilder {
219 #[inline]
220 #[doc(alias = "gst_discoverer_info_builder_free")]
221 fn drop(&mut self) {
222 unsafe {
223 ffi::gst_discoverer_info_builder_free(self.0.as_ptr());
224 }
225 }
226}
227
228#[cfg(test)]
229mod tests {
230 #[test]
231 #[cfg(feature = "v1_30")]
232 fn discoverer_info_builder_basic() {
233 use super::*;
234
235 gst::init().unwrap();
236
237 let audio_caps = gst::Caps::builder("audio/x-raw")
238 .field("format", "S16LE")
239 .build();
240 let audio_info =
241 crate::DiscovererAudioInfoBuilder::new("audio_stream", &audio_caps).build();
242
243 let mut tags = gst::TagList::new();
244 tags.get_mut()
245 .unwrap()
246 .add::<gst::tags::Title>(&"some title", gst::TagMergeMode::Append);
247
248 let info = DiscovererInfoBuilder::new("file:///tmp/test.wav", audio_info)
249 .duration(gst::ClockTime::from_seconds(5))
250 .live(false)
251 .seekable(true)
252 .result(DiscovererResult::Ok)
253 .tags(&tags)
254 .build();
255
256 assert_eq!(info.duration(), Some(gst::ClockTime::from_seconds(5)));
257 assert!(!info.is_live());
258 assert!(info.is_seekable());
259 assert_eq!(info.result(), DiscovererResult::Ok);
260 assert_eq!(info.uri(), glib::GString::from("file:///tmp/test.wav"));
261 }
262}