gstreamer_play/
play_message.rs

1use crate::{Play, PlayMediaInfo, PlayMessageType, PlayState};
2
3#[derive(Debug)]
4#[non_exhaustive]
5#[doc(alias = "GstPlayMessage")]
6pub enum PlayMessage<'a> {
7    #[doc(alias = "GST_PLAY_MESSAGE_URI_LOADED")]
8    UriLoaded(&'a UriLoaded),
9    #[doc(alias = "GST_PLAY_MESSAGE_POSITION_UPDATED")]
10    PositionUpdated(&'a PositionUpdated),
11    #[doc(alias = "GST_PLAY_MESSAGE_DURATION_CHANGED")]
12    DurationChanged(&'a DurationChanged),
13    #[doc(alias = "GST_PLAY_MESSAGE_STATE_CHANGED")]
14    StateChanged(&'a StateChanged),
15    #[doc(alias = "GST_PLAY_MESSAGE_BUFFERING")]
16    Buffering(&'a Buffering),
17    #[doc(alias = "GST_PLAY_MESSAGE_END_OF_STREAM")]
18    EndOfStream(&'a EndOfStream),
19    #[doc(alias = "GST_PLAY_MESSAGE_ERROR")]
20    Error(&'a Error),
21    #[doc(alias = "GST_PLAY_MESSAGE_WARNING")]
22    Warning(&'a Warning),
23    #[doc(alias = "GST_PLAY_MESSAGE_VIDEO_DIMENSIONS_CHANGED")]
24    VideoDimensionsChanged(&'a VideoDimensionsChanged),
25    #[doc(alias = "GST_PLAY_MESSAGE_MEDIA_INFO_UPDATED")]
26    MediaInfoUpdated(&'a MediaInfoUpdated),
27    #[doc(alias = "GST_PLAY_MESSAGE_VOLUME_CHANGED")]
28    VolumeChanged(&'a VolumeChanged),
29    #[doc(alias = "GST_PLAY_MESSAGE_MUTE_CHANGED")]
30    MuteChanged(&'a MuteChanged),
31    #[doc(alias = "GST_PLAY_MESSAGE_SEEK_DONE")]
32    SeekDone(&'a SeekDone),
33    Other(&'a Other),
34}
35
36macro_rules! declare_concrete_message(
37    ($name:ident) => {
38        #[repr(transparent)]
39        pub struct $name<T = gst::MessageRef>(T);
40
41        impl $name {
42            #[inline]
43            pub fn message(&self) -> &gst::MessageRef {
44                unsafe { &*(self as *const Self as *const gst::MessageRef) }
45            }
46
47            #[inline]
48            unsafe fn view(message: &gst::MessageRef) -> PlayMessage<'_> {
49                let message = &*(message as *const gst::MessageRef as *const Self);
50                PlayMessage::$name(message)
51            }
52        }
53
54        impl std::ops::Deref for $name {
55            type Target = gst::MessageRef;
56
57            #[inline]
58            fn deref(&self) -> &Self::Target {
59                unsafe {
60                    &*(self as *const Self as *const Self::Target)
61                }
62            }
63        }
64
65        impl ToOwned for $name {
66            type Owned = $name<gst::Message>;
67
68            #[inline]
69            fn to_owned(&self) -> Self::Owned {
70                $name::<gst::Message>(self.copy())
71            }
72        }
73
74        impl std::ops::Deref for $name<gst::Message> {
75            type Target = $name;
76
77            #[inline]
78            fn deref(&self) -> &Self::Target {
79                unsafe { &*(self.0.as_ptr() as *const Self::Target) }
80            }
81        }
82
83        impl std::borrow::Borrow<$name> for $name<gst::Message> {
84            #[inline]
85            fn borrow(&self) -> &$name {
86                &*self
87            }
88        }
89
90        impl From<$name<gst::Message>> for gst::Message {
91            #[inline]
92            fn from(concrete: $name<gst::Message>) -> Self {
93                skip_assert_initialized!();
94                concrete.0
95            }
96        }
97    }
98);
99
100declare_concrete_message!(UriLoaded);
101impl UriLoaded {
102    pub fn uri(&self) -> &glib::GStr {
103        self.message().structure().unwrap().get("uri").unwrap()
104    }
105}
106impl std::fmt::Debug for UriLoaded {
107    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
108        f.debug_struct("UriLoaded")
109            .field("structure", &self.message().structure())
110            .field("uri", &self.uri())
111            .finish()
112    }
113}
114
115declare_concrete_message!(PositionUpdated);
116impl PositionUpdated {
117    pub fn position(&self) -> Option<gst::ClockTime> {
118        self.message().structure().unwrap().get("position").unwrap()
119    }
120
121    #[cfg(feature = "v1_26")]
122    #[cfg_attr(docsrs, doc(cfg(feature = "v1_26")))]
123    #[doc(alias = "gst_play_message_get_uri")]
124    pub fn uri(&self) -> glib::GString {
125        use crate::ffi;
126        use glib::translate::*;
127
128        assert_initialized_main_thread!();
129        unsafe {
130            from_glib_none(ffi::gst_play_message_get_uri(mut_override(
131                self.message().as_ptr(),
132            )))
133        }
134    }
135}
136impl std::fmt::Debug for PositionUpdated {
137    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
138        f.debug_struct("PositionUpdated")
139            .field("structure", &self.message().structure())
140            .field("position", &self.position())
141            .finish()
142    }
143}
144
145declare_concrete_message!(DurationChanged);
146impl DurationChanged {
147    pub fn duration(&self) -> Option<gst::ClockTime> {
148        self.message().structure().unwrap().get("duration").unwrap()
149    }
150
151    #[cfg(feature = "v1_26")]
152    #[cfg_attr(docsrs, doc(cfg(feature = "v1_26")))]
153    #[doc(alias = "gst_play_message_get_uri")]
154    pub fn uri(&self) -> glib::GString {
155        use crate::ffi;
156        use glib::translate::*;
157
158        assert_initialized_main_thread!();
159        unsafe {
160            from_glib_none(ffi::gst_play_message_get_uri(mut_override(
161                self.message().as_ptr(),
162            )))
163        }
164    }
165}
166impl std::fmt::Debug for DurationChanged {
167    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
168        f.debug_struct("DurationChanged")
169            .field("structure", &self.message().structure())
170            .field("duration", &self.duration())
171            .finish()
172    }
173}
174
175declare_concrete_message!(StateChanged);
176impl StateChanged {
177    pub fn state(&self) -> PlayState {
178        self.message()
179            .structure()
180            .unwrap()
181            .get("play-state")
182            .unwrap()
183    }
184
185    #[cfg(feature = "v1_26")]
186    #[cfg_attr(docsrs, doc(cfg(feature = "v1_26")))]
187    #[doc(alias = "gst_play_message_get_uri")]
188    pub fn uri(&self) -> glib::GString {
189        use crate::ffi;
190        use glib::translate::*;
191
192        assert_initialized_main_thread!();
193        unsafe {
194            from_glib_none(ffi::gst_play_message_get_uri(mut_override(
195                self.message().as_ptr(),
196            )))
197        }
198    }
199}
200impl std::fmt::Debug for StateChanged {
201    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
202        f.debug_struct("StateChanged")
203            .field("structure", &self.message().structure())
204            .field("state", &self.state())
205            .finish()
206    }
207}
208
209declare_concrete_message!(Buffering);
210impl Buffering {
211    pub fn percent(&self) -> u32 {
212        self.message()
213            .structure()
214            .unwrap()
215            // Typo in the library
216            .get("bufferring-percent")
217            .unwrap()
218    }
219
220    #[cfg(feature = "v1_26")]
221    #[cfg_attr(docsrs, doc(cfg(feature = "v1_26")))]
222    #[doc(alias = "gst_play_message_get_uri")]
223    pub fn uri(&self) -> glib::GString {
224        use crate::ffi;
225        use glib::translate::*;
226
227        assert_initialized_main_thread!();
228        unsafe {
229            from_glib_none(ffi::gst_play_message_get_uri(mut_override(
230                self.message().as_ptr(),
231            )))
232        }
233    }
234}
235impl std::fmt::Debug for Buffering {
236    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
237        f.debug_struct("Buffering")
238            .field("structure", &self.message().structure())
239            .field("percent", &self.percent())
240            .finish()
241    }
242}
243
244declare_concrete_message!(EndOfStream);
245impl std::fmt::Debug for EndOfStream {
246    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
247        f.debug_struct("EndOfStream")
248            .field("structure", &self.message().structure())
249            .finish()
250    }
251}
252
253declare_concrete_message!(Error);
254impl Error {
255    pub fn error(&self) -> &glib::Error {
256        self.message().structure().unwrap().get("error").unwrap()
257    }
258
259    pub fn details(&self) -> Option<&gst::StructureRef> {
260        self.message()
261            .structure()
262            .unwrap()
263            .get_optional("error-details")
264            .unwrap()
265    }
266
267    #[cfg(feature = "v1_26")]
268    #[cfg_attr(docsrs, doc(cfg(feature = "v1_26")))]
269    #[doc(alias = "gst_play_message_get_uri")]
270    pub fn uri(&self) -> glib::GString {
271        use crate::ffi;
272        use glib::translate::*;
273
274        assert_initialized_main_thread!();
275        unsafe {
276            from_glib_none(ffi::gst_play_message_get_uri(mut_override(
277                self.message().as_ptr(),
278            )))
279        }
280    }
281
282    #[cfg(feature = "v1_26")]
283    #[cfg_attr(docsrs, doc(cfg(feature = "v1_26")))]
284    #[doc(alias = "gst_play_message_get_stream_id")]
285    pub fn stream_id(&self) -> Option<glib::GString> {
286        use crate::ffi;
287        use glib::translate::*;
288
289        assert_initialized_main_thread!();
290        unsafe {
291            from_glib_none(ffi::gst_play_message_get_stream_id(mut_override(
292                self.message().as_ptr(),
293            )))
294        }
295    }
296
297    #[cfg(feature = "v1_26")]
298    #[cfg_attr(docsrs, doc(cfg(feature = "v1_26")))]
299    #[doc(alias = "gst_play_message_parse_error_missing_plugin")]
300    pub fn missing_plugin(&self) -> Option<Vec<(glib::GString, glib::GString)>> {
301        use crate::ffi;
302        use glib::translate::*;
303
304        assert_initialized_main_thread!();
305        unsafe {
306            let mut descriptions = std::ptr::null_mut();
307            let mut installer_details = std::ptr::null_mut();
308            let ret = from_glib(ffi::gst_play_message_parse_error_missing_plugin(
309                mut_override(self.message().as_ptr()),
310                &mut descriptions,
311                &mut installer_details,
312            ));
313            if ret {
314                let mut ret = Vec::new();
315                for idx in 0.. {
316                    let description = *descriptions.add(idx);
317                    let installer_detail = *installer_details.add(idx);
318
319                    if description.is_null() {
320                        assert!(installer_detail.is_null());
321                        break;
322                    }
323
324                    ret.push((
325                        glib::GString::from_glib_full(description),
326                        glib::GString::from_glib_full(installer_detail),
327                    ));
328                }
329                glib::ffi::g_free(descriptions as glib::ffi::gpointer);
330                glib::ffi::g_free(installer_details as glib::ffi::gpointer);
331
332                Some(ret)
333            } else {
334                None
335            }
336        }
337    }
338}
339impl std::fmt::Debug for Error {
340    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
341        f.debug_struct("Error")
342            .field("structure", &self.message().structure())
343            .field("error", &self.error())
344            .field("details", &self.details())
345            .finish()
346    }
347}
348
349declare_concrete_message!(Warning);
350impl Warning {
351    pub fn error(&self) -> &glib::Error {
352        self.message().structure().unwrap().get("warning").unwrap()
353    }
354
355    pub fn details(&self) -> Option<&gst::StructureRef> {
356        self.message()
357            .structure()
358            .unwrap()
359            .get_optional("warning-details")
360            .unwrap()
361    }
362
363    #[cfg(feature = "v1_26")]
364    #[cfg_attr(docsrs, doc(cfg(feature = "v1_26")))]
365    #[doc(alias = "gst_play_message_get_uri")]
366    pub fn uri(&self) -> glib::GString {
367        use crate::ffi;
368        use glib::translate::*;
369
370        assert_initialized_main_thread!();
371        unsafe {
372            from_glib_none(ffi::gst_play_message_get_uri(mut_override(
373                self.message().as_ptr(),
374            )))
375        }
376    }
377
378    #[cfg(feature = "v1_26")]
379    #[cfg_attr(docsrs, doc(cfg(feature = "v1_26")))]
380    #[doc(alias = "gst_play_message_get_stream_id")]
381    pub fn stream_id(&self) -> Option<glib::GString> {
382        use crate::ffi;
383        use glib::translate::*;
384
385        assert_initialized_main_thread!();
386        unsafe {
387            from_glib_none(ffi::gst_play_message_get_stream_id(mut_override(
388                self.message().as_ptr(),
389            )))
390        }
391    }
392
393    #[cfg(feature = "v1_26")]
394    #[cfg_attr(docsrs, doc(cfg(feature = "v1_26")))]
395    #[doc(alias = "gst_play_message_parse_warning_missing_plugin")]
396    pub fn missing_plugin(&self) -> Option<Vec<(glib::GString, glib::GString)>> {
397        use crate::ffi;
398        use glib::translate::*;
399
400        assert_initialized_main_thread!();
401        unsafe {
402            let mut descriptions = std::ptr::null_mut();
403            let mut installer_details = std::ptr::null_mut();
404            let ret = from_glib(ffi::gst_play_message_parse_warning_missing_plugin(
405                mut_override(self.message().as_ptr()),
406                &mut descriptions,
407                &mut installer_details,
408            ));
409            if ret {
410                let mut ret = Vec::new();
411                for idx in 0.. {
412                    let description = *descriptions.add(idx);
413                    let installer_detail = *installer_details.add(idx);
414
415                    if description.is_null() {
416                        assert!(installer_detail.is_null());
417                        break;
418                    }
419
420                    ret.push((
421                        glib::GString::from_glib_full(description),
422                        glib::GString::from_glib_full(installer_detail),
423                    ));
424                }
425                glib::ffi::g_free(descriptions as glib::ffi::gpointer);
426                glib::ffi::g_free(installer_details as glib::ffi::gpointer);
427
428                Some(ret)
429            } else {
430                None
431            }
432        }
433    }
434}
435impl std::fmt::Debug for Warning {
436    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
437        f.debug_struct("Warning")
438            .field("structure", &self.message().structure())
439            .field("error", &self.error())
440            .field("details", &self.details())
441            .finish()
442    }
443}
444
445declare_concrete_message!(VideoDimensionsChanged);
446impl VideoDimensionsChanged {
447    pub fn width(&self) -> u32 {
448        self.message()
449            .structure()
450            .unwrap()
451            .get("video-width")
452            .unwrap()
453    }
454
455    pub fn height(&self) -> u32 {
456        self.message()
457            .structure()
458            .unwrap()
459            .get("video-height")
460            .unwrap()
461    }
462
463    #[cfg(feature = "v1_26")]
464    #[cfg_attr(docsrs, doc(cfg(feature = "v1_26")))]
465    #[doc(alias = "gst_play_message_get_uri")]
466    pub fn uri(&self) -> glib::GString {
467        use crate::ffi;
468        use glib::translate::*;
469
470        assert_initialized_main_thread!();
471        unsafe {
472            from_glib_none(ffi::gst_play_message_get_uri(mut_override(
473                self.message().as_ptr(),
474            )))
475        }
476    }
477}
478impl std::fmt::Debug for VideoDimensionsChanged {
479    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
480        f.debug_struct("VideoDimensionsChanged")
481            .field("structure", &self.message().structure())
482            .field("width", &self.width())
483            .field("height", &self.height())
484            .finish()
485    }
486}
487
488declare_concrete_message!(MediaInfoUpdated);
489impl MediaInfoUpdated {
490    pub fn media_info(&self) -> &PlayMediaInfo {
491        self.message()
492            .structure()
493            .unwrap()
494            .get("media-info")
495            .unwrap()
496    }
497
498    #[cfg(feature = "v1_26")]
499    #[cfg_attr(docsrs, doc(cfg(feature = "v1_26")))]
500    #[doc(alias = "gst_play_message_get_uri")]
501    pub fn uri(&self) -> glib::GString {
502        use crate::ffi;
503        use glib::translate::*;
504
505        assert_initialized_main_thread!();
506        unsafe {
507            from_glib_none(ffi::gst_play_message_get_uri(mut_override(
508                self.message().as_ptr(),
509            )))
510        }
511    }
512}
513impl std::fmt::Debug for MediaInfoUpdated {
514    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
515        f.debug_struct("MediaInfoUpdated")
516            .field("structure", &self.message().structure())
517            .field("media_info", &self.media_info())
518            .finish()
519    }
520}
521
522declare_concrete_message!(VolumeChanged);
523impl VolumeChanged {
524    pub fn volume(&self) -> f64 {
525        self.message().structure().unwrap().get("volume").unwrap()
526    }
527
528    #[cfg(feature = "v1_26")]
529    #[cfg_attr(docsrs, doc(cfg(feature = "v1_26")))]
530    #[doc(alias = "gst_play_message_get_uri")]
531    pub fn uri(&self) -> glib::GString {
532        use crate::ffi;
533        use glib::translate::*;
534
535        assert_initialized_main_thread!();
536        unsafe {
537            from_glib_none(ffi::gst_play_message_get_uri(mut_override(
538                self.message().as_ptr(),
539            )))
540        }
541    }
542}
543impl std::fmt::Debug for VolumeChanged {
544    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
545        f.debug_struct("VolumeChanged")
546            .field("structure", &self.message().structure())
547            .field("volume", &self.volume())
548            .finish()
549    }
550}
551
552declare_concrete_message!(MuteChanged);
553impl MuteChanged {
554    pub fn is_muted(&self) -> bool {
555        self.message().structure().unwrap().get("is-muted").unwrap()
556    }
557
558    #[cfg(feature = "v1_26")]
559    #[cfg_attr(docsrs, doc(cfg(feature = "v1_26")))]
560    #[doc(alias = "gst_play_message_get_uri")]
561    pub fn uri(&self) -> glib::GString {
562        use crate::ffi;
563        use glib::translate::*;
564
565        assert_initialized_main_thread!();
566        unsafe {
567            from_glib_none(ffi::gst_play_message_get_uri(mut_override(
568                self.message().as_ptr(),
569            )))
570        }
571    }
572}
573impl std::fmt::Debug for MuteChanged {
574    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
575        f.debug_struct("MuteChanged")
576            .field("structure", &self.message().structure())
577            .field("is_muted", &self.is_muted())
578            .finish()
579    }
580}
581
582declare_concrete_message!(SeekDone);
583impl SeekDone {
584    pub fn position(&self) -> Option<gst::ClockTime> {
585        self.message().structure().unwrap().get("position").unwrap()
586    }
587
588    #[cfg(feature = "v1_26")]
589    #[cfg_attr(docsrs, doc(cfg(feature = "v1_26")))]
590    #[doc(alias = "gst_play_message_get_uri")]
591    pub fn uri(&self) -> glib::GString {
592        use crate::ffi;
593        use glib::translate::*;
594
595        assert_initialized_main_thread!();
596        unsafe {
597            from_glib_none(ffi::gst_play_message_get_uri(mut_override(
598                self.message().as_ptr(),
599            )))
600        }
601    }
602}
603impl std::fmt::Debug for SeekDone {
604    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
605        f.debug_struct("SeekDone")
606            .field("structure", &self.message().structure())
607            .field("position", &self.position())
608            .finish()
609    }
610}
611
612declare_concrete_message!(Other);
613
614impl Other {
615    #[cfg(feature = "v1_26")]
616    #[cfg_attr(docsrs, doc(cfg(feature = "v1_26")))]
617    #[doc(alias = "gst_play_message_get_uri")]
618    pub fn uri(&self) -> glib::GString {
619        use crate::ffi;
620        use glib::translate::*;
621
622        assert_initialized_main_thread!();
623        unsafe {
624            from_glib_none(ffi::gst_play_message_get_uri(mut_override(
625                self.message().as_ptr(),
626            )))
627        }
628    }
629}
630
631impl std::fmt::Debug for Other {
632    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
633        f.debug_struct("Other")
634            .field("structure", &self.message().structure())
635            .finish()
636    }
637}
638
639impl PlayMessage<'_> {
640    #[doc(alias = "gst_play_message_parse_uri_loaded")]
641    #[doc(alias = "gst_play_message_parse_position_updated")]
642    #[doc(alias = "gst_play_message_parse_duration_updated")]
643    #[doc(alias = "gst_play_message_parse_duration_changed")]
644    #[doc(alias = "gst_play_message_parse_state_changed")]
645    #[doc(alias = "gst_play_message_parse_buffering")]
646    #[doc(alias = "gst_play_message_parse_buffering_percent")]
647    #[doc(alias = "gst_play_message_parse_error")]
648    #[doc(alias = "gst_play_message_parse_warning")]
649    #[doc(alias = "gst_play_message_parse_video_dimensions_changed")]
650    #[doc(alias = "gst_play_message_parse_media_info_updated")]
651    #[doc(alias = "gst_play_message_parse_muted_changed")]
652    #[doc(alias = "gst_play_message_parse_volume_changed")]
653    #[doc(alias = "gst_play_message_parse_seek_done")]
654    pub fn parse(msg: &gst::Message) -> Result<PlayMessage, glib::error::BoolError> {
655        skip_assert_initialized!();
656
657        if !Play::is_play_message(msg) {
658            return Err(glib::bool_error!("Invalid play message"));
659        }
660
661        unsafe {
662            match PlayMessageType::parse_type(msg) {
663                PlayMessageType::UriLoaded => Ok(UriLoaded::view(msg)),
664                PlayMessageType::PositionUpdated => Ok(PositionUpdated::view(msg)),
665                PlayMessageType::DurationChanged => Ok(DurationChanged::view(msg)),
666                PlayMessageType::StateChanged => Ok(StateChanged::view(msg)),
667                PlayMessageType::Buffering => Ok(Buffering::view(msg)),
668                PlayMessageType::EndOfStream => Ok(EndOfStream::view(msg)),
669                PlayMessageType::Error => Ok(Error::view(msg)),
670                PlayMessageType::Warning => Ok(Warning::view(msg)),
671                PlayMessageType::VideoDimensionsChanged => Ok(VideoDimensionsChanged::view(msg)),
672                PlayMessageType::MediaInfoUpdated => Ok(MediaInfoUpdated::view(msg)),
673                PlayMessageType::VolumeChanged => Ok(VolumeChanged::view(msg)),
674                PlayMessageType::MuteChanged => Ok(MuteChanged::view(msg)),
675                PlayMessageType::SeekDone => Ok(SeekDone::view(msg)),
676                _ => Ok(Other::view(msg)),
677            }
678        }
679    }
680}