// Copyright (C) 2016-2017 Sebastian Dröge // // Licensed under the Apache License, Version 2.0 or the MIT license // , at your // option. This file may not be copied, modified, or distributed // except according to those terms. use std::ffi::CStr; use std::mem; use ffi; use glib; use glib::translate::{from_glib, from_glib_full, FromGlibPtrContainer, ToGlib, ToGlibPtr}; use miniobject::*; use TocEntryType; use TocScope; use TocLoopType; use TagList; use TagMergeMode; pub type Toc = GstRc; pub struct TocRef(ffi::GstToc); unsafe impl MiniObject for TocRef { type GstType = ffi::GstToc; } impl GstRc { pub fn new(scope: TocScope) -> Self { assert_initialized_main_thread!(); unsafe { from_glib_full(ffi::gst_toc_new(scope.to_glib())) } } } impl TocRef { pub fn get_scope(&self) -> TocScope { unsafe { from_glib(ffi::gst_toc_get_scope(self.as_ptr())) } } pub fn find_entry(&self, uid: &str) -> Option { unsafe { let toc_entry = ffi::gst_toc_find_entry(self.as_ptr(), uid.to_glib_none().0); if toc_entry.is_null() { return None; } Some(TocEntry::from_glib_none( toc_entry as *const ffi::GstTocEntry, )) } } pub fn get_entries(&self) -> Vec { unsafe { FromGlibPtrContainer::from_glib_none(ffi::gst_toc_get_entries(self.as_ptr())) } } pub fn append_entry(&mut self, entry: TocEntry) { unsafe { ffi::gst_toc_append_entry(self.as_mut_ptr(), entry.into_ptr()); } } pub fn get_tags(&self) -> Option { unsafe { let tags = ffi::gst_toc_get_tags(self.as_ptr()); if tags.is_null() { return None; } Some(TagList::from_glib_none(tags as *const ffi::GstTagList)) } } pub fn set_tags(&mut self, tag_list: TagList) { unsafe { ffi::gst_toc_set_tags(self.as_mut_ptr(), tag_list.into_ptr()); } } pub fn merge_tags(&mut self, tag_list: TagList, mode: TagMergeMode) { unsafe { ffi::gst_toc_merge_tags(self.as_mut_ptr(), tag_list.as_mut_ptr(), mode.to_glib()); } } pub fn dump(&self) { unsafe { ffi::gst_toc_dump(self.as_mut_ptr()); } } } impl glib::types::StaticType for TocRef { fn static_type() -> glib::types::Type { unsafe { from_glib(ffi::gst_toc_get_type()) } } } impl ToOwned for TocRef { type Owned = GstRc; fn to_owned(&self) -> GstRc { unsafe { from_glib_full(ffi::gst_mini_object_copy(self.as_ptr() as *const _) as *mut _) } } } unsafe impl Sync for TocRef {} unsafe impl Send for TocRef {} pub type TocEntry = GstRc; pub struct TocEntryRef(ffi::GstTocEntry); unsafe impl MiniObject for TocEntryRef { type GstType = ffi::GstTocEntry; } impl GstRc { pub fn new(type_: TocEntryType, uid: &str) -> Self { assert_initialized_main_thread!(); unsafe { from_glib_full(ffi::gst_toc_entry_new( type_.to_glib(), uid.to_glib_none().0, )) } } } impl TocEntryRef { pub fn get_entry_type(&self) -> TocEntryType { unsafe { from_glib(ffi::gst_toc_entry_get_entry_type(self.as_ptr())) } } pub fn get_uid(&self) -> &str { unsafe { CStr::from_ptr(ffi::gst_toc_entry_get_uid(self.as_ptr())) .to_str() .unwrap() } } pub fn append_sub_entry(&mut self, subentry: TocEntry) { unsafe { ffi::gst_toc_entry_append_sub_entry(self.as_mut_ptr(), subentry.into_ptr()); } } pub fn get_sub_entries(&self) -> Vec { unsafe { FromGlibPtrContainer::from_glib_none(ffi::gst_toc_entry_get_sub_entries(self.as_ptr())) } } pub fn get_parent(&self) -> Option { unsafe { let parent = ffi::gst_toc_entry_get_parent(self.as_mut_ptr()); if parent.is_null() { return None; } Some(TocEntry::from_glib_none(parent as *const ffi::GstTocEntry)) } } pub fn get_start_stop_times(&self) -> Option<(i64, i64)> { unsafe { let mut start = mem::uninitialized(); let mut stop = mem::uninitialized(); if from_glib(ffi::gst_toc_entry_get_start_stop_times( self.as_ptr(), &mut start, &mut stop, )) { Some((start, stop)) } else { None } } } pub fn set_start_stop_times(&mut self, start: i64, stop: i64) { unsafe { ffi::gst_toc_entry_set_start_stop_times(self.as_mut_ptr(), start, stop); } } pub fn get_tags(&self) -> Option { unsafe { let tags = ffi::gst_toc_entry_get_tags(self.as_ptr()); if tags.is_null() { return None; } Some(TagList::from_glib_none(tags as *const ffi::GstTagList)) } } pub fn set_tags(&mut self, tag_list: TagList) { unsafe { ffi::gst_toc_entry_set_tags(self.as_mut_ptr(), tag_list.into_ptr()); } } pub fn merge_tags(&mut self, tag_list: TagList, mode: TagMergeMode) { unsafe { ffi::gst_toc_entry_merge_tags(self.as_mut_ptr(), tag_list.as_mut_ptr(), mode.to_glib()); } } pub fn is_alternative(&self) -> bool { unsafe { from_glib(ffi::gst_toc_entry_is_alternative(self.as_ptr())) } } pub fn is_sequence(&self) -> bool { unsafe { from_glib(ffi::gst_toc_entry_is_sequence(self.as_ptr())) } } pub fn get_loop(&self) -> Option<(TocLoopType, i32)> { unsafe { let mut loop_type = mem::uninitialized(); let mut repeat_count = mem::uninitialized(); if from_glib(ffi::gst_toc_entry_get_loop( self.as_ptr(), &mut loop_type, &mut repeat_count, )) { Some((from_glib(loop_type), repeat_count)) } else { None } } } pub fn set_loop(&mut self, loop_type: TocLoopType, repeat_count: i32) { unsafe { ffi::gst_toc_entry_set_loop(self.as_mut_ptr(), loop_type.to_glib(), repeat_count); } } } impl glib::types::StaticType for TocEntryRef { fn static_type() -> glib::types::Type { unsafe { from_glib(ffi::gst_toc_entry_get_type()) } } } impl ToOwned for TocEntryRef { type Owned = GstRc; fn to_owned(&self) -> GstRc { unsafe { from_glib_full(ffi::gst_mini_object_copy(self.as_ptr() as *const _) as *mut _) } } } unsafe impl Sync for TocEntryRef {} unsafe impl Send for TocEntryRef {} #[cfg(test)] mod tests { use super::*; #[test] fn test_simple() { ::init().unwrap(); // Top level toc entry let mut toc_entry = TocEntry::new(TocEntryType::Chapter, "chapter"); toc_entry.get_mut().unwrap().set_start_stop_times(1, 10); // Toc sub entry let toc_sub_entry = TocEntry::new(TocEntryType::Angle, "angle"); let parent = toc_sub_entry.get_parent(); assert!(parent.is_none()); // Append sub entry toc_entry.get_mut().unwrap().append_sub_entry(toc_sub_entry); // Toc let mut toc = Toc::new(TocScope::Global); assert_eq!(toc.get_scope(), TocScope::Global); // Append toc entry toc.get_mut().unwrap().append_entry(toc_entry); assert_eq!(toc.get_scope(), TocScope::Global); // Check toc entries let toc_entries = toc.get_entries(); assert_eq!(toc_entries.len(), 1); let toc_parent_entry = &toc_entries[0]; assert_eq!(toc_parent_entry.get_entry_type(), TocEntryType::Chapter); assert_eq!(toc_parent_entry.get_uid(), "chapter"); let start_stop_times = toc_parent_entry.get_start_stop_times(); assert!(start_stop_times.is_some()); assert_eq!(start_stop_times.unwrap(), (1, 10)); // Check sub entry let toc_sub_entries = toc_parent_entry.get_sub_entries(); assert_eq!(toc_sub_entries.len(), 1); let toc_sub_entry = &toc_sub_entries[0]; assert_eq!(toc_sub_entry.get_entry_type(), TocEntryType::Angle); let parent = toc_sub_entry.get_parent(); assert!(parent.is_some()); assert_eq!(parent.unwrap().get_entry_type(), TocEntryType::Chapter); } }