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