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