1 | // Take a look at the license at the top of the repository in the LICENSE file. |
2 | |
3 | use glib::translate::*; |
4 | |
5 | use crate::{ |
6 | prelude::*, FlowError, FlowSuccess, GhostPad, LoggableError, Pad, PadBuilder, PadFlags, |
7 | PadGetRangeSuccess, PadMode, StaticPadTemplate, |
8 | }; |
9 | |
10 | impl GhostPad { |
11 | #[doc (alias = "gst_ghost_pad_activate_mode_default" )] |
12 | pub fn activate_mode_default<P: IsA<GhostPad>>( |
13 | pad: &P, |
14 | parent: Option<&impl IsA<crate::Object>>, |
15 | mode: PadMode, |
16 | active: bool, |
17 | ) -> Result<(), glib::BoolError> { |
18 | skip_assert_initialized!(); |
19 | unsafe { |
20 | glib::result_from_gboolean!( |
21 | ffi::gst_ghost_pad_activate_mode_default( |
22 | pad.to_glib_none().0 as *mut ffi::GstPad, |
23 | parent.map(|p| p.as_ref()).to_glib_none().0, |
24 | mode.into_glib(), |
25 | active.into_glib(), |
26 | ), |
27 | "Failed to invoke the default activate mode function of the ghost pad" |
28 | ) |
29 | } |
30 | } |
31 | |
32 | #[doc (alias = "gst_ghost_pad_internal_activate_mode_default" )] |
33 | pub fn internal_activate_mode_default<P: IsA<GhostPad>>( |
34 | pad: &P, |
35 | parent: Option<&impl IsA<crate::Object>>, |
36 | mode: PadMode, |
37 | active: bool, |
38 | ) -> Result<(), glib::BoolError> { |
39 | skip_assert_initialized!(); |
40 | unsafe { |
41 | glib::result_from_gboolean!( |
42 | ffi::gst_ghost_pad_internal_activate_mode_default( |
43 | pad.to_glib_none().0 as *mut ffi::GstPad, |
44 | parent.map(|p| p.as_ref()).to_glib_none().0, |
45 | mode.into_glib(), |
46 | active.into_glib(), |
47 | ), |
48 | concat!( |
49 | "Failed to invoke the default activate mode function of a proxy pad " , |
50 | "that is owned by the ghost pad" |
51 | ) |
52 | ) |
53 | } |
54 | } |
55 | |
56 | // rustdoc-stripper-ignore-next |
57 | /// Creates a new [`GhostPad`] with an automatically generated name. |
58 | /// |
59 | /// Use [`GhostPad::builder_from_template()`] to get a [`PadBuilder`](crate::PadBuilder) |
60 | /// and define options. |
61 | #[doc (alias = "gst_ghost_pad_new_no_target" )] |
62 | pub fn new(direction: crate::PadDirection) -> Self { |
63 | skip_assert_initialized!(); |
64 | Self::builder(direction).build() |
65 | } |
66 | |
67 | // rustdoc-stripper-ignore-next |
68 | /// Creates a [`PadBuilder`](crate::PadBuilder) for a [`PadBuilder`] with an automatically generated name. |
69 | /// |
70 | /// Use [`PadBuilder::name`](crate::PadBuilder::name) or [`PadBuilder::maybe_name`](crate::PadBuilder::maybe_name) |
71 | /// to specify a different name. |
72 | #[doc (alias = "gst_ghost_pad_new_no_target" )] |
73 | pub fn builder(direction: crate::PadDirection) -> PadBuilder<Self> { |
74 | skip_assert_initialized!(); |
75 | PadBuilder::new(direction) |
76 | } |
77 | |
78 | // rustdoc-stripper-ignore-next |
79 | /// Creates a new [`GhostPad`] from the [`StaticPadTemplate`](crate::StaticPadTemplate). |
80 | /// |
81 | /// If the [`StaticPadTemplate`](crate::StaticPadTemplate) has a specific `name_template`, |
82 | /// i.e. if it's not a wildcard-name containing `%u`, `%s` or `%d`, |
83 | /// the `GhostPad` will automatically be named after the `name_template`. |
84 | /// |
85 | /// # Panics |
86 | /// |
87 | /// Panics if the `name_template` is a wildcard-name. |
88 | /// |
89 | /// Use [`GhostPad::builder_from_template()`] to get a [`PadBuilder`](crate::PadBuilder) |
90 | /// and define options. |
91 | #[doc (alias = "gst_ghost_pad_new_no_target_from_static_template" )] |
92 | pub fn from_static_template(templ: &StaticPadTemplate) -> Self { |
93 | skip_assert_initialized!(); |
94 | Self::builder_from_static_template(templ).build() |
95 | } |
96 | |
97 | // rustdoc-stripper-ignore-next |
98 | /// Creates a new [`PadBuilder`](crate::PadBuilder) for a [`GhostPad`] from the [`StaticPadTemplate`](crate::StaticPadTemplate). |
99 | /// |
100 | /// If the [`StaticPadTemplate`](crate::StaticPadTemplate) has a specific `name_template`, |
101 | /// i.e. if it's not a wildcard-name containing `%u`, `%s` or `%d`, |
102 | /// the `GhostPad` will automatically be named after the `name_template`. |
103 | /// |
104 | /// Use [`PadBuilder::name`](crate::PadBuilder::name) or [`PadBuilder::maybe_name`](crate::PadBuilder::maybe_name) |
105 | /// to specify a different name. |
106 | #[doc (alias = "gst_ghost_pad_new_no_target_from_static_template" )] |
107 | pub fn builder_from_static_template(templ: &StaticPadTemplate) -> PadBuilder<Self> { |
108 | skip_assert_initialized!(); |
109 | PadBuilder::from_static_template(templ) |
110 | } |
111 | |
112 | // rustdoc-stripper-ignore-next |
113 | /// Creates a new [`GhostPad`] from the [`PadTemplate`](crate::PadTemplate). |
114 | /// |
115 | /// If the [`PadTemplate`](crate::PadTemplate) has a specific `name_template`, |
116 | /// i.e. if it's not a wildcard-name containing `%u`, `%s` or `%d`, |
117 | /// the `GhostPad` will automatically be named after the `name_template`. |
118 | /// |
119 | /// # Panics |
120 | /// |
121 | /// Panics if the `name_template` is a wildcard-name. |
122 | /// |
123 | /// Use [`GhostPad::builder_from_template()`] to get a [`PadBuilder`](crate::PadBuilder) |
124 | /// and define options. |
125 | #[doc (alias = "gst_ghost_pad_new_no_target_from_template" )] |
126 | pub fn from_template(templ: &crate::PadTemplate) -> Self { |
127 | skip_assert_initialized!(); |
128 | Self::builder_from_template(templ).build() |
129 | } |
130 | |
131 | // rustdoc-stripper-ignore-next |
132 | /// Creates a new [`PadBuilder`](crate::PadBuilder) for a [`GhostPad`] from the [`PadTemplate`](crate::PadTemplate). |
133 | /// |
134 | /// If the [`PadTemplate`](crate::PadTemplate) has a specific `name_template`, |
135 | /// i.e. if it's not a wildcard-name containing `%u`, `%s` or `%d`, |
136 | /// the `GhostPad` will automatically be named after the `name_template`. |
137 | /// |
138 | /// Use [`PadBuilder::name`](crate::PadBuilder::name) or [`PadBuilder::maybe_name`](crate::PadBuilder::maybe_name) |
139 | /// to specify a different name. |
140 | #[doc (alias = "gst_ghost_pad_new_no_target_from_template" )] |
141 | pub fn builder_from_template(templ: &crate::PadTemplate) -> PadBuilder<Self> { |
142 | skip_assert_initialized!(); |
143 | PadBuilder::from_template(templ) |
144 | } |
145 | |
146 | // rustdoc-stripper-ignore-next |
147 | /// Creates a new [`GhostPad`] from the specified `target` `Pad`. |
148 | /// |
149 | /// The `GhostPad` will automatically be named after the `target` `name`. |
150 | /// |
151 | /// Use [`GhostPad::builder_with_target()`] to get a [`PadBuilder`](crate::PadBuilder) |
152 | /// and define options. |
153 | #[doc (alias = "gst_ghost_pad_new" )] |
154 | pub fn with_target<P: IsA<Pad> + IsA<crate::Object>>( |
155 | target: &P, |
156 | ) -> Result<Self, glib::BoolError> { |
157 | skip_assert_initialized!(); |
158 | Ok(Self::builder_with_target(target)?.build()) |
159 | } |
160 | |
161 | // rustdoc-stripper-ignore-next |
162 | /// Creates a new [`PadBuilder`](crate::PadBuilder) for a [`GhostPad`] from the specified `target` `Pad`. |
163 | /// |
164 | /// The `GhostPad` will automatically be named after the `target` `name`. |
165 | /// |
166 | /// Use [`PadBuilder::name`](crate::PadBuilder::name) or [`PadBuilder::maybe_name`](crate::PadBuilder::maybe_name) |
167 | /// to specify a different name. |
168 | #[doc (alias = "gst_ghost_pad_new_no_target_from_template" )] |
169 | pub fn builder_with_target<P: IsA<Pad> + IsA<crate::Object>>( |
170 | target: &P, |
171 | ) -> Result<PadBuilder<Self>, glib::BoolError> { |
172 | skip_assert_initialized!(); |
173 | let mut builder = Self::builder(target.direction()); |
174 | builder.needs_specific_name = true; |
175 | builder.with_target(target) |
176 | } |
177 | |
178 | // rustdoc-stripper-ignore-next |
179 | /// Creates a new [`GhostPad`] from the [`PadTemplate`](crate::PadTemplate) |
180 | /// with the specified `target` `Pad`. |
181 | /// |
182 | /// If the [`PadTemplate`](crate::PadTemplate) has a specific `name_template`, |
183 | /// i.e. if it's not a wildcard-name containing `%u`, `%s` or `%d`, |
184 | /// the `GhostPad` will automatically be named after the `name_template`. |
185 | /// |
186 | /// If the `name_template` is a wildcard-name, then the `target` `name` is used, |
187 | /// if it is compatible. Otherwise, a specific name must be provided using |
188 | /// [`PadBuilder::name`](crate::PadBuilder::name) or [`PadBuilder::maybe_name`](crate::PadBuilder::maybe_name). |
189 | #[doc (alias = "gst_ghost_pad_new_from_template" )] |
190 | pub fn from_template_with_target<P: IsA<Pad> + IsA<crate::Object>>( |
191 | templ: &crate::PadTemplate, |
192 | target: &P, |
193 | ) -> Result<Self, glib::BoolError> { |
194 | skip_assert_initialized!(); |
195 | Ok(Self::builder_from_template_with_target(templ, target)?.build()) |
196 | } |
197 | |
198 | // rustdoc-stripper-ignore-next |
199 | /// Creates a new [`PadBuilder`](crate::PadBuilder) for a [`GhostPad`] from the [`PadTemplate`](crate::PadTemplate) |
200 | /// with the specified `target` `Pad`. |
201 | /// |
202 | /// If the [`PadTemplate`](crate::PadTemplate) has a specific `name_template`, |
203 | /// i.e. if it's not a wildcard-name containing `%u`, `%s` or `%d`, |
204 | /// the `GhostPad` will automatically be named after the `name_template`. |
205 | /// |
206 | /// If the `name_template` is a wildcard-name, then the `target` `name` is used, |
207 | /// if it is compatible. Otherwise, a specific name must be provided using |
208 | /// [`PadBuilder::name`](crate::PadBuilder::name) or [`PadBuilder::maybe_name`](crate::PadBuilder::maybe_name). |
209 | #[doc (alias = "gst_ghost_pad_new_from_template" )] |
210 | pub fn builder_from_template_with_target<P: IsA<Pad> + IsA<crate::Object>>( |
211 | templ: &crate::PadTemplate, |
212 | target: &P, |
213 | ) -> Result<PadBuilder<Self>, glib::BoolError> { |
214 | skip_assert_initialized!(); |
215 | |
216 | if target.direction() != templ.direction() { |
217 | return Err(glib::bool_error!( |
218 | "Template and target have different directions" |
219 | )); |
220 | } |
221 | |
222 | Self::builder_from_template(templ).with_target(target) |
223 | } |
224 | } |
225 | |
226 | impl<T: IsA<GhostPad> + IsA<Pad>> PadBuilder<T> { |
227 | #[doc (alias = "gst_pad_set_activate_function" )] |
228 | pub fn proxy_pad_activate_function<F>(self, func: F) -> Self |
229 | where |
230 | F: Fn(&crate::ProxyPad, Option<&crate::Object>) -> Result<(), LoggableError> |
231 | + Send |
232 | + Sync |
233 | + 'static, |
234 | { |
235 | unsafe { |
236 | let proxy = self |
237 | .pad |
238 | .unsafe_cast_ref::<crate::ProxyPad>() |
239 | .internal() |
240 | .unwrap(); |
241 | proxy.set_activate_function(func); |
242 | } |
243 | |
244 | self |
245 | } |
246 | |
247 | #[doc (alias = "gst_pad_set_activatemode_function" )] |
248 | pub fn proxy_pad_activatemode_function<F>(self, func: F) -> Self |
249 | where |
250 | F: Fn( |
251 | &crate::ProxyPad, |
252 | Option<&crate::Object>, |
253 | crate::PadMode, |
254 | bool, |
255 | ) -> Result<(), LoggableError> |
256 | + Send |
257 | + Sync |
258 | + 'static, |
259 | { |
260 | unsafe { |
261 | let proxy = self |
262 | .pad |
263 | .unsafe_cast_ref::<crate::ProxyPad>() |
264 | .internal() |
265 | .unwrap(); |
266 | proxy.set_activatemode_function(func); |
267 | } |
268 | |
269 | self |
270 | } |
271 | |
272 | #[doc (alias = "gst_pad_set_chain_function" )] |
273 | pub fn proxy_pad_chain_function<F>(self, func: F) -> Self |
274 | where |
275 | F: Fn( |
276 | &crate::ProxyPad, |
277 | Option<&crate::Object>, |
278 | crate::Buffer, |
279 | ) -> Result<FlowSuccess, FlowError> |
280 | + Send |
281 | + Sync |
282 | + 'static, |
283 | { |
284 | unsafe { |
285 | let proxy = self |
286 | .pad |
287 | .unsafe_cast_ref::<crate::ProxyPad>() |
288 | .internal() |
289 | .unwrap(); |
290 | proxy.set_chain_function(func); |
291 | } |
292 | |
293 | self |
294 | } |
295 | |
296 | #[doc (alias = "gst_pad_set_chain_list_function" )] |
297 | pub fn proxy_pad_chain_list_function<F>(self, func: F) -> Self |
298 | where |
299 | F: Fn( |
300 | &crate::ProxyPad, |
301 | Option<&crate::Object>, |
302 | crate::BufferList, |
303 | ) -> Result<FlowSuccess, FlowError> |
304 | + Send |
305 | + Sync |
306 | + 'static, |
307 | { |
308 | unsafe { |
309 | let proxy = self |
310 | .pad |
311 | .unsafe_cast_ref::<crate::ProxyPad>() |
312 | .internal() |
313 | .unwrap(); |
314 | proxy.set_chain_list_function(func); |
315 | } |
316 | |
317 | self |
318 | } |
319 | |
320 | #[doc (alias = "gst_pad_set_event_function" )] |
321 | pub fn proxy_pad_event_function<F>(self, func: F) -> Self |
322 | where |
323 | F: Fn(&crate::ProxyPad, Option<&crate::Object>, crate::Event) -> bool |
324 | + Send |
325 | + Sync |
326 | + 'static, |
327 | { |
328 | unsafe { |
329 | let proxy = self |
330 | .pad |
331 | .unsafe_cast_ref::<crate::ProxyPad>() |
332 | .internal() |
333 | .unwrap(); |
334 | proxy.set_event_function(func); |
335 | } |
336 | |
337 | self |
338 | } |
339 | |
340 | #[doc (alias = "gst_pad_set_event_full_function" )] |
341 | pub fn proxy_pad_event_full_function<F>(self, func: F) -> Self |
342 | where |
343 | F: Fn( |
344 | &crate::ProxyPad, |
345 | Option<&crate::Object>, |
346 | crate::Event, |
347 | ) -> Result<FlowSuccess, FlowError> |
348 | + Send |
349 | + Sync |
350 | + 'static, |
351 | { |
352 | unsafe { |
353 | let proxy = self |
354 | .pad |
355 | .unsafe_cast_ref::<crate::ProxyPad>() |
356 | .internal() |
357 | .unwrap(); |
358 | proxy.set_event_full_function(func); |
359 | } |
360 | |
361 | self |
362 | } |
363 | |
364 | #[doc (alias = "gst_pad_set_getrange_function" )] |
365 | pub fn proxy_pad_getrange_function<F>(self, func: F) -> Self |
366 | where |
367 | F: Fn( |
368 | &crate::ProxyPad, |
369 | Option<&crate::Object>, |
370 | u64, |
371 | Option<&mut crate::BufferRef>, |
372 | u32, |
373 | ) -> Result<PadGetRangeSuccess, crate::FlowError> |
374 | + Send |
375 | + Sync |
376 | + 'static, |
377 | { |
378 | unsafe { |
379 | let proxy = self |
380 | .pad |
381 | .unsafe_cast_ref::<crate::ProxyPad>() |
382 | .internal() |
383 | .unwrap(); |
384 | proxy.set_getrange_function(func); |
385 | } |
386 | |
387 | self |
388 | } |
389 | |
390 | #[doc (alias = "gst_pad_set_iterate_internal_links_function" )] |
391 | pub fn proxy_pad_iterate_internal_links_function<F>(self, func: F) -> Self |
392 | where |
393 | F: Fn(&crate::ProxyPad, Option<&crate::Object>) -> crate::Iterator<Pad> |
394 | + Send |
395 | + Sync |
396 | + 'static, |
397 | { |
398 | unsafe { |
399 | let proxy = self |
400 | .pad |
401 | .unsafe_cast_ref::<crate::ProxyPad>() |
402 | .internal() |
403 | .unwrap(); |
404 | proxy.set_iterate_internal_links_function(func); |
405 | } |
406 | |
407 | self |
408 | } |
409 | |
410 | #[doc (alias = "gst_pad_set_link_function" )] |
411 | pub fn proxy_pad_link_function<F>(self, func: F) -> Self |
412 | where |
413 | F: Fn( |
414 | &crate::ProxyPad, |
415 | Option<&crate::Object>, |
416 | &Pad, |
417 | ) -> Result<crate::PadLinkSuccess, crate::PadLinkError> |
418 | + Send |
419 | + Sync |
420 | + 'static, |
421 | { |
422 | unsafe { |
423 | let proxy = self |
424 | .pad |
425 | .unsafe_cast_ref::<crate::ProxyPad>() |
426 | .internal() |
427 | .unwrap(); |
428 | proxy.set_link_function(func); |
429 | } |
430 | |
431 | self |
432 | } |
433 | |
434 | #[doc (alias = "gst_pad_set_query_function" )] |
435 | pub fn proxy_pad_query_function<F>(self, func: F) -> Self |
436 | where |
437 | F: Fn(&crate::ProxyPad, Option<&crate::Object>, &mut crate::QueryRef) -> bool |
438 | + Send |
439 | + Sync |
440 | + 'static, |
441 | { |
442 | unsafe { |
443 | let proxy = self |
444 | .pad |
445 | .unsafe_cast_ref::<crate::ProxyPad>() |
446 | .internal() |
447 | .unwrap(); |
448 | proxy.set_query_function(func); |
449 | } |
450 | |
451 | self |
452 | } |
453 | |
454 | #[doc (alias = "gst_pad_set_unlink_function" )] |
455 | pub fn proxy_pad_unlink_function<F>(self, func: F) -> Self |
456 | where |
457 | F: Fn(&crate::ProxyPad, Option<&crate::Object>) + Send + Sync + 'static, |
458 | { |
459 | unsafe { |
460 | let proxy = self |
461 | .pad |
462 | .unsafe_cast_ref::<crate::ProxyPad>() |
463 | .internal() |
464 | .unwrap(); |
465 | proxy.set_unlink_function(func); |
466 | } |
467 | |
468 | self |
469 | } |
470 | |
471 | pub fn proxy_pad_flags(self, flags: PadFlags) -> Self { |
472 | unsafe { |
473 | let proxy = self |
474 | .pad |
475 | .unsafe_cast_ref::<crate::ProxyPad>() |
476 | .internal() |
477 | .unwrap(); |
478 | proxy.set_pad_flags(flags); |
479 | } |
480 | |
481 | self |
482 | } |
483 | |
484 | // rustdoc-stripper-ignore-next |
485 | /// Specifies a `target` [`Pad`](crate::Pad) for the [`GhostPad`]. |
486 | /// |
487 | /// If the [`PadBuilder`](crate::PadBuilder) was created from |
488 | /// a [`PadTemplate`](crate::PadTemplate) and the `PadTemplate` has a specific `name_template`, |
489 | /// i.e. if it's not a wildcard-name containing `%u`, `%s` or `%d`, |
490 | /// the `GhostPad` will automatically be named after the `name_template`. |
491 | /// |
492 | /// If the `name_template` is a wildcard-name, then the `target` `name` is used, |
493 | /// if it is compatible. Otherwise, a specific name must be provided using |
494 | /// [`PadBuilder::name`](crate::PadBuilder::name) or [`PadBuilder::maybe_name`](crate::PadBuilder::maybe_name). |
495 | pub fn with_target<P: IsA<Pad> + IsA<crate::Object>>( |
496 | mut self, |
497 | target: &P, |
498 | ) -> Result<Self, glib::BoolError> { |
499 | assert_eq!(self.pad.direction(), target.direction()); |
500 | |
501 | self.pad.set_target(Some(target))?; |
502 | |
503 | if self.needs_specific_name { |
504 | let mut can_assign_target_name = true; |
505 | |
506 | if let Some(pad_template) = self.pad.pad_template() { |
507 | if pad_template.presence() == crate::PadPresence::Request { |
508 | // Check if the target name is compatible with the name template. |
509 | use crate::CAT_RUST; |
510 | |
511 | let target_name = target.name(); |
512 | let mut target_parts = target_name.split('_' ); |
513 | for template_part in pad_template.name_template().split('_' ) { |
514 | let Some(target_part) = target_parts.next() else { |
515 | crate::debug!( |
516 | CAT_RUST, |
517 | "Not using target Pad name ' {target_name}': not enough parts compared to template ' {}'" , |
518 | pad_template.name_template(), |
519 | ); |
520 | can_assign_target_name = false; |
521 | break; |
522 | }; |
523 | |
524 | if let Some(conv_spec_start) = template_part.find('%' ) { |
525 | if conv_spec_start > 0 |
526 | && !target_part.starts_with(&template_part[..conv_spec_start]) |
527 | { |
528 | crate::debug!( |
529 | CAT_RUST, |
530 | "Not using target Pad name ' {target_name}': mismatch template ' {}' prefix" , |
531 | pad_template.name_template(), |
532 | ); |
533 | can_assign_target_name = false; |
534 | break; |
535 | } |
536 | |
537 | let conv_spec_pos = conv_spec_start + 1; |
538 | match template_part.get(conv_spec_pos..=conv_spec_pos) { |
539 | Some("s" ) => { |
540 | // *There can be only one* %s |
541 | break; |
542 | } |
543 | Some("u" ) => { |
544 | if target_part |
545 | .get(conv_spec_start..) |
546 | .map_or(true, |s| s.parse::<u32>().is_err()) |
547 | { |
548 | crate::debug!( |
549 | CAT_RUST, |
550 | "Not using target Pad name ' {target_name}': can't parse '%u' from ' {target_part}' (template ' {}')" , |
551 | pad_template.name_template(), |
552 | ); |
553 | |
554 | can_assign_target_name = false; |
555 | break; |
556 | } |
557 | } |
558 | Some("d" ) => { |
559 | if target_part |
560 | .get(conv_spec_start..) |
561 | .map_or(true, |s| s.parse::<i32>().is_err()) |
562 | { |
563 | crate::debug!( |
564 | CAT_RUST, |
565 | "Not using target Pad name ' {target_name}': can't parse '%i' from ' {target_part}' (template ' {}')" , |
566 | pad_template.name_template(), |
567 | ); |
568 | |
569 | can_assign_target_name = false; |
570 | break; |
571 | } |
572 | } |
573 | other => unreachable!("Unexpected conversion specifier {other:?}" ), |
574 | } |
575 | } else if target_part != template_part { |
576 | can_assign_target_name = false; |
577 | break; |
578 | } |
579 | } |
580 | } |
581 | } |
582 | |
583 | if can_assign_target_name { |
584 | self.pad.set_property("name" , target.name()); |
585 | self.needs_specific_name = false; |
586 | } |
587 | } |
588 | |
589 | Ok(self) |
590 | } |
591 | } |
592 | |
593 | #[cfg (test)] |
594 | mod tests { |
595 | use super::*; |
596 | |
597 | #[test ] |
598 | fn no_template_no_target() { |
599 | crate::init().unwrap(); |
600 | |
601 | let ghost_pad = GhostPad::new(crate::PadDirection::Sink); |
602 | assert!(ghost_pad.name().starts_with("ghostpad" )); |
603 | |
604 | let ghost_pad = GhostPad::builder(crate::PadDirection::Sink).build(); |
605 | assert!(ghost_pad.name().starts_with("ghostpad" )); |
606 | |
607 | let ghost_pad = GhostPad::builder(crate::PadDirection::Sink) |
608 | .name("sink" ) |
609 | .build(); |
610 | assert_eq!(ghost_pad.name(), "sink" ); |
611 | } |
612 | |
613 | #[test ] |
614 | fn from_template() { |
615 | crate::init().unwrap(); |
616 | |
617 | let caps = crate::Caps::new_any(); |
618 | let wildcard_templ = crate::PadTemplate::new( |
619 | "sink_%u" , |
620 | crate::PadDirection::Sink, |
621 | crate::PadPresence::Request, |
622 | &caps, |
623 | ) |
624 | .unwrap(); |
625 | |
626 | let ghost_pad = GhostPad::builder_from_template(&wildcard_templ) |
627 | .name("my-ghostpad" ) |
628 | .build(); |
629 | assert_eq!(ghost_pad.name(), "my-ghostpad" ); |
630 | |
631 | let caps = crate::Caps::new_any(); |
632 | let templ = crate::PadTemplate::new( |
633 | "sink" , |
634 | crate::PadDirection::Sink, |
635 | crate::PadPresence::Always, |
636 | &caps, |
637 | ) |
638 | .unwrap(); |
639 | |
640 | let ghost_pad = GhostPad::from_template(&templ); |
641 | assert_eq!(ghost_pad.name(), "sink" ); |
642 | |
643 | let ghost_pad = GhostPad::builder_from_template(&templ).build(); |
644 | assert!(ghost_pad.name().starts_with("sink" )); |
645 | |
646 | let ghost_pad = GhostPad::builder_from_template(&templ) |
647 | .name("my-sink" ) |
648 | .build(); |
649 | assert_eq!(ghost_pad.name(), "my-sink" ); |
650 | } |
651 | |
652 | #[test ] |
653 | #[should_panic ] |
654 | fn from_template_missing_name() { |
655 | crate::init().unwrap(); |
656 | |
657 | let caps = crate::Caps::new_any(); |
658 | let templ = crate::PadTemplate::new( |
659 | "audio_%u" , |
660 | crate::PadDirection::Sink, |
661 | crate::PadPresence::Request, |
662 | &caps, |
663 | ) |
664 | .unwrap(); |
665 | |
666 | // Panic: attempt to build from a wildcard-named template |
667 | // without providing a name. |
668 | let _ghost_pad = GhostPad::from_template(&templ); |
669 | } |
670 | |
671 | #[test ] |
672 | #[should_panic ] |
673 | fn from_template_builder_missing_name() { |
674 | crate::init().unwrap(); |
675 | |
676 | let caps = crate::Caps::new_any(); |
677 | let templ = crate::PadTemplate::new( |
678 | "audio_%u" , |
679 | crate::PadDirection::Sink, |
680 | crate::PadPresence::Request, |
681 | &caps, |
682 | ) |
683 | .unwrap(); |
684 | |
685 | // Panic: attempt to build from a wildcard-named template |
686 | // without providing a name. |
687 | let _ghost_pad = GhostPad::builder_from_template(&templ).build(); |
688 | } |
689 | |
690 | #[test ] |
691 | fn with_target() { |
692 | crate::init().unwrap(); |
693 | |
694 | let caps = crate::Caps::new_any(); |
695 | let templ = crate::PadTemplate::new( |
696 | "test" , |
697 | crate::PadDirection::Sink, |
698 | crate::PadPresence::Always, |
699 | &caps, |
700 | ) |
701 | .unwrap(); |
702 | |
703 | let target = crate::Pad::builder_from_template(&templ).build(); |
704 | let ghost_pad = GhostPad::with_target(&target).unwrap(); |
705 | assert_eq!(ghost_pad.name(), "test" ); |
706 | |
707 | let target = crate::Pad::from_template(&templ); |
708 | let ghost_pad = GhostPad::builder_with_target(&target).unwrap().build(); |
709 | assert_eq!(ghost_pad.name(), "test" ); |
710 | |
711 | let target = crate::Pad::from_template(&templ); |
712 | let ghost_pad = GhostPad::builder_with_target(&target) |
713 | .unwrap() |
714 | .name("ghost_test" ) |
715 | .build(); |
716 | assert_eq!(ghost_pad.name(), "ghost_test" ); |
717 | } |
718 | |
719 | #[test ] |
720 | fn from_template_with_target() { |
721 | crate::init().unwrap(); |
722 | |
723 | let caps = crate::Caps::new_any(); |
724 | let sink_templ = crate::PadTemplate::new( |
725 | "sink" , |
726 | crate::PadDirection::Sink, |
727 | crate::PadPresence::Always, |
728 | &caps, |
729 | ) |
730 | .unwrap(); |
731 | |
732 | // # No conversion specifier, Always template |
733 | let ghost_templ = crate::PadTemplate::new( |
734 | "ghost_sink" , |
735 | crate::PadDirection::Sink, |
736 | crate::PadPresence::Always, |
737 | &caps, |
738 | ) |
739 | .unwrap(); |
740 | |
741 | let target = crate::Pad::from_template(&sink_templ); |
742 | let ghost_pad = GhostPad::from_template_with_target(&ghost_templ, &target).unwrap(); |
743 | assert_eq!(ghost_pad.name(), "ghost_sink" ); |
744 | |
745 | let target = crate::Pad::from_template(&sink_templ); |
746 | let ghost_pad = GhostPad::builder_from_template_with_target(&ghost_templ, &target) |
747 | .unwrap() |
748 | .build(); |
749 | assert_eq!(ghost_pad.name(), "ghost_sink" ); |
750 | |
751 | let target = crate::Pad::from_template(&sink_templ); |
752 | let ghost_pad = GhostPad::builder_from_template_with_target(&ghost_templ, &target) |
753 | .unwrap() |
754 | .name("my-sink" ) |
755 | .build(); |
756 | assert_eq!(ghost_pad.name(), "my-sink" ); |
757 | |
758 | // # Request template %u |
759 | let wildcard_u_templ = crate::PadTemplate::new( |
760 | "sink_%u" , |
761 | crate::PadDirection::Sink, |
762 | crate::PadPresence::Request, |
763 | &caps, |
764 | ) |
765 | .unwrap(); |
766 | |
767 | // ## Incompatible target but specific name |
768 | let target = crate::Pad::from_template(&sink_templ); |
769 | let ghost_pad = GhostPad::builder_from_template_with_target(&wildcard_u_templ, &target) |
770 | .unwrap() |
771 | .name("sink_0" ) |
772 | .build(); |
773 | assert_eq!(ghost_pad.name(), "sink_0" ); |
774 | |
775 | // ## Compatible target |
776 | let sink_0_templ = crate::PadTemplate::new( |
777 | "sink_0" , |
778 | crate::PadDirection::Sink, |
779 | crate::PadPresence::Always, |
780 | &caps, |
781 | ) |
782 | .unwrap(); |
783 | let target = crate::Pad::from_template(&sink_0_templ); |
784 | let ghost_pad = GhostPad::builder_from_template_with_target(&wildcard_u_templ, &target) |
785 | .unwrap() |
786 | .build(); |
787 | assert_eq!(ghost_pad.name(), "sink_0" ); |
788 | |
789 | // # Request template %d_%u |
790 | let wildcard_u_templ = crate::PadTemplate::new( |
791 | "sink_%d_%u" , |
792 | crate::PadDirection::Sink, |
793 | crate::PadPresence::Request, |
794 | &caps, |
795 | ) |
796 | .unwrap(); |
797 | |
798 | // ## Incompatible target but specific name |
799 | let target = crate::Pad::from_template(&sink_templ); |
800 | let ghost_pad = GhostPad::builder_from_template_with_target(&wildcard_u_templ, &target) |
801 | .unwrap() |
802 | .name("sink_-1_0" ) |
803 | .build(); |
804 | assert_eq!(ghost_pad.name(), "sink_-1_0" ); |
805 | |
806 | // ## Compatible target |
807 | let sink_m2_0_templ = crate::PadTemplate::new( |
808 | "sink_-2_0" , |
809 | crate::PadDirection::Sink, |
810 | crate::PadPresence::Always, |
811 | &caps, |
812 | ) |
813 | .unwrap(); |
814 | let target = crate::Pad::from_template(&sink_m2_0_templ); |
815 | let ghost_pad = GhostPad::builder_from_template_with_target(&wildcard_u_templ, &target) |
816 | .unwrap() |
817 | .build(); |
818 | assert_eq!(ghost_pad.name(), "sink_-2_0" ); |
819 | |
820 | // # Request template %s |
821 | let wildcard_s_templ = crate::PadTemplate::new( |
822 | "sink_%s" , |
823 | crate::PadDirection::Sink, |
824 | crate::PadPresence::Request, |
825 | &caps, |
826 | ) |
827 | .unwrap(); |
828 | |
829 | // ## Incompatible target but specific name |
830 | let target = crate::Pad::from_template(&sink_templ); |
831 | let ghost_pad = GhostPad::builder_from_template_with_target(&wildcard_s_templ, &target) |
832 | .unwrap() |
833 | .name("sink_ghost_test" ) |
834 | .build(); |
835 | assert_eq!(ghost_pad.name(), "sink_ghost_test" ); |
836 | |
837 | // ## Compatible target |
838 | let sink_test_templ = crate::PadTemplate::new( |
839 | "sink_test" , |
840 | crate::PadDirection::Sink, |
841 | crate::PadPresence::Always, |
842 | &caps, |
843 | ) |
844 | .unwrap(); |
845 | let target = crate::Pad::from_template(&sink_test_templ); |
846 | let ghost_pad = GhostPad::builder_from_template_with_target(&wildcard_s_templ, &target) |
847 | .unwrap() |
848 | .build(); |
849 | assert_eq!(ghost_pad.name(), "sink_test" ); |
850 | } |
851 | |
852 | #[test ] |
853 | #[should_panic ] |
854 | fn from_template_with_target_incompatible_prefix() { |
855 | crate::init().unwrap(); |
856 | |
857 | let caps = crate::Caps::new_any(); |
858 | let wildcard_templ = crate::PadTemplate::new( |
859 | "sink_%u" , |
860 | crate::PadDirection::Sink, |
861 | crate::PadPresence::Request, |
862 | &caps, |
863 | ) |
864 | .unwrap(); |
865 | |
866 | let templ = crate::PadTemplate::new( |
867 | "audio_0" , |
868 | crate::PadDirection::Sink, |
869 | crate::PadPresence::Always, |
870 | &caps, |
871 | ) |
872 | .unwrap(); |
873 | |
874 | let target = crate::Pad::from_template(&templ); |
875 | // Panic: attempt to build from a wildcard-named template |
876 | // with a target name with a different prefix |
877 | // without providing a name. |
878 | let _ghost_pad = GhostPad::builder_from_template_with_target(&wildcard_templ, &target) |
879 | .unwrap() |
880 | .build(); |
881 | } |
882 | |
883 | #[test ] |
884 | #[should_panic ] |
885 | fn from_template_with_target_missing_part() { |
886 | crate::init().unwrap(); |
887 | |
888 | let caps = crate::Caps::new_any(); |
889 | let wildcard_templ = crate::PadTemplate::new( |
890 | "sink_%u_%s" , |
891 | crate::PadDirection::Sink, |
892 | crate::PadPresence::Request, |
893 | &caps, |
894 | ) |
895 | .unwrap(); |
896 | |
897 | let templ = crate::PadTemplate::new( |
898 | "sink_0" , |
899 | crate::PadDirection::Sink, |
900 | crate::PadPresence::Always, |
901 | &caps, |
902 | ) |
903 | .unwrap(); |
904 | |
905 | let target = crate::Pad::from_template(&templ); |
906 | // Panic: attempt to build from a wildcard-named template |
907 | // with a target name missing a part |
908 | // without providing a name. |
909 | let _ghost_pad = GhostPad::builder_from_template_with_target(&wildcard_templ, &target) |
910 | .unwrap() |
911 | .build(); |
912 | } |
913 | |
914 | #[test ] |
915 | #[should_panic ] |
916 | fn from_template_with_target_incompatible_conversion_unsigned() { |
917 | crate::init().unwrap(); |
918 | |
919 | let caps = crate::Caps::new_any(); |
920 | let wildcard_templ = crate::PadTemplate::new( |
921 | "sink_%u" , |
922 | crate::PadDirection::Sink, |
923 | crate::PadPresence::Request, |
924 | &caps, |
925 | ) |
926 | .unwrap(); |
927 | |
928 | let templ = crate::PadTemplate::new( |
929 | "sink_-1" , |
930 | crate::PadDirection::Sink, |
931 | crate::PadPresence::Always, |
932 | &caps, |
933 | ) |
934 | .unwrap(); |
935 | |
936 | let target = crate::Pad::from_template(&templ); |
937 | // Panic: attempt to build from a wildcard-named template |
938 | // with a target name %d, expecting %u |
939 | // without providing a name. |
940 | let _ghost_pad = GhostPad::builder_from_template_with_target(&wildcard_templ, &target) |
941 | .unwrap() |
942 | .build(); |
943 | } |
944 | |
945 | #[test ] |
946 | #[should_panic ] |
947 | fn from_template_with_target_incompatible_conversion_decimal() { |
948 | crate::init().unwrap(); |
949 | |
950 | let caps = crate::Caps::new_any(); |
951 | let wildcard_templ = crate::PadTemplate::new( |
952 | "sink_%u" , |
953 | crate::PadDirection::Sink, |
954 | crate::PadPresence::Request, |
955 | &caps, |
956 | ) |
957 | .unwrap(); |
958 | |
959 | let templ = crate::PadTemplate::new( |
960 | "sink_test" , |
961 | crate::PadDirection::Sink, |
962 | crate::PadPresence::Always, |
963 | &caps, |
964 | ) |
965 | .unwrap(); |
966 | |
967 | let target = crate::Pad::from_template(&templ); |
968 | // Panic: attempt to build from a wildcard-named template |
969 | // with a target name with %s, expecting %d |
970 | // without providing a name. |
971 | let _ghost_pad = GhostPad::builder_from_template_with_target(&wildcard_templ, &target) |
972 | .unwrap() |
973 | .build(); |
974 | } |
975 | |
976 | #[test ] |
977 | #[should_panic ] |
978 | fn from_template_with_target_incompatible_missing_decimal() { |
979 | crate::init().unwrap(); |
980 | |
981 | let caps = crate::Caps::new_any(); |
982 | let wildcard_templ = crate::PadTemplate::new( |
983 | "sink_%d" , |
984 | crate::PadDirection::Sink, |
985 | crate::PadPresence::Request, |
986 | &caps, |
987 | ) |
988 | .unwrap(); |
989 | |
990 | let templ = crate::PadTemplate::new( |
991 | "sink_" , |
992 | crate::PadDirection::Sink, |
993 | crate::PadPresence::Always, |
994 | &caps, |
995 | ) |
996 | .unwrap(); |
997 | |
998 | let target = crate::Pad::from_template(&templ); |
999 | // Panic: attempt to build from a wildcard-named template |
1000 | // with a target name missing a number, expecting %d |
1001 | // without providing a name. |
1002 | let _ghost_pad = GhostPad::builder_from_template_with_target(&wildcard_templ, &target) |
1003 | .unwrap() |
1004 | .build(); |
1005 | } |
1006 | } |
1007 | |