gstreamer/subclass/
error.rs
1use thiserror::Error;
4
5use crate::{prelude::ElementExt, ErrorMessage, FlowReturn};
6
7#[doc(hidden)]
8#[inline(never)]
9pub fn post_panic_error_message(
10 element: &crate::Element,
11 src: &crate::Object,
12 panic: Option<Box<dyn std::any::Any + Send + 'static>>,
13) {
14 let cause = panic.as_ref().and_then(|err| {
15 err.downcast_ref::<&str>()
16 .copied()
17 .or_else(|| err.downcast_ref::<String>().map(|s| s.as_str()))
18 });
19
20 let msg = if let Some(cause) = cause {
21 crate::message::Error::builder(crate::LibraryError::Failed, &format!("Panicked: {cause}"))
22 .src(src)
23 .build()
24 } else {
25 crate::message::Error::builder(crate::LibraryError::Failed, "Panicked")
26 .src(src)
27 .build()
28 };
29
30 let _ = element.post_message(msg);
31}
32
33#[macro_export]
34macro_rules! panic_to_error(
35 ($imp:expr, $ret:expr, $code:block) => {{
36 #[allow(clippy::unused_unit)]
37 #[cfg(panic = "abort")]
38 {
39 if true {
40 #[allow(unused_mut)]
41 let mut closure = || { $code };
42 closure()
43 } else {
44 let _imp = $imp;
45 $ret
46 }
47 }
48 #[cfg(not(panic = "abort"))]
49 {
50 let panicked = $imp.panicked();
51 let element = $crate::glib::subclass::types::ObjectSubclassExt::obj($imp);
52 let element = unsafe { $crate::glib::prelude::Cast::unsafe_cast_ref::<$crate::Element>(element.as_ref()) };
53 if panicked.load(std::sync::atomic::Ordering::Relaxed) {
54 $crate::subclass::post_panic_error_message(
55 element,
56 $crate::glib::prelude::Cast::upcast_ref::<$crate::Object>(element),
57 None,
58 );
59 $ret
60 } else {
61 let result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| $code));
62
63 match result {
64 Ok(result) => result,
65 Err(err) => {
66 panicked.store(true, std::sync::atomic::Ordering::Relaxed);
67 $crate::subclass::post_panic_error_message(
68 element,
69 $crate::glib::prelude::Cast::upcast_ref::<$crate::Object>(element),
70 Some(err),
71 );
72 $ret
73 }
74 }
75 }
76 }
77 }};
78);
79
80#[derive(Clone, Debug, PartialEq, Eq, Error)]
81pub enum FlowError {
82 #[error("Flushing")]
83 Flushing,
84 #[error("Eos")]
85 Eos,
86 #[error("Not Negotiated")]
87 NotNegotiated(ErrorMessage),
88 #[error("Error")]
89 Error(ErrorMessage),
90}
91
92impl From<FlowError> for FlowReturn {
93 fn from(err: FlowError) -> Self {
94 FlowReturn::from(&err)
95 }
96}
97
98impl From<&FlowError> for FlowReturn {
99 fn from(err: &FlowError) -> FlowReturn {
100 match *err {
101 FlowError::Flushing => FlowReturn::Flushing,
102 FlowError::Eos => FlowReturn::Eos,
103 FlowError::NotNegotiated(..) => FlowReturn::NotNegotiated,
104 FlowError::Error(..) => FlowReturn::Error,
105 }
106 }
107}