forked from mirrors/gstreamer-rs
Add bindings for GstToc/TocSetter
https://github.com/sdroege/gstreamer-rs/pull/22 Fixes https://github.com/sdroege/gstreamer-rs/issues/10
This commit is contained in:
parent
bc3cfc0195
commit
04f09ebc86
9 changed files with 757 additions and 23 deletions
|
@ -60,6 +60,10 @@ generate = [
|
||||||
"Gst.TagSetter",
|
"Gst.TagSetter",
|
||||||
"Gst.QOSType",
|
"Gst.QOSType",
|
||||||
"Gst.EventType",
|
"Gst.EventType",
|
||||||
|
"Gst.TocScope",
|
||||||
|
"Gst.TocEntryType",
|
||||||
|
"Gst.TocLoopType",
|
||||||
|
"Gst.TocSetter",
|
||||||
]
|
]
|
||||||
|
|
||||||
manual = [
|
manual = [
|
||||||
|
@ -161,6 +165,11 @@ name = "Gst.Context"
|
||||||
status = "manual"
|
status = "manual"
|
||||||
ref_mode = "ref"
|
ref_mode = "ref"
|
||||||
|
|
||||||
|
[[object]]
|
||||||
|
name = "Gst.Toc"
|
||||||
|
status = "manual"
|
||||||
|
ref_mode = "ref"
|
||||||
|
|
||||||
[[object]]
|
[[object]]
|
||||||
name = "Gst.DateTime"
|
name = "Gst.DateTime"
|
||||||
status = "generate"
|
status = "generate"
|
||||||
|
|
143
examples/src/bin/toc.rs
Normal file
143
examples/src/bin/toc.rs
Normal file
|
@ -0,0 +1,143 @@
|
||||||
|
extern crate gstreamer as gst;
|
||||||
|
use gst::*;
|
||||||
|
|
||||||
|
extern crate glib;
|
||||||
|
use glib::*;
|
||||||
|
|
||||||
|
use std::env;
|
||||||
|
use std::u64;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
gst::init().unwrap();
|
||||||
|
|
||||||
|
let args: Vec<_> = env::args().collect();
|
||||||
|
let uri: &str = if args.len() == 2 {
|
||||||
|
args[1].as_ref()
|
||||||
|
} else {
|
||||||
|
panic!("Usage: toc file_path");
|
||||||
|
};
|
||||||
|
|
||||||
|
let pipeline = gst::Pipeline::new(None);
|
||||||
|
let src = gst::ElementFactory::make("filesrc", None).unwrap();
|
||||||
|
let decodebin = gst::ElementFactory::make("decodebin", None).unwrap();
|
||||||
|
|
||||||
|
src.set_property("location", &Value::from(uri)).unwrap();
|
||||||
|
|
||||||
|
pipeline.add_many(&[&src, &decodebin]).unwrap();
|
||||||
|
gst::Element::link_many(&[&src, &decodebin]).unwrap();
|
||||||
|
|
||||||
|
// Need to move a new reference into the closure
|
||||||
|
let pipeline_clone = pipeline.clone();
|
||||||
|
decodebin.connect_pad_added(move |_, src_pad| {
|
||||||
|
let pipeline = &pipeline_clone;
|
||||||
|
|
||||||
|
let (is_audio, is_video) = {
|
||||||
|
let caps = src_pad.get_current_caps().unwrap();
|
||||||
|
let structure = caps.get_structure(0).unwrap();
|
||||||
|
let name = structure.get_name();
|
||||||
|
|
||||||
|
(name.starts_with("audio/"), name.starts_with("video/"))
|
||||||
|
};
|
||||||
|
|
||||||
|
if is_audio {
|
||||||
|
let queue = gst::ElementFactory::make("queue", None).unwrap();
|
||||||
|
let sink = gst::ElementFactory::make("fakesink", None).unwrap();
|
||||||
|
|
||||||
|
let elements = &[&queue, &sink];
|
||||||
|
pipeline.add_many(elements).unwrap();
|
||||||
|
gst::Element::link_many(elements).unwrap();
|
||||||
|
|
||||||
|
for e in elements {
|
||||||
|
e.sync_state_with_parent().unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
let sink_pad = queue.get_static_pad("sink").unwrap();
|
||||||
|
assert_eq!(src_pad.link(&sink_pad), gst::PadLinkReturn::Ok);
|
||||||
|
} else if is_video {
|
||||||
|
let queue = gst::ElementFactory::make("queue", None).unwrap();
|
||||||
|
let sink = gst::ElementFactory::make("fakesink", None).unwrap();
|
||||||
|
|
||||||
|
let elements = &[&queue, &sink];
|
||||||
|
pipeline.add_many(elements).unwrap();
|
||||||
|
gst::Element::link_many(elements).unwrap();
|
||||||
|
|
||||||
|
for e in elements {
|
||||||
|
e.sync_state_with_parent().unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
let sink_pad = queue.get_static_pad("sink").unwrap();
|
||||||
|
assert_eq!(src_pad.link(&sink_pad), gst::PadLinkReturn::Ok);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
assert_ne!(
|
||||||
|
pipeline.set_state(gst::State::Paused),
|
||||||
|
gst::StateChangeReturn::Failure
|
||||||
|
);
|
||||||
|
|
||||||
|
let bus = pipeline.get_bus().unwrap();
|
||||||
|
|
||||||
|
loop {
|
||||||
|
let msg = match bus.timed_pop(u64::MAX) {
|
||||||
|
None => break,
|
||||||
|
Some(msg) => msg,
|
||||||
|
};
|
||||||
|
|
||||||
|
match msg.view() {
|
||||||
|
MessageView::Eos(..) => break,
|
||||||
|
MessageView::Error(err) => {
|
||||||
|
println!(
|
||||||
|
"Error from {}: {} ({:?})",
|
||||||
|
msg.get_src().get_path_string(),
|
||||||
|
err.get_error(),
|
||||||
|
err.get_debug()
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
MessageView::AsyncDone(_) => break,
|
||||||
|
MessageView::Toc(msg_toc) => {
|
||||||
|
let (toc, updated) = msg_toc.get_toc();
|
||||||
|
println!(
|
||||||
|
"\nReceived toc: {:?} - updated: {}",
|
||||||
|
toc.get_scope(),
|
||||||
|
updated
|
||||||
|
);
|
||||||
|
if let Some(tags) = toc.get_tags() {
|
||||||
|
println!("- tags: {}", tags.to_string());
|
||||||
|
}
|
||||||
|
for toc_entry in toc.get_entries() {
|
||||||
|
println!(
|
||||||
|
"\t{:?} - {}",
|
||||||
|
toc_entry.get_entry_type(),
|
||||||
|
toc_entry.get_uid()
|
||||||
|
);
|
||||||
|
if let Some((start, stop)) = toc_entry.get_start_stop_times() {
|
||||||
|
println!("\t- start: {}, stop: {}", start, stop);
|
||||||
|
}
|
||||||
|
if let Some(tags) = toc_entry.get_tags() {
|
||||||
|
println!("\t- tags: {}", tags.to_string());
|
||||||
|
}
|
||||||
|
for toc_sub_entry in toc_entry.get_sub_entries() {
|
||||||
|
println!(
|
||||||
|
"\n\t\t{:?} - {}",
|
||||||
|
toc_sub_entry.get_entry_type(),
|
||||||
|
toc_sub_entry.get_uid()
|
||||||
|
);
|
||||||
|
if let Some((start, stop)) = toc_sub_entry.get_start_stop_times() {
|
||||||
|
println!("\t\t- start: {}, stop: {}", start, stop);
|
||||||
|
}
|
||||||
|
if let Some(tags) = toc_sub_entry.get_tags() {
|
||||||
|
println!("\t\t- tags: {:?}", tags.to_string());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assert_ne!(
|
||||||
|
pipeline.set_state(gst::State::Null),
|
||||||
|
gst::StateChangeReturn::Failure
|
||||||
|
);
|
||||||
|
}
|
|
@ -2126,6 +2126,198 @@ impl SetValue for TagMergeMode {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
|
||||||
|
pub enum TocEntryType {
|
||||||
|
Angle,
|
||||||
|
Version,
|
||||||
|
Edition,
|
||||||
|
Invalid,
|
||||||
|
Title,
|
||||||
|
Track,
|
||||||
|
Chapter,
|
||||||
|
#[doc(hidden)]
|
||||||
|
__Unknown(i32),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
|
impl ToGlib for TocEntryType {
|
||||||
|
type GlibType = ffi::GstTocEntryType;
|
||||||
|
|
||||||
|
fn to_glib(&self) -> ffi::GstTocEntryType {
|
||||||
|
match *self {
|
||||||
|
TocEntryType::Angle => ffi::GST_TOC_ENTRY_TYPE_ANGLE,
|
||||||
|
TocEntryType::Version => ffi::GST_TOC_ENTRY_TYPE_VERSION,
|
||||||
|
TocEntryType::Edition => ffi::GST_TOC_ENTRY_TYPE_EDITION,
|
||||||
|
TocEntryType::Invalid => ffi::GST_TOC_ENTRY_TYPE_INVALID,
|
||||||
|
TocEntryType::Title => ffi::GST_TOC_ENTRY_TYPE_TITLE,
|
||||||
|
TocEntryType::Track => ffi::GST_TOC_ENTRY_TYPE_TRACK,
|
||||||
|
TocEntryType::Chapter => ffi::GST_TOC_ENTRY_TYPE_CHAPTER,
|
||||||
|
TocEntryType::__Unknown(value) => unsafe{std::mem::transmute(value)}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
|
impl FromGlib<ffi::GstTocEntryType> for TocEntryType {
|
||||||
|
fn from_glib(value: ffi::GstTocEntryType) -> Self {
|
||||||
|
skip_assert_initialized!();
|
||||||
|
match value as i32 {
|
||||||
|
-3 => TocEntryType::Angle,
|
||||||
|
-2 => TocEntryType::Version,
|
||||||
|
-1 => TocEntryType::Edition,
|
||||||
|
0 => TocEntryType::Invalid,
|
||||||
|
1 => TocEntryType::Title,
|
||||||
|
2 => TocEntryType::Track,
|
||||||
|
3 => TocEntryType::Chapter,
|
||||||
|
value => TocEntryType::__Unknown(value),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl StaticType for TocEntryType {
|
||||||
|
fn static_type() -> Type {
|
||||||
|
unsafe { from_glib(ffi::gst_toc_entry_type_get_type()) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> FromValueOptional<'a> for TocEntryType {
|
||||||
|
unsafe fn from_value_optional(value: &Value) -> Option<Self> {
|
||||||
|
Some(FromValue::from_value(value))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> FromValue<'a> for TocEntryType {
|
||||||
|
unsafe fn from_value(value: &Value) -> Self {
|
||||||
|
from_glib(std::mem::transmute::<i32, ffi::GstTocEntryType>(gobject_ffi::g_value_get_enum(value.to_glib_none().0)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SetValue for TocEntryType {
|
||||||
|
unsafe fn set_value(value: &mut Value, this: &Self) {
|
||||||
|
gobject_ffi::g_value_set_enum(value.to_glib_none_mut().0, this.to_glib() as i32)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
|
||||||
|
pub enum TocLoopType {
|
||||||
|
None,
|
||||||
|
Forward,
|
||||||
|
Reverse,
|
||||||
|
PingPong,
|
||||||
|
#[doc(hidden)]
|
||||||
|
__Unknown(i32),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
|
impl ToGlib for TocLoopType {
|
||||||
|
type GlibType = ffi::GstTocLoopType;
|
||||||
|
|
||||||
|
fn to_glib(&self) -> ffi::GstTocLoopType {
|
||||||
|
match *self {
|
||||||
|
TocLoopType::None => ffi::GST_TOC_LOOP_NONE,
|
||||||
|
TocLoopType::Forward => ffi::GST_TOC_LOOP_FORWARD,
|
||||||
|
TocLoopType::Reverse => ffi::GST_TOC_LOOP_REVERSE,
|
||||||
|
TocLoopType::PingPong => ffi::GST_TOC_LOOP_PING_PONG,
|
||||||
|
TocLoopType::__Unknown(value) => unsafe{std::mem::transmute(value)}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
|
impl FromGlib<ffi::GstTocLoopType> for TocLoopType {
|
||||||
|
fn from_glib(value: ffi::GstTocLoopType) -> Self {
|
||||||
|
skip_assert_initialized!();
|
||||||
|
match value as i32 {
|
||||||
|
0 => TocLoopType::None,
|
||||||
|
1 => TocLoopType::Forward,
|
||||||
|
2 => TocLoopType::Reverse,
|
||||||
|
3 => TocLoopType::PingPong,
|
||||||
|
value => TocLoopType::__Unknown(value),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl StaticType for TocLoopType {
|
||||||
|
fn static_type() -> Type {
|
||||||
|
unsafe { from_glib(ffi::gst_toc_loop_type_get_type()) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> FromValueOptional<'a> for TocLoopType {
|
||||||
|
unsafe fn from_value_optional(value: &Value) -> Option<Self> {
|
||||||
|
Some(FromValue::from_value(value))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> FromValue<'a> for TocLoopType {
|
||||||
|
unsafe fn from_value(value: &Value) -> Self {
|
||||||
|
from_glib(std::mem::transmute::<i32, ffi::GstTocLoopType>(gobject_ffi::g_value_get_enum(value.to_glib_none().0)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SetValue for TocLoopType {
|
||||||
|
unsafe fn set_value(value: &mut Value, this: &Self) {
|
||||||
|
gobject_ffi::g_value_set_enum(value.to_glib_none_mut().0, this.to_glib() as i32)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
|
||||||
|
pub enum TocScope {
|
||||||
|
Global,
|
||||||
|
Current,
|
||||||
|
#[doc(hidden)]
|
||||||
|
__Unknown(i32),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
|
impl ToGlib for TocScope {
|
||||||
|
type GlibType = ffi::GstTocScope;
|
||||||
|
|
||||||
|
fn to_glib(&self) -> ffi::GstTocScope {
|
||||||
|
match *self {
|
||||||
|
TocScope::Global => ffi::GST_TOC_SCOPE_GLOBAL,
|
||||||
|
TocScope::Current => ffi::GST_TOC_SCOPE_CURRENT,
|
||||||
|
TocScope::__Unknown(value) => unsafe{std::mem::transmute(value)}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
|
impl FromGlib<ffi::GstTocScope> for TocScope {
|
||||||
|
fn from_glib(value: ffi::GstTocScope) -> Self {
|
||||||
|
skip_assert_initialized!();
|
||||||
|
match value as i32 {
|
||||||
|
1 => TocScope::Global,
|
||||||
|
2 => TocScope::Current,
|
||||||
|
value => TocScope::__Unknown(value),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl StaticType for TocScope {
|
||||||
|
fn static_type() -> Type {
|
||||||
|
unsafe { from_glib(ffi::gst_toc_scope_get_type()) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> FromValueOptional<'a> for TocScope {
|
||||||
|
unsafe fn from_value_optional(value: &Value) -> Option<Self> {
|
||||||
|
Some(FromValue::from_value(value))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> FromValue<'a> for TocScope {
|
||||||
|
unsafe fn from_value(value: &Value) -> Self {
|
||||||
|
from_glib(std::mem::transmute::<i32, ffi::GstTocScope>(gobject_ffi::g_value_get_enum(value.to_glib_none().0)))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SetValue for TocScope {
|
||||||
|
unsafe fn set_value(value: &mut Value, this: &Self) {
|
||||||
|
gobject_ffi::g_value_set_enum(value.to_glib_none_mut().0, this.to_glib() as i32)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
|
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
|
||||||
pub enum URIError {
|
pub enum URIError {
|
||||||
UnsupportedProtocol,
|
UnsupportedProtocol,
|
||||||
|
|
|
@ -88,6 +88,10 @@ mod tag_setter;
|
||||||
pub use self::tag_setter::TagSetter;
|
pub use self::tag_setter::TagSetter;
|
||||||
pub use self::tag_setter::TagSetterExt;
|
pub use self::tag_setter::TagSetterExt;
|
||||||
|
|
||||||
|
mod toc_setter;
|
||||||
|
pub use self::toc_setter::TocSetter;
|
||||||
|
pub use self::toc_setter::TocSetterExt;
|
||||||
|
|
||||||
mod u_r_i_handler;
|
mod u_r_i_handler;
|
||||||
pub use self::u_r_i_handler::URIHandler;
|
pub use self::u_r_i_handler::URIHandler;
|
||||||
pub use self::u_r_i_handler::URIHandlerExt;
|
pub use self::u_r_i_handler::URIHandlerExt;
|
||||||
|
@ -123,6 +127,9 @@ pub use self::enums::StreamError;
|
||||||
pub use self::enums::StreamStatusType;
|
pub use self::enums::StreamStatusType;
|
||||||
pub use self::enums::StructureChangeType;
|
pub use self::enums::StructureChangeType;
|
||||||
pub use self::enums::TagMergeMode;
|
pub use self::enums::TagMergeMode;
|
||||||
|
pub use self::enums::TocEntryType;
|
||||||
|
pub use self::enums::TocLoopType;
|
||||||
|
pub use self::enums::TocScope;
|
||||||
pub use self::enums::URIError;
|
pub use self::enums::URIError;
|
||||||
pub use self::enums::URIType;
|
pub use self::enums::URIType;
|
||||||
|
|
||||||
|
@ -229,5 +236,6 @@ pub mod traits {
|
||||||
#[cfg(feature = "v1_10")]
|
#[cfg(feature = "v1_10")]
|
||||||
pub use super::StreamCollectionExt;
|
pub use super::StreamCollectionExt;
|
||||||
pub use super::TagSetterExt;
|
pub use super::TagSetterExt;
|
||||||
|
pub use super::TocSetterExt;
|
||||||
pub use super::URIHandlerExt;
|
pub use super::URIHandlerExt;
|
||||||
}
|
}
|
||||||
|
|
54
gstreamer/src/auto/toc_setter.rs
Normal file
54
gstreamer/src/auto/toc_setter.rs
Normal file
|
@ -0,0 +1,54 @@
|
||||||
|
// This file was generated by gir (3294959) from gir-files (???)
|
||||||
|
// DO NOT EDIT
|
||||||
|
|
||||||
|
use Element;
|
||||||
|
use Object;
|
||||||
|
use Toc;
|
||||||
|
use ffi;
|
||||||
|
use glib::object::IsA;
|
||||||
|
use glib::translate::*;
|
||||||
|
use glib_ffi;
|
||||||
|
use gobject_ffi;
|
||||||
|
use std::mem;
|
||||||
|
use std::ptr;
|
||||||
|
|
||||||
|
glib_wrapper! {
|
||||||
|
pub struct TocSetter(Object<ffi::GstTocSetter>): Element, Object;
|
||||||
|
|
||||||
|
match fn {
|
||||||
|
get_type => || ffi::gst_toc_setter_get_type(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe impl Send for TocSetter {}
|
||||||
|
unsafe impl Sync for TocSetter {}
|
||||||
|
|
||||||
|
pub trait TocSetterExt {
|
||||||
|
fn get_toc(&self) -> Option<Toc>;
|
||||||
|
|
||||||
|
fn reset(&self);
|
||||||
|
|
||||||
|
fn set_toc<'a, P: Into<Option<&'a Toc>>>(&self, toc: P);
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<O: IsA<TocSetter>> TocSetterExt for O {
|
||||||
|
fn get_toc(&self) -> Option<Toc> {
|
||||||
|
unsafe {
|
||||||
|
from_glib_full(ffi::gst_toc_setter_get_toc(self.to_glib_none().0))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn reset(&self) {
|
||||||
|
unsafe {
|
||||||
|
ffi::gst_toc_setter_reset(self.to_glib_none().0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn set_toc<'a, P: Into<Option<&'a Toc>>>(&self, toc: P) {
|
||||||
|
let toc = toc.into();
|
||||||
|
let toc = toc.to_glib_none();
|
||||||
|
unsafe {
|
||||||
|
ffi::gst_toc_setter_set_toc(self.to_glib_none().0, toc.0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -187,7 +187,7 @@ impl Event {
|
||||||
EosBuilder::new()
|
EosBuilder::new()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_toc(toc: (), updated: bool) -> TocBuilder {
|
pub fn new_toc(toc: &::Toc, updated: bool) -> TocBuilder {
|
||||||
TocBuilder::new(toc, updated)
|
TocBuilder::new(toc, updated)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -468,8 +468,18 @@ impl<'a> StreamGroupDone<'a> {
|
||||||
|
|
||||||
pub struct Eos<'a>(&'a EventRef);
|
pub struct Eos<'a>(&'a EventRef);
|
||||||
|
|
||||||
// TODO
|
|
||||||
pub struct Toc<'a>(&'a EventRef);
|
pub struct Toc<'a>(&'a EventRef);
|
||||||
|
impl<'a> Toc<'a> {
|
||||||
|
pub fn get_toc(&self) -> (&'a ::TocRef, bool) {
|
||||||
|
unsafe {
|
||||||
|
let mut toc = ptr::null_mut();
|
||||||
|
let mut updated = mem::uninitialized();
|
||||||
|
|
||||||
|
ffi::gst_event_parse_toc(self.0.as_mut_ptr(), &mut toc, &mut updated);
|
||||||
|
(::TocRef::from_ptr(toc), from_glib(updated))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub struct Protection<'a>(&'a EventRef);
|
pub struct Protection<'a>(&'a EventRef);
|
||||||
impl<'a> Protection<'a> {
|
impl<'a> Protection<'a> {
|
||||||
|
@ -932,16 +942,14 @@ impl EosBuilder {
|
||||||
event_builder_generic_impl!(|_| ffi::gst_event_new_eos());
|
event_builder_generic_impl!(|_| ffi::gst_event_new_eos());
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO Toc
|
pub struct TocBuilder<'a> {
|
||||||
pub struct TocBuilder {
|
|
||||||
seqnum: Option<u32>,
|
seqnum: Option<u32>,
|
||||||
running_time_offset: Option<i64>,
|
running_time_offset: Option<i64>,
|
||||||
#[allow(unused)]
|
toc: &'a ::Toc,
|
||||||
toc: (),
|
|
||||||
updated: bool,
|
updated: bool,
|
||||||
}
|
}
|
||||||
impl TocBuilder {
|
impl<'a> TocBuilder<'a> {
|
||||||
pub fn new(toc: (), updated: bool) -> Self {
|
pub fn new(toc: &'a ::Toc, updated: bool) -> Self {
|
||||||
Self {
|
Self {
|
||||||
seqnum: None,
|
seqnum: None,
|
||||||
running_time_offset: None,
|
running_time_offset: None,
|
||||||
|
@ -951,7 +959,7 @@ impl TocBuilder {
|
||||||
}
|
}
|
||||||
|
|
||||||
event_builder_generic_impl!(|s: &Self| {
|
event_builder_generic_impl!(|s: &Self| {
|
||||||
ffi::gst_event_new_toc(ptr::null_mut(), s.updated.to_glib())
|
ffi::gst_event_new_toc(s.toc.to_glib_none().0, s.updated.to_glib())
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -100,6 +100,9 @@ pub use value::*;
|
||||||
mod segment;
|
mod segment;
|
||||||
pub use segment::*;
|
pub use segment::*;
|
||||||
|
|
||||||
|
pub mod toc;
|
||||||
|
pub use toc::{Toc, TocEntry, TocEntryRef, TocRef};
|
||||||
|
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
|
|
||||||
pub fn init() -> Result<(), glib::Error> {
|
pub fn init() -> Result<(), glib::Error> {
|
||||||
|
|
|
@ -249,7 +249,7 @@ impl Message {
|
||||||
QosBuilder::new(live, running_time, stream_time, timestamp, duration)
|
QosBuilder::new(live, running_time, stream_time, timestamp, duration)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn new_toc(toc: (), updated: bool) -> TocBuilder {
|
pub fn new_toc(toc: &::Toc, updated: bool) -> TocBuilder {
|
||||||
TocBuilder::new(toc, updated)
|
TocBuilder::new(toc, updated)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -878,7 +878,14 @@ impl<'a> Progress<'a> {
|
||||||
|
|
||||||
pub struct Toc<'a>(&'a MessageRef);
|
pub struct Toc<'a>(&'a MessageRef);
|
||||||
impl<'a> Toc<'a> {
|
impl<'a> Toc<'a> {
|
||||||
// TODO get_toc()
|
pub fn get_toc(&self) -> (::Toc, bool) {
|
||||||
|
unsafe {
|
||||||
|
let mut toc = ptr::null_mut();
|
||||||
|
let mut updated = mem::uninitialized();
|
||||||
|
ffi::gst_message_parse_toc(self.0.as_mut_ptr(), &mut toc, &mut updated);
|
||||||
|
(from_glib_full(toc), from_glib(updated))
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ResetTime<'a>(&'a MessageRef);
|
pub struct ResetTime<'a>(&'a MessageRef);
|
||||||
|
@ -1895,16 +1902,14 @@ impl<'a> ProgressBuilder<'a> {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO Toc
|
pub struct TocBuilder<'a> {
|
||||||
pub struct TocBuilder {
|
|
||||||
src: Option<Object>,
|
src: Option<Object>,
|
||||||
seqnum: Option<u32>,
|
seqnum: Option<u32>,
|
||||||
#[allow(unused)]
|
toc: &'a ::Toc,
|
||||||
toc: (),
|
|
||||||
updated: bool,
|
updated: bool,
|
||||||
}
|
}
|
||||||
impl TocBuilder {
|
impl<'a> TocBuilder<'a> {
|
||||||
pub fn new(toc: () /* &'a Toc */, updated: bool) -> Self {
|
pub fn new(toc: &'a ::Toc, updated: bool) -> Self {
|
||||||
Self {
|
Self {
|
||||||
src: None,
|
src: None,
|
||||||
seqnum: None,
|
seqnum: None,
|
||||||
|
@ -1913,12 +1918,8 @@ impl TocBuilder {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
message_builder_generic_impl!(|s: &mut Self, src| {
|
message_builder_generic_impl!(|s: &Self, src| {
|
||||||
ffi::gst_message_new_toc(
|
ffi::gst_message_new_toc(src, s.toc.to_glib_none().0, s.updated.to_glib())
|
||||||
src,
|
|
||||||
ptr::null_mut(), /*s.structure.to_glib_full()*/
|
|
||||||
s.updated.to_glib(),
|
|
||||||
)
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
316
gstreamer/src/toc.rs
Normal file
316
gstreamer/src/toc.rs
Normal file
|
@ -0,0 +1,316 @@
|
||||||
|
// Copyright (C) 2016-2017 Sebastian Dröge <sebastian@centricular.com>
|
||||||
|
//
|
||||||
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
||||||
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
||||||
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, 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<TocRef>;
|
||||||
|
pub struct TocRef(ffi::GstToc);
|
||||||
|
|
||||||
|
unsafe impl MiniObject for TocRef {
|
||||||
|
type GstType = ffi::GstToc;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl GstRc<TocRef> {
|
||||||
|
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<TocEntry> {
|
||||||
|
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<TocEntry> {
|
||||||
|
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<TagList> {
|
||||||
|
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.into_ptr(), mode.to_glib());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn dump(&self) {
|
||||||
|
unsafe {
|
||||||
|
ffi::gst_toc_dump(self.as_mut_ptr());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl glib::types::StaticType for GstRc<TocRef> {
|
||||||
|
fn static_type() -> glib::types::Type {
|
||||||
|
unsafe { from_glib(ffi::gst_toc_get_type()) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ToOwned for TocRef {
|
||||||
|
type Owned = GstRc<TocRef>;
|
||||||
|
|
||||||
|
fn to_owned(&self) -> GstRc<TocRef> {
|
||||||
|
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<TocEntryRef>;
|
||||||
|
pub struct TocEntryRef(ffi::GstTocEntry);
|
||||||
|
|
||||||
|
unsafe impl MiniObject for TocEntryRef {
|
||||||
|
type GstType = ffi::GstTocEntry;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl GstRc<TocEntryRef> {
|
||||||
|
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<TocEntry> {
|
||||||
|
unsafe {
|
||||||
|
FromGlibPtrContainer::from_glib_none(ffi::gst_toc_entry_get_sub_entries(self.as_ptr()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_parent(&self) -> Option<TocEntry> {
|
||||||
|
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<TagList> {
|
||||||
|
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 GstRc<TocEntryRef> {
|
||||||
|
fn static_type() -> glib::types::Type {
|
||||||
|
unsafe { from_glib(ffi::gst_toc_entry_get_type()) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ToOwned for TocEntryRef {
|
||||||
|
type Owned = GstRc<TocEntryRef>;
|
||||||
|
|
||||||
|
fn to_owned(&self) -> GstRc<TocEntryRef> {
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue