gstreamer_audio/subclass/
audio_src.rs
1use std::mem;
4
5use glib::{prelude::*, translate::*};
6use gst::LoggableError;
7use gst_base::subclass::prelude::*;
8
9use super::prelude::*;
10use crate::{ffi, AudioRingBufferSpec, AudioSrc};
11
12pub trait AudioSrcImpl: AudioSrcImplExt + AudioBaseSrcImpl {
13 fn close(&self) -> Result<(), LoggableError> {
15 self.parent_close()
16 }
17
18 fn delay(&self) -> u32 {
20 self.parent_delay()
21 }
22
23 fn open(&self) -> Result<(), LoggableError> {
25 self.parent_open()
26 }
27
28 fn prepare(&self, spec: &mut AudioRingBufferSpec) -> Result<(), LoggableError> {
30 AudioSrcImplExt::parent_prepare(self, spec)
31 }
32
33 fn unprepare(&self) -> Result<(), LoggableError> {
35 self.parent_unprepare()
36 }
37
38 fn read(&self, audio_data: &mut [u8]) -> Result<(u32, Option<gst::ClockTime>), LoggableError> {
46 self.parent_read(audio_data)
47 }
48
49 fn reset(&self) {
51 self.parent_reset()
52 }
53}
54
55mod sealed {
56 pub trait Sealed {}
57 impl<T: super::AudioSrcImplExt> Sealed for T {}
58}
59
60pub trait AudioSrcImplExt: sealed::Sealed + ObjectSubclass {
61 fn parent_close(&self) -> Result<(), LoggableError> {
62 unsafe {
63 let data = Self::type_data();
64 let parent_class = data.as_ref().parent_class() as *mut ffi::GstAudioSrcClass;
65 let f = match (*parent_class).close {
66 None => return Ok(()),
67 Some(f) => f,
68 };
69 gst::result_from_gboolean!(
70 f(self.obj().unsafe_cast_ref::<AudioSrc>().to_glib_none().0),
71 gst::CAT_RUST,
72 "Failed to close element using the parent function"
73 )
74 }
75 }
76
77 fn parent_delay(&self) -> u32 {
78 unsafe {
79 let data = Self::type_data();
80 let parent_class = data.as_ref().parent_class() as *mut ffi::GstAudioSrcClass;
81 let f = match (*parent_class).delay {
82 Some(f) => f,
83 None => return 0,
84 };
85 f(self.obj().unsafe_cast_ref::<AudioSrc>().to_glib_none().0)
86 }
87 }
88
89 fn parent_open(&self) -> Result<(), LoggableError> {
90 unsafe {
91 let data = Self::type_data();
92 let parent_class = data.as_ref().parent_class() as *mut ffi::GstAudioSrcClass;
93 let f = match (*parent_class).open {
94 Some(f) => f,
95 None => return Ok(()),
96 };
97 gst::result_from_gboolean!(
98 f(self.obj().unsafe_cast_ref::<AudioSrc>().to_glib_none().0),
99 gst::CAT_RUST,
100 "Failed to open element using the parent function"
101 )
102 }
103 }
104
105 fn parent_prepare(&self, spec: &mut AudioRingBufferSpec) -> Result<(), LoggableError> {
106 unsafe {
107 let data = Self::type_data();
108 let parent_class = data.as_ref().parent_class() as *mut ffi::GstAudioSrcClass;
109 let f = match (*parent_class).prepare {
110 Some(f) => f,
111 None => return Ok(()),
112 };
113 gst::result_from_gboolean!(
114 f(
115 self.obj().unsafe_cast_ref::<AudioSrc>().to_glib_none().0,
116 &mut spec.0
117 ),
118 gst::CAT_RUST,
119 "Failed to prepare element using the parent function"
120 )
121 }
122 }
123
124 fn parent_unprepare(&self) -> Result<(), LoggableError> {
125 unsafe {
126 let data = Self::type_data();
127 let parent_class = data.as_ref().parent_class() as *mut ffi::GstAudioSrcClass;
128 let f = match (*parent_class).unprepare {
129 Some(f) => f,
130 None => {
131 return Err(gst::loggable_error!(
132 gst::CAT_RUST,
133 "Unprepare is not implemented!"
134 ))
135 }
136 };
137 gst::result_from_gboolean!(
138 f(self.obj().unsafe_cast_ref::<AudioSrc>().to_glib_none().0),
139 gst::CAT_RUST,
140 "Failed to unprepare element using the parent function"
141 )
142 }
143 }
144
145 fn parent_read(
146 &self,
147 buffer: &mut [u8],
148 ) -> Result<(u32, Option<gst::ClockTime>), LoggableError> {
149 unsafe {
150 let data = Self::type_data();
151 let parent_class = data.as_ref().parent_class() as *mut ffi::GstAudioSrcClass;
152 let f = match (*parent_class).read {
153 Some(f) => f,
154 None => return Ok((0, gst::ClockTime::NONE)),
155 };
156 let buffer_ptr = buffer.as_mut_ptr() as *mut _;
157 let mut timestamp = mem::MaybeUninit::uninit();
158 let ret = f(
159 self.obj().unsafe_cast_ref::<AudioSrc>().to_glib_none().0,
160 buffer_ptr,
161 buffer.len() as u32,
162 timestamp.as_mut_ptr(),
163 );
164 if ret > 0 {
165 Ok((ret, from_glib(timestamp.assume_init())))
166 } else {
167 Err(gst::loggable_error!(
168 gst::CAT_RUST,
169 "Failed to read using the parent function"
170 ))
171 }
172 }
173 }
174
175 fn parent_reset(&self) {
176 unsafe {
177 let data = Self::type_data();
178 let parent_class = data.as_ref().parent_class() as *mut ffi::GstAudioSrcClass;
179 if let Some(f) = (*parent_class).reset {
180 f(self.obj().unsafe_cast_ref::<AudioSrc>().to_glib_none().0)
181 }
182 }
183 }
184}
185
186impl<T: AudioSrcImpl> AudioSrcImplExt for T {}
187
188unsafe impl<T: AudioSrcImpl> IsSubclassable<T> for AudioSrc {
189 fn class_init(klass: &mut glib::Class<Self>) {
190 Self::parent_class_init::<T>(klass);
191 let klass = klass.as_mut();
192 klass.close = Some(audiosrc_close::<T>);
193 klass.delay = Some(audiosrc_delay::<T>);
194 klass.open = Some(audiosrc_open::<T>);
195 klass.prepare = Some(audiosrc_prepare::<T>);
196 klass.unprepare = Some(audiosrc_unprepare::<T>);
197 klass.read = Some(audiosrc_read::<T>);
198 klass.reset = Some(audiosrc_reset::<T>);
199 }
200}
201
202unsafe extern "C" fn audiosrc_close<T: AudioSrcImpl>(
203 ptr: *mut ffi::GstAudioSrc,
204) -> glib::ffi::gboolean {
205 let instance = &*(ptr as *mut T::Instance);
206 let imp = instance.imp();
207
208 gst::panic_to_error!(imp, false, {
209 match imp.close() {
210 Ok(()) => true,
211 Err(err) => {
212 err.log_with_imp(imp);
213 false
214 }
215 }
216 })
217 .into_glib()
218}
219
220unsafe extern "C" fn audiosrc_delay<T: AudioSrcImpl>(ptr: *mut ffi::GstAudioSrc) -> u32 {
221 let instance = &*(ptr as *mut T::Instance);
222 let imp = instance.imp();
223
224 gst::panic_to_error!(imp, 0, { imp.delay() })
225}
226
227unsafe extern "C" fn audiosrc_open<T: AudioSrcImpl>(
228 ptr: *mut ffi::GstAudioSrc,
229) -> glib::ffi::gboolean {
230 let instance = &*(ptr as *mut T::Instance);
231 let imp = instance.imp();
232
233 gst::panic_to_error!(imp, false, {
234 match imp.open() {
235 Ok(()) => true,
236 Err(err) => {
237 err.log_with_imp(imp);
238 false
239 }
240 }
241 })
242 .into_glib()
243}
244
245unsafe extern "C" fn audiosrc_prepare<T: AudioSrcImpl>(
246 ptr: *mut ffi::GstAudioSrc,
247 spec: *mut ffi::GstAudioRingBufferSpec,
248) -> glib::ffi::gboolean {
249 let instance = &*(ptr as *mut T::Instance);
250 let imp = instance.imp();
251
252 let spec = &mut *(spec as *mut AudioRingBufferSpec);
253
254 gst::panic_to_error!(imp, false, {
255 match AudioSrcImpl::prepare(imp, spec) {
256 Ok(()) => true,
257 Err(err) => {
258 err.log_with_imp(imp);
259 false
260 }
261 }
262 })
263 .into_glib()
264}
265
266unsafe extern "C" fn audiosrc_unprepare<T: AudioSrcImpl>(
267 ptr: *mut ffi::GstAudioSrc,
268) -> glib::ffi::gboolean {
269 let instance = &*(ptr as *mut T::Instance);
270 let imp = instance.imp();
271
272 gst::panic_to_error!(imp, false, {
273 match imp.unprepare() {
274 Ok(()) => true,
275 Err(err) => {
276 err.log_with_imp(imp);
277 false
278 }
279 }
280 })
281 .into_glib()
282}
283
284unsafe extern "C" fn audiosrc_read<T: AudioSrcImpl>(
285 ptr: *mut ffi::GstAudioSrc,
286 data: glib::ffi::gpointer,
287 length: u32,
288 timestamp: *mut gst::ffi::GstClockTime,
289) -> u32 {
290 let instance = &*(ptr as *mut T::Instance);
291 let imp = instance.imp();
292 let data_slice = if length == 0 {
293 &mut []
294 } else {
295 std::slice::from_raw_parts_mut(data as *mut u8, length as usize)
296 };
297
298 gst::panic_to_error!(imp, 0, {
299 let (res, timestamp_res) = imp.read(data_slice).unwrap_or((0, gst::ClockTime::NONE));
300 *timestamp = timestamp_res.into_glib();
301
302 res
303 })
304}
305
306unsafe extern "C" fn audiosrc_reset<T: AudioSrcImpl>(ptr: *mut ffi::GstAudioSrc) {
307 let instance = &*(ptr as *mut T::Instance);
308 let imp = instance.imp();
309
310 gst::panic_to_error!(imp, (), {
311 imp.reset();
312 });
313}