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    pub unsafe fn from_meta(meta: &gst::MetaRef<'a, AnalyticsRelationMeta>, id: u32) -> Self {
276        skip_assert_initialized!();
277        AnalyticsMtdRef {
278            meta: meta.clone(),
279            id,
280            mtd_type: PhantomData,
281        }
282    }
283
284    #[doc(alias = "gst_analytics_mtd_get_mtd_type")]
285    pub fn mtd_type(&self) -> ffi::GstAnalyticsMtdType {
286        unsafe {
287            let mtd = ffi::GstAnalyticsMtd::unsafe_from(self);
288            ffi::gst_analytics_mtd_get_mtd_type(&mtd)
289        }
290    }
291}
292impl<'a> AnalyticsMtdRef<'a, AnalyticsAnyMtd> {
293    pub fn downcast<T: AnalyticsMtd>(
294        self,
295    ) -> Result<AnalyticsMtdRef<'a, T>, AnalyticsMtdRef<'a, AnalyticsAnyMtd>> {
296        if self.mtd_type() == T::mtd_type() {
297            Ok(AnalyticsMtdRef {
298                id: self.id,
299                meta: self.meta,
300                mtd_type: PhantomData,
301            })
302        } else {
303            Err(self)
304        }
305    }
306
307    pub fn downcast_ref<T: AnalyticsMtd>(&self) -> Option<&AnalyticsMtdRef<'a, T>> {
308        unsafe {
309            if self.mtd_type() == T::mtd_type() {
310                Some(&*(self as *const _ as *const _))
311            } else {
312                None
313            }
314        }
315    }
316}
317
318impl<'a> AnalyticsMtdRefMut<'a, AnalyticsAnyMtd> {
319    pub fn downcast_mut<T: AnalyticsMtd>(&mut self) -> Option<&mut AnalyticsMtdRefMut<'a, T>> {
320        unsafe {
321            if self.as_ref().mtd_type() == T::mtd_type() {
322                Some(&mut *(self as *mut _ as *mut _))
323            } else {
324                None
325            }
326        }
327    }
328}
329
330impl<'a, T: AnalyticsMtd> UnsafeFrom<&AnalyticsMtdRef<'a, T>> for ffi::GstAnalyticsMtd {
331    unsafe fn unsafe_from(t: &AnalyticsMtdRef<'a, T>) -> Self {
332        unsafe {
333            ffi::GstAnalyticsMtd {
334                id: t.id,
335                meta: t.meta.as_mut_ptr(),
336            }
337        }
338    }
339}
340
341pub trait AnalyticsMetaRefMutExt<'a>: sealed::Sealed {
342    #[doc(alias = "gst_analytics_relation_meta_get_mtd")]
343    fn mtd_mut<T: AnalyticsMtd>(&'a mut self, an_meta_id: u32)
344    -> Option<AnalyticsMtdRefMut<'a, T>>;
345
346    fn iter_mut<T: AnalyticsMtd>(&'a mut self) -> AnalyticsMtdIterMut<'a, T>;
347    fn iter_direct_related_mut<T: AnalyticsMtd>(
348        &'a mut self,
349        an_meta_id: u32,
350        rel_type: RelTypes,
351    ) -> AnalyticsMtdIterMut<'a, T>;
352}
353
354impl<'a> AnalyticsMetaRefMutExt<'a>
355    for gst::MetaRefMut<'a, AnalyticsRelationMeta, gst::meta::Standalone>
356{
357    fn mtd_mut<T: AnalyticsMtd>(
358        &'a mut self,
359        an_meta_id: u32,
360    ) -> Option<AnalyticsMtdRefMut<'a, T>> {
361        unsafe {
362            let mut mtd = std::mem::MaybeUninit::uninit();
363            let ret = from_glib(ffi::gst_analytics_relation_meta_get_mtd(
364                self.as_mut_ptr(),
365                an_meta_id,
366                T::mtd_type(),
367                mtd.as_mut_ptr(),
368            ));
369            let id = mtd.assume_init().id;
370
371            if ret {
372                Some(AnalyticsMtdRefMut::from_meta(self, id))
373            } else {
374                None
375            }
376        }
377    }
378
379    fn iter_mut<T: AnalyticsMtd>(&'a mut self) -> AnalyticsMtdIterMut<'a, T> {
380        AnalyticsMtdIterMut::new(self)
381    }
382    fn iter_direct_related_mut<T: AnalyticsMtd>(
383        &'a mut self,
384        an_meta_id: u32,
385        rel_type: RelTypes,
386    ) -> AnalyticsMtdIterMut<'a, T> {
387        AnalyticsMtdIterMut::new_direct_related(self, an_meta_id, rel_type.into_glib())
388    }
389}
390
391unsafe impl MetaAPI for AnalyticsRelationMeta {
392    type GstType = ffi::GstAnalyticsRelationMeta;
393
394    #[doc(alias = "gst_analytics_relation_meta_api_get_type")]
395    #[inline]
396    fn meta_api() -> glib::Type {
397        unsafe { from_glib(ffi::gst_analytics_relation_meta_api_get_type()) }
398    }
399}
400
401pub unsafe trait AnalyticsMtd {
402    fn mtd_type() -> ffi::GstAnalyticsMtdType;
403}
404
405pub trait AnalyticsMtdExt: AnalyticsMtd {
406    #[doc(alias = "gst_analytics_mtd_type_get_name")]
407    fn type_name() -> &'static str {
408        unsafe {
409            let ptr = ffi::gst_analytics_mtd_type_get_name(Self::mtd_type());
410            std::ffi::CStr::from_ptr(ptr).to_str().unwrap()
411        }
412    }
413}
414
415impl<T: AnalyticsMtd> AnalyticsMtdExt for T {}
416
417impl<'a, T: AnalyticsMtd> AnalyticsMtdRefMut<'a, T> {
418    pub fn id(&self) -> u32 {
419        self.id
420    }
421
422    pub unsafe fn from_meta(
423        meta: &'a mut gst::MetaRefMut<'a, AnalyticsRelationMeta, gst::meta::Standalone>,
424        id: u32,
425    ) -> Self {
426        skip_assert_initialized!();
427        AnalyticsMtdRefMut {
428            meta,
429            id,
430            mtd_type: PhantomData,
431        }
432    }
433}
434
435impl<'a, T: AnalyticsMtd> UnsafeFrom<&mut AnalyticsMtdRefMut<'a, T>> for ffi::GstAnalyticsMtd {
436    unsafe fn unsafe_from(t: &mut AnalyticsMtdRefMut<'a, T>) -> Self {
437        ffi::GstAnalyticsMtd {
438            id: t.id,
439            meta: t.meta.as_mut_ptr(),
440        }
441    }
442}
443
444impl<'a, T: AnalyticsMtd> From<AnalyticsMtdRefMut<'a, T>> for AnalyticsMtdRef<'a, T> {
445    fn from(value: AnalyticsMtdRefMut<'a, T>) -> Self {
446        skip_assert_initialized!();
447        AnalyticsMtdRef {
448            meta: value.meta.as_ref().clone(),
449            id: value.id,
450            mtd_type: value.mtd_type,
451        }
452    }
453}
454
455impl<'a, T: AnalyticsMtd> From<&mut AnalyticsMtdRefMut<'a, T>> for AnalyticsMtdRef<'a, T> {
456    fn from(value: &mut AnalyticsMtdRefMut<'a, T>) -> Self {
457        skip_assert_initialized!();
458        AnalyticsMtdRef {
459            meta: value.meta.as_ref().clone(),
460            id: value.id,
461            mtd_type: value.mtd_type,
462        }
463    }
464}
465
466impl<'a, T: AnalyticsMtd> AsRef<AnalyticsMtdRef<'a, T>> for AnalyticsMtdRefMut<'a, T> {
467    #[inline]
468    fn as_ref(&self) -> &AnalyticsMtdRef<'a, T> {
469        unsafe { &*(self as *const AnalyticsMtdRefMut<'a, T> as *const AnalyticsMtdRef<'a, T>) }
470    }
471}
472
473macro_rules! define_mtd_iter {
474    ($name:ident, $metaref:ty, $itemref:ty, $copy_meta:expr) => {
475        #[must_use = "iterators are lazy and do nothing unless consumed"]
476        pub struct $name<'a, T: AnalyticsMtd> {
477            meta: $metaref,
478            state: glib::ffi::gpointer,
479            mtd_type: ffi::GstAnalyticsMtdType,
480            an_meta_id: u32,
481            rel_type: ffi::GstAnalyticsRelTypes,
482            phantom: std::marker::PhantomData<T>,
483        }
484
485        impl<'a, T: AnalyticsMtd> $name<'a, T> {
486            fn new(meta: $metaref) -> Self {
487                skip_assert_initialized!();
488                $name {
489                    meta,
490                    state: std::ptr::null_mut(),
491                    mtd_type: T::mtd_type(),
492                    an_meta_id: u32::MAX,
493                    rel_type: RelTypes::ANY.into_glib(),
494                    phantom: PhantomData,
495                }
496            }
497            fn new_direct_related(
498                meta: $metaref,
499                an_meta_id: u32,
500                rel_type: ffi::GstAnalyticsRelTypes,
501            ) -> Self {
502                skip_assert_initialized!();
503                $name {
504                    meta,
505                    state: std::ptr::null_mut(),
506                    mtd_type: T::mtd_type(),
507                    an_meta_id,
508                    rel_type,
509                    phantom: PhantomData,
510                }
511            }
512        }
513
514        impl<'a, T: AnalyticsMtd + 'a> Iterator for $name<'a, T> {
515            type Item = $itemref;
516
517            fn next(&mut self) -> Option<Self::Item> {
518                unsafe {
519                    let mut mtd = ffi::GstAnalyticsMtd::unsafe_from(&**self.meta);
520                    let ret = {
521                        if self.an_meta_id == u32::MAX {
522                            ffi::gst_analytics_relation_meta_iterate(
523                                self.meta.as_mut_ptr(),
524                                &mut self.state,
525                                self.mtd_type,
526                                &mut mtd,
527                            )
528                        } else {
529                            ffi::gst_analytics_relation_meta_get_direct_related(
530                                self.meta.as_mut_ptr(),
531                                self.an_meta_id,
532                                self.rel_type,
533                                self.mtd_type,
534                                &mut self.state,
535                                &mut mtd,
536                            )
537                        }
538                    };
539                    if from_glib(ret) {
540                        // This is a known clippy limitation
541                        // https://github.com/rust-lang/rust-clippy/issues/1553
542                        #[allow(clippy::redundant_closure_call)]
543                        Some(Self::Item::from_meta($copy_meta(self.meta), mtd.id))
544                    } else {
545                        None
546                    }
547                }
548            }
549        }
550    };
551}
552
553define_mtd_iter!(
554    AnalyticsMtdIter,
555    &'a gst::MetaRef<'a, AnalyticsRelationMeta>,
556    AnalyticsMtdRef<'a, T>,
557    |meta| meta
558);
559
560define_mtd_iter!(
561    AnalyticsMtdIterMut,
562    &'a mut gst::MetaRefMut<'a, AnalyticsRelationMeta, gst::meta::Standalone>,
563    AnalyticsMtdRefMut<'a, T>,
564    |meta: &mut _| &mut *(meta as *mut gst::MetaRefMut<
565        'a,
566        AnalyticsRelationMeta,
567        gst::meta::Standalone,
568    >)
569);
570
571#[derive(Debug)]
572pub enum AnalyticsAnyMtd {}
573
574unsafe impl AnalyticsMtd for AnalyticsAnyMtd {
575    fn mtd_type() -> ffi::GstAnalyticsMtdType {
576        ffi::GST_ANALYTICS_MTD_TYPE_ANY as ffi::GstAnalyticsMtdType
577    }
578}
579
580#[cfg(test)]
581mod tests {
582    use crate::*;
583
584    #[test]
585    fn build_relation_meta() {
586        gst::init().unwrap();
587
588        let mut buf = gst::Buffer::new();
589
590        let meta = AnalyticsRelationMeta::add(buf.make_mut());
591
592        assert!(meta.is_empty());
593    }
594
595    #[test]
596    fn build_relation_meta_full() {
597        gst::init().unwrap();
598
599        let mut buf = gst::Buffer::new();
600
601        let params = AnalyticsRelationMetaInitParams::new(10, 10);
602        let meta = AnalyticsRelationMeta::add_full(buf.make_mut(), &params);
603
604        assert!(meta.is_empty());
605    }
606
607    #[test]
608    fn relations() {
609        gst::init().unwrap();
610
611        let mut buf = gst::Buffer::new();
612        let _ = AnalyticsRelationMeta::add(buf.make_mut());
613
614        let mut meta = buf.make_mut().meta_mut::<AnalyticsRelationMeta>().unwrap();
615        let od = meta
616            .add_od_mtd(glib::Quark::from_str("blb"), 0, 1, 10, 20, 0.8)
617            .unwrap();
618        let od1_id = od.id();
619
620        let od = meta
621            .add_od_mtd(glib::Quark::from_str("blb"), 0, 1, 10, 20, 0.8)
622            .unwrap();
623        let od2_id = od.id();
624
625        let od: AnalyticsMtdRef<'_, AnalyticsODMtd> = meta
626            .add_od_mtd(glib::Quark::from_str("blb"), 0, 1, 10, 20, 0.8)
627            .unwrap();
628        let od3_id = od.id();
629
630        meta.set_relation(RelTypes::IS_PART_OF, od1_id, od2_id)
631            .unwrap();
632        meta.set_relation(RelTypes::IS_PART_OF, od2_id, od3_id)
633            .unwrap();
634
635        meta.set_relation(RelTypes::IS_PART_OF, 8888, 9999)
636            .expect_err("Invalid id");
637
638        let meta = buf.meta::<AnalyticsRelationMeta>().unwrap();
639        assert!(meta.relation(od1_id, od2_id) == crate::RelTypes::IS_PART_OF);
640        assert!(meta.relation(od2_id, od3_id) == crate::RelTypes::IS_PART_OF);
641
642        assert!(meta.exist(od1_id, od2_id, 1, crate::RelTypes::IS_PART_OF));
643        assert!(meta.exist(od1_id, od3_id, 2, crate::RelTypes::IS_PART_OF));
644        assert!(!meta.exist(od2_id, od1_id, 1, crate::RelTypes::IS_PART_OF));
645        assert!(!meta.exist(od1_id, od3_id, 1, crate::RelTypes::IS_PART_OF));
646        assert!(!meta.exist(od1_id, od2_id, 1, crate::RelTypes::CONTAIN));
647
648        let path = meta
649            .exist_path(od1_id, od3_id, 3, crate::RelTypes::ANY)
650            .unwrap();
651
652        assert_eq!(path.as_slice().len(), 3);
653        assert_eq!(path.as_slice()[0], od1_id);
654        assert_eq!(path.as_slice()[1], od2_id);
655        assert_eq!(path.as_slice()[2], od3_id);
656
657        assert_eq!(meta.len(), meta.iter::<AnalyticsAnyMtd>().count());
658        assert_eq!(meta.len(), meta.iter::<AnalyticsODMtd>().count());
659        for mtd in meta.iter::<AnalyticsODMtd>() {
660            assert_eq!(mtd.obj_type().unwrap(), glib::Quark::from_str("blb"))
661        }
662
663        assert_eq!(meta.len(), meta.iter::<AnalyticsAnyMtd>().count());
664        for mtd in meta.iter::<AnalyticsAnyMtd>() {
665            if let Ok(mtd) = mtd.downcast::<AnalyticsODMtd>() {
666                assert_eq!(mtd.obj_type().unwrap(), glib::Quark::from_str("blb"))
667            }
668        }
669
670        assert_eq!(
671            meta.iter_direct_related::<AnalyticsODMtd>(od1_id, crate::RelTypes::IS_PART_OF)
672                .count(),
673            1
674        );
675        assert_eq!(
676            meta.iter_direct_related::<AnalyticsODMtd>(od2_id, crate::RelTypes::IS_PART_OF)
677                .count(),
678            1
679        );
680        assert_eq!(
681            meta.iter_direct_related::<AnalyticsODMtd>(od3_id, crate::RelTypes::IS_PART_OF)
682                .count(),
683            0
684        );
685        assert_eq!(
686            meta.iter_direct_related::<AnalyticsODMtd>(od1_id, crate::RelTypes::CONTAIN)
687                .count(),
688            0
689        );
690
691        assert_eq!(
692            meta.iter_direct_related::<AnalyticsAnyMtd>(od1_id, crate::RelTypes::CONTAIN)
693                .count(),
694            0
695        );
696        for mtd in meta.iter_direct_related::<AnalyticsODMtd>(od1_id, crate::RelTypes::IS_PART_OF) {
697            assert_eq!(mtd.obj_type().unwrap(), glib::Quark::from_str("blb"))
698        }
699
700        let mut meta = buf.make_mut().meta_mut::<AnalyticsRelationMeta>().unwrap();
701        assert_eq!(meta.len(), meta.iter_mut::<AnalyticsAnyMtd>().count());
702
703        let mut meta = buf.make_mut().meta_mut::<AnalyticsRelationMeta>().unwrap();
704        let _ = meta.add_tracking_mtd(10, gst::ClockTime::from_seconds(10));
705        let _ = meta.add_tracking_mtd(10, gst::ClockTime::from_seconds(10));
706
707        for mut item in meta.iter_mut::<AnalyticsTrackingMtd>() {
708            item.set_lost().unwrap();
709        }
710    }
711}