gstreamer/subclass/
error.rs1use thiserror::Error;
4
5use crate::{ErrorMessage, FlowReturn, prelude::ElementExt};
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 #[allow(unused_unsafe)]
49 #[cfg(not(panic = "abort"))]
50 {
51 let panicked = $imp.panicked();
52 let element = $crate::glib::subclass::types::ObjectSubclassExt::obj($imp);
53 let element = unsafe { $crate::glib::prelude::Cast::unsafe_cast_ref::<$crate::Element>(element.as_ref()) };
54 if panicked.load(std::sync::atomic::Ordering::Relaxed) {
55 $crate::subclass::post_panic_error_message(
56 element,
57 $crate::glib::prelude::Cast::upcast_ref::<$crate::Object>(element),
58 None,
59 );
60 $ret
61 } else {
62 let result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| $code));
63
64 match result {
65 Ok(result) => result,
66 Err(err) => {
67 panicked.store(true, std::sync::atomic::Ordering::Relaxed);
68 $crate::subclass::post_panic_error_message(
69 element,
70 $crate::glib::prelude::Cast::upcast_ref::<$crate::Object>(element),
71 Some(err),
72 );
73 $ret
74 }
75 }
76 }
77 }
78 }};
79);
80
81#[macro_export]
82macro_rules! pad_panic_to_error(
83 ($imp:expr, $ret:expr, $code:block) => {{
84 #[allow(clippy::unused_unit)]
85 #[cfg(panic = "abort")]
86 {
87 if true {
88 #[allow(unused_mut)]
89 let mut closure = || { $code };
90 closure()
91 } else {
92 let _imp = $imp;
93 $ret
94 }
95 }
96 #[allow(unused_unsafe)]
97 #[cfg(not(panic = "abort"))]
98 {
99 let panicked = $imp.panicked();
100 let pad = $crate::glib::subclass::types::ObjectSubclassExt::obj($imp);
101 let pad = unsafe { $crate::glib::prelude::Cast::unsafe_cast_ref::<$crate::Pad>(pad.as_ref()) };
102 if panicked.load(std::sync::atomic::Ordering::Relaxed) {
103 if let Some(element) = $crate::prelude::PadExt::parent_element(pad) {
104 $crate::subclass::post_panic_error_message(
105 &element,
106 $crate::glib::prelude::Cast::upcast_ref::<$crate::Object>(pad),
107 None,
108 );
109 } else {
110 $crate::error!($crate::CAT_RUST, imp = $imp, "Pad has panicked");
111 }
112 $ret
113 } else {
114 let result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| $code));
115
116 match result {
117 Ok(result) => result,
118 Err(err) => {
119 panicked.store(true, std::sync::atomic::Ordering::Relaxed);
120 if let Some(element) = $crate::prelude::PadExt::parent_element(pad) {
121 $crate::subclass::post_panic_error_message(
122 &element,
123 $crate::glib::prelude::Cast::upcast_ref::<$crate::Object>(pad),
124 Some(err),
125 );
126 } else if let Some(cause) = err.downcast_ref::<&str>()
127 .copied()
128 .or_else(|| err.downcast_ref::<String>().map(|s| s.as_str())) {
129 $crate::error!($crate::CAT_RUST, imp = $imp, "Pad has panicked: {cause}");
130 } else {
131 $crate::error!($crate::CAT_RUST, imp = $imp, "Pad has panicked");
132 }
133
134 $ret
135 }
136 }
137 }
138 }
139 }};
140);
141
142#[derive(Clone, Debug, PartialEq, Eq, Error)]
143pub enum FlowError {
144 #[error("Flushing")]
145 Flushing,
146 #[error("Eos")]
147 Eos,
148 #[error("Not Negotiated")]
149 NotNegotiated(ErrorMessage),
150 #[error("Error")]
151 Error(ErrorMessage),
152}
153
154impl From<FlowError> for FlowReturn {
155 fn from(err: FlowError) -> Self {
156 FlowReturn::from(&err)
157 }
158}
159
160impl From<&FlowError> for FlowReturn {
161 fn from(err: &FlowError) -> FlowReturn {
162 match *err {
163 FlowError::Flushing => FlowReturn::Flushing,
164 FlowError::Eos => FlowReturn::Eos,
165 FlowError::NotNegotiated(..) => FlowReturn::NotNegotiated,
166 FlowError::Error(..) => FlowReturn::Error,
167 }
168 }
169}