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#[derive(Clone, Debug, PartialEq, Eq, Error)]
82pub enum FlowError {
83 #[error("Flushing")]
84 Flushing,
85 #[error("Eos")]
86 Eos,
87 #[error("Not Negotiated")]
88 NotNegotiated(ErrorMessage),
89 #[error("Error")]
90 Error(ErrorMessage),
91}
92
93impl From<FlowError> for FlowReturn {
94 fn from(err: FlowError) -> Self {
95 FlowReturn::from(&err)
96 }
97}
98
99impl From<&FlowError> for FlowReturn {
100 fn from(err: &FlowError) -> FlowReturn {
101 match *err {
102 FlowError::Flushing => FlowReturn::Flushing,
103 FlowError::Eos => FlowReturn::Eos,
104 FlowError::NotNegotiated(..) => FlowReturn::NotNegotiated,
105 FlowError::Error(..) => FlowReturn::Error,
106 }
107 }
108}