diff --git a/Cargo.toml b/Cargo.toml index 490c7077b..166c7a9a2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -37,6 +37,7 @@ default-members = [ "gstreamer-rtsp", "gstreamer-rtsp-server", "gstreamer-sdp", + "gstreamer-tag", "gstreamer-validate", "gstreamer-video", "gstreamer-webrtc", @@ -89,6 +90,7 @@ members = [ "gstreamer-rtsp", "gstreamer-rtsp-server", "gstreamer-sdp", + "gstreamer-tag", "gstreamer-validate", "gstreamer-video", "gstreamer-webrtc", diff --git a/gstreamer-tag/Cargo.toml b/gstreamer-tag/Cargo.toml new file mode 100644 index 000000000..3a3f557ed --- /dev/null +++ b/gstreamer-tag/Cargo.toml @@ -0,0 +1,36 @@ +[package] +name = "gstreamer-tag" +version = "0.22.0" +authors = [ + "Sebastian Dröge ", + "Marc Wiblishauser ", +] +categories = ["api-bindings", "multimedia"] +description = "Rust bindings for GStreamer Tag Support library" +repository = "https://gitlab.freedesktop.org/gstreamer/gstreamer-rs" +license = "MIT OR Apache-2.0" +readme = "README.md" +homepage = "https://gstreamer.freedesktop.org" +documentation = "https://gstreamer.pages.freedesktop.org/gstreamer-rs/stable/latest/docs/gstreamer_tag/" +keywords = ["gstreamer", "multimedia", "audio", "tag", "tags", "gnome"] +edition = "2021" +rust-version = "1.70" + +[dependencies] +libc = "0.2" +ffi = { package = "gstreamer-tag-sys", path = "sys" } +glib = { git = "https://github.com/gtk-rs/gtk-rs-core" } +gst = { package = "gstreamer", path = "../gstreamer" } + +[features] +default = [] +v1_16 = ["gst/v1_16", "ffi/v1_16"] +v1_18 = ["gst/v1_18", "ffi/v1_18", "v1_16"] +v1_20 = ["gst/v1_20", "ffi/v1_20", "v1_18"] +v1_22 = ["gst/v1_22", "ffi/v1_22", "v1_20"] +v1_24 = ["gst/v1_24", "ffi/v1_24", "v1_22"] + +[package.metadata.docs.rs] +all-features = true +rustc-args = ["--cfg", "docsrs"] +rustdoc-args = ["--cfg", "docsrs", "--generate-link-to-definition"] diff --git a/gstreamer-tag/README.md b/gstreamer-tag/README.md new file mode 100644 index 000000000..3bf6efaff --- /dev/null +++ b/gstreamer-tag/README.md @@ -0,0 +1,214 @@ +# gstreamer-tag-rs [![crates.io](https://img.shields.io/crates/v/gstreamer-tag.svg)](https://crates.io/crates/gstreamer-tag) [![pipeline status](https://gitlab.freedesktop.org/gstreamer/gstreamer-rs/badges/main/pipeline.svg)](https://gitlab.freedesktop.org/gstreamer/gstreamer-rs/commits/main) + +[GStreamer](https://gstreamer.freedesktop.org/) (Tag support library) bindings for Rust. +Documentation can be found [here](https://gstreamer.pages.freedesktop.org/gstreamer-rs/stable/latest/docs/gstreamer_tag/). + +These bindings are providing a safe API that can be used to interface with +GStreamer, e.g. for writing GStreamer-based applications and GStreamer plugins. + +The bindings are mostly 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. + +## Table of Contents +1. [Installation](#installation) + 1. [Linux/BSDs](#installation-linux) + 1. [macOS](#installation-macos) + 1. [Windows](#installation-windows) +1. [Getting Started](#getting-started) +1. [License](#license) +1. [Contribution](#contribution) + + + +## Installation + +To build the GStreamer bindings or anything depending on them, you need to +have at least GStreamer 1.14 and gst-plugins-base 1.14 installed. In addition, +some of the examples/tutorials require various GStreamer plugins to be +available, which can be found in gst-plugins-base, gst-plugins-good, +gst-plugins-bad, gst-plugins-ugly and/or gst-libav. + + + +### Linux/BSDs + +You need to install the above mentioned packages with your distributions +package manager, or build them from source. + +On Debian/Ubuntu they can be installed with + +```console +$ apt-get install libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev \ + gstreamer1.0-plugins-base gstreamer1.0-plugins-good \ + gstreamer1.0-plugins-bad gstreamer1.0-plugins-ugly \ + gstreamer1.0-libav libgstrtspserver-1.0-dev libges-1.0-dev +``` + +The minimum required version of the above libraries is >= 1.14. If you +build the gstreamer-player sub-crate, or any of the examples that +depend on gstreamer-player, you must ensure that in addition to the above +packages, `libgstreamer-plugins-bad1.0-dev` is installed. See the `Cargo.toml` +files for the full details, + +```console +$ apt-get install libgstreamer-plugins-bad1.0-dev +``` + +Package names on other distributions should be similar. +Please submit a pull request with instructions for yours. + + + +### macOS + +You can install GStreamer and the plugins via [Homebrew](https://brew.sh/) or +by installing the [binaries](https://gstreamer.freedesktop.org/data/pkg/osx/) +provided by the GStreamer project. + +We recommend using the official GStreamer binaries over Homebrew, especially +as GStreamer in Homebrew is [currently broken](https://github.com/orgs/Homebrew/discussions/3740#discussioncomment-3804964). + +#### GStreamer Binaries + +You need to download the *two* `.pkg` files from the GStreamer website and +install them, e.g. `gstreamer-1.0-1.20.4-universal.pkg` and +`gstreamer-1.0-devel-1.20.4-universal.pkg`. + +After installation, you also need to set the `PATH` environment variable as +follows + +```console +$ export PATH="/Library/Frameworks/GStreamer.framework/Versions/1.0/bin${PATH:+:$PATH}" +``` + +Also note that the `pkg-config` from GStreamer should be the first one in +the `PATH` as other versions have all kinds of quirks that will cause +problems. + +#### Homebrew + +Homebrew only installs various plugins if explicitly enabled, so some extra +`--with-*` flags may be required. + +```console +$ brew install gstreamer gst-plugins-base gst-plugins-good \ + gst-plugins-bad gst-plugins-ugly gst-libav gst-rtsp-server \ + gst-editing-services --with-orc --with-libogg --with-opus \ + --with-pango --with-theora --with-libvorbis --with-libvpx \ + --enable-gtk3 +``` + +Make sure the version of these libraries is >= 1.14. + + + +### Windows + +You can install GStreamer and the plugins via [MSYS2](http://www.msys2.org/) +with `pacman` or by installing the +[binaries](https://gstreamer.freedesktop.org/data/pkg/windows/) provided by +the GStreamer project. + +We recommend using the official GStreamer binaries over MSYS2. + +#### GStreamer Binaries + +You need to download the *two* `.msi` files for your platform from the +GStreamer website and install them, e.g. `gstreamer-1.0-x86_64-1.20.4.msi` and +`gstreamer-1.0-devel-x86_64-1.20.4.msi`. Make sure to select the version that +matches your Rust toolchain, i.e. MinGW or MSVC. + +After installation set the ``PATH` environment variable as follows: + +```console +# For a UNIX-style shell: +$ export PATH="c:/gstreamer/1.0/msvc_x86_64/bin${PATH:+:$PATH}" + +# For cmd.exe: +$ set PATH=C:\gstreamer\1.0\msvc_x86_64\bin;%PATH% +``` + +Make sure to update the path to where you have actually installed GStreamer +and for the corresponding toolchain. + +Also note that the `pkg-config.exe` from GStreamer should be the first one in +the `PATH` as other versions have all kinds of quirks that will cause +problems. + +#### MSYS2 / pacman + +```console +$ pacman -S glib2-devel pkg-config \ + mingw-w64-x86_64-gstreamer mingw-w64-x86_64-gst-plugins-base \ + mingw-w64-x86_64-gst-plugins-good mingw-w64-x86_64-gst-plugins-bad \ + mingw-w64-x86_64-gst-plugins-ugly mingw-w64-x86_64-gst-libav \ + mingw-w64-x86_64-gst-rtsp-server +``` + +Make sure the version of these libraries is >= 1.14. + +Note that the version of `pkg-config` included in `MSYS2` is +[known to have problems](https://github.com/rust-lang/pkg-config-rs/issues/51#issuecomment-346300858) +compiling GStreamer, so you may need to install another version. One option +would be [`pkg-config-lite`](https://sourceforge.net/projects/pkgconfiglite/). + + + +## Getting Started + +The API reference can be found +[here](https://gstreamer.pages.freedesktop.org/gstreamer-rs/stable/latest/docs/gstreamer/), however it is +only the Rust API reference and does not explain any of the concepts. + +For getting started with GStreamer development, the best would be to follow +the [documentation](https://gstreamer.freedesktop.org/documentation/) on the +GStreamer website, especially the [Application Development +Manual](https://gstreamer.freedesktop.org/documentation/application-development/). +While being C-centric, it explains all the fundamental concepts of GStreamer +and the code examples should be relatively easily translatable to Rust. The +API is basically the same, function/struct names are the same and everything +is only more convenient (hopefully) and safer. + +In addition there are +[tutorials](https://gstreamer.freedesktop.org/documentation/tutorials/) on the +GStreamer website. Many of them were ported to Rust already and the code can +be found in the +[tutorials](https://gitlab.freedesktop.org/gstreamer/gstreamer-rs/tree/main/tutorials) +directory. + +Some further examples for various aspects of GStreamer and how to use it from +Rust can be found in the +[examples](https://gitlab.freedesktop.org/gstreamer/gstreamer-rs/tree/main/examples) +directory. + +Various GStreamer plugins written in Rust can be found in the +[gst-plugins-rs](https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs) +repository. + + + +## LICENSE + +gstreamer-rs and all crates contained in here are licensed under either of + + * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or + http://www.apache.org/licenses/LICENSE-2.0) + * MIT license ([LICENSE-MIT](LICENSE-MIT) or + http://opensource.org/licenses/MIT) + +at your option. + +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, as defined in the Apache-2.0 license, shall be +dual licensed as above, without any additional terms or conditions. diff --git a/gstreamer-tag/src/lib.rs b/gstreamer-tag/src/lib.rs new file mode 100644 index 000000000..9524e128f --- /dev/null +++ b/gstreamer-tag/src/lib.rs @@ -0,0 +1,23 @@ +// Take a look at the license at the top of the repository in the LICENSE file. + +#![cfg_attr(docsrs, feature(doc_cfg))] +#![allow(clippy::missing_safety_doc)] +#![doc = include_str!("../README.md")] + +pub use ffi; +pub use glib; +pub use gst; + +macro_rules! skip_assert_initialized { + () => {}; +} + +mod tags; +pub use crate::tags::*; + +// Re-export all the traits in a prelude module, so that applications +// can always "use gst_tag::prelude::*" without getting conflicts +pub mod prelude { + #[doc(hidden)] + pub use gst::prelude::*; +} diff --git a/gstreamer-tag/src/tags.rs b/gstreamer-tag/src/tags.rs new file mode 100644 index 000000000..a920a0781 --- /dev/null +++ b/gstreamer-tag/src/tags.rs @@ -0,0 +1,37 @@ +use gst::glib::translate::*; +use std::ptr; + +pub struct ExtendedComment { + pub key: Option, + pub lang: Option, + pub value: glib::GString, +} + +#[doc(alias = "gst_tag_parse_extended_comment")] +pub fn tag_parse_extended_comment( + ext_comment: &str, + fail_if_no_key: bool, +) -> Result { + skip_assert_initialized!(); + unsafe { + let mut c_key = ptr::null_mut(); + let mut c_lang = ptr::null_mut(); + let mut c_value = ptr::null_mut(); + let res: bool = from_glib(ffi::gst_tag_parse_extended_comment( + ext_comment.to_glib_none().0, + &mut c_key, + &mut c_lang, + &mut c_value, + fail_if_no_key.into_glib(), + )); + if !res { + Err(glib::bool_error!("Failed to parse extended comment")) + } else { + let key = from_glib_full(c_key); + let lang = from_glib_full(c_lang); + let value = from_glib_full(c_value); + + Ok(ExtendedComment { key, lang, value }) + } + } +} diff --git a/gstreamer-tag/tests/check_gir.rs b/gstreamer-tag/tests/check_gir.rs deleted file mode 100644 index 2ccf5ff05..000000000 --- a/gstreamer-tag/tests/check_gir.rs +++ /dev/null @@ -1,8 +0,0 @@ -// Take a look at the license at the top of the repository in the LICENSE file. - -#[test] -fn check_gir_file() { - let res = gir_format_check::check_gir_file("Gir.toml"); - println!("{res}"); - assert_eq!(res.nb_errors, 0); -}