diff --git a/Cargo.toml b/Cargo.toml index f5f5df086..75f03e52c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,4 +17,5 @@ members = [ "gstreamer-webrtc-sys", "gstreamer-gl-sys", "gstreamer-editing-services-sys", + "gstreamer-check-sys", ] diff --git a/Gir_GstCheck.toml b/Gir_GstCheck.toml new file mode 100644 index 000000000..9f6cb093d --- /dev/null +++ b/Gir_GstCheck.toml @@ -0,0 +1,18 @@ +[options] +girs_dir = "gir-files" +library = "GstCheck" +version = "1.0" +min_cfg_version = "1.0" +target_path = "gstreamer-check-sys" +work_mode = "sys" + +ignore = [ +] + +external_libraries = [ + "GLib", + "GObject", +] + +[external_libraries] +gstreamer="Gst" diff --git a/gstreamer-check-sys/CHANGELOG.md b/gstreamer-check-sys/CHANGELOG.md new file mode 100644 index 000000000..e7f22619e --- /dev/null +++ b/gstreamer-check-sys/CHANGELOG.md @@ -0,0 +1,110 @@ +# Changelog +All notable changes to this project will be documented in this file. + +The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) +and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html), +specifically the [variant used by Rust](http://doc.crates.io/manifest.html#the-version-field). + +## [0.6.0] - 2018-09-08 +### Changed +- Updated everything to GStreamer 1.14.2 +- Various fixes to how the code generator is used +- Regenerate with latest GIR code generator + +### Fixed +- WebRTCICETransport and WebRTCDTLSTransport have the correct parent class + struct +- gstreamer-webrtc-sys correctly depends/links to gstreamer-sys +- Removed unneeded dependencies from the code generator configuration files + +## [0.5.0] - 2018-03-20 +### Changed +- Updated everything to GStreamer 1.14.0 + +### Added +- GstSdp, GstRtsp, GstRtspServer and GstWebRTC bindings + +### Fixed +- Use external_libraries feature of gir to require less manual editing +- Remove some unused crates from dependencies +- Disale print_system_libs in calls to pkg-config to work better with + non-system installs of GStreamer + +## [0.4.1] - 2018-02-18 +### Fixed +- Fix native library name of GstNet bindings + +## [0.4.0] - 2017-12-23 +### Added +- GstNet bindings +- Debug impls for basically every type +- Script to automatically regenerate everything + +### Changed +- gst_player_[sg]et_multiview_mode() argument types were changed from + GstMultiviewMode to GstMultiviewFramePacking, which is the correct subset + of the former that is allowed here +- gst_plugin_add_dependency() takes *mut *mut c_char as argument type instead + of *mut *const c_char + +## [0.3.0] - 2017-11-26 +### Added +- GstMpegTs bindings + +### Changed +- GstDebugColorFlags from an enum to a bitfield +- Updated to bitflags 1.0 +- Added support for the "dox" feature to generate documentation for all + possible versions +- Depend on glib-sys/gobject-sys 0.5 + +### Fixes +- GstStackTraceFlags, gst_flow_combiner_ref/unref are only available since + 1.12 and 1.12.1 respectively +- All C enums are represented as integers + constants now to prevent undefined + behaviour when out-of-range values are received + +## [0.2.1] - 2017-09-10 +### Changed +- Add README.md to all crates directly + +### Fixed +- Fix various compiler warnings +- Fix versioning/feature mess. Now each library has features for all major + versions and for the correct minor versions that added API. +- Removed Cargo.lock from GIT + +## [0.2.0] - 2017-08-28 +### Added +- Add GstPlayer bindings + +### Changed +- Depend on bitflags 0.9 +- Update GIR files to 1.12.1 release +- Fix various errors in the GIR files, backported from GStreamer GIT master +- Depend on gobject-sys/glib-sys 0.4.0 for various improvements +- Regenerated everything with latest GIR + +## [0.1.1] - 2017-05-10 +### Added +- Add GstTag and GstApp bindings +- Add lots of missing fields to all the structs thanks to GIR improvements + +### Changed +- Update GIR files to 1.12.0 release +- Depend on gobject-sys/glib-sys 0.3.4 release for more complete structs +- Regenerated everything with latest GIR + +## [0.1.0] - 2017-04-09 + +- Initial release of the autogenerated GStreamer FFI bindings. + +[Unreleased]: https://github.com/sdroege/gstreamer-sys/compare/0.6.0...HEAD +[0.6.0]: https://github.com/sdroege/gstreamer-sys/compare/0.5.0...0.6.0 +[0.5.0]: https://github.com/sdroege/gstreamer-sys/compare/0.4.1...0.5.0 +[0.4.1]: https://github.com/sdroege/gstreamer-sys/compare/0.4.0...0.4.1 +[0.4.0]: https://github.com/sdroege/gstreamer-sys/compare/0.3.0...0.4.0 +[0.3.0]: https://github.com/sdroege/gstreamer-sys/compare/0.2.1...0.3.0 +[0.2.1]: https://github.com/sdroege/gstreamer-sys/compare/0.2.0...0.2.1 +[0.2.0]: https://github.com/sdroege/gstreamer-sys/compare/0.1.1...0.2.0 +[0.1.1]: https://github.com/sdroege/gstreamer-sys/compare/0.1.0...0.1.1 diff --git a/gstreamer-check-sys/Cargo.toml b/gstreamer-check-sys/Cargo.toml new file mode 100644 index 000000000..6be40c992 --- /dev/null +++ b/gstreamer-check-sys/Cargo.toml @@ -0,0 +1,49 @@ +[badges.travis-ci] +branch = "master" +repository = "sdroege/gstreamer-sys" + +[build-dependencies] +pkg-config = "0.3.7" + +[dependencies] +libc = "0.2" + +[dependencies.glib-sys] +git = "https://github.com/gtk-rs/sys" + +[dependencies.gobject-sys] +git = "https://github.com/gtk-rs/sys" + +[dependencies.gstreamer-sys] +path = "../gstreamer-sys" + +[dev-dependencies] +shell-words = "0.1.0" +tempdir = "0.3" + +[features] +dox = [] +v1_10 = ["v1_8"] +v1_12 = ["v1_10"] +v1_14 = ["v1_12"] +#v1_16 = ["v1_14"] +v1_2 = [] +v1_4 = ["v1_2"] +v1_6 = ["v1_4"] +v1_8 = ["v1_6"] + +[lib] +name = "gstreamer_check_sys" + +[package] +authors = ["Sebastian Dröge "] +build = "build.rs" +description = "FFI bindings to libgstcheck-1.0" +homepage = "https://gstreamer.freedesktop.org" +keywords = ["ffi", "gstreamer", "gnome", "multimedia"] +license = "MIT" +links = "gstreamer-check-1.0" +name = "gstreamer-check-sys" +readme = "README.md" +repository = "https://github.com/sdroege/gstreamer-sys" +version = "0.7.0" diff --git a/gstreamer-check-sys/LICENSE b/gstreamer-check-sys/LICENSE new file mode 100644 index 000000000..3d76f6e2f --- /dev/null +++ b/gstreamer-check-sys/LICENSE @@ -0,0 +1,23 @@ +The MIT License (MIT) + +Copyright (c) 2017 Sebastian Dröge . + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + diff --git a/gstreamer-check-sys/README.md b/gstreamer-check-sys/README.md new file mode 100644 index 000000000..962822b96 --- /dev/null +++ b/gstreamer-check-sys/README.md @@ -0,0 +1,31 @@ +# gstreamer-sys [![crates.io](https://img.shields.io/crates/v/gstreamer-sys.svg)](https://crates.io/crates/gstreamer-sys) [![Build Status](https://travis-ci.org/sdroege/gstreamer-sys.svg?branch=master)](https://travis-ci.org/sdroege/gstreamer-sys) + +[GStreamer](https://gstreamer.freedesktop.org/) (Check library) FFI bindings for Rust. + +These bindings are providing unsafe FFI API that can be used to interface with +GStreamer. Generally they are meant to be used as the building block for +higher-level abstractions like: + + * Application-side bindings for GStreamer: https://github.com/sdroege/gstreamer-rs + * Crate for writing GStreamer plugins in Rust: https://github.com/sdroege/gst-plugin-rs + +The bindings are autogenerated with [gir](https://github.com/gtk-rs/gir/) +based on the [GObject-Introspection](https://wiki.gnome.org/Projects/GObjectIntrospection/) +API metadata provided by the GStreamer project. + +## LICENSE + +gstreamer-sys and all crates contained here are licensed under the MIT +license ([LICENSE](LICENSE) or http://opensource.org/licenses/MIT). + +GStreamer itself is licensed under the Lesser General Public License version +2.1 or (at your option) any later version: +https://www.gnu.org/licenses/lgpl-2.1.html + +## Contribution + +Any kinds of contributions are welcome as a pull request. + +Unless you explicitly state otherwise, any contribution intentionally submitted +for inclusion in gstreamer-rs by you shall be licensed under the MIT license as above, +without any additional terms or conditions. diff --git a/gstreamer-check-sys/build.rs b/gstreamer-check-sys/build.rs new file mode 100644 index 000000000..9c6e227c6 --- /dev/null +++ b/gstreamer-check-sys/build.rs @@ -0,0 +1,78 @@ +extern crate pkg_config; + +use pkg_config::{Config, Error}; +use std::env; +use std::io::prelude::*; +use std::io; +use std::process; + +fn main() { + if let Err(s) = find() { + let _ = writeln!(io::stderr(), "{}", s); + process::exit(1); + } +} + +fn find() -> Result<(), Error> { + let package_name = "gstreamer-check-1.0"; + let shared_libs = ["gstcheck-1.0"]; + let version = if cfg!(feature = "v1_16") { + "1.16" + } else if cfg!(feature = "v1_14") { + "1.14" + } else if cfg!(feature = "v1_12") { + "1.12" + } else if cfg!(feature = "v1_10") { + "1.10" + } else if cfg!(feature = "v1_8") { + "1.8" + } else if cfg!(feature = "v1_6") { + "1.6" + } else if cfg!(feature = "v1_4") { + "1.4" + } else if cfg!(feature = "v1_2") { + "1.2" + } else { + "1.0" + }; + + if let Ok(lib_dir) = env::var("GTK_LIB_DIR") { + for lib_ in shared_libs.iter() { + println!("cargo:rustc-link-lib=dylib={}", lib_); + } + println!("cargo:rustc-link-search=native={}", lib_dir); + return Ok(()) + } + + let target = env::var("TARGET").expect("TARGET environment variable doesn't exist"); + let hardcode_shared_libs = target.contains("windows"); + + let mut config = Config::new(); + config.atleast_version(version); + config.print_system_libs(false); + if hardcode_shared_libs { + config.cargo_metadata(false); + } + match config.probe(package_name) { + Ok(library) => { + if hardcode_shared_libs { + for lib_ in shared_libs.iter() { + println!("cargo:rustc-link-lib=dylib={}", lib_); + } + for path in library.link_paths.iter() { + println!("cargo:rustc-link-search=native={}", + path.to_str().expect("library path doesn't exist")); + } + } + Ok(()) + } + Err(Error::EnvNoPkgConfig(_)) | Err(Error::Command { .. }) => { + for lib_ in shared_libs.iter() { + println!("cargo:rustc-link-lib=dylib={}", lib_); + } + Ok(()) + } + Err(err) => Err(err), + } +} + diff --git a/gstreamer-check-sys/src/lib.rs b/gstreamer-check-sys/src/lib.rs new file mode 100644 index 000000000..43ecd1c36 --- /dev/null +++ b/gstreamer-check-sys/src/lib.rs @@ -0,0 +1,332 @@ +// This file was generated by gir (https://github.com/gtk-rs/gir @ 82cdb44) +// from gir-files (https://github.com/gtk-rs/gir-files @ ???) +// DO NOT EDIT + +#![allow(non_camel_case_types, non_upper_case_globals, non_snake_case)] +#![cfg_attr(feature = "cargo-clippy", allow(approx_constant, type_complexity, unreadable_literal))] + +extern crate libc; +extern crate glib_sys as glib; +extern crate gobject_sys as gobject; +extern crate gstreamer_sys as gst; + +#[allow(unused_imports)] +use libc::{c_int, c_char, c_uchar, c_float, c_uint, c_double, + c_short, c_ushort, c_long, c_ulong, + c_void, size_t, ssize_t, intptr_t, uintptr_t, time_t, FILE}; + +#[allow(unused_imports)] +use glib::{gboolean, gconstpointer, gpointer, GType}; + +// Callbacks +pub type GstHarnessPrepareBufferFunc = Option *mut gst::GstBuffer>; +pub type GstHarnessPrepareEventFunc = Option *mut gst::GstEvent>; + +// Records +#[repr(C)] +#[derive(Copy, Clone)] +pub struct GstHarness { + pub element: *mut gst::GstElement, + pub srcpad: *mut gst::GstPad, + pub sinkpad: *mut gst::GstPad, + pub src_harness: *mut GstHarness, + pub sink_harness: *mut GstHarness, + pub priv_: *mut GstHarnessPrivate, +} + +impl ::std::fmt::Debug for GstHarness { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + f.debug_struct(&format!("GstHarness @ {:?}", self as *const _)) + .field("element", &self.element) + .field("srcpad", &self.srcpad) + .field("sinkpad", &self.sinkpad) + .field("src_harness", &self.src_harness) + .field("sink_harness", &self.sink_harness) + .finish() + } +} + +#[repr(C)] +pub struct GstHarnessPrivate(c_void); + +impl ::std::fmt::Debug for GstHarnessPrivate { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + f.debug_struct(&format!("GstHarnessPrivate @ {:?}", self as *const _)) + .finish() + } +} + +#[repr(C)] +pub struct GstHarnessThread(c_void); + +impl ::std::fmt::Debug for GstHarnessThread { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + f.debug_struct(&format!("GstHarnessThread @ {:?}", self as *const _)) + .finish() + } +} + +#[repr(C)] +pub struct GstStreamConsistency(c_void); + +impl ::std::fmt::Debug for GstStreamConsistency { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + f.debug_struct(&format!("GstStreamConsistency @ {:?}", self as *const _)) + .finish() + } +} + +#[repr(C)] +#[derive(Copy, Clone)] +pub struct GstTestClockClass { + pub parent_class: gst::GstClockClass, +} + +impl ::std::fmt::Debug for GstTestClockClass { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + f.debug_struct(&format!("GstTestClockClass @ {:?}", self as *const _)) + .field("parent_class", &self.parent_class) + .finish() + } +} + +#[repr(C)] +pub struct GstTestClockPrivate(c_void); + +impl ::std::fmt::Debug for GstTestClockPrivate { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + f.debug_struct(&format!("GstTestClockPrivate @ {:?}", self as *const _)) + .finish() + } +} + +// Classes +#[repr(C)] +#[derive(Copy, Clone)] +pub struct GstTestClock { + pub parent: gst::GstClock, + pub priv_: *mut GstTestClockPrivate, +} + +impl ::std::fmt::Debug for GstTestClock { + fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result { + f.debug_struct(&format!("GstTestClock @ {:?}", self as *const _)) + .field("parent", &self.parent) + .finish() + } +} + +extern "C" { + + //========================================================================= + // GstHarness + //========================================================================= + #[cfg(any(feature = "v1_6", feature = "dox"))] + pub fn gst_harness_add_element_full(h: *mut GstHarness, element: *mut gst::GstElement, hsrc: *mut gst::GstStaticPadTemplate, element_sinkpad_name: *const c_char, hsink: *mut gst::GstStaticPadTemplate, element_srcpad_name: *const c_char); + #[cfg(any(feature = "v1_6", feature = "dox"))] + pub fn gst_harness_add_element_sink_pad(h: *mut GstHarness, sinkpad: *mut gst::GstPad); + #[cfg(any(feature = "v1_6", feature = "dox"))] + pub fn gst_harness_add_element_src_pad(h: *mut GstHarness, srcpad: *mut gst::GstPad); + #[cfg(any(feature = "v1_6", feature = "dox"))] + pub fn gst_harness_add_parse(h: *mut GstHarness, launchline: *const c_char); + #[cfg(any(feature = "v1_6", feature = "dox"))] + pub fn gst_harness_add_probe(h: *mut GstHarness, element_name: *const c_char, pad_name: *const c_char, mask: gst::GstPadProbeType, callback: gst::GstPadProbeCallback, user_data: gpointer, destroy_data: glib::GDestroyNotify); + #[cfg(any(feature = "v1_16", feature = "dox"))] + pub fn gst_harness_add_propose_allocation_meta(h: *mut GstHarness, api: GType, params: *const gst::GstStructure); + #[cfg(any(feature = "v1_6", feature = "dox"))] + pub fn gst_harness_add_sink(h: *mut GstHarness, sink_element_name: *const c_char); + #[cfg(any(feature = "v1_6", feature = "dox"))] + pub fn gst_harness_add_sink_harness(h: *mut GstHarness, sink_harness: *mut GstHarness); + #[cfg(any(feature = "v1_6", feature = "dox"))] + pub fn gst_harness_add_sink_parse(h: *mut GstHarness, launchline: *const c_char); + #[cfg(any(feature = "v1_6", feature = "dox"))] + pub fn gst_harness_add_src(h: *mut GstHarness, src_element_name: *const c_char, has_clock_wait: gboolean); + #[cfg(any(feature = "v1_6", feature = "dox"))] + pub fn gst_harness_add_src_harness(h: *mut GstHarness, src_harness: *mut GstHarness, has_clock_wait: gboolean); + #[cfg(any(feature = "v1_6", feature = "dox"))] + pub fn gst_harness_add_src_parse(h: *mut GstHarness, launchline: *const c_char, has_clock_wait: gboolean); + #[cfg(any(feature = "v1_6", feature = "dox"))] + pub fn gst_harness_buffers_in_queue(h: *mut GstHarness) -> c_uint; + #[cfg(any(feature = "v1_6", feature = "dox"))] + pub fn gst_harness_buffers_received(h: *mut GstHarness) -> c_uint; + #[cfg(any(feature = "v1_6", feature = "dox"))] + pub fn gst_harness_crank_multiple_clock_waits(h: *mut GstHarness, waits: c_uint) -> gboolean; + #[cfg(any(feature = "v1_6", feature = "dox"))] + pub fn gst_harness_crank_single_clock_wait(h: *mut GstHarness) -> gboolean; + #[cfg(any(feature = "v1_6", feature = "dox"))] + pub fn gst_harness_create_buffer(h: *mut GstHarness, size: size_t) -> *mut gst::GstBuffer; + #[cfg(any(feature = "v1_6", feature = "dox"))] + pub fn gst_harness_dump_to_file(h: *mut GstHarness, filename: *const c_char); + #[cfg(any(feature = "v1_6", feature = "dox"))] + pub fn gst_harness_events_in_queue(h: *mut GstHarness) -> c_uint; + #[cfg(any(feature = "v1_6", feature = "dox"))] + pub fn gst_harness_events_received(h: *mut GstHarness) -> c_uint; + #[cfg(any(feature = "v1_6", feature = "dox"))] + pub fn gst_harness_find_element(h: *mut GstHarness, element_name: *const c_char) -> *mut gst::GstElement; + #[cfg(any(feature = "v1_6", feature = "dox"))] + pub fn gst_harness_get(h: *mut GstHarness, element_name: *const c_char, first_property_name: *const c_char, ...); + #[cfg(any(feature = "v1_6", feature = "dox"))] + pub fn gst_harness_get_allocator(h: *mut GstHarness, allocator: *mut *mut gst::GstAllocator, params: *mut gst::GstAllocationParams); + #[cfg(any(feature = "v1_6", feature = "dox"))] + pub fn gst_harness_get_last_pushed_timestamp(h: *mut GstHarness) -> gst::GstClockTime; + #[cfg(any(feature = "v1_6", feature = "dox"))] + pub fn gst_harness_get_testclock(h: *mut GstHarness) -> *mut GstTestClock; + #[cfg(any(feature = "v1_6", feature = "dox"))] + pub fn gst_harness_play(h: *mut GstHarness); + #[cfg(any(feature = "v1_6", feature = "dox"))] + pub fn gst_harness_pull(h: *mut GstHarness) -> *mut gst::GstBuffer; + #[cfg(any(feature = "v1_6", feature = "dox"))] + pub fn gst_harness_pull_event(h: *mut GstHarness) -> *mut gst::GstEvent; + #[cfg(any(feature = "v1_6", feature = "dox"))] + pub fn gst_harness_pull_upstream_event(h: *mut GstHarness) -> *mut gst::GstEvent; + #[cfg(any(feature = "v1_6", feature = "dox"))] + pub fn gst_harness_push(h: *mut GstHarness, buffer: *mut gst::GstBuffer) -> gst::GstFlowReturn; + #[cfg(any(feature = "v1_6", feature = "dox"))] + pub fn gst_harness_push_and_pull(h: *mut GstHarness, buffer: *mut gst::GstBuffer) -> *mut gst::GstBuffer; + #[cfg(any(feature = "v1_6", feature = "dox"))] + pub fn gst_harness_push_event(h: *mut GstHarness, event: *mut gst::GstEvent) -> gboolean; + #[cfg(any(feature = "v1_6", feature = "dox"))] + pub fn gst_harness_push_from_src(h: *mut GstHarness) -> gst::GstFlowReturn; + #[cfg(any(feature = "v1_6", feature = "dox"))] + pub fn gst_harness_push_to_sink(h: *mut GstHarness) -> gst::GstFlowReturn; + #[cfg(any(feature = "v1_6", feature = "dox"))] + pub fn gst_harness_push_upstream_event(h: *mut GstHarness, event: *mut gst::GstEvent) -> gboolean; + #[cfg(any(feature = "v1_6", feature = "dox"))] + pub fn gst_harness_query_latency(h: *mut GstHarness) -> gst::GstClockTime; + #[cfg(any(feature = "v1_6", feature = "dox"))] + pub fn gst_harness_set(h: *mut GstHarness, element_name: *const c_char, first_property_name: *const c_char, ...); + #[cfg(any(feature = "v1_6", feature = "dox"))] + pub fn gst_harness_set_blocking_push_mode(h: *mut GstHarness); + #[cfg(any(feature = "v1_6", feature = "dox"))] + pub fn gst_harness_set_caps(h: *mut GstHarness, in_: *mut gst::GstCaps, out: *mut gst::GstCaps); + #[cfg(any(feature = "v1_6", feature = "dox"))] + pub fn gst_harness_set_caps_str(h: *mut GstHarness, in_: *const c_char, out: *const c_char); + #[cfg(any(feature = "v1_6", feature = "dox"))] + pub fn gst_harness_set_drop_buffers(h: *mut GstHarness, drop_buffers: gboolean); + #[cfg(any(feature = "v1_6", feature = "dox"))] + pub fn gst_harness_set_forwarding(h: *mut GstHarness, forwarding: gboolean); + #[cfg(any(feature = "v1_6", feature = "dox"))] + pub fn gst_harness_set_propose_allocator(h: *mut GstHarness, allocator: *mut gst::GstAllocator, params: *const gst::GstAllocationParams); + #[cfg(any(feature = "v1_6", feature = "dox"))] + pub fn gst_harness_set_sink_caps(h: *mut GstHarness, caps: *mut gst::GstCaps); + #[cfg(any(feature = "v1_6", feature = "dox"))] + pub fn gst_harness_set_sink_caps_str(h: *mut GstHarness, str: *const c_char); + #[cfg(any(feature = "v1_6", feature = "dox"))] + pub fn gst_harness_set_src_caps(h: *mut GstHarness, caps: *mut gst::GstCaps); + #[cfg(any(feature = "v1_6", feature = "dox"))] + pub fn gst_harness_set_src_caps_str(h: *mut GstHarness, str: *const c_char); + #[cfg(any(feature = "v1_6", feature = "dox"))] + pub fn gst_harness_set_time(h: *mut GstHarness, time: gst::GstClockTime) -> gboolean; + #[cfg(any(feature = "v1_6", feature = "dox"))] + pub fn gst_harness_set_upstream_latency(h: *mut GstHarness, latency: gst::GstClockTime); + #[cfg(any(feature = "v1_6", feature = "dox"))] + pub fn gst_harness_sink_push_many(h: *mut GstHarness, pushes: c_int) -> gst::GstFlowReturn; + #[cfg(any(feature = "v1_6", feature = "dox"))] + pub fn gst_harness_src_crank_and_push_many(h: *mut GstHarness, cranks: c_int, pushes: c_int) -> gst::GstFlowReturn; + #[cfg(any(feature = "v1_6", feature = "dox"))] + pub fn gst_harness_src_push_event(h: *mut GstHarness) -> gboolean; + #[cfg(any(feature = "v1_6", feature = "dox"))] + pub fn gst_harness_stress_custom_start(h: *mut GstHarness, init: glib::GFunc, callback: glib::GFunc, data: gpointer, sleep: c_ulong) -> *mut GstHarnessThread; + #[cfg(any(feature = "v1_6", feature = "dox"))] + pub fn gst_harness_stress_property_start_full(h: *mut GstHarness, name: *const c_char, value: *const gobject::GValue, sleep: c_ulong) -> *mut GstHarnessThread; + #[cfg(any(feature = "v1_6", feature = "dox"))] + pub fn gst_harness_stress_push_buffer_start_full(h: *mut GstHarness, caps: *mut gst::GstCaps, segment: *const gst::GstSegment, buf: *mut gst::GstBuffer, sleep: c_ulong) -> *mut GstHarnessThread; + #[cfg(any(feature = "v1_6", feature = "dox"))] + pub fn gst_harness_stress_push_buffer_with_cb_start_full(h: *mut GstHarness, caps: *mut gst::GstCaps, segment: *const gst::GstSegment, func: GstHarnessPrepareBufferFunc, data: gpointer, notify: glib::GDestroyNotify, sleep: c_ulong) -> *mut GstHarnessThread; + #[cfg(any(feature = "v1_6", feature = "dox"))] + pub fn gst_harness_stress_push_event_start_full(h: *mut GstHarness, event: *mut gst::GstEvent, sleep: c_ulong) -> *mut GstHarnessThread; + #[cfg(any(feature = "v1_8", feature = "dox"))] + pub fn gst_harness_stress_push_event_with_cb_start_full(h: *mut GstHarness, func: GstHarnessPrepareEventFunc, data: gpointer, notify: glib::GDestroyNotify, sleep: c_ulong) -> *mut GstHarnessThread; + #[cfg(any(feature = "v1_6", feature = "dox"))] + pub fn gst_harness_stress_push_upstream_event_start_full(h: *mut GstHarness, event: *mut gst::GstEvent, sleep: c_ulong) -> *mut GstHarnessThread; + #[cfg(any(feature = "v1_8", feature = "dox"))] + pub fn gst_harness_stress_push_upstream_event_with_cb_start_full(h: *mut GstHarness, func: GstHarnessPrepareEventFunc, data: gpointer, notify: glib::GDestroyNotify, sleep: c_ulong) -> *mut GstHarnessThread; + #[cfg(any(feature = "v1_6", feature = "dox"))] + pub fn gst_harness_stress_requestpad_start_full(h: *mut GstHarness, templ: *mut gst::GstPadTemplate, name: *const c_char, caps: *mut gst::GstCaps, release: gboolean, sleep: c_ulong) -> *mut GstHarnessThread; + #[cfg(any(feature = "v1_6", feature = "dox"))] + pub fn gst_harness_stress_statechange_start_full(h: *mut GstHarness, sleep: c_ulong) -> *mut GstHarnessThread; + #[cfg(any(feature = "v1_14", feature = "dox"))] + pub fn gst_harness_take_all_data(h: *mut GstHarness, size: *mut size_t) -> *mut u8; + #[cfg(any(feature = "v1_14", feature = "dox"))] + pub fn gst_harness_take_all_data_as_buffer(h: *mut GstHarness) -> *mut gst::GstBuffer; + #[cfg(any(feature = "v1_14", feature = "dox"))] + pub fn gst_harness_take_all_data_as_bytes(h: *mut GstHarness) -> *mut glib::GBytes; + #[cfg(any(feature = "v1_6", feature = "dox"))] + pub fn gst_harness_teardown(h: *mut GstHarness); + #[cfg(any(feature = "v1_6", feature = "dox"))] + pub fn gst_harness_try_pull(h: *mut GstHarness) -> *mut gst::GstBuffer; + #[cfg(any(feature = "v1_6", feature = "dox"))] + pub fn gst_harness_try_pull_event(h: *mut GstHarness) -> *mut gst::GstEvent; + #[cfg(any(feature = "v1_6", feature = "dox"))] + pub fn gst_harness_try_pull_upstream_event(h: *mut GstHarness) -> *mut gst::GstEvent; + #[cfg(any(feature = "v1_6", feature = "dox"))] + pub fn gst_harness_upstream_events_in_queue(h: *mut GstHarness) -> c_uint; + #[cfg(any(feature = "v1_6", feature = "dox"))] + pub fn gst_harness_upstream_events_received(h: *mut GstHarness) -> c_uint; + #[cfg(any(feature = "v1_6", feature = "dox"))] + pub fn gst_harness_use_systemclock(h: *mut GstHarness); + #[cfg(any(feature = "v1_6", feature = "dox"))] + pub fn gst_harness_use_testclock(h: *mut GstHarness); + #[cfg(any(feature = "v1_6", feature = "dox"))] + pub fn gst_harness_wait_for_clock_id_waits(h: *mut GstHarness, waits: c_uint, timeout: c_uint) -> gboolean; + #[cfg(any(feature = "v1_6", feature = "dox"))] + pub fn gst_harness_new(element_name: *const c_char) -> *mut GstHarness; + #[cfg(any(feature = "v1_8", feature = "dox"))] + pub fn gst_harness_new_empty() -> *mut GstHarness; + #[cfg(any(feature = "v1_6", feature = "dox"))] + pub fn gst_harness_new_full(element: *mut gst::GstElement, hsrc: *mut gst::GstStaticPadTemplate, element_sinkpad_name: *const c_char, hsink: *mut gst::GstStaticPadTemplate, element_srcpad_name: *const c_char) -> *mut GstHarness; + #[cfg(any(feature = "v1_6", feature = "dox"))] + pub fn gst_harness_new_parse(launchline: *const c_char) -> *mut GstHarness; + #[cfg(any(feature = "v1_6", feature = "dox"))] + pub fn gst_harness_new_with_element(element: *mut gst::GstElement, element_sinkpad_name: *const c_char, element_srcpad_name: *const c_char) -> *mut GstHarness; + #[cfg(any(feature = "v1_6", feature = "dox"))] + pub fn gst_harness_new_with_padnames(element_name: *const c_char, element_sinkpad_name: *const c_char, element_srcpad_name: *const c_char) -> *mut GstHarness; + #[cfg(any(feature = "v1_6", feature = "dox"))] + pub fn gst_harness_new_with_templates(element_name: *const c_char, hsrc: *mut gst::GstStaticPadTemplate, hsink: *mut gst::GstStaticPadTemplate) -> *mut GstHarness; + #[cfg(any(feature = "v1_6", feature = "dox"))] + pub fn gst_harness_stress_thread_stop(t: *mut GstHarnessThread) -> c_uint; + + //========================================================================= + // GstTestClock + //========================================================================= + pub fn gst_test_clock_get_type() -> GType; + #[cfg(any(feature = "v1_2", feature = "dox"))] + pub fn gst_test_clock_new() -> *mut gst::GstClock; + #[cfg(any(feature = "v1_2", feature = "dox"))] + pub fn gst_test_clock_new_with_start_time(start_time: gst::GstClockTime) -> *mut gst::GstClock; + #[cfg(any(feature = "v1_4", feature = "dox"))] + pub fn gst_test_clock_id_list_get_latest_time(pending_list: *const glib::GList) -> gst::GstClockTime; + #[cfg(any(feature = "v1_2", feature = "dox"))] + pub fn gst_test_clock_advance_time(test_clock: *mut GstTestClock, delta: gst::GstClockTimeDiff); + #[cfg(any(feature = "v1_8", feature = "dox"))] + pub fn gst_test_clock_crank(test_clock: *mut GstTestClock) -> gboolean; + #[cfg(any(feature = "v1_2", feature = "dox"))] + pub fn gst_test_clock_get_next_entry_time(test_clock: *mut GstTestClock) -> gst::GstClockTime; + #[cfg(any(feature = "v1_2", feature = "dox"))] + pub fn gst_test_clock_has_id(test_clock: *mut GstTestClock, id: gst::GstClockID) -> gboolean; + #[cfg(any(feature = "v1_2", feature = "dox"))] + pub fn gst_test_clock_peek_id_count(test_clock: *mut GstTestClock) -> c_uint; + #[cfg(any(feature = "v1_2", feature = "dox"))] + pub fn gst_test_clock_peek_next_pending_id(test_clock: *mut GstTestClock, pending_id: *mut gst::GstClockID) -> gboolean; + #[cfg(any(feature = "v1_4", feature = "dox"))] + pub fn gst_test_clock_process_id_list(test_clock: *mut GstTestClock, pending_list: *const glib::GList) -> c_uint; + #[cfg(any(feature = "v1_2", feature = "dox"))] + pub fn gst_test_clock_process_next_clock_id(test_clock: *mut GstTestClock) -> gst::GstClockID; + #[cfg(any(feature = "v1_2", feature = "dox"))] + pub fn gst_test_clock_set_time(test_clock: *mut GstTestClock, new_time: gst::GstClockTime); + #[cfg(any(feature = "v1_4", feature = "dox"))] + pub fn gst_test_clock_wait_for_multiple_pending_ids(test_clock: *mut GstTestClock, count: c_uint, pending_list: *mut *mut glib::GList); + #[cfg(any(feature = "v1_2", feature = "dox"))] + pub fn gst_test_clock_wait_for_next_pending_id(test_clock: *mut GstTestClock, pending_id: *mut gst::GstClockID); + #[cfg(any(feature = "v1_2", feature = "dox"))] + pub fn gst_test_clock_wait_for_pending_id_count(test_clock: *mut GstTestClock, count: c_uint); + + //========================================================================= + // Other functions + //========================================================================= + pub fn gst_consistency_checker_add_pad(consist: *mut GstStreamConsistency, pad: *mut gst::GstPad) -> gboolean; + pub fn gst_consistency_checker_free(consist: *mut GstStreamConsistency); + pub fn gst_consistency_checker_new(pad: *mut gst::GstPad) -> *mut GstStreamConsistency; + pub fn gst_consistency_checker_reset(consist: *mut GstStreamConsistency); + +} diff --git a/gstreamer-check-sys/tests/abi.rs b/gstreamer-check-sys/tests/abi.rs new file mode 100644 index 000000000..b3ab4f5f8 --- /dev/null +++ b/gstreamer-check-sys/tests/abi.rs @@ -0,0 +1,242 @@ +// This file was generated by gir (https://github.com/gtk-rs/gir @ 82cdb44) +// from gir-files (https://github.com/gtk-rs/gir-files @ ???) +// DO NOT EDIT + +extern crate gstreamer_check_sys; +extern crate shell_words; +extern crate tempdir; +use std::env; +use std::error::Error; +use std::path::Path; +use std::mem::{align_of, size_of}; +use std::process::Command; +use std::str; +use gstreamer_check_sys::*; + +static PACKAGES: &[&str] = &["gstreamer-check-1.0"]; + +#[derive(Clone, Debug)] +struct Compiler { + pub args: Vec, +} + +impl Compiler { + pub fn new() -> Result> { + let mut args = get_var("CC", "cc")?; + args.push("-Wno-deprecated-declarations".to_owned()); + // For %z support in printf when using MinGW. + args.push("-D__USE_MINGW_ANSI_STDIO".to_owned()); + args.extend(get_var("CFLAGS", "")?); + args.extend(get_var("CPPFLAGS", "")?); + args.extend(pkg_config_cflags(PACKAGES)?); + Ok(Compiler { args }) + } + + pub fn define<'a, V: Into>>(&mut self, var: &str, val: V) { + let arg = match val.into() { + None => format!("-D{}", var), + Some(val) => format!("-D{}={}", var, val), + }; + self.args.push(arg); + } + + pub fn compile(&self, src: &Path, out: &Path) -> Result<(), Box> { + let mut cmd = self.to_command(); + cmd.arg(src); + cmd.arg("-o"); + cmd.arg(out); + let status = cmd.spawn()?.wait()?; + if !status.success() { + return Err(format!("compilation command {:?} failed, {}", + &cmd, status).into()); + } + Ok(()) + } + + fn to_command(&self) -> Command { + let mut cmd = Command::new(&self.args[0]); + cmd.args(&self.args[1..]); + cmd + } +} + +fn get_var(name: &str, default: &str) -> Result, Box> { + match env::var(name) { + Ok(value) => Ok(shell_words::split(&value)?), + Err(env::VarError::NotPresent) => Ok(shell_words::split(default)?), + Err(err) => Err(format!("{} {}", name, err).into()), + } +} + +fn pkg_config_cflags(packages: &[&str]) -> Result, Box> { + if packages.is_empty() { + return Ok(Vec::new()); + } + let mut cmd = Command::new("pkg-config"); + cmd.arg("--cflags"); + cmd.args(packages); + let out = cmd.output()?; + if !out.status.success() { + return Err(format!("command {:?} returned {}", + &cmd, out.status).into()); + } + let stdout = str::from_utf8(&out.stdout)?; + Ok(shell_words::split(stdout.trim())?) +} + + +#[derive(Copy, Clone, Debug, Eq, PartialEq)] +struct Layout { + size: usize, + alignment: usize, +} + +#[derive(Copy, Clone, Debug, Default, Eq, PartialEq)] +struct Results { + /// Number of successfully completed tests. + passed: usize, + /// Total number of failed tests (including those that failed to compile). + failed: usize, + /// Number of tests that failed to compile. + failed_to_compile: usize, +} + +impl Results { + fn record_passed(&mut self) { + self.passed += 1; + } + fn record_failed(&mut self) { + self.failed += 1; + } + fn record_failed_to_compile(&mut self) { + self.failed += 1; + self.failed_to_compile += 1; + } + fn summary(&self) -> String { + format!( + "{} passed; {} failed (compilation errors: {})", + self.passed, + self.failed, + self.failed_to_compile) + } + fn expect_total_success(&self) { + if self.failed == 0 { + println!("OK: {}", self.summary()); + } else { + panic!("FAILED: {}", self.summary()); + }; + } +} + +#[test] +fn cross_validate_constants_with_c() { + let tmpdir = tempdir::TempDir::new("abi").expect("temporary directory"); + let cc = Compiler::new().expect("configured compiler"); + + assert_eq!("1", + get_c_value(tmpdir.path(), &cc, "1").expect("C constant"), + "failed to obtain correct constant value for 1"); + + let mut results : Results = Default::default(); + for (i, &(name, rust_value)) in RUST_CONSTANTS.iter().enumerate() { + match get_c_value(tmpdir.path(), &cc, name) { + Err(e) => { + results.record_failed_to_compile(); + eprintln!("{}", e); + }, + Ok(ref c_value) => { + if rust_value == c_value { + results.record_passed(); + } else { + results.record_failed(); + eprintln!("Constant value mismatch for {}\nRust: {:?}\nC: {:?}", + name, rust_value, c_value); + } + } + }; + if (i + 1) % 25 == 0 { + println!("constants ... {}", results.summary()); + } + } + results.expect_total_success(); +} + +#[test] +fn cross_validate_layout_with_c() { + let tmpdir = tempdir::TempDir::new("abi").expect("temporary directory"); + let cc = Compiler::new().expect("configured compiler"); + + assert_eq!(Layout {size: 1, alignment: 1}, + get_c_layout(tmpdir.path(), &cc, "char").expect("C layout"), + "failed to obtain correct layout for char type"); + + let mut results : Results = Default::default(); + for (i, &(name, rust_layout)) in RUST_LAYOUTS.iter().enumerate() { + match get_c_layout(tmpdir.path(), &cc, name) { + Err(e) => { + results.record_failed_to_compile(); + eprintln!("{}", e); + }, + Ok(c_layout) => { + if rust_layout == c_layout { + results.record_passed(); + } else { + results.record_failed(); + eprintln!("Layout mismatch for {}\nRust: {:?}\nC: {:?}", + name, rust_layout, &c_layout); + } + } + }; + if (i + 1) % 25 == 0 { + println!("layout ... {}", results.summary()); + } + } + results.expect_total_success(); +} + +fn get_c_layout(dir: &Path, cc: &Compiler, name: &str) -> Result> { + let exe = dir.join("layout"); + let mut cc = cc.clone(); + cc.define("ABI_TYPE_NAME", name); + cc.compile(Path::new("tests/layout.c"), &exe)?; + + let mut abi_cmd = Command::new(exe); + let output = abi_cmd.output()?; + if !output.status.success() { + return Err(format!("command {:?} failed, {:?}", + &abi_cmd, &output).into()); + } + + let stdout = str::from_utf8(&output.stdout)?; + let mut words = stdout.trim().split_whitespace(); + let size = words.next().unwrap().parse().unwrap(); + let alignment = words.next().unwrap().parse().unwrap(); + Ok(Layout {size, alignment}) +} + +fn get_c_value(dir: &Path, cc: &Compiler, name: &str) -> Result> { + let exe = dir.join("constant"); + let mut cc = cc.clone(); + cc.define("ABI_CONSTANT_NAME", name); + cc.compile(Path::new("tests/constant.c"), &exe)?; + + let mut abi_cmd = Command::new(exe); + let output = abi_cmd.output()?; + if !output.status.success() { + return Err(format!("command {:?} failed, {:?}", + &abi_cmd, &output).into()); + } + + Ok(str::from_utf8(&output.stdout)?.trim().to_owned()) +} + +const RUST_LAYOUTS: &[(&str, Layout)] = &[ + ("GstHarness", Layout {size: size_of::(), alignment: align_of::()}), + ("GstTestClock", Layout {size: size_of::(), alignment: align_of::()}), + ("GstTestClockClass", Layout {size: size_of::(), alignment: align_of::()}), +]; + +const RUST_CONSTANTS: &[(&str, &str)] = &[ +]; + + diff --git a/gstreamer-check-sys/tests/constant.c b/gstreamer-check-sys/tests/constant.c new file mode 100644 index 000000000..5d6fbefa5 --- /dev/null +++ b/gstreamer-check-sys/tests/constant.c @@ -0,0 +1,27 @@ +// This file was generated by gir (https://github.com/gtk-rs/gir @ 82cdb44) +// from gir-files (https://github.com/gtk-rs/gir-files @ ???) +// DO NOT EDIT + +#include "manual.h" +#include + +int main() { + printf(_Generic((ABI_CONSTANT_NAME), + char *: "%s", + const char *: "%s", + char: "%c", + signed char: "%hhd", + unsigned char: "%hhu", + short int: "%hd", + unsigned short int: "%hu", + int: "%d", + unsigned int: "%u", + long: "%ld", + unsigned long: "%lu", + long long: "%lld", + unsigned long long: "%llu", + double: "%f", + long double: "%ld"), + ABI_CONSTANT_NAME); + return 0; +} diff --git a/gstreamer-check-sys/tests/layout.c b/gstreamer-check-sys/tests/layout.c new file mode 100644 index 000000000..c2f9f51b5 --- /dev/null +++ b/gstreamer-check-sys/tests/layout.c @@ -0,0 +1,12 @@ +// This file was generated by gir (https://github.com/gtk-rs/gir @ 82cdb44) +// from gir-files (https://github.com/gtk-rs/gir-files @ ???) +// DO NOT EDIT + +#include "manual.h" +#include +#include + +int main() { + printf("%zu\n%zu", sizeof(ABI_TYPE_NAME), alignof(ABI_TYPE_NAME)); + return 0; +} diff --git a/gstreamer-check-sys/tests/manual.h b/gstreamer-check-sys/tests/manual.h new file mode 100644 index 000000000..d1407d72b --- /dev/null +++ b/gstreamer-check-sys/tests/manual.h @@ -0,0 +1,3 @@ +// Feel free to edit this file, it won't be regenerated by gir generator unless removed. + +#include