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 #[deprecated = "use builder.other_field() instead"]
143 #[allow(clippy::needless_update)]
144 pub fn other_fields(
145 self,
146 other_fields: &[(&'a str, &'a (dyn ToSendValue + Sync))],
147 ) -> Self {
148 Self {
149 builder: self.builder.other_fields(other_fields),
150 ..self
151 }
152 }
153
154 #[must_use = "Building the message without using it has no effect"]
155 #[allow(clippy::redundant_closure_call)]
156 pub fn build(mut self) -> Message {
157 skip_assert_initialized!();
158 unsafe {
159 let src = self.builder.src.to_glib_none().0;
160 let msg = $new_fn(&mut self, src);
161 if let Some(seqnum) = self.builder.seqnum {
162 gst_ffi::gst_message_set_seqnum(msg, seqnum.into_glib());
163 }
164
165 #[cfg(feature = "v1_26")]
166 if let Some(details) = self.builder.details {
167 gst_ffi::gst_message_set_details(msg, details.into_glib_ptr());
168 }
169
170 if !self.builder.other_fields.is_empty() {
171 let structure = gst_ffi::gst_message_writable_structure(msg);
172
173 if !structure.is_null() {
174 let structure =
175 gst::StructureRef::from_glib_borrow_mut(structure as *mut _);
176
177 for (k, v) in self.builder.other_fields {
178 structure.set_value(k, v);
179 }
180 }
181 }
182
183 from_glib_full(msg)
184 }
185 }
186 };
187}
188
189struct MessageBuilder<'a> {
190 src: Option<Element>,
191 seqnum: Option<Seqnum>,
192 #[cfg(feature = "v1_26")]
193 details: Option<gst::Structure>,
194 other_fields: Vec<(&'a str, glib::SendValue)>,
195}
196
197impl<'a> MessageBuilder<'a> {
198 fn new() -> Self {
199 skip_assert_initialized!();
200 Self {
201 src: None,
202 seqnum: None,
203 #[cfg(feature = "v1_26")]
204 details: None,
205 other_fields: Vec::new(),
206 }
207 }
208
209 fn src<O: IsA<Element> + Cast + Clone>(self, src: &O) -> Self {
210 Self {
211 src: Some(src.clone().upcast::<Element>()),
212 ..self
213 }
214 }
215
216 fn seqnum(self, seqnum: Seqnum) -> Self {
217 Self {
218 seqnum: Some(seqnum),
219 ..self
220 }
221 }
222
223 #[cfg(feature = "v1_26")]
224 #[cfg_attr(docsrs, doc(cfg(feature = "v1_26")))]
225 #[doc(alias = "gst_message_set_details")]
226 fn details(self, details: gst::Structure) -> Self {
227 Self {
228 details: Some(details),
229 ..self
230 }
231 }
232
233 fn other_field(self, name: &'a str, value: impl ToSendValue) -> Self {
234 let mut other_fields = self.other_fields;
235 other_fields.push((name, value.to_send_value()));
236
237 Self {
238 other_fields,
239 ..self
240 }
241 }
242
243 fn other_fields(self, other_fields: &[(&'a str, &'a (dyn ToSendValue + Sync))]) -> Self {
244 let mut s = self;
245
246 for (name, value) in other_fields {
247 s = s.other_field(name, value.to_send_value());
248 }
249
250 s
251 }
252}
253
254enum MessageBuilderDetail<'a> {
255 Decoder(&'a gst::Caps),
256 Encoder(&'a gst::Caps),
257 Element(&'a str),
258 Sink(&'a str),
259 Src(&'a str),
260}
261
262#[must_use = "The builder must be built to be used"]
263pub struct MissingPluginMessageBuilder<'a> {
264 builder: MessageBuilder<'a>,
265 detail: MessageBuilderDetail<'a>,
266 #[cfg(feature = "v1_26")]
267 stream_id: Option<&'a str>,
268}
269
270impl<'a> MissingPluginMessageBuilder<'a> {
271 fn new(detail: MessageBuilderDetail<'a>) -> Self {
272 skip_assert_initialized!();
273 Self {
274 builder: MessageBuilder::new(),
275 detail,
276 #[cfg(feature = "v1_26")]
277 stream_id: None,
278 }
279 }
280
281 message_builder_generic_impl!(|s: &Self, src| {
282 let msg = match s.detail {
283 MessageBuilderDetail::Decoder(caps) => {
284 ffi::gst_missing_decoder_message_new(src, caps.to_glib_none().0)
285 }
286 MessageBuilderDetail::Encoder(caps) => {
287 ffi::gst_missing_encoder_message_new(src, caps.to_glib_none().0)
288 }
289 MessageBuilderDetail::Element(name) => {
290 ffi::gst_missing_element_message_new(src, name.to_glib_none().0)
291 }
292 MessageBuilderDetail::Sink(protocol) => {
293 ffi::gst_missing_uri_sink_message_new(src, protocol.to_glib_none().0)
294 }
295 MessageBuilderDetail::Src(protocol) => {
296 ffi::gst_missing_uri_source_message_new(src, protocol.to_glib_none().0)
297 }
298 };
299
300 #[cfg(feature = "v1_26")]
301 if let Some(stream_id) = s.stream_id {
302 ffi::gst_missing_plugin_message_set_stream_id(msg, stream_id.to_glib_none().0);
303 }
304
305 msg
306 });
307}
308
309#[derive(Clone, Debug)]
310pub struct MissingPluginMessage<'a> {
311 pub msg: &'a gst::MessageRef,
312}
313
314impl<'a> MissingPluginMessage<'a> {
315 #[doc(alias = "gst_missing_decoder_message_new")]
316 #[allow(clippy::new_ret_no_self)]
317 pub fn for_decoder(caps: &'a gst::Caps) -> gst::Message {
318 skip_assert_initialized!();
319 MissingPluginMessageBuilder::new(MessageBuilderDetail::Decoder(caps)).build()
320 }
321
322 #[doc(alias = "gst_missing_decoder_message_new")]
323 pub fn builder_for_decoder(caps: &'a gst::Caps) -> MissingPluginMessageBuilder<'a> {
324 skip_assert_initialized!();
325 MissingPluginMessageBuilder::new(MessageBuilderDetail::Decoder(caps))
326 }
327
328 #[doc(alias = "gst_missing_encoder_message_new")]
329 #[allow(clippy::new_ret_no_self)]
330 pub fn for_encoder(caps: &'a gst::Caps) -> gst::Message {
331 skip_assert_initialized!();
332 MissingPluginMessageBuilder::new(MessageBuilderDetail::Encoder(caps)).build()
333 }
334
335 #[doc(alias = "gst_missing_encoder_message_new")]
336 pub fn builder_for_encoder(caps: &'a gst::Caps) -> MissingPluginMessageBuilder<'a> {
337 skip_assert_initialized!();
338 MissingPluginMessageBuilder::new(MessageBuilderDetail::Encoder(caps))
339 }
340
341 #[doc(alias = "gst_missing_element_message_new")]
342 #[allow(clippy::new_ret_no_self)]
343 pub fn for_element(name: &'a str) -> gst::Message {
344 skip_assert_initialized!();
345 MissingPluginMessageBuilder::new(MessageBuilderDetail::Element(name)).build()
346 }
347
348 #[doc(alias = "gst_missing_element_message_new")]
349 pub fn builder_for_element(name: &'a str) -> MissingPluginMessageBuilder<'a> {
350 skip_assert_initialized!();
351 MissingPluginMessageBuilder::new(MessageBuilderDetail::Element(name))
352 }
353
354 #[doc(alias = "gst_missing_uri_source_message_new")]
355 #[allow(clippy::new_ret_no_self)]
356 pub fn for_uri_source(protocol: &'a str) -> gst::Message {
357 skip_assert_initialized!();
358 MissingPluginMessageBuilder::new(MessageBuilderDetail::Src(protocol)).build()
359 }
360
361 #[doc(alias = "gst_missing_uri_source_message_new")]
362 pub fn builder_for_uri_source(protocol: &'a str) -> MissingPluginMessageBuilder<'a> {
363 skip_assert_initialized!();
364 MissingPluginMessageBuilder::new(MessageBuilderDetail::Src(protocol))
365 }
366
367 #[doc(alias = "gst_missing_uri_sink_message_new")]
368 #[allow(clippy::new_ret_no_self)]
369 pub fn for_uri_sink(protocol: &'a str) -> gst::Message {
370 skip_assert_initialized!();
371 MissingPluginMessageBuilder::new(MessageBuilderDetail::Sink(protocol)).build()
372 }
373
374 #[doc(alias = "gst_missing_uri_sink_message_new")]
375 pub fn builder_for_uri_sink(protocol: &'a str) -> MissingPluginMessageBuilder<'a> {
376 skip_assert_initialized!();
377 MissingPluginMessageBuilder::new(MessageBuilderDetail::Sink(protocol))
378 }
379
380 #[doc(alias = "gst_is_missing_plugin_message")]
381 pub fn is(msg: &gst::MessageRef) -> bool {
382 skip_assert_initialized!();
383 unsafe {
384 from_glib(ffi::gst_is_missing_plugin_message(mut_override(
385 msg.as_ptr(),
386 )))
387 }
388 }
389
390 pub fn parse(msg: &'a gst::MessageRef) -> Result<Self, glib::error::BoolError> {
391 skip_assert_initialized!();
392 if Self::is(msg) {
393 Ok(MissingPluginMessage { msg })
394 } else {
395 Err(glib::bool_error!("Invalid missing plugin message"))
396 }
397 }
398
399 #[doc(alias = "gst_missing_plugin_message_get_description")]
400 pub fn description(&self) -> glib::GString {
401 unsafe {
402 from_glib_full(ffi::gst_missing_plugin_message_get_description(
403 mut_override(self.msg.as_ptr()),
404 ))
405 }
406 }
407
408 #[doc(alias = "gst_missing_plugin_message_get_installer_detail")]
409 pub fn installer_detail(&self) -> glib::GString {
410 unsafe {
411 from_glib_full(ffi::gst_missing_plugin_message_get_installer_detail(
412 mut_override(self.msg.as_ptr()),
413 ))
414 }
415 }
416
417 #[cfg(feature = "v1_26")]
418 #[cfg_attr(docsrs, doc(cfg(feature = "v1_26")))]
419 #[doc(alias = "gst_missing_plugin_message_get_stream_id")]
420 pub fn stream_id(&self) -> Option<&glib::GStr> {
421 unsafe {
422 let stream_id =
423 ffi::gst_missing_plugin_message_get_stream_id(mut_override(self.msg.as_ptr()));
424 if stream_id.is_null() {
425 None
426 } else {
427 Some(glib::GStr::from_ptr(stream_id))
428 }
429 }
430 }
431}
432
433#[doc(alias = "gst_missing_decoder_installer_detail_new")]
434pub fn missing_decoder_installer_detail_new(caps: &gst::Caps) -> glib::GString {
435 skip_assert_initialized!();
436 unsafe {
437 from_glib_full(ffi::gst_missing_decoder_installer_detail_new(mut_override(
438 caps.as_ptr(),
439 )))
440 }
441}
442
443#[doc(alias = "gst_missing_encoder_installer_detail_new")]
444pub fn missing_encoder_installer_detail_new(caps: &gst::Caps) -> glib::GString {
445 skip_assert_initialized!();
446 unsafe {
447 from_glib_full(ffi::gst_missing_encoder_installer_detail_new(mut_override(
448 caps.as_ptr(),
449 )))
450 }
451}
452
453#[doc(alias = "gst_missing_element_installer_detail_new")]
454pub fn missing_element_installer_detail_new(name: &str) -> glib::GString {
455 skip_assert_initialized!();
456 unsafe {
457 from_glib_full(ffi::gst_missing_element_installer_detail_new(mut_override(
458 name.to_glib_none().0,
459 )))
460 }
461}
462
463#[doc(alias = "gst_missing_uri_source_installer_detail_new")]
464pub fn missing_uri_source_installer_detail_new(protocol: &str) -> glib::GString {
465 skip_assert_initialized!();
466 unsafe {
467 from_glib_full(ffi::gst_missing_uri_source_installer_detail_new(
468 mut_override(protocol.to_glib_none().0),
469 ))
470 }
471}
472
473#[doc(alias = "gst_missing_uri_sink_installer_detail_new")]
474pub fn missing_uri_sink_installer_detail_new(protocol: &str) -> glib::GString {
475 skip_assert_initialized!();
476 unsafe {
477 from_glib_full(ffi::gst_missing_uri_sink_installer_detail_new(
478 mut_override(protocol.to_glib_none().0),
479 ))
480 }
481}
482
483#[doc(alias = "gst_install_plugins_supported")]
484pub fn install_plugins_supported() -> bool {
485 skip_assert_initialized!();
486 unsafe { from_glib(ffi::gst_install_plugins_supported()) }
487}
488
489#[doc(alias = "gst_install_plugins_installation_in_progress")]
490pub fn install_plugins_installation_in_progress() -> bool {
491 skip_assert_initialized!();
492 unsafe { from_glib(ffi::gst_install_plugins_installation_in_progress()) }
493}
494
495#[doc(alias = "gst_install_plugins_sync")]
496pub fn install_plugins_sync(
497 details: &[&str],
498 ctx: Option<&crate::InstallPluginsContext>,
499) -> crate::InstallPluginsReturn {
500 skip_assert_initialized!();
501 unsafe {
502 from_glib(ffi::gst_install_plugins_sync(
503 ToGlibPtr::<*const *mut _>::to_glib_none(&glib::StrV::from(details)).0
504 as *const *const _,
505 ctx.to_glib_none().0,
506 ))
507 }
508}
509
510#[doc(alias = "gst_install_plugins_async")]
511pub fn install_plugins_async<F: FnOnce(crate::InstallPluginsReturn) + Send + 'static>(
512 details: &[&str],
513 ctx: Option<&crate::InstallPluginsContext>,
514 func: F,
515) -> crate::InstallPluginsReturn {
516 skip_assert_initialized!();
517
518 let user_data: Box<Option<F>> = Box::new(Some(func));
519
520 unsafe extern "C" fn trampoline<F: FnOnce(crate::InstallPluginsReturn) + Send + 'static>(
521 ret: ffi::GstInstallPluginsReturn,
522 user_data: glib::ffi::gpointer,
523 ) {
524 let callback = Box::from_raw(user_data as *mut F);
525 callback(from_glib(ret));
526 }
527
528 unsafe {
529 from_glib(ffi::gst_install_plugins_async(
530 ToGlibPtr::<*const *mut _>::to_glib_none(&glib::StrV::from(details)).0
531 as *const *const _,
532 ctx.to_glib_none().0,
533 Some(trampoline::<F>),
534 Box::into_raw(user_data) as *mut _,
535 ))
536 }
537}