Skip to main content

gstreamer_analytics/
relation_meta.rs

1// Take a look at the license at the top of the repository in the LICENSE file.
2
3use glib::translate::*;
4use gst::prelude::*;
5use std::marker::PhantomData;
6
7use crate::{RelTypes, ffi};
8
9#[repr(transparent)]
10#[doc(alias = "GstAnalyticsRelationMeta")]
11pub struct AnalyticsRelationMeta(ffi::GstAnalyticsRelationMeta);
12
13unsafe impl Send for AnalyticsRelationMeta {}
14unsafe impl Sync for AnalyticsRelationMeta {}
15
16#[derive(Debug, Copy, Clone)]
17#[doc(alias = "GstAnalyticsRelationMetaInitParams")]
18pub struct AnalyticsRelationMetaInitParams(ffi::GstAnalyticsRelationMetaInitParams);
19
20impl Default for AnalyticsRelationMetaInitParams {
21    fn default() -> Self {
22        Self(ffi::GstAnalyticsRelationMetaInitParams {
23            initial_relation_order: 0,
24            initial_buf_size: 0,
25        })
26    }
27}
28
29impl AnalyticsRelationMetaInitParams {
30    pub fn new(initial_relation_order: usize, initial_buf_size: usize) -> Self {
31        skip_assert_initialized!();
32        Self(ffi::GstAnalyticsRelationMetaInitParams {
33            initial_relation_order,
34            initial_buf_size,
35        })
36    }
37}
38
39#[derive(Debug, Clone)]
40pub struct AnalyticsMtdRef<'a, T: AnalyticsMtd> {
41    id: u32,
42    meta: gst::MetaRef<'a, AnalyticsRelationMeta>,
43    mtd_type: PhantomData<&'a T>,
44}
45
46#[derive(Debug)]
47pub struct AnalyticsMtdRefMut<'a, T: AnalyticsMtd> {
48    id: u32,
49    meta: &'a mut gst::MetaRefMut<'a, AnalyticsRelationMeta, gst::meta::Standalone>,
50    mtd_type: PhantomData<&'a T>,
51}
52
53pub struct AnalyticsRelationPath {
54    garray: *mut glib::ffi::GArray,
55}
56
57impl std::fmt::Debug for AnalyticsRelationMeta {
58    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> Result<(), std::fmt::Error> {
59        f.debug_struct("AnalyticsRelationMeta")
60            .field("len", &self.len())
61            .finish()
62    }
63}
64
65impl AnalyticsRelationMeta {
66    #[doc(alias = "gst_buffer_add_analytics_relation_meta")]
67    pub fn add(buffer: &mut gst::BufferRef) -> gst::MetaRefMut<'_, Self, gst::meta::Standalone> {
68        skip_assert_initialized!();
69
70        unsafe {
71            let meta_ptr = ffi::gst_buffer_add_analytics_relation_meta(buffer.as_mut_ptr());
72            Self::from_mut_ptr(buffer, meta_ptr)
73        }
74    }
75
76    #[doc(alias = "gst_buffer_add_analytics_relation_meta_full")]
77    pub fn add_full<'a>(
78        buffer: &'a mut gst::BufferRef,
79        init_params: &AnalyticsRelationMetaInitParams,
80    ) -> gst::MetaRefMut<'a, Self, gst::meta::Standalone> {
81        skip_assert_initialized!();
82
83        unsafe {
84            let meta_ptr = ffi::gst_buffer_add_analytics_relation_meta_full(
85                buffer.as_mut_ptr(),
86                mut_override(&init_params.0),
87            );
88            Self::from_mut_ptr(buffer, meta_ptr)
89        }
90    }
91
92    #[doc(alias = "gst_analytics_relation_get_length")]
93    pub fn len(&self) -> usize {
94        unsafe { ffi::gst_analytics_relation_get_length(self.as_mut_ptr()) }
95    }
96
97    pub fn is_empty(&self) -> bool {
98        self.len() == 0
99    }
100
101    #[doc(alias = "gst_analytics_relation_meta_set_relation")]
102    pub fn set_relation(
103        &mut self,
104        type_: crate::RelTypes,
105        an_meta_first_id: u32,
106        an_meta_second_id: u32,
107    ) -> Result<(), glib::BoolError> {
108        let ret = unsafe {
109            from_glib(ffi::gst_analytics_relation_meta_set_relation(
110                self.as_mut_ptr(),
111                type_.into_glib(),
112                an_meta_first_id,
113                an_meta_second_id,
114            ))
115        };
116
117        if ret {
118            Ok(())
119        } else {
120            Err(glib::bool_error!(
121                "Could not set relation {:}->{:} of type {:?}",
122                an_meta_first_id,
123                an_meta_second_id,
124                type_
125            ))
126        }
127    }
128
129    #[doc(alias = "gst_analytics_relation_meta_get_relation")]
130    pub fn relation(&self, an_meta_first_id: u32, an_meta_second_id: u32) -> crate::RelTypes {
131        unsafe {
132            from_glib(ffi::gst_analytics_relation_meta_get_relation(
133                self.as_mut_ptr(),
134                an_meta_first_id,
135                an_meta_second_id,
136            ))
137        }
138    }
139
140    #[doc(alias = "gst_analytics_relation_meta_exist")]
141    pub fn exist(
142        &self,
143        an_meta_first_id: u32,
144        an_meta_second_id: u32,
145        relation_span: i32,
146        cond_types: crate::RelTypes,
147    ) -> bool {
148        unsafe {
149            from_glib(ffi::gst_analytics_relation_meta_exist(
150                self.as_mut_ptr(),
151                an_meta_first_id,
152                an_meta_second_id,
153                relation_span,
154                cond_types.into_glib(),
155                std::ptr::null_mut(),
156            ))
157        }
158    }
159
160    #[doc(alias = "gst_analytics_relation_meta_exist")]
161    pub fn exist_path(
162        &self,
163        an_meta_first_id: u32,
164        an_meta_second_id: u32,
165        relation_span: i32,
166        cond_types: crate::RelTypes,
167    ) -> Result<AnalyticsRelationPath, glib::BoolError> {
168        let mut array = std::ptr::null_mut::<glib::ffi::GArray>();
169        let ret = unsafe {
170            from_glib(ffi::gst_analytics_relation_meta_exist(
171                self.as_mut_ptr(),
172                an_meta_first_id,
173                an_meta_second_id,
174                relation_span,
175                cond_types.into_glib(),
176                &mut array,
177            ))
178        };
179
180        if ret {
181            Ok(AnalyticsRelationPath { garray: array })
182        } else {
183            Err(glib::bool_error!("Such relation doesn't exist"))
184        }
185    }
186
187    pub unsafe fn as_mut_ptr(&self) -> *mut ffi::GstAnalyticsRelationMeta {
188        mut_override(&self.0)
189    }
190}
191
192impl UnsafeFrom<&AnalyticsRelationMeta> for ffi::GstAnalyticsMtd {
193    unsafe fn unsafe_from(t: &AnalyticsRelationMeta) -> Self {
194        unsafe {
195            ffi::GstAnalyticsMtd {
196                id: 0,
197                meta: t.as_mut_ptr(),
198            }
199        }
200    }
201}
202
203impl AnalyticsRelationPath {
204    pub fn as_slice(&self) -> &[u32] {
205        unsafe {
206            std::slice::from_raw_parts(
207                (*self.garray).data as *const u32,
208                (*self.garray).len as usize,
209            )
210        }
211    }
212}
213
214impl Drop for AnalyticsRelationPath {
215    fn drop(&mut self) {
216        unsafe {
217            glib::ffi::g_array_free(self.garray, glib::ffi::GTRUE);
218        }
219    }
220}
221
222mod sealed {
223    pub trait Sealed {}
224    impl<T> Sealed for T {}
225}
226
227pub trait AnalyticsMetaRefExt<'a>: sealed::Sealed {
228    #[doc(alias = "gst_analytics_relation_meta_get_mtd")]
229    fn mtd<T: AnalyticsMtd>(&self, an_meta_id: u32) -> Option<AnalyticsMtdRef<'a, T>>;
230    fn iter<T: AnalyticsMtd>(&'a self) -> AnalyticsMtdIter<'a, T>;
231    fn iter_direct_related<T: AnalyticsMtd>(
232        &'a self,
233        an_meta_id: u32,
234        rel_type: RelTypes,
235    ) -> AnalyticsMtdIter<'a, T>;
236}
237
238impl<'a> AnalyticsMetaRefExt<'a> for gst::MetaRef<'a, AnalyticsRelationMeta> {
239    fn mtd<T: AnalyticsMtd>(&self, an_meta_id: u32) -> Option<AnalyticsMtdRef<'a, T>> {
240        unsafe {
241            let mut mtd = std::mem::MaybeUninit::uninit();
242            let ret = from_glib(ffi::gst_analytics_relation_meta_get_mtd(
243                self.as_mut_ptr(),
244                an_meta_id,
245                T::mtd_type(),
246                mtd.as_mut_ptr(),
247            ));
248            let id = mtd.assume_init().id;
249
250            if ret {
251                Some(AnalyticsMtdRef::from_meta(self, id))
252            } else {
253                None
254            }
255        }
256    }
257
258    fn iter<T: AnalyticsMtd>(&'a self) -> AnalyticsMtdIter<'a, T> {
259        AnalyticsMtdIter::new(self)
260    }
261    fn iter_direct_related<T: AnalyticsMtd>(
262        &'a self,
263        an_meta_id: u32,
264        rel_type: RelTypes,
265    ) -> AnalyticsMtdIter<'a, T> {
266        AnalyticsMtdIter::new_direct_related(self, an_meta_id, rel_type.into_glib())
267    }
268}
269
270impl<'a, T: AnalyticsMtd> AnalyticsMtdRef<'a, T> {
271    pub fn id(&self) -> u32 {
272        self.id
273    }
274
275    #[cfg(feature = "v1_28")]
276    pub(crate) fn meta_ref(&self) -> &gst::MetaRef<'a, AnalyticsRelationMeta> {
277        &self.meta
278    }
279
280    pub unsafe fn from_meta(meta: &gst::MetaRef<'a, AnalyticsRelationMeta>, id: u32) -> Self {
281        skip_assert_initialized!();
282        AnalyticsMtdRef {
283            meta: meta.clone(),
284            id,
285            mtd_type: PhantomData,
286        }
287    }
288
289    #[doc(alias = "gst_analytics_mtd_get_mtd_type")]
290    pub fn mtd_type(&self) -> ffi::GstAnalyticsMtdType {
291        unsafe {
292            let mtd = ffi::GstAnalyticsMtd::unsafe_from(self);
293            ffi::gst_analytics_mtd_get_mtd_type(&mtd)
294        }
295    }
296
297    #[cfg(feature = "v1_30")]
298    #[cfg_attr(docsrs, doc(cfg(feature = "v1_30")))]
299    #[doc(alias = "gst_analytics_mtd_get_semantic_tag")]
300    pub fn semantic_tag(&self) -> Result<glib::GString, glib::BoolError> {
301        unsafe {
302            let mtd = ffi::GstAnalyticsMtd::unsafe_from(self);
303            let tag = ffi::gst_analytics_mtd_get_semantic_tag(&mtd);
304            if tag.is_null() {
305                Err(glib::bool_error!("Could not retrieve semantic tag"))
306            } else {
307                Ok(from_glib_full(tag))
308            }
309        }
310    }
311
312    #[cfg(feature = "v1_30")]
313    #[cfg_attr(docsrs, doc(cfg(feature = "v1_30")))]
314    #[doc(alias = "gst_analytics_mtd_has_semantic_tag")]
315    pub fn has_semantic_tag(&self, tag: &str) -> bool {
316        unsafe {
317            let mtd = ffi::GstAnalyticsMtd::unsafe_from(self);
318            from_glib(ffi::gst_analytics_mtd_has_semantic_tag(
319                &mtd,
320                tag.to_glib_none().0,
321            ))
322        }
323    }
324
325    #[cfg(feature = "v1_30")]
326    #[cfg_attr(docsrs, doc(cfg(feature = "v1_30")))]
327    #[doc(alias = "gst_analytics_mtd_semantic_tag_has_prefix")]
328    pub fn semantic_tag_has_prefix(&self, prefix: &str) -> bool {
329        unsafe {
330            let mtd = ffi::GstAnalyticsMtd::unsafe_from(self);
331            from_glib(ffi::gst_analytics_mtd_semantic_tag_has_prefix(
332                &mtd,
333                prefix.to_glib_none().0,
334            ))
335        }
336    }
337}
338impl<'a> AnalyticsMtdRef<'a, AnalyticsAnyMtd> {
339    pub fn downcast<T: AnalyticsMtd>(
340        self,
341    ) -> Result<AnalyticsMtdRef<'a, T>, AnalyticsMtdRef<'a, AnalyticsAnyMtd>> {
342        if self.mtd_type() == T::mtd_type() {
343            Ok(AnalyticsMtdRef {
344                id: self.id,
345                meta: self.meta,
346                mtd_type: PhantomData,
347            })
348        } else {
349            Err(self)
350        }
351    }
352
353    pub fn downcast_ref<T: AnalyticsMtd>(&self) -> Option<&AnalyticsMtdRef<'a, T>> {
354        unsafe {
355            if self.mtd_type() == T::mtd_type() {
356                Some(&*(self as *const _ as *const _))
357            } else {
358                None
359            }
360        }
361    }
362}
363
364impl<'a> AnalyticsMtdRefMut<'a, AnalyticsAnyMtd> {
365    pub fn downcast_mut<T: AnalyticsMtd>(&mut self) -> Option<&mut AnalyticsMtdRefMut<'a, T>> {
366        unsafe {
367            if self.as_ref().mtd_type() == T::mtd_type() {
368                Some(&mut *(self as *mut _ as *mut _))
369            } else {
370                None
371            }
372        }
373    }
374}
375
376impl<'a, T: AnalyticsMtd> UnsafeFrom<&AnalyticsMtdRef<'a, T>> for ffi::GstAnalyticsMtd {
377    unsafe fn unsafe_from(t: &AnalyticsMtdRef<'a, T>) -> Self {
378        unsafe {
379            ffi::GstAnalyticsMtd {
380                id: t.id,
381                meta: t.meta.as_mut_ptr(),
382            }
383        }
384    }
385}
386
387pub trait AnalyticsMetaRefMutExt<'a>: sealed::Sealed {
388    #[doc(alias = "gst_analytics_relation_meta_get_mtd")]
389    fn mtd_mut<T: AnalyticsMtd>(&'a mut self, an_meta_id: u32)
390    -> Option<AnalyticsMtdRefMut<'a, T>>;
391
392    fn iter_mut<T: AnalyticsMtd>(&'a mut self) -> AnalyticsMtdIterMut<'a, T>;
393    fn iter_direct_related_mut<T: AnalyticsMtd>(
394        &'a mut self,
395        an_meta_id: u32,
396        rel_type: RelTypes,
397    ) -> AnalyticsMtdIterMut<'a, T>;
398}
399
400impl<'a> AnalyticsMetaRefMutExt<'a>
401    for gst::MetaRefMut<'a, AnalyticsRelationMeta, gst::meta::Standalone>
402{
403    fn mtd_mut<T: AnalyticsMtd>(
404        &'a mut self,
405        an_meta_id: u32,
406    ) -> Option<AnalyticsMtdRefMut<'a, T>> {
407        unsafe {
408            let mut mtd = std::mem::MaybeUninit::uninit();
409            let ret = from_glib(ffi::gst_analytics_relation_meta_get_mtd(
410                self.as_mut_ptr(),
411                an_meta_id,
412                T::mtd_type(),
413                mtd.as_mut_ptr(),
414            ));
415            let id = mtd.assume_init().id;
416
417            if ret {
418                Some(AnalyticsMtdRefMut::from_meta(self, id))
419            } else {
420                None
421            }
422        }
423    }
424
425    fn iter_mut<T: AnalyticsMtd>(&'a mut self) -> AnalyticsMtdIterMut<'a, T> {
426        AnalyticsMtdIterMut::new(self)
427    }
428    fn iter_direct_related_mut<T: AnalyticsMtd>(
429        &'a mut self,
430        an_meta_id: u32,
431        rel_type: RelTypes,
432    ) -> AnalyticsMtdIterMut<'a, T> {
433        AnalyticsMtdIterMut::new_direct_related(self, an_meta_id, rel_type.into_glib())
434    }
435}
436
437unsafe impl MetaAPI for AnalyticsRelationMeta {
438    type GstType = ffi::GstAnalyticsRelationMeta;
439
440    #[doc(alias = "gst_analytics_relation_meta_api_get_type")]
441    #[inline]
442    fn meta_api() -> glib::Type {
443        unsafe { from_glib(ffi::gst_analytics_relation_meta_api_get_type()) }
444    }
445}
446
447pub unsafe trait AnalyticsMtd {
448    fn mtd_type() -> ffi::GstAnalyticsMtdType;
449}
450
451pub trait AnalyticsMtdExt: AnalyticsMtd {
452    #[doc(alias = "gst_analytics_mtd_type_get_name")]
453    fn type_name() -> &'static str {
454        unsafe {
455            let ptr = ffi::gst_analytics_mtd_type_get_name(Self::mtd_type());
456            std::ffi::CStr::from_ptr(ptr).to_str().unwrap()
457        }
458    }
459}
460
461impl<T: AnalyticsMtd> AnalyticsMtdExt for T {}
462
463impl<'a, T: AnalyticsMtd> AnalyticsMtdRefMut<'a, T> {
464    pub fn id(&self) -> u32 {
465        self.id
466    }
467
468    pub unsafe fn from_meta(
469        meta: &'a mut gst::MetaRefMut<'a, AnalyticsRelationMeta, gst::meta::Standalone>,
470        id: u32,
471    ) -> Self {
472        skip_assert_initialized!();
473        AnalyticsMtdRefMut {
474            meta,
475            id,
476            mtd_type: PhantomData,
477        }
478    }
479
480    #[cfg(feature = "v1_30")]
481    #[cfg_attr(docsrs, doc(cfg(feature = "v1_30")))]
482    #[doc(alias = "gst_analytics_mtd_set_semantic_tag")]
483    pub fn set_semantic_tag(&mut self, tag: &str) -> Result<(), glib::BoolError> {
484        let ret = unsafe {
485            let mut mtd = ffi::GstAnalyticsMtd::unsafe_from(self);
486            from_glib(ffi::gst_analytics_mtd_set_semantic_tag(
487                &mut mtd,
488                tag.to_glib_none().0,
489            ))
490        };
491
492        if ret {
493            Ok(())
494        } else {
495            Err(glib::bool_error!("Couldn't set semantic tag"))
496        }
497    }
498}
499
500impl<'a, T: AnalyticsMtd> UnsafeFrom<&mut AnalyticsMtdRefMut<'a, T>> for ffi::GstAnalyticsMtd {
501    unsafe fn unsafe_from(t: &mut AnalyticsMtdRefMut<'a, T>) -> Self {
502        ffi::GstAnalyticsMtd {
503            id: t.id,
504            meta: t.meta.as_mut_ptr(),
505        }
506    }
507}
508
509impl<'a, T: AnalyticsMtd> From<AnalyticsMtdRefMut<'a, T>> for AnalyticsMtdRef<'a, T> {
510    fn from(value: AnalyticsMtdRefMut<'a, T>) -> Self {
511        skip_assert_initialized!();
512        AnalyticsMtdRef {
513            meta: value.meta.as_ref().clone(),
514            id: value.id,
515            mtd_type: value.mtd_type,
516        }
517    }
518}
519
520impl<'a, T: AnalyticsMtd> From<&mut AnalyticsMtdRefMut<'a, T>> for AnalyticsMtdRef<'a, T> {
521    fn from(value: &mut AnalyticsMtdRefMut<'a, T>) -> Self {
522        skip_assert_initialized!();
523        AnalyticsMtdRef {
524            meta: value.meta.as_ref().clone(),
525            id: value.id,
526            mtd_type: value.mtd_type,
527        }
528    }
529}
530
531impl<'a, T: AnalyticsMtd> AsRef<AnalyticsMtdRef<'a, T>> for AnalyticsMtdRefMut<'a, T> {
532    #[inline]
533    fn as_ref(&self) -> &AnalyticsMtdRef<'a, T> {
534        unsafe { &*(self as *const AnalyticsMtdRefMut<'a, T> as *const AnalyticsMtdRef<'a, T>) }
535    }
536}
537
538macro_rules! define_mtd_iter {
539    ($name:ident, $metaref:ty, $itemref:ty, $copy_meta:expr) => {
540        #[must_use = "iterators are lazy and do nothing unless consumed"]
541        pub struct $name<'a, T: AnalyticsMtd> {
542            meta: $metaref,
543            state: glib::ffi::gpointer,
544            mtd_type: ffi::GstAnalyticsMtdType,
545            an_meta_id: u32,
546            rel_type: ffi::GstAnalyticsRelTypes,
547            phantom: std::marker::PhantomData<T>,
548        }
549
550        impl<'a, T: AnalyticsMtd> $name<'a, T> {
551            fn new(meta: $metaref) -> Self {
552                skip_assert_initialized!();
553                $name {
554                    meta,
555                    state: std::ptr::null_mut(),
556                    mtd_type: T::mtd_type(),
557                    an_meta_id: u32::MAX,
558                    rel_type: RelTypes::ANY.into_glib(),
559                    phantom: PhantomData,
560                }
561            }
562            fn new_direct_related(
563                meta: $metaref,
564                an_meta_id: u32,
565                rel_type: ffi::GstAnalyticsRelTypes,
566            ) -> Self {
567                skip_assert_initialized!();
568                $name {
569                    meta,
570                    state: std::ptr::null_mut(),
571                    mtd_type: T::mtd_type(),
572                    an_meta_id,
573                    rel_type,
574                    phantom: PhantomData,
575                }
576            }
577        }
578
579        impl<'a, T: AnalyticsMtd + 'a> Iterator for $name<'a, T> {
580            type Item = $itemref;
581
582            fn next(&mut self) -> Option<Self::Item> {
583                unsafe {
584                    let mut mtd = ffi::GstAnalyticsMtd::unsafe_from(&**self.meta);
585                    let ret = {
586                        if self.an_meta_id == u32::MAX {
587                            ffi::gst_analytics_relation_meta_iterate(
588                                self.meta.as_mut_ptr(),
589                                &mut self.state,
590                                self.mtd_type,
591                                &mut mtd,
592                            )
593                        } else {
594                            ffi::gst_analytics_relation_meta_get_direct_related(
595                                self.meta.as_mut_ptr(),
596                                self.an_meta_id,
597                                self.rel_type,
598                                self.mtd_type,
599                                &mut self.state,
600                                &mut mtd,
601                            )
602                        }
603                    };
604                    if from_glib(ret) {
605                        // This is a known clippy limitation
606                        // https://github.com/rust-lang/rust-clippy/issues/1553
607                        #[allow(clippy::redundant_closure_call)]
608                        Some(Self::Item::from_meta($copy_meta(self.meta), mtd.id))
609                    } else {
610                        None
611                    }
612                }
613            }
614        }
615    };
616}
617
618define_mtd_iter!(
619    AnalyticsMtdIter,
620    &'a gst::MetaRef<'a, AnalyticsRelationMeta>,
621    AnalyticsMtdRef<'a, T>,
622    |meta| meta
623);
624
625define_mtd_iter!(
626    AnalyticsMtdIterMut,
627    &'a mut gst::MetaRefMut<'a, AnalyticsRelationMeta, gst::meta::Standalone>,
628    AnalyticsMtdRefMut<'a, T>,
629    |meta: &mut _| &mut *(meta as *mut gst::MetaRefMut<
630        'a,
631        AnalyticsRelationMeta,
632        gst::meta::Standalone,
633    >)
634);
635
636#[derive(Debug)]
637pub enum AnalyticsAnyMtd {}
638
639unsafe impl AnalyticsMtd for AnalyticsAnyMtd {
640    fn mtd_type() -> ffi::GstAnalyticsMtdType {
641        ffi::GST_ANALYTICS_MTD_TYPE_ANY as ffi::GstAnalyticsMtdType
642    }
643}
644
645#[cfg(test)]
646mod tests {
647    use crate::*;
648
649    #[test]
650    fn build_relation_meta() {
651        gst::init().unwrap();
652
653        let mut buf = gst::Buffer::new();
654
655        let meta = AnalyticsRelationMeta::add(buf.make_mut());
656
657        assert!(meta.is_empty());
658    }
659
660    #[test]
661    fn build_relation_meta_full() {
662        gst::init().unwrap();
663
664        let mut buf = gst::Buffer::new();
665
666        let params = AnalyticsRelationMetaInitParams::new(10, 10);
667        let meta = AnalyticsRelationMeta::add_full(buf.make_mut(), &params);
668
669        assert!(meta.is_empty());
670    }
671
672    #[test]
673    fn relations() {
674        gst::init().unwrap();
675
676        let mut buf = gst::Buffer::new();
677        let _ = AnalyticsRelationMeta::add(buf.make_mut());
678
679        let mut meta = buf.make_mut().meta_mut::<AnalyticsRelationMeta>().unwrap();
680        let od = meta
681            .add_od_mtd(glib::Quark::from_str("blb"), 0, 1, 10, 20, 0.8)
682            .unwrap();
683        let od1_id = od.id();
684
685        let od = meta
686            .add_od_mtd(glib::Quark::from_str("blb"), 0, 1, 10, 20, 0.8)
687            .unwrap();
688        let od2_id = od.id();
689
690        let od: AnalyticsMtdRef<'_, AnalyticsODMtd> = meta
691            .add_od_mtd(glib::Quark::from_str("blb"), 0, 1, 10, 20, 0.8)
692            .unwrap();
693        let od3_id = od.id();
694
695        meta.set_relation(RelTypes::IS_PART_OF, od1_id, od2_id)
696            .unwrap();
697        meta.set_relation(RelTypes::IS_PART_OF, od2_id, od3_id)
698            .unwrap();
699
700        meta.set_relation(RelTypes::IS_PART_OF, 8888, 9999)
701            .expect_err("Invalid id");
702
703        let meta = buf.meta::<AnalyticsRelationMeta>().unwrap();
704        assert!(meta.relation(od1_id, od2_id) == crate::RelTypes::IS_PART_OF);
705        assert!(meta.relation(od2_id, od3_id) == crate::RelTypes::IS_PART_OF);
706
707        assert!(meta.exist(od1_id, od2_id, 1, crate::RelTypes::IS_PART_OF));
708        assert!(meta.exist(od1_id, od3_id, 2, crate::RelTypes::IS_PART_OF));
709        assert!(!meta.exist(od2_id, od1_id, 1, crate::RelTypes::IS_PART_OF));
710        assert!(!meta.exist(od1_id, od3_id, 1, crate::RelTypes::IS_PART_OF));
711        assert!(!meta.exist(od1_id, od2_id, 1, crate::RelTypes::CONTAIN));
712
713        let path = meta
714            .exist_path(od1_id, od3_id, 3, crate::RelTypes::ANY)
715            .unwrap();
716
717        assert_eq!(path.as_slice().len(), 3);
718        assert_eq!(path.as_slice()[0], od1_id);
719        assert_eq!(path.as_slice()[1], od2_id);
720        assert_eq!(path.as_slice()[2], od3_id);
721
722        assert_eq!(meta.len(), meta.iter::<AnalyticsAnyMtd>().count());
723        assert_eq!(meta.len(), meta.iter::<AnalyticsODMtd>().count());
724        for mtd in meta.iter::<AnalyticsODMtd>() {
725            assert_eq!(mtd.obj_type().unwrap(), glib::Quark::from_str("blb"))
726        }
727
728        assert_eq!(meta.len(), meta.iter::<AnalyticsAnyMtd>().count());
729        for mtd in meta.iter::<AnalyticsAnyMtd>() {
730            if let Ok(mtd) = mtd.downcast::<AnalyticsODMtd>() {
731                assert_eq!(mtd.obj_type().unwrap(), glib::Quark::from_str("blb"))
732            }
733        }
734
735        assert_eq!(
736            meta.iter_direct_related::<AnalyticsODMtd>(od1_id, crate::RelTypes::IS_PART_OF)
737                .count(),
738            1
739        );
740        assert_eq!(
741            meta.iter_direct_related::<AnalyticsODMtd>(od2_id, crate::RelTypes::IS_PART_OF)
742                .count(),
743            1
744        );
745        assert_eq!(
746            meta.iter_direct_related::<AnalyticsODMtd>(od3_id, crate::RelTypes::IS_PART_OF)
747                .count(),
748            0
749        );
750        assert_eq!(
751            meta.iter_direct_related::<AnalyticsODMtd>(od1_id, crate::RelTypes::CONTAIN)
752                .count(),
753            0
754        );
755
756        assert_eq!(
757            meta.iter_direct_related::<AnalyticsAnyMtd>(od1_id, crate::RelTypes::CONTAIN)
758                .count(),
759            0
760        );
761        for mtd in meta.iter_direct_related::<AnalyticsODMtd>(od1_id, crate::RelTypes::IS_PART_OF) {
762            assert_eq!(mtd.obj_type().unwrap(), glib::Quark::from_str("blb"))
763        }
764
765        let mut meta = buf.make_mut().meta_mut::<AnalyticsRelationMeta>().unwrap();
766        assert_eq!(meta.len(), meta.iter_mut::<AnalyticsAnyMtd>().count());
767
768        let mut meta = buf.make_mut().meta_mut::<AnalyticsRelationMeta>().unwrap();
769        let _ = meta.add_tracking_mtd(10, gst::ClockTime::from_seconds(10));
770        let _ = meta.add_tracking_mtd(10, gst::ClockTime::from_seconds(10));
771
772        for mut item in meta.iter_mut::<AnalyticsTrackingMtd>() {
773            item.set_lost().unwrap();
774        }
775    }
776}