Commit c8910aae authored by Sebastian Dröge's avatar Sebastian Dröge 🍵

Initial gstreamer-audio bindings

Only wrapping AudioInfo and AudioFormatInfo and related for now.

https://github.com/sdroege/gstreamer-rs/issues/4
parent 146b3092
[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)" = "<none>"
"checksum gobject-sys 0.3.4 (git+https://github.com/gtk-rs/sys)" = "<none>"
"checksum gstreamer-app-sys 0.1.1 (git+https://github.com/sdroege/gstreamer-sys)" = "<none>"
"checksum gstreamer-audio-sys 0.1.1 (git+https://github.com/sdroege/gstreamer-sys)" = "<none>"
"checksum gstreamer-base-sys 0.1.1 (git+https://github.com/sdroege/gstreamer-sys)" = "<none>"
"checksum gstreamer-sys 0.1.1 (git+https://github.com/sdroege/gstreamer-sys)" = "<none>"
"checksum gstreamer-tag-sys 0.1.1 (git+https://github.com/sdroege/gstreamer-sys)" = "<none>"
"checksum gtk 0.1.3 (git+https://github.com/gtk-rs/gtk)" = "<none>"
"checksum gtk-sys 0.3.4 (git+https://github.com/gtk-rs/sys)" = "<none>"
"checksum iovec 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "29d062ee61fccdf25be172e70f34c9f6efc597e1fb8f6526e8437b2046ab26be"
......
......@@ -3,5 +3,6 @@
members = [
"gstreamer",
"gstreamer-app",
"gstreamer-audio",
"examples",
]
[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"
This diff is collapsed.
[package]
name = "gstreamer-audio"
version = "0.1.0"
authors = ["Sebastian Dröge <sebastian@centricular.com>"]
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 = []
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() {}
This diff is collapsed.
// Copyright (C) 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 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<AudioInfo> {
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<Self> {
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<gst::Caps> {
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<i64> {
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);
}
}
This diff is collapsed.
// 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<ffi::GstAudioFlags> 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<Self> {
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<ffi::GstAudioFormatFlags> 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<Self> {
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<ffi::GstAudioPackFlags> 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<Self> {
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())
}
}
// 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 {
}
// Copyright (C) 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.
#[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::*;
......@@ -206,6 +206,8 @@ impl Segment {
(ret, stream_time)
}