1use glib::{translate::*, value::ToSendValue};
4use gst::{ffi as gst_ffi, prelude::*, Element, Message, Seqnum};
5
6use crate::ffi;
7
8macro_rules! message_builder_generic_impl {
9 ($new_fn:expr) => {
10 #[allow(clippy::needless_update)]
11 pub fn src<O: IsA<Element> + Cast + Clone>(self, src: &O) -> Self {
12 Self {
13 builder: self.builder.src(src),
14 ..self
15 }
16 }
17
18 #[allow(clippy::needless_update)]
19 pub fn src_if<O: IsA<Element> + Cast + Clone>(self, src: &O, predicate: bool) -> Self {
20 if predicate {
21 self.src(src)
22 } else {
23 self
24 }
25 }
26
27 #[allow(clippy::needless_update)]
28 pub fn src_if_some<O: IsA<Element> + Cast + Clone>(self, src: Option<&O>) -> Self {
29 if let Some(src) = src {
30 self.src(src)
31 } else {
32 self
33 }
34 }
35
36 #[doc(alias = "gst_message_set_seqnum")]
37 #[allow(clippy::needless_update)]
38 pub fn seqnum(self, seqnum: Seqnum) -> Self {
39 Self {
40 builder: self.builder.seqnum(seqnum),
41 ..self
42 }
43 }
44
45 #[doc(alias = "gst_message_set_seqnum")]
46 #[allow(clippy::needless_update)]
47 pub fn seqnum_if(self, seqnum: Seqnum, predicate: bool) -> Self {
48 if predicate {
49 self.seqnum(seqnum)
50 } else {
51 self
52 }
53 }
54
55 #[doc(alias = "gst_message_set_seqnum")]
56 #[allow(clippy::needless_update)]
57 pub fn seqnum_if_some(self, seqnum: Option<Seqnum>) -> Self {
58 if let Some(seqnum) = seqnum {
59 self.seqnum(seqnum)
60 } else {
61 self
62 }
63 }
64
65 #[cfg(feature = "v1_26")]
66 #[cfg_attr(docsrs, doc(cfg(feature = "v1_26")))]
67 #[doc(alias = "gst_message_set_details")]
68 pub fn details(self, details: gst::Structure) -> Self {
69 Self {
70 builder: self.builder.details(details),
71 ..self
72 }
73 }
74
75 #[cfg(feature = "v1_26")]
76 #[cfg_attr(docsrs, doc(cfg(feature = "v1_26")))]
77 #[doc(alias = "gst_message_set_details")]
78 pub fn details_if(self, details: gst::Structure, predicate: bool) -> Self {
79 if predicate {
80 self.details(details)
81 } else {
82 self
83 }
84 }
85
86 #[cfg(feature = "v1_26")]
87 #[cfg_attr(docsrs, doc(cfg(feature = "v1_26")))]
88 #[doc(alias = "gst_message_set_details")]
89 pub fn details_if_some(self, details: Option<gst::Structure>) -> Self {
90 if let Some(details) = details {
91 self.details(details)
92 } else {
93 self
94 }
95 }
96
97 #[cfg(feature = "v1_26")]
98 #[cfg_attr(docsrs, doc(cfg(feature = "v1_26")))]
99 #[doc(alias = "gst_missing_plugin_message_set_stream_id")]
100 pub fn stream_id(self, stream_id: &'a str) -> Self {
101 Self {
102 stream_id: Some(stream_id),
103 ..self
104 }
105 }
106
107 #[cfg(feature = "v1_26")]
108 #[cfg_attr(docsrs, doc(cfg(feature = "v1_26")))]
109 #[doc(alias = "gst_missing_plugin_message_set_stream_id")]
110 pub fn stream_id_if(self, stream_id: &'a str, predicate: bool) -> Self {
111 if predicate {
112 self.stream_id(stream_id)
113 } else {
114 self
115 }
116 }
117
118 #[cfg(feature = "v1_26")]
119 #[cfg_attr(docsrs, doc(cfg(feature = "v1_26")))]
120 #[doc(alias = "gst_missing_plugin_message_set_stream_id")]
121 pub fn stream_id_if_some(self, stream_id: Option<&'a str>) -> Self {
122 if let Some(stream_id) = stream_id {
123 self.stream_id(stream_id)
124 } else {
125 self
126 }
127 }
128
129 pub fn other_field(self, name: &'a str, value: impl ToSendValue) -> Self {
134 Self {
135 builder: self.builder.other_field(name, value),
136 ..self
137 }
138 }
139
140 gst::impl_builder_gvalue_extra_setters!(other_field);
141
142 #[must_use = "Building the message without using it has no effect"]
143 #[allow(clippy::redundant_closure_call)]
144 pub fn build(mut self) -> Message {
145 skip_assert_initialized!();
146 unsafe {
147 let src = self.builder.src.to_glib_none().0;
148 let msg = $new_fn(&mut self, src);
149 if let Some(seqnum) = self.builder.seqnum {
150 gst_ffi::gst_message_set_seqnum(msg, seqnum.into_glib());
151 }
152
153 #[cfg(feature = "v1_26")]
154 if let Some(details) = self.builder.details {
155 gst_ffi::gst_message_set_details(msg, details.into_glib_ptr());
156 }
157
158 if !self.builder.other_fields.is_empty() {
159 let structure = gst_ffi::gst_message_writable_structure(msg);
160
161 if !structure.is_null() {
162 let structure =
163 gst::StructureRef::from_glib_borrow_mut(structure as *mut _);
164
165 for (k, v) in self.builder.other_fields {
166 structure.set_value(k, v);
167 }
168 }
169 }
170
171 from_glib_full(msg)
172 }
173 }
174 };
175}
176
177struct MessageBuilder<'a> {
178 src: Option<Element>,
179 seqnum: Option<Seqnum>,
180 #[cfg(feature = "v1_26")]
181 details: Option<gst::Structure>,
182 other_fields: Vec<(&'a str, glib::SendValue)>,
183}
184
185impl<'a> MessageBuilder<'a> {
186 fn new() -> Self {
187 skip_assert_initialized!();
188 Self {
189 src: None,
190 seqnum: None,
191 #[cfg(feature = "v1_26")]
192 details: None,
193 other_fields: Vec::new(),
194 }
195 }
196
197 fn src<O: IsA<Element> + Cast + Clone>(self, src: &O) -> Self {
198 Self {
199 src: Some(src.clone().upcast::<Element>()),
200 ..self
201 }
202 }
203
204 fn seqnum(self, seqnum: Seqnum) -> Self {
205 Self {
206 seqnum: Some(seqnum),
207 ..self
208 }
209 }
210
211 #[cfg(feature = "v1_26")]
212 #[cfg_attr(docsrs, doc(cfg(feature = "v1_26")))]
213 #[doc(alias = "gst_message_set_details")]
214 fn details(self, details: gst::Structure) -> Self {
215 Self {
216 details: Some(details),
217 ..self
218 }
219 }
220
221 fn other_field(self, name: &'a str, value: impl ToSendValue) -> Self {
222 let mut other_fields = self.other_fields;
223 other_fields.push((name, value.to_send_value()));
224
225 Self {
226 other_fields,
227 ..self
228 }
229 }
230}
231
232enum MessageBuilderDetail<'a> {
233 Decoder(&'a gst::Caps),
234 Encoder(&'a gst::Caps),
235 Element(&'a str),
236 Sink(&'a str),
237 Src(&'a str),
238}
239
240#[must_use = "The builder must be built to be used"]
241pub struct MissingPluginMessageBuilder<'a> {
242 builder: MessageBuilder<'a>,
243 detail: MessageBuilderDetail<'a>,
244 #[cfg(feature = "v1_26")]
245 stream_id: Option<&'a str>,
246}
247
248impl<'a> MissingPluginMessageBuilder<'a> {
249 fn new(detail: MessageBuilderDetail<'a>) -> Self {
250 skip_assert_initialized!();
251 Self {
252 builder: MessageBuilder::new(),
253 detail,
254 #[cfg(feature = "v1_26")]
255 stream_id: None,
256 }
257 }
258
259 message_builder_generic_impl!(|s: &Self, src| {
260 let msg = match s.detail {
261 MessageBuilderDetail::Decoder(caps) => {
262 ffi::gst_missing_decoder_message_new(src, caps.to_glib_none().0)
263 }
264 MessageBuilderDetail::Encoder(caps) => {
265 ffi::gst_missing_encoder_message_new(src, caps.to_glib_none().0)
266 }
267 MessageBuilderDetail::Element(name) => {
268 ffi::gst_missing_element_message_new(src, name.to_glib_none().0)
269 }
270 MessageBuilderDetail::Sink(protocol) => {
271 ffi::gst_missing_uri_sink_message_new(src, protocol.to_glib_none().0)
272 }
273 MessageBuilderDetail::Src(protocol) => {
274 ffi::gst_missing_uri_source_message_new(src, protocol.to_glib_none().0)
275 }
276 };
277
278 #[cfg(feature = "v1_26")]
279 if let Some(stream_id) = s.stream_id {
280 ffi::gst_missing_plugin_message_set_stream_id(msg, stream_id.to_glib_none().0);
281 }
282
283 msg
284 });
285}
286
287#[derive(Clone, Debug)]
288pub struct MissingPluginMessage<'a> {
289 pub msg: &'a gst::MessageRef,
290}
291
292impl<'a> MissingPluginMessage<'a> {
293 #[doc(alias = "gst_missing_decoder_message_new")]
294 #[allow(clippy::new_ret_no_self)]
295 pub fn for_decoder(caps: &'a gst::Caps) -> gst::Message {
296 skip_assert_initialized!();
297 MissingPluginMessageBuilder::new(MessageBuilderDetail::Decoder(caps)).build()
298 }
299
300 #[doc(alias = "gst_missing_decoder_message_new")]
301 pub fn builder_for_decoder(caps: &'a gst::Caps) -> MissingPluginMessageBuilder<'a> {
302 skip_assert_initialized!();
303 MissingPluginMessageBuilder::new(MessageBuilderDetail::Decoder(caps))
304 }
305
306 #[doc(alias = "gst_missing_encoder_message_new")]
307 #[allow(clippy::new_ret_no_self)]
308 pub fn for_encoder(caps: &'a gst::Caps) -> gst::Message {
309 skip_assert_initialized!();
310 MissingPluginMessageBuilder::new(MessageBuilderDetail::Encoder(caps)).build()
311 }
312
313 #[doc(alias = "gst_missing_encoder_message_new")]
314 pub fn builder_for_encoder(caps: &'a gst::Caps) -> MissingPluginMessageBuilder<'a> {
315 skip_assert_initialized!();
316 MissingPluginMessageBuilder::new(MessageBuilderDetail::Encoder(caps))
317 }
318
319 #[doc(alias = "gst_missing_element_message_new")]
320 #[allow(clippy::new_ret_no_self)]
321 pub fn for_element(name: &'a str) -> gst::Message {
322 skip_assert_initialized!();
323 MissingPluginMessageBuilder::new(MessageBuilderDetail::Element(name)).build()
324 }
325
326 #[doc(alias = "gst_missing_element_message_new")]
327 pub fn builder_for_element(name: &'a str) -> MissingPluginMessageBuilder<'a> {
328 skip_assert_initialized!();
329 MissingPluginMessageBuilder::new(MessageBuilderDetail::Element(name))
330 }
331
332 #[doc(alias = "gst_missing_uri_source_message_new")]
333 #[allow(clippy::new_ret_no_self)]
334 pub fn for_uri_source(protocol: &'a str) -> gst::Message {
335 skip_assert_initialized!();
336 MissingPluginMessageBuilder::new(MessageBuilderDetail::Src(protocol)).build()
337 }
338
339 #[doc(alias = "gst_missing_uri_source_message_new")]
340 pub fn builder_for_uri_source(protocol: &'a str) -> MissingPluginMessageBuilder<'a> {
341 skip_assert_initialized!();
342 MissingPluginMessageBuilder::new(MessageBuilderDetail::Src(protocol))
343 }
344
345 #[doc(alias = "gst_missing_uri_sink_message_new")]
346 #[allow(clippy::new_ret_no_self)]
347 pub fn for_uri_sink(protocol: &'a str) -> gst::Message {
348 skip_assert_initialized!();
349 MissingPluginMessageBuilder::new(MessageBuilderDetail::Sink(protocol)).build()
350 }
351
352 #[doc(alias = "gst_missing_uri_sink_message_new")]
353 pub fn builder_for_uri_sink(protocol: &'a str) -> MissingPluginMessageBuilder<'a> {
354 skip_assert_initialized!();
355 MissingPluginMessageBuilder::new(MessageBuilderDetail::Sink(protocol))
356 }
357
358 #[doc(alias = "gst_is_missing_plugin_message")]
359 pub fn is(msg: &gst::MessageRef) -> bool {
360 skip_assert_initialized!();
361 unsafe {
362 from_glib(ffi::gst_is_missing_plugin_message(mut_override(
363 msg.as_ptr(),
364 )))
365 }
366 }
367
368 pub fn parse(msg: &'a gst::MessageRef) -> Result<Self, glib::error::BoolError> {
369 skip_assert_initialized!();
370 if Self::is(msg) {
371 Ok(MissingPluginMessage { msg })
372 } else {
373 Err(glib::bool_error!("Invalid missing plugin message"))
374 }
375 }
376
377 #[doc(alias = "gst_missing_plugin_message_get_description")]
378 pub fn description(&self) -> glib::GString {
379 unsafe {
380 from_glib_full(ffi::gst_missing_plugin_message_get_description(
381 mut_override(self.msg.as_ptr()),
382 ))
383 }
384 }
385
386 #[doc(alias = "gst_missing_plugin_message_get_installer_detail")]
387 pub fn installer_detail(&self) -> glib::GString {
388 unsafe {
389 from_glib_full(ffi::gst_missing_plugin_message_get_installer_detail(
390 mut_override(self.msg.as_ptr()),
391 ))
392 }
393 }
394
395 #[cfg(feature = "v1_26")]
396 #[cfg_attr(docsrs, doc(cfg(feature = "v1_26")))]
397 #[doc(alias = "gst_missing_plugin_message_get_stream_id")]
398 pub fn stream_id(&self) -> Option<&glib::GStr> {
399 unsafe {
400 let stream_id =
401 ffi::gst_missing_plugin_message_get_stream_id(mut_override(self.msg.as_ptr()));
402 if stream_id.is_null() {
403 None
404 } else {
405 Some(glib::GStr::from_ptr(stream_id))
406 }
407 }
408 }
409}
410
411#[doc(alias = "gst_missing_decoder_installer_detail_new")]
412pub fn missing_decoder_installer_detail_new(caps: &gst::Caps) -> glib::GString {
413 skip_assert_initialized!();
414 unsafe {
415 from_glib_full(ffi::gst_missing_decoder_installer_detail_new(mut_override(
416 caps.as_ptr(),
417 )))
418 }
419}
420
421#[doc(alias = "gst_missing_encoder_installer_detail_new")]
422pub fn missing_encoder_installer_detail_new(caps: &gst::Caps) -> glib::GString {
423 skip_assert_initialized!();
424 unsafe {
425 from_glib_full(ffi::gst_missing_encoder_installer_detail_new(mut_override(
426 caps.as_ptr(),
427 )))
428 }
429}
430
431#[doc(alias = "gst_missing_element_installer_detail_new")]
432pub fn missing_element_installer_detail_new(name: &str) -> glib::GString {
433 skip_assert_initialized!();
434 unsafe {
435 from_glib_full(ffi::gst_missing_element_installer_detail_new(mut_override(
436 name.to_glib_none().0,
437 )))
438 }
439}
440
441#[doc(alias = "gst_missing_uri_source_installer_detail_new")]
442pub fn missing_uri_source_installer_detail_new(protocol: &str) -> glib::GString {
443 skip_assert_initialized!();
444 unsafe {
445 from_glib_full(ffi::gst_missing_uri_source_installer_detail_new(
446 mut_override(protocol.to_glib_none().0),
447 ))
448 }
449}
450
451#[doc(alias = "gst_missing_uri_sink_installer_detail_new")]
452pub fn missing_uri_sink_installer_detail_new(protocol: &str) -> glib::GString {
453 skip_assert_initialized!();
454 unsafe {
455 from_glib_full(ffi::gst_missing_uri_sink_installer_detail_new(
456 mut_override(protocol.to_glib_none().0),
457 ))
458 }
459}
460
461#[doc(alias = "gst_install_plugins_supported")]
462pub fn install_plugins_supported() -> bool {
463 skip_assert_initialized!();
464 unsafe { from_glib(ffi::gst_install_plugins_supported()) }
465}
466
467#[doc(alias = "gst_install_plugins_installation_in_progress")]
468pub fn install_plugins_installation_in_progress() -> bool {
469 skip_assert_initialized!();
470 unsafe { from_glib(ffi::gst_install_plugins_installation_in_progress()) }
471}
472
473#[doc(alias = "gst_install_plugins_sync")]
474pub fn install_plugins_sync(
475 details: &[&str],
476 ctx: Option<&crate::InstallPluginsContext>,
477) -> crate::InstallPluginsReturn {
478 skip_assert_initialized!();
479 unsafe {
480 from_glib(ffi::gst_install_plugins_sync(
481 ToGlibPtr::<*const *mut _>::to_glib_none(&glib::StrV::from(details)).0
482 as *const *const _,
483 ctx.to_glib_none().0,
484 ))
485 }
486}
487
488#[doc(alias = "gst_install_plugins_async")]
489pub fn install_plugins_async<F: FnOnce(crate::InstallPluginsReturn) + Send + 'static>(
490 details: &[&str],
491 ctx: Option<&crate::InstallPluginsContext>,
492 func: F,
493) -> crate::InstallPluginsReturn {
494 skip_assert_initialized!();
495
496 let user_data: Box<Option<F>> = Box::new(Some(func));
497
498 unsafe extern "C" fn trampoline<F: FnOnce(crate::InstallPluginsReturn) + Send + 'static>(
499 ret: ffi::GstInstallPluginsReturn,
500 user_data: glib::ffi::gpointer,
501 ) {
502 let callback = Box::from_raw(user_data as *mut F);
503 callback(from_glib(ret));
504 }
505
506 unsafe {
507 from_glib(ffi::gst_install_plugins_async(
508 ToGlibPtr::<*const *mut _>::to_glib_none(&glib::StrV::from(details)).0
509 as *const *const _,
510 ctx.to_glib_none().0,
511 Some(trampoline::<F>),
512 Box::into_raw(user_data) as *mut _,
513 ))
514 }
515}