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