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 .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}