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 #[must_use = "Building the message without using it has no effect"]
80 #[allow(clippy::redundant_closure_call)]
81 pub fn build(mut self) -> Message {
82 skip_assert_initialized!();
83 unsafe {
84 let src = self.builder.src.to_glib_none().0;
85 let msg = $new_fn(&mut self, src);
86 if let Some(seqnum) = self.builder.seqnum {
87 gst_ffi::gst_message_set_seqnum(msg, seqnum.into_glib());
88 }
89
90 if !self.builder.other_fields.is_empty() {
91 let structure = gst_ffi::gst_message_writable_structure(msg);
92
93 if !structure.is_null() {
94 let structure =
95 gst::StructureRef::from_glib_borrow_mut(structure as *mut _);
96
97 for (k, v) in self.builder.other_fields {
98 structure.set_value(k, v);
99 }
100 }
101 }
102
103 from_glib_full(msg)
104 }
105 }
106 };
107}
108
109struct MessageBuilder<'a> {
110 src: Option<Object>,
111 seqnum: Option<Seqnum>,
112 other_fields: Vec<(&'a str, glib::SendValue)>,
113}
114
115impl<'a> MessageBuilder<'a> {
116 pub(crate) fn new() -> Self {
117 skip_assert_initialized!();
118 Self {
119 src: None,
120 seqnum: None,
121 other_fields: Vec::new(),
122 }
123 }
124
125 pub fn src<O: IsA<Object> + Cast + Clone>(self, src: &O) -> Self {
126 Self {
127 src: Some(src.clone().upcast::<Object>()),
128 ..self
129 }
130 }
131
132 pub fn seqnum(self, seqnum: Seqnum) -> Self {
133 Self {
134 seqnum: Some(seqnum),
135 ..self
136 }
137 }
138
139 fn other_field(self, name: &'a str, value: impl ToSendValue) -> Self {
140 let mut other_fields = self.other_fields;
141 other_fields.push((name, value.to_send_value()));
142
143 Self {
144 other_fields,
145 ..self
146 }
147 }
148}
149
150#[must_use = "The builder must be built to be used"]
151pub struct NavigationEventMessageBuilder<'a> {
152 builder: MessageBuilder<'a>,
153 event: gst::Event,
154}
155
156impl<'a> NavigationEventMessageBuilder<'a> {
157 fn new(event: gst::Event) -> Self {
158 skip_assert_initialized!();
159 Self {
160 builder: MessageBuilder::new(),
161 event,
162 }
163 }
164
165 message_builder_generic_impl!(|s: &Self, src| ffi::gst_navigation_message_new_event(
166 src,
167 s.event.to_glib_none().0
168 ));
169}
170
171#[derive(Clone, Debug)]
172pub struct NavigationEventMessage {
173 pub event: gst::Event,
174}
175
176impl PartialEq for NavigationEventMessage {
177 fn eq(&self, other: &Self) -> bool {
178 self.event.as_ptr() == other.event.as_ptr()
179 }
180}
181
182impl Eq for NavigationEventMessage {}
183
184impl NavigationEventMessage {
185 #[doc(alias = "gst_navigation_message_new_event")]
186 #[allow(clippy::new_ret_no_self)]
187 pub fn new(event: gst::Event) -> gst::Message {
188 skip_assert_initialized!();
189 NavigationEventMessageBuilder::new(event).build()
190 }
191
192 pub fn builder<'a>(event: gst::Event) -> NavigationEventMessageBuilder<'a> {
193 skip_assert_initialized!();
194 NavigationEventMessageBuilder::new(event)
195 }
196
197 #[doc(alias = "gst_navigation_message_parse_event")]
198 pub fn parse(msg: &gst::MessageRef) -> Result<Self, glib::error::BoolError> {
199 skip_assert_initialized!();
200 unsafe {
201 let mut event = ptr::null_mut();
202 let ret = from_glib(ffi::gst_navigation_message_parse_event(
203 msg.as_mut_ptr(),
204 &mut event,
205 ));
206 if ret {
207 Ok(Self {
208 event: from_glib_full(event),
209 })
210 } else {
211 Err(glib::bool_error!("Invalid navigation event msg"))
212 }
213 }
214 }
215}
216
217#[derive(Clone, PartialEq, Eq, Debug)]
218pub enum NavigationMessage {
219 Event(NavigationEventMessage),
220}
221
222impl NavigationMessage {
223 #[doc(alias = "gst_navigation_message_get_type")]
224 pub fn type_(msg: &gst::MessageRef) -> NavigationMessageType {
225 skip_assert_initialized!();
226 unsafe { from_glib(ffi::gst_navigation_message_get_type(msg.as_mut_ptr())) }
227 }
228
229 #[doc(alias = "gst_navigation_message_parse_event")]
230 pub fn parse(msg: &gst::MessageRef) -> Result<Self, glib::error::BoolError> {
231 skip_assert_initialized!();
232
233 let event_type: NavigationMessageType = Self::type_(msg);
234
235 match event_type {
236 NavigationMessageType::Event => NavigationEventMessage::parse(msg).map(Self::Event),
237 _ => Err(glib::bool_error!(
238 "Unsupported navigation msg {:?}",
239 event_type
240 )),
241 }
242 }
243}