gstreamer_video/
video_message.rs
1use std::ptr;
4
5use glib::{
6 translate::{from_glib, from_glib_full, IntoGlib, ToGlibPtr},
7 value::ToSendValue,
8};
9use gst::{ffi as gst_ffi, prelude::*, Message, Object, Seqnum};
10
11use crate::{ffi, NavigationMessageType};
12
13macro_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
121struct MessageBuilder<'a> {
122 src: Option<Object>,
123 seqnum: Option<Seqnum>,
124 other_fields: Vec<(&'a str, glib::SendValue)>,
125}
126
127impl<'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"]
173pub struct NavigationEventMessageBuilder<'a> {
174 builder: MessageBuilder<'a>,
175 event: gst::Event,
176}
177
178impl<'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)]
194pub struct NavigationEventMessage {
195 pub event: gst::Event,
196}
197
198impl PartialEq for NavigationEventMessage {
199 fn eq(&self, other: &Self) -> bool {
200 self.event.as_ptr() == other.event.as_ptr()
201 }
202}
203
204impl Eq for NavigationEventMessage {}
205
206impl 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)]
240pub enum NavigationMessage {
241 Event(NavigationEventMessage),
242}
243
244impl 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(ffi::gst_navigation_message_get_type(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}