1 | // Take a look at the license at the top of the repository in the LICENSE file. |
2 | |
3 | use std::ptr; |
4 | |
5 | use glib::{ |
6 | translate::{from_glib, from_glib_full, IntoGlib, ToGlibPtr}, |
7 | value::ToSendValue, |
8 | }; |
9 | use gst::{ffi as gst_ffi, prelude::*, Message, Object, Seqnum}; |
10 | |
11 | use crate::{ffi, NavigationMessageType}; |
12 | |
13 | macro_rules! message_builder_generic_impl { |
14 | ($new_fn:expr) => { |
15 | #[allow(clippy::needless_update)] |
16 | pub fn src<O: IsA<Object> + Cast + Clone>(self, src: &O) -> Self { |
17 | Self { |
18 | builder: self.builder.src(src), |
19 | ..self |
20 | } |
21 | } |
22 | |
23 | #[allow(clippy::needless_update)] |
24 | pub fn src_if<O: IsA<Object> + Cast + Clone>(self, src: &O, predicate: bool) -> Self { |
25 | if predicate { |
26 | self.src(src) |
27 | } else { |
28 | self |
29 | } |
30 | } |
31 | |
32 | #[allow(clippy::needless_update)] |
33 | pub fn src_if_some<O: IsA<Object> + Cast + Clone>(self, src: Option<&O>) -> Self { |
34 | if let Some(src) = src { |
35 | self.src(src) |
36 | } else { |
37 | self |
38 | } |
39 | } |
40 | |
41 | #[doc(alias = "gst_message_set_seqnum" )] |
42 | #[allow(clippy::needless_update)] |
43 | pub fn seqnum(self, seqnum: Seqnum) -> Self { |
44 | Self { |
45 | builder: self.builder.seqnum(seqnum), |
46 | ..self |
47 | } |
48 | } |
49 | |
50 | #[doc(alias = "gst_message_set_seqnum" )] |
51 | #[allow(clippy::needless_update)] |
52 | pub fn seqnum_if(self, seqnum: Seqnum, predicate: bool) -> Self { |
53 | if predicate { |
54 | self.seqnum(seqnum) |
55 | } else { |
56 | self |
57 | } |
58 | } |
59 | |
60 | #[doc(alias = "gst_message_set_seqnum" )] |
61 | #[allow(clippy::needless_update)] |
62 | pub fn seqnum_if_some(self, seqnum: Option<Seqnum>) -> Self { |
63 | if let Some(seqnum) = seqnum { |
64 | self.seqnum(seqnum) |
65 | } else { |
66 | self |
67 | } |
68 | } |
69 | |
70 | pub fn other_field(self, name: &'a str, value: impl ToSendValue) -> Self { |
71 | Self { |
72 | builder: self.builder.other_field(name, value), |
73 | ..self |
74 | } |
75 | } |
76 | |
77 | gst::impl_builder_gvalue_extra_setters!(other_field); |
78 | |
79 | #[deprecated = "use builder.other_field() instead" ] |
80 | #[allow(clippy::needless_update)] |
81 | pub fn other_fields( |
82 | self, |
83 | other_fields: &[(&'a str, &'a (dyn ToSendValue + Sync))], |
84 | ) -> Self { |
85 | Self { |
86 | builder: self.builder.other_fields(other_fields), |
87 | ..self |
88 | } |
89 | } |
90 | |
91 | #[must_use = "Building the message without using it has no effect" ] |
92 | #[allow(clippy::redundant_closure_call)] |
93 | pub fn build(mut self) -> Message { |
94 | skip_assert_initialized!(); |
95 | unsafe { |
96 | let src = self.builder.src.to_glib_none().0; |
97 | let msg = $new_fn(&mut self, src); |
98 | if let Some(seqnum) = self.builder.seqnum { |
99 | gst_ffi::gst_message_set_seqnum(msg, seqnum.into_glib()); |
100 | } |
101 | |
102 | if !self.builder.other_fields.is_empty() { |
103 | let structure = gst_ffi::gst_message_writable_structure(msg); |
104 | |
105 | if !structure.is_null() { |
106 | let structure = |
107 | gst::StructureRef::from_glib_borrow_mut(structure as *mut _); |
108 | |
109 | for (k, v) in self.builder.other_fields { |
110 | structure.set_value(k, v); |
111 | } |
112 | } |
113 | } |
114 | |
115 | from_glib_full(msg) |
116 | } |
117 | } |
118 | }; |
119 | } |
120 | |
121 | struct MessageBuilder<'a> { |
122 | src: Option<Object>, |
123 | seqnum: Option<Seqnum>, |
124 | other_fields: Vec<(&'a str, glib::SendValue)>, |
125 | } |
126 | |
127 | impl<'a> MessageBuilder<'a> { |
128 | pub(crate) fn new() -> Self { |
129 | skip_assert_initialized!(); |
130 | Self { |
131 | src: None, |
132 | seqnum: None, |
133 | other_fields: Vec::new(), |
134 | } |
135 | } |
136 | |
137 | pub fn src<O: IsA<Object> + Cast + Clone>(self, src: &O) -> Self { |
138 | Self { |
139 | src: Some(src.clone().upcast::<Object>()), |
140 | ..self |
141 | } |
142 | } |
143 | |
144 | pub fn seqnum(self, seqnum: Seqnum) -> Self { |
145 | Self { |
146 | seqnum: Some(seqnum), |
147 | ..self |
148 | } |
149 | } |
150 | |
151 | fn other_field(self, name: &'a str, value: impl ToSendValue) -> Self { |
152 | let mut other_fields = self.other_fields; |
153 | other_fields.push((name, value.to_send_value())); |
154 | |
155 | Self { |
156 | other_fields, |
157 | ..self |
158 | } |
159 | } |
160 | |
161 | fn other_fields(self, other_fields: &[(&'a str, &'a (dyn ToSendValue + Sync))]) -> Self { |
162 | let mut s = self; |
163 | |
164 | for (name, value) in other_fields { |
165 | s = s.other_field(name, value.to_send_value()); |
166 | } |
167 | |
168 | s |
169 | } |
170 | } |
171 | |
172 | #[must_use = "The builder must be built to be used" ] |
173 | pub struct NavigationEventMessageBuilder<'a> { |
174 | builder: MessageBuilder<'a>, |
175 | event: gst::Event, |
176 | } |
177 | |
178 | impl<'a> NavigationEventMessageBuilder<'a> { |
179 | fn new(event: gst::Event) -> Self { |
180 | skip_assert_initialized!(); |
181 | Self { |
182 | builder: MessageBuilder::new(), |
183 | event, |
184 | } |
185 | } |
186 | |
187 | message_builder_generic_impl!(|s: &Self, src| ffi::gst_navigation_message_new_event( |
188 | src, |
189 | s.event.to_glib_none().0 |
190 | )); |
191 | } |
192 | |
193 | #[derive (Clone, Debug)] |
194 | pub struct NavigationEventMessage { |
195 | pub event: gst::Event, |
196 | } |
197 | |
198 | impl PartialEq for NavigationEventMessage { |
199 | fn eq(&self, other: &Self) -> bool { |
200 | self.event.as_ptr() == other.event.as_ptr() |
201 | } |
202 | } |
203 | |
204 | impl Eq for NavigationEventMessage {} |
205 | |
206 | impl NavigationEventMessage { |
207 | #[doc (alias = "gst_navigation_message_new_event" )] |
208 | #[allow (clippy::new_ret_no_self)] |
209 | pub fn new(event: gst::Event) -> gst::Message { |
210 | skip_assert_initialized!(); |
211 | NavigationEventMessageBuilder::new(event).build() |
212 | } |
213 | |
214 | pub fn builder<'a>(event: gst::Event) -> NavigationEventMessageBuilder<'a> { |
215 | skip_assert_initialized!(); |
216 | NavigationEventMessageBuilder::new(event) |
217 | } |
218 | |
219 | #[doc (alias = "gst_navigation_message_parse_event" )] |
220 | pub fn parse(msg: &gst::MessageRef) -> Result<Self, glib::error::BoolError> { |
221 | skip_assert_initialized!(); |
222 | unsafe { |
223 | let mut event = ptr::null_mut(); |
224 | let ret = from_glib(ffi::gst_navigation_message_parse_event( |
225 | msg.as_mut_ptr(), |
226 | &mut event, |
227 | )); |
228 | if ret { |
229 | Ok(Self { |
230 | event: from_glib_full(event), |
231 | }) |
232 | } else { |
233 | Err(glib::bool_error!("Invalid navigation event msg" )) |
234 | } |
235 | } |
236 | } |
237 | } |
238 | |
239 | #[derive (Clone, PartialEq, Eq, Debug)] |
240 | pub enum NavigationMessage { |
241 | Event(NavigationEventMessage), |
242 | } |
243 | |
244 | impl NavigationMessage { |
245 | #[doc (alias = "gst_navigation_message_get_type" )] |
246 | pub fn type_(msg: &gst::MessageRef) -> NavigationMessageType { |
247 | skip_assert_initialized!(); |
248 | unsafe { from_glib(val:ffi::gst_navigation_message_get_type(message:msg.as_mut_ptr())) } |
249 | } |
250 | |
251 | #[doc (alias = "gst_navigation_message_parse_event" )] |
252 | pub fn parse(msg: &gst::MessageRef) -> Result<Self, glib::error::BoolError> { |
253 | skip_assert_initialized!(); |
254 | |
255 | let event_type: NavigationMessageType = Self::type_(msg); |
256 | |
257 | match event_type { |
258 | NavigationMessageType::Event => NavigationEventMessage::parse(msg).map(Self::Event), |
259 | _ => Err(glib::bool_error!( |
260 | "Unsupported navigation msg {:?}" , |
261 | event_type |
262 | )), |
263 | } |
264 | } |
265 | } |
266 | |