From c8910aae08746dcdf77661d589c1342d759b2f9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Wed, 9 Aug 2017 01:29:49 +0300 Subject: [PATCH] Initial gstreamer-audio bindings Only wrapping AudioInfo and AudioFormatInfo and related for now. https://github.com/sdroege/gstreamer-rs/issues/4 --- Cargo.lock | 51 +++- Cargo.toml | 1 + Gir_GstAudio.toml | 37 +++ docs/gstreamer-audio/docs.md | 268 +++++++++++++++++ gstreamer-audio/Cargo.toml | 33 +++ gstreamer-audio/build.rs | 34 +++ gstreamer-audio/src/audio_format_info.rs | 363 +++++++++++++++++++++++ gstreamer-audio/src/audio_info.rs | 286 ++++++++++++++++++ gstreamer-audio/src/auto/enums.rs | 359 ++++++++++++++++++++++ gstreamer-audio/src/auto/flags.rs | 157 ++++++++++ gstreamer-audio/src/auto/mod.rs | 25 ++ gstreamer-audio/src/lib.rs | 48 +++ gstreamer/src/segment.rs | 2 + 13 files changed, 1662 insertions(+), 2 deletions(-) create mode 100644 Gir_GstAudio.toml create mode 100644 docs/gstreamer-audio/docs.md create mode 100644 gstreamer-audio/Cargo.toml create mode 100644 gstreamer-audio/build.rs create mode 100644 gstreamer-audio/src/audio_format_info.rs create mode 100644 gstreamer-audio/src/audio_info.rs create mode 100644 gstreamer-audio/src/auto/enums.rs create mode 100644 gstreamer-audio/src/auto/flags.rs create mode 100644 gstreamer-audio/src/auto/mod.rs create mode 100644 gstreamer-audio/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index f982830c8..3e154d90f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1,5 +1,5 @@ [root] -name = "gstreamer-app" +name = "gstreamer-audio" version = "0.1.0" dependencies = [ "bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", @@ -7,8 +7,9 @@ dependencies = [ "glib-sys 0.3.4 (git+https://github.com/gtk-rs/sys)", "gobject-sys 0.3.4 (git+https://github.com/gtk-rs/sys)", "gstreamer 0.1.0", - "gstreamer-app-sys 0.1.1 (git+https://github.com/sdroege/gstreamer-sys)", + "gstreamer-audio-sys 0.1.1 (git+https://github.com/sdroege/gstreamer-sys)", "gstreamer-sys 0.1.1 (git+https://github.com/sdroege/gstreamer-sys)", + "lazy_static 0.2.8 (registry+https://github.com/rust-lang/crates.io-index)", "libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)", "rustdoc-stripper 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -246,6 +247,21 @@ dependencies = [ "rustdoc-stripper 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "gstreamer-app" +version = "0.1.0" +dependencies = [ + "bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", + "glib 0.1.3 (git+https://github.com/gtk-rs/glib)", + "glib-sys 0.3.4 (git+https://github.com/gtk-rs/sys)", + "gobject-sys 0.3.4 (git+https://github.com/gtk-rs/sys)", + "gstreamer 0.1.0", + "gstreamer-app-sys 0.1.1 (git+https://github.com/sdroege/gstreamer-sys)", + "gstreamer-sys 0.1.1 (git+https://github.com/sdroege/gstreamer-sys)", + "libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)", + "rustdoc-stripper 0.1.4 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "gstreamer-app-sys" version = "0.1.1" @@ -260,6 +276,21 @@ dependencies = [ "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "gstreamer-audio-sys" +version = "0.1.1" +source = "git+https://github.com/sdroege/gstreamer-sys#252abbaeda64a3fdd8ccab291297500e3cdf6499" +dependencies = [ + "bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", + "glib-sys 0.3.4 (git+https://github.com/gtk-rs/sys)", + "gobject-sys 0.3.4 (git+https://github.com/gtk-rs/sys)", + "gstreamer-base-sys 0.1.1 (git+https://github.com/sdroege/gstreamer-sys)", + "gstreamer-sys 0.1.1 (git+https://github.com/sdroege/gstreamer-sys)", + "gstreamer-tag-sys 0.1.1 (git+https://github.com/sdroege/gstreamer-sys)", + "libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)", + "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "gstreamer-base-sys" version = "0.1.1" @@ -285,6 +316,20 @@ dependencies = [ "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "gstreamer-tag-sys" +version = "0.1.1" +source = "git+https://github.com/sdroege/gstreamer-sys#252abbaeda64a3fdd8ccab291297500e3cdf6499" +dependencies = [ + "bitflags 0.9.1 (registry+https://github.com/rust-lang/crates.io-index)", + "glib-sys 0.3.4 (git+https://github.com/gtk-rs/sys)", + "gobject-sys 0.3.4 (git+https://github.com/gtk-rs/sys)", + "gstreamer-base-sys 0.1.1 (git+https://github.com/sdroege/gstreamer-sys)", + "gstreamer-sys 0.1.1 (git+https://github.com/sdroege/gstreamer-sys)", + "libc 0.2.29 (registry+https://github.com/rust-lang/crates.io-index)", + "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "gtk" version = "0.1.3" @@ -560,8 +605,10 @@ dependencies = [ "checksum glib-sys 0.3.4 (git+https://github.com/gtk-rs/sys)" = "" "checksum gobject-sys 0.3.4 (git+https://github.com/gtk-rs/sys)" = "" "checksum gstreamer-app-sys 0.1.1 (git+https://github.com/sdroege/gstreamer-sys)" = "" +"checksum gstreamer-audio-sys 0.1.1 (git+https://github.com/sdroege/gstreamer-sys)" = "" "checksum gstreamer-base-sys 0.1.1 (git+https://github.com/sdroege/gstreamer-sys)" = "" "checksum gstreamer-sys 0.1.1 (git+https://github.com/sdroege/gstreamer-sys)" = "" +"checksum gstreamer-tag-sys 0.1.1 (git+https://github.com/sdroege/gstreamer-sys)" = "" "checksum gtk 0.1.3 (git+https://github.com/gtk-rs/gtk)" = "" "checksum gtk-sys 0.3.4 (git+https://github.com/gtk-rs/sys)" = "" "checksum iovec 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "29d062ee61fccdf25be172e70f34c9f6efc597e1fb8f6526e8437b2046ab26be" diff --git a/Cargo.toml b/Cargo.toml index 4f543e6cd..e2f2fb712 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,5 +3,6 @@ members = [ "gstreamer", "gstreamer-app", + "gstreamer-audio", "examples", ] diff --git a/Gir_GstAudio.toml b/Gir_GstAudio.toml new file mode 100644 index 000000000..c8c48d36a --- /dev/null +++ b/Gir_GstAudio.toml @@ -0,0 +1,37 @@ +[options] +girs_dir = "gir-files" +library = "GstAudio" +version = "1.0" +min_cfg_version = "1.8" +target_path = "gstreamer-audio" +work_mode = "normal" +concurrency = "send+sync" +generate_safety_asserts = true + +external_libraries = [ + "GLib", + "GObject", + "Gst", +] + +generate = [ + "GstAudio.AudioFlags", + "GstAudio.AudioFormat", + "GstAudio.AudioFormatFlags", + "GstAudio.AudioLayout", + "GstAudio.AudioPackFlags", + "GstAudio.AudioChannelPosition", +] + +manual = [ + "GObject.Object", + "Gst.Object", + "GstAudio.AudioInfo", + "GstAudio.AudioFormatInfo", +] + +[[object]] +name = "Gst.Caps" +status = "manual" +ref_mode = "ref" + diff --git a/docs/gstreamer-audio/docs.md b/docs/gstreamer-audio/docs.md new file mode 100644 index 000000000..db14eae55 --- /dev/null +++ b/docs/gstreamer-audio/docs.md @@ -0,0 +1,268 @@ + + +Audio channel positions. + +These are the channels defined in SMPTE 2036-2-2008 +Table 1 for 22.2 audio systems with the Surround and Wide channels from +DTS Coherent Acoustics (v.1.3.1) and 10.2 and 7.1 layouts. In the caps the +actual channel layout is expressed with a channel count and a channel mask, +which describes the existing channels. The positions in the bit mask correspond +to the enum values. +For negotiation it is allowed to have more bits set in the channel mask than +the number of channels to specify the allowed channel positions but this is +not allowed in negotiated caps. It is not allowed in any situation other +than the one mentioned below to have less bits set in the channel mask than +the number of channels. + +`AudioChannelPosition::Mono` can only be used with a single mono channel that +has no direction information and would be mixed into all directional channels. +This is expressed in caps by having a single channel and no channel mask. + +`AudioChannelPosition::None` can only be used if all channels have this position. +This is expressed in caps by having a channel mask with no bits set. + +As another special case it is allowed to have two channels without a channel mask. +This implicitely means that this is a stereo stream with a front left and front right +channel. + +used for position-less channels, e.g. + from a sound card that records 1024 channels; mutually exclusive with + any other channel position + +Mono without direction; + can only be used with 1 channel + +invalid position + +Front left + +Front right + +Front center + +Low-frequency effects 1 (subwoofer) + +Rear left + +Rear right + +Front left of center + +Front right of center + +Rear center + +Low-frequency effects 2 (subwoofer) + +Side left + +Side right + +Top front left + +Top front right + +Top front center + +Top center + +Top rear left + +Top rear right + +Top side right + +Top rear right + +Top rear center + +Bottom front center + +Bottom front left + +Bottom front right + +Wide left (between front left and side left) + +Wide right (between front right and side right) + +Surround left (between rear left and side left) + +Surround right (between rear right and side right) + +Enum value describing the most common audio formats. + +unknown or unset audio format + +encoded audio format + +8 bits in 8 bits, signed + +8 bits in 8 bits, unsigned + +16 bits in 16 bits, signed, little endian + +16 bits in 16 bits, signed, big endian + +16 bits in 16 bits, unsigned, little endian + +16 bits in 16 bits, unsigned, big endian + +24 bits in 32 bits, signed, little endian + +24 bits in 32 bits, signed, big endian + +24 bits in 32 bits, unsigned, little endian + +24 bits in 32 bits, unsigned, big endian + +32 bits in 32 bits, signed, little endian + +32 bits in 32 bits, signed, big endian + +32 bits in 32 bits, unsigned, little endian + +32 bits in 32 bits, unsigned, big endian + +24 bits in 24 bits, signed, little endian + +24 bits in 24 bits, signed, big endian + +24 bits in 24 bits, unsigned, little endian + +24 bits in 24 bits, unsigned, big endian + +20 bits in 24 bits, signed, little endian + +20 bits in 24 bits, signed, big endian + +20 bits in 24 bits, unsigned, little endian + +20 bits in 24 bits, unsigned, big endian + +18 bits in 24 bits, signed, little endian + +18 bits in 24 bits, signed, big endian + +18 bits in 24 bits, unsigned, little endian + +18 bits in 24 bits, unsigned, big endian + +32-bit floating point samples, little endian + +32-bit floating point samples, big endian + +64-bit floating point samples, little endian + +64-bit floating point samples, big endian + +16 bits in 16 bits, signed, native endianness + +16 bits in 16 bits, unsigned, native endianness + +24 bits in 32 bits, signed, native endianness + +24 bits in 32 bits, unsigned, native endianness + +32 bits in 32 bits, signed, native endianness + +32 bits in 32 bits, unsigned, native endianness + +24 bits in 24 bits, signed, native endianness + +24 bits in 24 bits, unsigned, native endianness + +20 bits in 24 bits, signed, native endianness + +20 bits in 24 bits, unsigned, native endianness + +18 bits in 24 bits, signed, native endianness + +18 bits in 24 bits, unsigned, native endianness + +32-bit floating point samples, native endianness + +64-bit floating point samples, native endianness + +Information for an audio format. + +Information describing audio properties. This information can be filled +in from GstCaps with `AudioInfo::from_caps`. + +Use the provided macros to access the info in this structure. + +Allocate a new `AudioInfo` that is also initialized with +`AudioInfo::init`. + +# Returns + +a new `AudioInfo`. free with `AudioInfo::free`. + +Converts among various `gst::Format` types. This function handles +GST_FORMAT_BYTES, GST_FORMAT_TIME, and GST_FORMAT_DEFAULT. For +raw audio, GST_FORMAT_DEFAULT corresponds to audio frames. This +function can be used to handle pad queries of the type GST_QUERY_CONVERT. +## `src_fmt` +`gst::Format` of the `src_val` +## `src_val` +value to convert +## `dest_fmt` +`gst::Format` of the `dest_val` +## `dest_val` +pointer to destination value + +# Returns + +TRUE if the conversion was successful. + +Copy a GstAudioInfo structure. + +# Returns + +a new `AudioInfo`. free with gst_audio_info_free. + +Free a GstAudioInfo structure previously allocated with `AudioInfo::new` +or `AudioInfo::copy`. + +Parse `caps` and update `self`. +## `caps` +a `gst::Caps` + +# Returns + +TRUE if `caps` could be parsed + +Initialize `self` with default values. + +Compares two `AudioInfo` and returns whether they are equal or not +## `other` +a `AudioInfo` + +# Returns + +`true` if `self` and `other` are equal, else `false`. + +Set the default info for the audio info of `format` and `rate` and `channels`. + +Note: This initializes `self` first, no values are preserved. +## `format` +the format +## `rate` +the samplerate +## `channels` +the number of channels +## `position` +the channel positions + +Convert the values of `self` into a `gst::Caps`. + +# Returns + +the new `gst::Caps` containing the + info of `self`. + +Layout of the audio samples for the different channels. + +interleaved audio + +non-interleaved audio diff --git a/gstreamer-audio/Cargo.toml b/gstreamer-audio/Cargo.toml new file mode 100644 index 000000000..cc0ea59fc --- /dev/null +++ b/gstreamer-audio/Cargo.toml @@ -0,0 +1,33 @@ +[package] +name = "gstreamer-audio" +version = "0.1.0" +authors = ["Sebastian Dröge "] +categories = ["api-bindings", "multimedia"] +description = "Rust bindings for GStreamer Audio library" +repository = "https://github.com/sdroege/gstreamer-rs" +license = "MIT/Apache-2.0" +documentation = "https://gstreamer.freedesktop.org" +keywords = ["gstreamer", "multimedia", "audio", "video", "gnome"] +build = "build.rs" + +[dependencies] +bitflags = "0.9" +libc = "0.2" +glib-sys = { version = "0.3.4", git = "https://github.com/gtk-rs/sys" } +gobject-sys = { version = "0.3.4", git = "https://github.com/gtk-rs/sys" } +gstreamer-sys = { version = "0.1.1", git = "https://github.com/sdroege/gstreamer-sys", features = ["v1_8"] } +gstreamer-audio-sys = { version = "0.1.1", git = "https://github.com/sdroege/gstreamer-sys", features = ["v1_8"] } +glib = { version = "0.1.3", git = "https://github.com/gtk-rs/glib" } +gstreamer = { version = "0.1.0", path = "../gstreamer" } +lazy_static = "0.2" + +[build-dependencies.rustdoc-stripper] +version = "0.1" +optional = true + +[features] +v1_10 = ["gstreamer-sys/v1_10"] +v1_12 = ["gstreamer-sys/v1_12", "v1_10"] +embed-lgpl-docs = ["rustdoc-stripper"] +purge-lgpl-docs = ["rustdoc-stripper"] +default-features = [] diff --git a/gstreamer-audio/build.rs b/gstreamer-audio/build.rs new file mode 100644 index 000000000..57c16674a --- /dev/null +++ b/gstreamer-audio/build.rs @@ -0,0 +1,34 @@ +fn main() { + manage_docs(); +} + +#[cfg(any(feature = "embed-lgpl-docs", feature = "purge-lgpl-docs"))] +fn manage_docs() { + extern crate stripper_lib; + use std::io; + + let path = "src"; + let ignores: &[&str] = &[]; + + stripper_lib::loop_over_files( + path.as_ref(), + &mut |w, s| stripper_lib::strip_comments(w, s, &mut io::sink(), true), + &ignores, + false, + ); + + #[cfg(feature = "embed-lgpl-docs")] + { + let docs = include_str!("../docs/gstreamer-audio/docs.md"); + let mut infos = stripper_lib::parse_cmts(docs.lines(), true); + stripper_lib::loop_over_files( + path.as_ref(), + &mut |w, s| stripper_lib::regenerate_comments(w, s, &mut infos, true, true), + &ignores, + false, + ); + } +} + +#[cfg(not(any(feature = "embed-lgpl-docs", feature = "purge-lgpl-docs")))] +fn manage_docs() {} diff --git a/gstreamer-audio/src/audio_format_info.rs b/gstreamer-audio/src/audio_format_info.rs new file mode 100644 index 000000000..fc52a638b --- /dev/null +++ b/gstreamer-audio/src/audio_format_info.rs @@ -0,0 +1,363 @@ +// Copyright (C) 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 ffi; + +use std::ffi::CStr; +use std::fmt; +use std::str; + +use glib::translate::{from_glib, FromGlib, ToGlib, ToGlibPtr}; + +#[derive(PartialEq, Eq, Debug)] +pub enum AudioEndianness { + Unknown, + LittleEndian = 1234, + BigEndian = 4321, +} + +impl FromGlib for AudioEndianness { + fn from_glib(value: i32) -> Self { + match value { + 1234 => AudioEndianness::LittleEndian, + 4321 => AudioEndianness::BigEndian, + _ => AudioEndianness::Unknown, + } + } +} + +impl ToGlib for AudioEndianness { + type GlibType = i32; + + fn to_glib(&self) -> i32 { + match *self { + AudioEndianness::LittleEndian => 1234, + AudioEndianness::BigEndian => 4321, + _ => 0, + } + } +} + +impl ::AudioFormat { + pub fn build_integer( + sign: bool, + endianness: AudioEndianness, + width: i32, + depth: i32, + ) -> ::AudioFormat { + unsafe { + from_glib(ffi::gst_audio_format_build_integer( + sign.to_glib(), + endianness.to_glib(), + width, + depth, + )) + } + } +} + +impl str::FromStr for ::AudioFormat { + type Err = (); + + fn from_str(s: &str) -> Result { + unsafe { + let format = ffi::gst_audio_format_from_string(s.to_glib_none().0); + if format == ffi::GST_AUDIO_FORMAT_UNKNOWN { + Err(()) + } else { + Ok(from_glib(format)) + } + } + } +} + +#[cfg(target_endian = "big")] +pub const FORMAT_S16: ::AudioFormat = ::AudioFormat::S16be; +#[cfg(target_endian = "big")] +pub const FORMAT_U16: ::AudioFormat = ::AudioFormat::U16be; +#[cfg(target_endian = "big")] +pub const FORMAT_S2432: ::AudioFormat = ::AudioFormat::S2432be; +#[cfg(target_endian = "big")] +pub const FORMAT_U2432: ::AudioFormat = ::AudioFormat::U2432be; +#[cfg(target_endian = "big")] +pub const FORMAT_S32: ::AudioFormat = ::AudioFormat::S32be; +#[cfg(target_endian = "big")] +pub const FORMAT_U32: ::AudioFormat = ::AudioFormat::S32be; +#[cfg(target_endian = "big")] +pub const FORMAT_S24: ::AudioFormat = ::AudioFormat::S24be; +#[cfg(target_endian = "big")] +pub const FORMAT_U24: ::AudioFormat = ::AudioFormat::S24be; +#[cfg(target_endian = "big")] +pub const FORMAT_S20: ::AudioFormat = ::AudioFormat::S20be; +#[cfg(target_endian = "big")] +pub const FORMAT_U20: ::AudioFormat = ::AudioFormat::S20be; +#[cfg(target_endian = "big")] +pub const FORMAT_S18: ::AudioFormat = ::AudioFormat::S18be; +#[cfg(target_endian = "big")] +pub const FORMAT_U18: ::AudioFormat = ::AudioFormat::S18be; +#[cfg(target_endian = "big")] +pub const FORMAT_F32: ::AudioFormat = ::AudioFormat::F32be; +#[cfg(target_endian = "big")] +pub const FORMAT_F64: ::AudioFormat = ::AudioFormat::F64be; + +#[cfg(target_endian = "little")] +pub const FORMAT_S16: ::AudioFormat = ::AudioFormat::S16le; +#[cfg(target_endian = "little")] +pub const FORMAT_U16: ::AudioFormat = ::AudioFormat::U16le; +#[cfg(target_endian = "little")] +pub const FORMAT_S2432: ::AudioFormat = ::AudioFormat::S2432le; +#[cfg(target_endian = "little")] +pub const FORMAT_U2432: ::AudioFormat = ::AudioFormat::U2432le; +#[cfg(target_endian = "little")] +pub const FORMAT_S32: ::AudioFormat = ::AudioFormat::S32le; +#[cfg(target_endian = "little")] +pub const FORMAT_U32: ::AudioFormat = ::AudioFormat::S32le; +#[cfg(target_endian = "little")] +pub const FORMAT_S24: ::AudioFormat = ::AudioFormat::S24le; +#[cfg(target_endian = "little")] +pub const FORMAT_U24: ::AudioFormat = ::AudioFormat::S24le; +#[cfg(target_endian = "little")] +pub const FORMAT_S20: ::AudioFormat = ::AudioFormat::S20le; +#[cfg(target_endian = "little")] +pub const FORMAT_U20: ::AudioFormat = ::AudioFormat::S20le; +#[cfg(target_endian = "little")] +pub const FORMAT_S18: ::AudioFormat = ::AudioFormat::S18le; +#[cfg(target_endian = "little")] +pub const FORMAT_U18: ::AudioFormat = ::AudioFormat::S18le; +#[cfg(target_endian = "little")] +pub const FORMAT_F32: ::AudioFormat = ::AudioFormat::F32le; +#[cfg(target_endian = "little")] +pub const FORMAT_F64: ::AudioFormat = ::AudioFormat::F64le; + +pub struct AudioFormatInfo(&'static ffi::GstAudioFormatInfo); + +impl AudioFormatInfo { + pub fn from_format(format: ::AudioFormat) -> AudioFormatInfo { + unsafe { + let info = ffi::gst_audio_format_get_info(format.to_glib()); + assert!(!info.is_null()); + + AudioFormatInfo(&*info) + } + } + + pub fn format(&self) -> ::AudioFormat { + from_glib(self.0.format) + } + + pub fn name(&self) -> &'static str { + unsafe { CStr::from_ptr(self.0.name).to_str().unwrap() } + } + + pub fn description(&self) -> &'static str { + unsafe { CStr::from_ptr(self.0.description).to_str().unwrap() } + } + + pub fn flags(&self) -> ::AudioFormatFlags { + from_glib(self.0.flags) + } + + pub fn endianness(&self) -> AudioEndianness { + from_glib(self.0.endianness) + } + + pub fn width(&self) -> i32 { + self.0.width + } + + pub fn depth(&self) -> i32 { + self.0.depth + } + + pub fn unpack_format(&self) -> ::AudioFormat { + from_glib(self.0.unpack_format) + } + + pub fn silence(&self) -> &'static [u8] { + &self.0.silence + } + + pub fn unpack(&self, flags: ::AudioPackFlags, dest: &mut [u8], src: &[u8]) { + let unpack_format = Self::from_format(self.unpack_format()); + let unpack_width = unpack_format.width() as usize; + + if unpack_width == 0 || self.0.unpack_func.is_none() { + panic!("No unpack format for {:?}", self); + } + + let self_width = self.width() as usize; + if self_width == 0 { + panic!("No width for {:?}", self); + } + + if src.len() % (self_width / 8) != 0 { + panic!("Incomplete number of samples in src"); + } + + let nsamples = src.len() / (self_width / 8); + + if dest.len() != nsamples * (unpack_width / 8) { + panic!("Invalid dest length"); + } + + unsafe { + (self.0.unpack_func.as_ref().unwrap())( + self.0, + flags.to_glib(), + dest.as_mut_ptr() as *mut _, + src.as_ptr() as *mut _, + nsamples as i32, + ); + } + } + + pub fn pack(&self, flags: ::AudioPackFlags, dest: &mut [u8], src: &[u8]) { + let unpack_format = Self::from_format(self.unpack_format()); + let unpack_width = unpack_format.width() as usize; + + if unpack_width == 0 || self.0.pack_func.is_none() { + panic!("No unpack format for {:?}", self); + } + + let self_width = self.width() as usize; + if self_width == 0 { + panic!("No width for {:?}", self); + } + + if src.len() % (unpack_width / 8) != 0 { + panic!("Incomplete number of samples in src"); + } + + let nsamples = src.len() / (unpack_width / 8); + + if dest.len() != nsamples * (self_width / 8) { + panic!("Invalid dest length"); + } + + unsafe { + (self.0.pack_func.as_ref().unwrap())( + self.0, + flags.to_glib(), + src.as_ptr() as *mut _, + dest.as_mut_ptr() as *mut _, + nsamples as i32, + ); + } + } + + pub fn fill_silence(&self, dest: &mut [u8]) { + let self_width = self.width() as usize; + + if self_width == 0 { + panic!("Filling with silence unsupported"); + } + + if dest.len() % (self_width / 8) != 0 { + panic!("Incomplete number of samples in dest"); + } + + unsafe { + ffi::gst_audio_format_fill_silence(self.0, dest.as_mut_ptr() as *mut _, dest.len()) + } + } + + pub fn is_float(&self) -> bool { + self.flags().contains(::AUDIO_FORMAT_FLAG_FLOAT) + } + + pub fn is_integer(&self) -> bool { + self.flags().contains(::AUDIO_FORMAT_FLAG_INTEGER) + } + + pub fn is_signed(&self) -> bool { + self.flags().contains(::AUDIO_FORMAT_FLAG_SIGNED) + } + + + pub fn is_little_endian(&self) -> bool { + self.endianness() == AudioEndianness::LittleEndian + } + + pub fn is_big_endian(&self) -> bool { + self.endianness() == AudioEndianness::BigEndian + } +} + +unsafe impl Sync for AudioFormatInfo {} +unsafe impl Send for AudioFormatInfo {} + +impl PartialEq for AudioFormatInfo { + fn eq(&self, other: &Self) -> bool { + self.format() == other.format() + } +} + +impl Eq for AudioFormatInfo {} + +impl fmt::Debug for AudioFormatInfo { + fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { + f.write_str(self.name()) + } +} + +impl From<::AudioFormat> for AudioFormatInfo { + fn from(f: ::AudioFormat) -> Self { + Self::from_format(f) + } +} + +impl str::FromStr for ::AudioFormatInfo { + type Err = (); + + fn from_str(s: &str) -> Result { + unsafe { + let format = ffi::gst_audio_format_from_string(s.to_glib_none().0); + if format == ffi::GST_AUDIO_FORMAT_UNKNOWN { + Err(()) + } else { + Ok(AudioFormatInfo::from_format(from_glib(format))) + } + } + } +} + +#[cfg(test)] +mod tests { + use super::*; + use gst; + + #[test] + fn test_get() { + gst::init().unwrap(); + + let info = AudioFormatInfo::from_format(::AudioFormat::S16le); + assert_eq!(info.name(), "S16LE"); + + let other_info = "S16LE".parse().unwrap(); + assert_eq!(info, other_info); + } + + #[test] + fn pack_unpack() { + gst::init().unwrap(); + + let info = AudioFormatInfo::from_format(::AudioFormat::S16le); + let unpack_info = AudioFormatInfo::from_format(info.unpack_format()); + + assert!(unpack_info.width() > 0); + + let input = [0, 0, 255, 255, 128, 128, 64, 64]; + let mut unpacked = [0; 16]; + let mut output = [0; 8]; + + info.unpack(::AUDIO_PACK_FLAG_NONE, &mut unpacked, &input); + info.pack(::AUDIO_PACK_FLAG_NONE, &mut output, &unpacked); + + assert_eq!(input, output); + } +} diff --git a/gstreamer-audio/src/audio_info.rs b/gstreamer-audio/src/audio_info.rs new file mode 100644 index 000000000..25413897c --- /dev/null +++ b/gstreamer-audio/src/audio_info.rs @@ -0,0 +1,286 @@ +// Copyright (C) 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 ffi; + +use gst; +use gst::miniobject::MiniObject; +use glib::translate::{from_glib, from_glib_full, ToGlib}; + +use std::mem; +use std::ptr; + +pub struct AudioInfo(ffi::GstAudioInfo); + +pub struct AudioInfoBuilder<'a> { + format: ::AudioFormat, + rate: u32, + channels: u32, + positions: Option<&'a [::AudioChannelPosition]>, + flags: Option<::AudioFlags>, + layout: Option<::AudioLayout>, +} + +impl<'a> AudioInfoBuilder<'a> { + pub fn build(self) -> Option { + unsafe { + let mut info = mem::uninitialized(); + let mut positions_raw = Vec::new(); + + let positions_ptr = match self.positions { + Some(p) => { + if p.len() != self.channels as usize { + return None; + } + + positions_raw.reserve(self.channels as usize); + for i in p { + positions_raw.push(i.to_glib()); + } + + let valid: bool = from_glib(ffi::gst_audio_check_valid_channel_positions( + positions_raw.as_mut_ptr(), + self.channels as i32, + true.to_glib(), + )); + if !valid { + return None; + } + + positions_raw.as_ptr() + } + None => ptr::null(), + }; + + + ffi::gst_audio_info_set_format( + &mut info, + self.format.to_glib(), + self.rate as i32, + self.channels as i32, + positions_ptr, + ); + + if info.finfo.is_null() || info.rate <= 0 || info.channels <= 0 { + return None; + } + + if let Some(flags) = self.flags { + info.flags = flags.to_glib(); + } + + if let Some(layout) = self.layout { + info.layout = layout.to_glib(); + } + + Some(AudioInfo(info)) + } + } + + pub fn positions(self, positions: &'a [::AudioChannelPosition]) -> AudioInfoBuilder<'a> { + Self { + positions: Some(positions), + ..self + } + } + + pub fn flags(self, flags: ::AudioFlags) -> Self { + Self { + flags: Some(flags), + ..self + } + } + + pub fn layout(self, layout: ::AudioLayout) -> Self { + Self { + layout: Some(layout), + ..self + } + } +} + +impl AudioInfo { + pub fn new<'a>(format: ::AudioFormat, rate: u32, channels: u32) -> AudioInfoBuilder<'a> { + AudioInfoBuilder { + format: format, + rate: rate, + channels: channels, + positions: None, + flags: None, + layout: None, + } + } + + pub fn from_caps(caps: &gst::Caps) -> Option { + unsafe { + let mut info = mem::uninitialized(); + if from_glib(ffi::gst_audio_info_from_caps(&mut info, caps.as_ptr())) { + Some(AudioInfo(info)) + } else { + None + } + } + } + + pub fn to_caps(&self) -> Option { + unsafe { + let caps = ffi::gst_audio_info_to_caps(&self.0); + if caps.is_null() { + None + } else { + Some(from_glib_full(caps)) + } + } + } + + pub fn convert( + &self, + src_fmt: gst::Format, + src_val: i64, + dest_fmt: gst::Format, + ) -> Option { + unsafe { + let mut dest_val = mem::uninitialized(); + if from_glib(ffi::gst_audio_info_convert( + &self.0, + src_fmt.to_glib(), + src_val, + dest_fmt.to_glib(), + &mut dest_val, + )) { + Some(dest_val) + } else { + None + } + } + } + + pub fn format(&self) -> ::AudioFormat { + unsafe { from_glib((*self.0.finfo).format) } + } + + pub fn format_info(&self) -> ::AudioFormatInfo { + ::AudioFormatInfo::from_format(self.format()) + } + + pub fn layout(&self) -> ::AudioLayout { + from_glib(self.0.layout) + } + + pub fn rate(&self) -> u32 { + self.0.rate as u32 + } + + pub fn channels(&self) -> u32 { + self.0.channels as u32 + } + + pub fn bpf(&self) -> u32 { + self.0.bpf as u32 + } + + pub fn positions(&self) -> Vec<::AudioChannelPosition> { + let mut v = Vec::with_capacity(self.0.channels as usize); + for i in 0..(self.0.channels as usize) { + v.push(from_glib(self.0.position[i])); + } + + v + } +} + +impl Clone for AudioInfo { + fn clone(&self) -> Self { + unsafe { AudioInfo(ptr::read(&self.0)) } + } +} + +impl PartialEq for AudioInfo { + fn eq(&self, other: &Self) -> bool { + unsafe { from_glib(ffi::gst_audio_info_is_equal(&self.0, &other.0)) } + } +} + +impl Eq for AudioInfo {} + +#[cfg(test)] +mod tests { + use super::*; + use gst; + + #[test] + fn test_new() { + gst::init().unwrap(); + + let info = AudioInfo::new(::AudioFormat::S16le, 48000, 2) + .build() + .unwrap(); + assert_eq!(info.format(), ::AudioFormat::S16le); + assert_eq!(info.rate(), 48000); + assert_eq!(info.channels(), 2); + assert_eq!( + &info.positions(), + &[ + ::AudioChannelPosition::FrontLeft, + ::AudioChannelPosition::FrontRight + ] + ); + + let positions = [ + ::AudioChannelPosition::RearLeft, + ::AudioChannelPosition::RearRight, + ]; + let info = AudioInfo::new(::AudioFormat::S16le, 48000, 2) + .positions(&positions) + .build() + .unwrap(); + assert_eq!(info.format(), ::AudioFormat::S16le); + assert_eq!(info.rate(), 48000); + assert_eq!(info.channels(), 2); + assert_eq!( + &info.positions(), + &[ + ::AudioChannelPosition::RearLeft, + ::AudioChannelPosition::RearRight + ] + ); + } + + #[test] + fn test_from_to_caps() { + gst::init().unwrap(); + + let caps = gst::Caps::new_simple( + "audio/x-raw", + &[ + ("format", &"S16LE"), + ("rate", &48000), + ("channels", &2), + ("layout", &"interleaved"), + ("channel-mask", &gst::Bitmask::new(0x3)), + ], + ); + let info = AudioInfo::from_caps(&caps).unwrap(); + assert_eq!(info.format(), ::AudioFormat::S16le); + assert_eq!(info.rate(), 48000); + assert_eq!(info.channels(), 2); + assert_eq!( + &info.positions(), + &[ + ::AudioChannelPosition::FrontLeft, + ::AudioChannelPosition::FrontRight + ] + ); + + let caps2 = info.to_caps().unwrap(); + assert_eq!(caps, caps2); + + let info2 = AudioInfo::from_caps(&caps2).unwrap(); + assert!(info == info2); + } +} diff --git a/gstreamer-audio/src/auto/enums.rs b/gstreamer-audio/src/auto/enums.rs new file mode 100644 index 000000000..48efbf631 --- /dev/null +++ b/gstreamer-audio/src/auto/enums.rs @@ -0,0 +1,359 @@ +// This file was generated by gir (3294959+) from gir-files (???) +// DO NOT EDIT + +use ffi; +use glib::Type; +use glib::StaticType; +use glib::value::{Value, SetValue, FromValue, FromValueOptional}; +use gobject_ffi; +use glib::translate::*; +use std; + +#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)] +pub enum AudioChannelPosition { + None, + Mono, + Invalid, + FrontLeft, + FrontRight, + FrontCenter, + Lfe1, + RearLeft, + RearRight, + FrontLeftOfCenter, + FrontRightOfCenter, + RearCenter, + Lfe2, + SideLeft, + SideRight, + TopFrontLeft, + TopFrontRight, + TopFrontCenter, + TopCenter, + TopRearLeft, + TopRearRight, + TopSideLeft, + TopSideRight, + TopRearCenter, + BottomFrontCenter, + BottomFrontLeft, + BottomFrontRight, + WideLeft, + WideRight, + SurroundLeft, + SurroundRight, + #[doc(hidden)] + __Unknown(i32), +} + +#[doc(hidden)] +impl ToGlib for AudioChannelPosition { + type GlibType = ffi::GstAudioChannelPosition; + + fn to_glib(&self) -> ffi::GstAudioChannelPosition { + match *self { + AudioChannelPosition::None => ffi::GST_AUDIO_CHANNEL_POSITION_NONE, + AudioChannelPosition::Mono => ffi::GST_AUDIO_CHANNEL_POSITION_MONO, + AudioChannelPosition::Invalid => ffi::GST_AUDIO_CHANNEL_POSITION_INVALID, + AudioChannelPosition::FrontLeft => ffi::GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT, + AudioChannelPosition::FrontRight => ffi::GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT, + AudioChannelPosition::FrontCenter => ffi::GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER, + AudioChannelPosition::Lfe1 => ffi::GST_AUDIO_CHANNEL_POSITION_LFE1, + AudioChannelPosition::RearLeft => ffi::GST_AUDIO_CHANNEL_POSITION_REAR_LEFT, + AudioChannelPosition::RearRight => ffi::GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT, + AudioChannelPosition::FrontLeftOfCenter => ffi::GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT_OF_CENTER, + AudioChannelPosition::FrontRightOfCenter => ffi::GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT_OF_CENTER, + AudioChannelPosition::RearCenter => ffi::GST_AUDIO_CHANNEL_POSITION_REAR_CENTER, + AudioChannelPosition::Lfe2 => ffi::GST_AUDIO_CHANNEL_POSITION_LFE2, + AudioChannelPosition::SideLeft => ffi::GST_AUDIO_CHANNEL_POSITION_SIDE_LEFT, + AudioChannelPosition::SideRight => ffi::GST_AUDIO_CHANNEL_POSITION_SIDE_RIGHT, + AudioChannelPosition::TopFrontLeft => ffi::GST_AUDIO_CHANNEL_POSITION_TOP_FRONT_LEFT, + AudioChannelPosition::TopFrontRight => ffi::GST_AUDIO_CHANNEL_POSITION_TOP_FRONT_RIGHT, + AudioChannelPosition::TopFrontCenter => ffi::GST_AUDIO_CHANNEL_POSITION_TOP_FRONT_CENTER, + AudioChannelPosition::TopCenter => ffi::GST_AUDIO_CHANNEL_POSITION_TOP_CENTER, + AudioChannelPosition::TopRearLeft => ffi::GST_AUDIO_CHANNEL_POSITION_TOP_REAR_LEFT, + AudioChannelPosition::TopRearRight => ffi::GST_AUDIO_CHANNEL_POSITION_TOP_REAR_RIGHT, + AudioChannelPosition::TopSideLeft => ffi::GST_AUDIO_CHANNEL_POSITION_TOP_SIDE_LEFT, + AudioChannelPosition::TopSideRight => ffi::GST_AUDIO_CHANNEL_POSITION_TOP_SIDE_RIGHT, + AudioChannelPosition::TopRearCenter => ffi::GST_AUDIO_CHANNEL_POSITION_TOP_REAR_CENTER, + AudioChannelPosition::BottomFrontCenter => ffi::GST_AUDIO_CHANNEL_POSITION_BOTTOM_FRONT_CENTER, + AudioChannelPosition::BottomFrontLeft => ffi::GST_AUDIO_CHANNEL_POSITION_BOTTOM_FRONT_LEFT, + AudioChannelPosition::BottomFrontRight => ffi::GST_AUDIO_CHANNEL_POSITION_BOTTOM_FRONT_RIGHT, + AudioChannelPosition::WideLeft => ffi::GST_AUDIO_CHANNEL_POSITION_WIDE_LEFT, + AudioChannelPosition::WideRight => ffi::GST_AUDIO_CHANNEL_POSITION_WIDE_RIGHT, + AudioChannelPosition::SurroundLeft => ffi::GST_AUDIO_CHANNEL_POSITION_SURROUND_LEFT, + AudioChannelPosition::SurroundRight => ffi::GST_AUDIO_CHANNEL_POSITION_SURROUND_RIGHT, + AudioChannelPosition::__Unknown(value) => unsafe{std::mem::transmute(value)} + } + } +} + +#[doc(hidden)] +impl FromGlib for AudioChannelPosition { + fn from_glib(value: ffi::GstAudioChannelPosition) -> Self { + skip_assert_initialized!(); + match value as i32 { + -3 => AudioChannelPosition::None, + -2 => AudioChannelPosition::Mono, + -1 => AudioChannelPosition::Invalid, + 0 => AudioChannelPosition::FrontLeft, + 1 => AudioChannelPosition::FrontRight, + 2 => AudioChannelPosition::FrontCenter, + 3 => AudioChannelPosition::Lfe1, + 4 => AudioChannelPosition::RearLeft, + 5 => AudioChannelPosition::RearRight, + 6 => AudioChannelPosition::FrontLeftOfCenter, + 7 => AudioChannelPosition::FrontRightOfCenter, + 8 => AudioChannelPosition::RearCenter, + 9 => AudioChannelPosition::Lfe2, + 10 => AudioChannelPosition::SideLeft, + 11 => AudioChannelPosition::SideRight, + 12 => AudioChannelPosition::TopFrontLeft, + 13 => AudioChannelPosition::TopFrontRight, + 14 => AudioChannelPosition::TopFrontCenter, + 15 => AudioChannelPosition::TopCenter, + 16 => AudioChannelPosition::TopRearLeft, + 17 => AudioChannelPosition::TopRearRight, + 18 => AudioChannelPosition::TopSideLeft, + 19 => AudioChannelPosition::TopSideRight, + 20 => AudioChannelPosition::TopRearCenter, + 21 => AudioChannelPosition::BottomFrontCenter, + 22 => AudioChannelPosition::BottomFrontLeft, + 23 => AudioChannelPosition::BottomFrontRight, + 24 => AudioChannelPosition::WideLeft, + 25 => AudioChannelPosition::WideRight, + 26 => AudioChannelPosition::SurroundLeft, + 27 => AudioChannelPosition::SurroundRight, + value => AudioChannelPosition::__Unknown(value), + } + } +} + +impl StaticType for AudioChannelPosition { + fn static_type() -> Type { + unsafe { from_glib(ffi::gst_audio_channel_position_get_type()) } + } +} + +impl<'a> FromValueOptional<'a> for AudioChannelPosition { + unsafe fn from_value_optional(value: &Value) -> Option { + Some(FromValue::from_value(value)) + } +} + +impl<'a> FromValue<'a> for AudioChannelPosition { + unsafe fn from_value(value: &Value) -> Self { + from_glib(std::mem::transmute::(gobject_ffi::g_value_get_enum(value.to_glib_none().0))) + } +} + +impl SetValue for AudioChannelPosition { + 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 AudioFormat { + Unknown, + Encoded, + S8, + U8, + S16le, + S16be, + U16le, + U16be, + S2432le, + S2432be, + U2432le, + U2432be, + S32le, + S32be, + U32le, + U32be, + S24le, + S24be, + U24le, + U24be, + S20le, + S20be, + U20le, + U20be, + S18le, + S18be, + U18le, + U18be, + F32le, + F32be, + F64le, + F64be, + #[doc(hidden)] + __Unknown(i32), +} + +#[doc(hidden)] +impl ToGlib for AudioFormat { + type GlibType = ffi::GstAudioFormat; + + fn to_glib(&self) -> ffi::GstAudioFormat { + match *self { + AudioFormat::Unknown => ffi::GST_AUDIO_FORMAT_UNKNOWN, + AudioFormat::Encoded => ffi::GST_AUDIO_FORMAT_ENCODED, + AudioFormat::S8 => ffi::GST_AUDIO_FORMAT_S8, + AudioFormat::U8 => ffi::GST_AUDIO_FORMAT_U8, + AudioFormat::S16le => ffi::GST_AUDIO_FORMAT_S16LE, + AudioFormat::S16be => ffi::GST_AUDIO_FORMAT_S16BE, + AudioFormat::U16le => ffi::GST_AUDIO_FORMAT_U16LE, + AudioFormat::U16be => ffi::GST_AUDIO_FORMAT_U16BE, + AudioFormat::S2432le => ffi::GST_AUDIO_FORMAT_S24_32LE, + AudioFormat::S2432be => ffi::GST_AUDIO_FORMAT_S24_32BE, + AudioFormat::U2432le => ffi::GST_AUDIO_FORMAT_U24_32LE, + AudioFormat::U2432be => ffi::GST_AUDIO_FORMAT_U24_32BE, + AudioFormat::S32le => ffi::GST_AUDIO_FORMAT_S32LE, + AudioFormat::S32be => ffi::GST_AUDIO_FORMAT_S32BE, + AudioFormat::U32le => ffi::GST_AUDIO_FORMAT_U32LE, + AudioFormat::U32be => ffi::GST_AUDIO_FORMAT_U32BE, + AudioFormat::S24le => ffi::GST_AUDIO_FORMAT_S24LE, + AudioFormat::S24be => ffi::GST_AUDIO_FORMAT_S24BE, + AudioFormat::U24le => ffi::GST_AUDIO_FORMAT_U24LE, + AudioFormat::U24be => ffi::GST_AUDIO_FORMAT_U24BE, + AudioFormat::S20le => ffi::GST_AUDIO_FORMAT_S20LE, + AudioFormat::S20be => ffi::GST_AUDIO_FORMAT_S20BE, + AudioFormat::U20le => ffi::GST_AUDIO_FORMAT_U20LE, + AudioFormat::U20be => ffi::GST_AUDIO_FORMAT_U20BE, + AudioFormat::S18le => ffi::GST_AUDIO_FORMAT_S18LE, + AudioFormat::S18be => ffi::GST_AUDIO_FORMAT_S18BE, + AudioFormat::U18le => ffi::GST_AUDIO_FORMAT_U18LE, + AudioFormat::U18be => ffi::GST_AUDIO_FORMAT_U18BE, + AudioFormat::F32le => ffi::GST_AUDIO_FORMAT_F32LE, + AudioFormat::F32be => ffi::GST_AUDIO_FORMAT_F32BE, + AudioFormat::F64le => ffi::GST_AUDIO_FORMAT_F64LE, + AudioFormat::F64be => ffi::GST_AUDIO_FORMAT_F64BE, + AudioFormat::__Unknown(value) => unsafe{std::mem::transmute(value)} + } + } +} + +#[doc(hidden)] +impl FromGlib for AudioFormat { + fn from_glib(value: ffi::GstAudioFormat) -> Self { + skip_assert_initialized!(); + match value as i32 { + 0 => AudioFormat::Unknown, + 1 => AudioFormat::Encoded, + 2 => AudioFormat::S8, + 3 => AudioFormat::U8, + 4 => AudioFormat::S16le, + 5 => AudioFormat::S16be, + 6 => AudioFormat::U16le, + 7 => AudioFormat::U16be, + 8 => AudioFormat::S2432le, + 9 => AudioFormat::S2432be, + 10 => AudioFormat::U2432le, + 11 => AudioFormat::U2432be, + 12 => AudioFormat::S32le, + 13 => AudioFormat::S32be, + 14 => AudioFormat::U32le, + 15 => AudioFormat::U32be, + 16 => AudioFormat::S24le, + 17 => AudioFormat::S24be, + 18 => AudioFormat::U24le, + 19 => AudioFormat::U24be, + 20 => AudioFormat::S20le, + 21 => AudioFormat::S20be, + 22 => AudioFormat::U20le, + 23 => AudioFormat::U20be, + 24 => AudioFormat::S18le, + 25 => AudioFormat::S18be, + 26 => AudioFormat::U18le, + 27 => AudioFormat::U18be, + 28 => AudioFormat::F32le, + 29 => AudioFormat::F32be, + 30 => AudioFormat::F64le, + 31 => AudioFormat::F64be, + value => AudioFormat::__Unknown(value), + } + } +} + +impl StaticType for AudioFormat { + fn static_type() -> Type { + unsafe { from_glib(ffi::gst_audio_format_get_type()) } + } +} + +impl<'a> FromValueOptional<'a> for AudioFormat { + unsafe fn from_value_optional(value: &Value) -> Option { + Some(FromValue::from_value(value)) + } +} + +impl<'a> FromValue<'a> for AudioFormat { + unsafe fn from_value(value: &Value) -> Self { + from_glib(std::mem::transmute::(gobject_ffi::g_value_get_enum(value.to_glib_none().0))) + } +} + +impl SetValue for AudioFormat { + 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 AudioLayout { + Interleaved, + NonInterleaved, + #[doc(hidden)] + __Unknown(i32), +} + +#[doc(hidden)] +impl ToGlib for AudioLayout { + type GlibType = ffi::GstAudioLayout; + + fn to_glib(&self) -> ffi::GstAudioLayout { + match *self { + AudioLayout::Interleaved => ffi::GST_AUDIO_LAYOUT_INTERLEAVED, + AudioLayout::NonInterleaved => ffi::GST_AUDIO_LAYOUT_NON_INTERLEAVED, + AudioLayout::__Unknown(value) => unsafe{std::mem::transmute(value)} + } + } +} + +#[doc(hidden)] +impl FromGlib for AudioLayout { + fn from_glib(value: ffi::GstAudioLayout) -> Self { + skip_assert_initialized!(); + match value as i32 { + 0 => AudioLayout::Interleaved, + 1 => AudioLayout::NonInterleaved, + value => AudioLayout::__Unknown(value), + } + } +} + +impl StaticType for AudioLayout { + fn static_type() -> Type { + unsafe { from_glib(ffi::gst_audio_layout_get_type()) } + } +} + +impl<'a> FromValueOptional<'a> for AudioLayout { + unsafe fn from_value_optional(value: &Value) -> Option { + Some(FromValue::from_value(value)) + } +} + +impl<'a> FromValue<'a> for AudioLayout { + unsafe fn from_value(value: &Value) -> Self { + from_glib(std::mem::transmute::(gobject_ffi::g_value_get_enum(value.to_glib_none().0))) + } +} + +impl SetValue for AudioLayout { + 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) + } +} + diff --git a/gstreamer-audio/src/auto/flags.rs b/gstreamer-audio/src/auto/flags.rs new file mode 100644 index 000000000..bd689f0ad --- /dev/null +++ b/gstreamer-audio/src/auto/flags.rs @@ -0,0 +1,157 @@ +// This file was generated by gir (3294959+) from gir-files (???) +// DO NOT EDIT + +use ffi; +use glib::Type; +use glib::StaticType; +use glib::value::{Value, SetValue, FromValue, FromValueOptional}; +use gobject_ffi; +use glib::translate::*; + +bitflags! { + pub struct AudioFlags: u32 { + const AUDIO_FLAG_NONE = 0; + const AUDIO_FLAG_UNPOSITIONED = 1; + } +} + +#[doc(hidden)] +impl ToGlib for AudioFlags { + type GlibType = ffi::GstAudioFlags; + + fn to_glib(&self) -> ffi::GstAudioFlags { + ffi::GstAudioFlags::from_bits_truncate(self.bits()) + } +} + +#[doc(hidden)] +impl FromGlib for AudioFlags { + fn from_glib(value: ffi::GstAudioFlags) -> AudioFlags { + skip_assert_initialized!(); + AudioFlags::from_bits_truncate(value.bits()) + } +} + +impl StaticType for AudioFlags { + fn static_type() -> Type { + unsafe { from_glib(ffi::gst_audio_flags_get_type()) } + } +} + +impl<'a> FromValueOptional<'a> for AudioFlags { + unsafe fn from_value_optional(value: &Value) -> Option { + Some(FromValue::from_value(value)) + } +} + +impl<'a> FromValue<'a> for AudioFlags { + unsafe fn from_value(value: &Value) -> Self { + from_glib(ffi::GstAudioFlags::from_bits_truncate(gobject_ffi::g_value_get_flags(value.to_glib_none().0))) + } +} + +impl SetValue for AudioFlags { + unsafe fn set_value(value: &mut Value, this: &Self) { + gobject_ffi::g_value_set_flags(value.to_glib_none_mut().0, this.to_glib().bits()) + } +} + +bitflags! { + pub struct AudioFormatFlags: u32 { + const AUDIO_FORMAT_FLAG_INTEGER = 1; + const AUDIO_FORMAT_FLAG_FLOAT = 2; + const AUDIO_FORMAT_FLAG_SIGNED = 4; + const AUDIO_FORMAT_FLAG_COMPLEX = 16; + const AUDIO_FORMAT_FLAG_UNPACK = 32; + } +} + +#[doc(hidden)] +impl ToGlib for AudioFormatFlags { + type GlibType = ffi::GstAudioFormatFlags; + + fn to_glib(&self) -> ffi::GstAudioFormatFlags { + ffi::GstAudioFormatFlags::from_bits_truncate(self.bits()) + } +} + +#[doc(hidden)] +impl FromGlib for AudioFormatFlags { + fn from_glib(value: ffi::GstAudioFormatFlags) -> AudioFormatFlags { + skip_assert_initialized!(); + AudioFormatFlags::from_bits_truncate(value.bits()) + } +} + +impl StaticType for AudioFormatFlags { + fn static_type() -> Type { + unsafe { from_glib(ffi::gst_audio_format_flags_get_type()) } + } +} + +impl<'a> FromValueOptional<'a> for AudioFormatFlags { + unsafe fn from_value_optional(value: &Value) -> Option { + Some(FromValue::from_value(value)) + } +} + +impl<'a> FromValue<'a> for AudioFormatFlags { + unsafe fn from_value(value: &Value) -> Self { + from_glib(ffi::GstAudioFormatFlags::from_bits_truncate(gobject_ffi::g_value_get_flags(value.to_glib_none().0))) + } +} + +impl SetValue for AudioFormatFlags { + unsafe fn set_value(value: &mut Value, this: &Self) { + gobject_ffi::g_value_set_flags(value.to_glib_none_mut().0, this.to_glib().bits()) + } +} + +bitflags! { + pub struct AudioPackFlags: u32 { + const AUDIO_PACK_FLAG_NONE = 0; + const AUDIO_PACK_FLAG_TRUNCATE_RANGE = 1; + } +} + +#[doc(hidden)] +impl ToGlib for AudioPackFlags { + type GlibType = ffi::GstAudioPackFlags; + + fn to_glib(&self) -> ffi::GstAudioPackFlags { + ffi::GstAudioPackFlags::from_bits_truncate(self.bits()) + } +} + +#[doc(hidden)] +impl FromGlib for AudioPackFlags { + fn from_glib(value: ffi::GstAudioPackFlags) -> AudioPackFlags { + skip_assert_initialized!(); + AudioPackFlags::from_bits_truncate(value.bits()) + } +} + +impl StaticType for AudioPackFlags { + fn static_type() -> Type { + unsafe { from_glib(ffi::gst_audio_pack_flags_get_type()) } + } +} + +impl<'a> FromValueOptional<'a> for AudioPackFlags { + unsafe fn from_value_optional(value: &Value) -> Option { + Some(FromValue::from_value(value)) + } +} + +impl<'a> FromValue<'a> for AudioPackFlags { + unsafe fn from_value(value: &Value) -> Self { + from_glib(ffi::GstAudioPackFlags::from_bits_truncate(gobject_ffi::g_value_get_flags(value.to_glib_none().0))) + } +} + +impl SetValue for AudioPackFlags { + unsafe fn set_value(value: &mut Value, this: &Self) { + gobject_ffi::g_value_set_flags(value.to_glib_none_mut().0, this.to_glib().bits()) + } +} + diff --git a/gstreamer-audio/src/auto/mod.rs b/gstreamer-audio/src/auto/mod.rs new file mode 100644 index 000000000..c2d028b02 --- /dev/null +++ b/gstreamer-audio/src/auto/mod.rs @@ -0,0 +1,25 @@ +// This file was generated by gir (3294959+) from gir-files (???) +// DO NOT EDIT + +mod enums; +pub use self::enums::AudioChannelPosition; +pub use self::enums::AudioFormat; +pub use self::enums::AudioLayout; + +mod flags; +pub use self::flags::AudioFlags; +pub use self::flags::AUDIO_FLAG_NONE; +pub use self::flags::AUDIO_FLAG_UNPOSITIONED; +pub use self::flags::AudioFormatFlags; +pub use self::flags::AUDIO_FORMAT_FLAG_INTEGER; +pub use self::flags::AUDIO_FORMAT_FLAG_FLOAT; +pub use self::flags::AUDIO_FORMAT_FLAG_SIGNED; +pub use self::flags::AUDIO_FORMAT_FLAG_COMPLEX; +pub use self::flags::AUDIO_FORMAT_FLAG_UNPACK; +pub use self::flags::AudioPackFlags; +pub use self::flags::AUDIO_PACK_FLAG_NONE; +pub use self::flags::AUDIO_PACK_FLAG_TRUNCATE_RANGE; + +#[doc(hidden)] +pub mod traits { +} diff --git a/gstreamer-audio/src/lib.rs b/gstreamer-audio/src/lib.rs new file mode 100644 index 000000000..fc10fc7e9 --- /dev/null +++ b/gstreamer-audio/src/lib.rs @@ -0,0 +1,48 @@ +// Copyright (C) 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. + +#[macro_use] +extern crate bitflags; +extern crate libc; +#[macro_use] +extern crate lazy_static; + +extern crate glib_sys as glib_ffi; +extern crate gobject_sys as gobject_ffi; +extern crate gstreamer_sys as gst_ffi; +extern crate gstreamer_audio_sys as ffi; +extern crate gstreamer as gst; + +#[macro_use] +extern crate glib; + +macro_rules! callback_guard { + () => ( + let _guard = ::glib::CallbackGuard::new(); + ) +} + +macro_rules! skip_assert_initialized { + () => ( + ) +} + +pub use glib::{Cast, Continue, Error, IsA, StaticType, ToValue, Type, TypedValue, Value}; + +#[cfg_attr(feature = "cargo-clippy", allow(unreadable_literal))] +#[cfg_attr(feature = "cargo-clippy", allow(transmute_ptr_to_ref))] +#[cfg_attr(feature = "cargo-clippy", allow(too_many_arguments))] +#[cfg_attr(feature = "cargo-clippy", allow(match_same_arms))] +mod auto; +pub use auto::*; +pub use auto::traits::*; + +mod audio_format_info; +pub use audio_format_info::*; +mod audio_info; +pub use audio_info::*; diff --git a/gstreamer/src/segment.rs b/gstreamer/src/segment.rs index 77013c2fc..e6ce8cf21 100644 --- a/gstreamer/src/segment.rs +++ b/gstreamer/src/segment.rs @@ -206,6 +206,8 @@ impl Segment { (ret, stream_time) } } + + // TODO getter/setter } impl PartialEq for Segment {