1 | // Take a look at the license at the top of the repository in the LICENSE file. |
2 | |
3 | use glib::{prelude::*, translate::*}; |
4 | use gst::LoggableError; |
5 | use gst_base::subclass::prelude::*; |
6 | |
7 | use super::prelude::*; |
8 | use crate::{AudioRingBufferSpec, AudioSink}; |
9 | |
10 | pub trait AudioSinkImpl: AudioSinkImplExt + AudioBaseSinkImpl { |
11 | fn close(&self) -> Result<(), LoggableError> { |
12 | self.parent_close() |
13 | } |
14 | |
15 | fn delay(&self) -> u32 { |
16 | self.parent_delay() |
17 | } |
18 | |
19 | fn open(&self) -> Result<(), LoggableError> { |
20 | self.parent_open() |
21 | } |
22 | |
23 | fn prepare(&self, spec: &mut AudioRingBufferSpec) -> Result<(), LoggableError> { |
24 | AudioSinkImplExt::parent_prepare(self, spec) |
25 | } |
26 | |
27 | fn unprepare(&self) -> Result<(), LoggableError> { |
28 | self.parent_unprepare() |
29 | } |
30 | |
31 | fn write(&self, audio_data: &[u8]) -> Result<i32, LoggableError> { |
32 | self.parent_write(audio_data) |
33 | } |
34 | |
35 | fn reset(&self) { |
36 | self.parent_reset() |
37 | } |
38 | } |
39 | |
40 | mod sealed { |
41 | pub trait Sealed {} |
42 | impl<T: super::AudioSinkImplExt> Sealed for T {} |
43 | } |
44 | |
45 | pub trait AudioSinkImplExt: sealed::Sealed + ObjectSubclass { |
46 | fn parent_close(&self) -> Result<(), LoggableError> { |
47 | unsafe { |
48 | let data = Self::type_data(); |
49 | let parent_class = data.as_ref().parent_class() as *mut ffi::GstAudioSinkClass; |
50 | let f = match (*parent_class).close { |
51 | None => return Ok(()), |
52 | Some(f) => f, |
53 | }; |
54 | gst::result_from_gboolean!( |
55 | f(self.obj().unsafe_cast_ref::<AudioSink>().to_glib_none().0), |
56 | gst::CAT_RUST, |
57 | "Failed to close element using the parent function" |
58 | ) |
59 | } |
60 | } |
61 | |
62 | fn parent_delay(&self) -> u32 { |
63 | unsafe { |
64 | let data = Self::type_data(); |
65 | let parent_class = data.as_ref().parent_class() as *mut ffi::GstAudioSinkClass; |
66 | let f = match (*parent_class).delay { |
67 | Some(f) => f, |
68 | None => return 0, |
69 | }; |
70 | f(self.obj().unsafe_cast_ref::<AudioSink>().to_glib_none().0) |
71 | } |
72 | } |
73 | |
74 | fn parent_open(&self) -> Result<(), LoggableError> { |
75 | unsafe { |
76 | let data = Self::type_data(); |
77 | let parent_class = data.as_ref().parent_class() as *mut ffi::GstAudioSinkClass; |
78 | let f = match (*parent_class).open { |
79 | Some(f) => f, |
80 | None => return Ok(()), |
81 | }; |
82 | gst::result_from_gboolean!( |
83 | f(self.obj().unsafe_cast_ref::<AudioSink>().to_glib_none().0), |
84 | gst::CAT_RUST, |
85 | "Failed to open element using the parent function" |
86 | ) |
87 | } |
88 | } |
89 | |
90 | fn parent_prepare(&self, spec: &mut AudioRingBufferSpec) -> Result<(), LoggableError> { |
91 | unsafe { |
92 | let data = Self::type_data(); |
93 | let parent_class = data.as_ref().parent_class() as *mut ffi::GstAudioSinkClass; |
94 | let f = match (*parent_class).prepare { |
95 | Some(f) => f, |
96 | None => return Ok(()), |
97 | }; |
98 | gst::result_from_gboolean!( |
99 | f( |
100 | self.obj().unsafe_cast_ref::<AudioSink>().to_glib_none().0, |
101 | &mut spec.0 |
102 | ), |
103 | gst::CAT_RUST, |
104 | "Failed to prepare element using the parent function" |
105 | ) |
106 | } |
107 | } |
108 | |
109 | fn parent_unprepare(&self) -> Result<(), LoggableError> { |
110 | unsafe { |
111 | let data = Self::type_data(); |
112 | let parent_class = data.as_ref().parent_class() as *mut ffi::GstAudioSinkClass; |
113 | let f = match (*parent_class).unprepare { |
114 | Some(f) => f, |
115 | None => { |
116 | return Err(gst::loggable_error!( |
117 | gst::CAT_RUST, |
118 | "Unprepare is not implemented!" |
119 | )) |
120 | } |
121 | }; |
122 | gst::result_from_gboolean!( |
123 | f(self.obj().unsafe_cast_ref::<AudioSink>().to_glib_none().0), |
124 | gst::CAT_RUST, |
125 | "Failed to unprepare element using the parent function" |
126 | ) |
127 | } |
128 | } |
129 | |
130 | fn parent_write(&self, buffer: &[u8]) -> Result<i32, LoggableError> { |
131 | unsafe { |
132 | let data = Self::type_data(); |
133 | let parent_class = data.as_ref().parent_class() as *mut ffi::GstAudioSinkClass; |
134 | let f = match (*parent_class).write { |
135 | Some(f) => f, |
136 | None => return Ok(-1), |
137 | }; |
138 | let buffer_ptr = buffer.as_ptr() as *const _ as *mut _; |
139 | let ret = f( |
140 | self.obj().unsafe_cast_ref::<AudioSink>().to_glib_none().0, |
141 | buffer_ptr, |
142 | buffer.len() as u32, |
143 | ); |
144 | if ret > 0 { |
145 | Ok(ret) |
146 | } else { |
147 | Err(gst::loggable_error!( |
148 | gst::CAT_RUST, |
149 | "Failed to write using the parent function" |
150 | )) |
151 | } |
152 | } |
153 | } |
154 | |
155 | fn parent_reset(&self) { |
156 | unsafe { |
157 | let data = Self::type_data(); |
158 | let parent_class = data.as_ref().parent_class() as *mut ffi::GstAudioSinkClass; |
159 | if let Some(f) = (*parent_class).reset { |
160 | f(self.obj().unsafe_cast_ref::<AudioSink>().to_glib_none().0) |
161 | } |
162 | } |
163 | } |
164 | } |
165 | |
166 | impl<T: AudioSinkImpl> AudioSinkImplExt for T {} |
167 | |
168 | unsafe impl<T: AudioSinkImpl> IsSubclassable<T> for AudioSink { |
169 | fn class_init(klass: &mut glib::Class<Self>) { |
170 | Self::parent_class_init::<T>(class:klass); |
171 | let klass: &mut GstAudioSinkClass = klass.as_mut(); |
172 | klass.close = Some(audiosink_close::<T>); |
173 | klass.delay = Some(audiosink_delay::<T>); |
174 | klass.open = Some(audiosink_open::<T>); |
175 | klass.prepare = Some(audiosink_prepare::<T>); |
176 | klass.unprepare = Some(audiosink_unprepare::<T>); |
177 | klass.write = Some(audiosink_write::<T>); |
178 | klass.reset = Some(audiosink_reset::<T>); |
179 | } |
180 | } |
181 | |
182 | unsafe extern "C" fn audiosink_close<T: AudioSinkImpl>( |
183 | ptr: *mut ffi::GstAudioSink, |
184 | ) -> glib::ffi::gboolean { |
185 | let instance: &::Instance = &*(ptr as *mut T::Instance); |
186 | let imp: &T = instance.imp(); |
187 | |
188 | gstbool::panic_to_error!(imp, false, { |
189 | match imp.close() { |
190 | Ok(()) => true, |
191 | Err(err) => { |
192 | err.log_with_imp(imp); |
193 | false |
194 | } |
195 | } |
196 | }) |
197 | .into_glib() |
198 | } |
199 | |
200 | unsafe extern "C" fn audiosink_delay<T: AudioSinkImpl>(ptr: *mut ffi::GstAudioSink) -> u32 { |
201 | let instance: &::Instance = &*(ptr as *mut T::Instance); |
202 | let imp: &T = instance.imp(); |
203 | |
204 | gst::panic_to_error!(imp, 0, { imp.delay() }) |
205 | } |
206 | |
207 | unsafe extern "C" fn audiosink_open<T: AudioSinkImpl>( |
208 | ptr: *mut ffi::GstAudioSink, |
209 | ) -> glib::ffi::gboolean { |
210 | let instance: &::Instance = &*(ptr as *mut T::Instance); |
211 | let imp: &T = instance.imp(); |
212 | |
213 | gstbool::panic_to_error!(imp, false, { |
214 | match imp.open() { |
215 | Ok(()) => true, |
216 | Err(err) => { |
217 | err.log_with_imp(imp); |
218 | false |
219 | } |
220 | } |
221 | }) |
222 | .into_glib() |
223 | } |
224 | |
225 | unsafe extern "C" fn audiosink_prepare<T: AudioSinkImpl>( |
226 | ptr: *mut ffi::GstAudioSink, |
227 | spec: *mut ffi::GstAudioRingBufferSpec, |
228 | ) -> glib::ffi::gboolean { |
229 | let instance: &::Instance = &*(ptr as *mut T::Instance); |
230 | let imp: &T = instance.imp(); |
231 | |
232 | let spec: &mut AudioRingBufferSpec = &mut *(spec as *mut AudioRingBufferSpec); |
233 | |
234 | gstbool::panic_to_error!(imp, false, { |
235 | match AudioSinkImpl::prepare(imp, spec) { |
236 | Ok(()) => true, |
237 | Err(err) => { |
238 | err.log_with_imp(imp); |
239 | false |
240 | } |
241 | } |
242 | }) |
243 | .into_glib() |
244 | } |
245 | |
246 | unsafe extern "C" fn audiosink_unprepare<T: AudioSinkImpl>( |
247 | ptr: *mut ffi::GstAudioSink, |
248 | ) -> glib::ffi::gboolean { |
249 | let instance: &::Instance = &*(ptr as *mut T::Instance); |
250 | let imp: &T = instance.imp(); |
251 | |
252 | gstbool::panic_to_error!(imp, false, { |
253 | match imp.unprepare() { |
254 | Ok(()) => true, |
255 | Err(err) => { |
256 | err.log_with_imp(imp); |
257 | false |
258 | } |
259 | } |
260 | }) |
261 | .into_glib() |
262 | } |
263 | |
264 | unsafe extern "C" fn audiosink_write<T: AudioSinkImpl>( |
265 | ptr: *mut ffi::GstAudioSink, |
266 | data: glib::ffi::gpointer, |
267 | length: u32, |
268 | ) -> i32 { |
269 | let instance: &::Instance = &*(ptr as *mut T::Instance); |
270 | let imp: &T = instance.imp(); |
271 | let data_slice: &[u8] = if length == 0 { |
272 | &[] |
273 | } else { |
274 | std::slice::from_raw_parts(data as *const u8, len:length as usize) |
275 | }; |
276 | |
277 | gst::panic_to_error!(imp, -1, { imp.write(data_slice).unwrap_or(-1) }) |
278 | } |
279 | |
280 | unsafe extern "C" fn audiosink_reset<T: AudioSinkImpl>(ptr: *mut ffi::GstAudioSink) { |
281 | let instance: &::Instance = &*(ptr as *mut T::Instance); |
282 | let imp: &T = instance.imp(); |
283 | |
284 | gst::panic_to_error!(imp, (), { |
285 | imp.reset(); |
286 | }); |
287 | } |
288 | |