From 1e12354cd5facd4954c1a15b8ece769381ea86ff Mon Sep 17 00:00:00 2001 From: Philippe Normand Date: Mon, 7 Aug 2017 15:35:57 +0100 Subject: [PATCH] GstPlayer: make it build and add simple example --- Cargo.lock | 31 + Cargo.toml | 1 + Gir_GstPlayer.toml | 82 +- docs/gstreamer-player/docs.md | 794 +++++++++++++ examples/Cargo.toml | 5 + examples/src/bin/player.rs | 96 ++ examples/src/bin/utils/mod.rs | 9 +- gstreamer-app/Cargo.toml | 4 +- gstreamer-player/Cargo.toml | 30 + gstreamer-player/build.rs | 34 + gstreamer-player/src/auto/enums.rs | 2 +- gstreamer-player/src/auto/flags.rs | 2 +- gstreamer-player/src/auto/mod.rs | 4 +- gstreamer-player/src/auto/player.rs | 1031 +++++++---------- .../src/auto/player_audio_info.rs | 2 +- ...player_g_main_context_signal_dispatcher.rs | 2 +- .../src/auto/player_media_info.rs | 10 +- .../src/auto/player_signal_dispatcher.rs | 2 +- .../src/auto/player_stream_info.rs | 2 +- .../src/auto/player_subtitle_info.rs | 2 +- .../src/auto/player_video_info.rs | 2 +- .../player_video_overlay_video_renderer.rs | 2 +- .../src/auto/player_video_renderer.rs | 2 +- .../src/auto/player_visualization.rs | 2 +- gstreamer-player/src/lib.rs | 46 + gstreamer-player/src/player.rs | 46 + 26 files changed, 1615 insertions(+), 630 deletions(-) create mode 100644 docs/gstreamer-player/docs.md create mode 100644 examples/src/bin/player.rs create mode 100644 gstreamer-player/Cargo.toml create mode 100644 gstreamer-player/build.rs create mode 100644 gstreamer-player/src/lib.rs create mode 100644 gstreamer-player/src/player.rs diff --git a/Cargo.lock b/Cargo.lock index eec06710c..14cdda2c8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -112,6 +112,7 @@ dependencies = [ "glib 0.1.3 (git+https://github.com/gtk-rs/glib)", "gstreamer 0.1.0", "gstreamer-app 0.1.0", + "gstreamer-player 0.1.0", "gtk 0.1.3 (git+https://github.com/gtk-rs/gtk)", "send-cell 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "tokio-core 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)", @@ -327,6 +328,35 @@ dependencies = [ "pkg-config 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "gstreamer-player" +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-player-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-player-sys" +version = "0.1.1" +source = "git+https://github.com/sdroege/gstreamer-sys#669b24f66122067891bb5548e3ef85bc63493c19" +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-sys 0.1.1 (git+https://github.com/sdroege/gstreamer-sys)", + "gstreamer-video-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-sys" version = "0.1.1" @@ -658,6 +688,7 @@ dependencies = [ "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-player-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 gstreamer-video-sys 0.1.1 (git+https://github.com/sdroege/gstreamer-sys)" = "" diff --git a/Cargo.toml b/Cargo.toml index 7aa35d615..d2d62dcc2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,6 +4,7 @@ members = [ "gstreamer", "gstreamer-app", "gstreamer-audio", + "gstreamer-player", "gstreamer-video", "examples", ] diff --git a/Gir_GstPlayer.toml b/Gir_GstPlayer.toml index f7202446b..d10c6e216 100644 --- a/Gir_GstPlayer.toml +++ b/Gir_GstPlayer.toml @@ -2,7 +2,7 @@ girs_dir = "gir-files" library = "GstPlayer" version = "1.0" -min_cfg_version = "1.10" +min_cfg_version = "1.12" target_path = "gstreamer-player" work_mode = "normal" concurrency = "send+sync" @@ -14,7 +14,6 @@ external_libraries = [ ] generate = [ - "GstPlayer.Player", "GstPlayer.PlayerAudioInfo", "GstPlayer.PlayerColorBalanceType", "GstPlayer.PlayerError", @@ -36,7 +35,6 @@ manual = [ "GLib.MainContext", "GObject.Object", "Gst.ClockTime", - "Gst.Structure", "Gst.Element", ] @@ -54,3 +52,81 @@ ref_mode = "ref" name = "Gst.Sample" status = "manual" ref_mode = "ref" + + +[[object]] +name = "Gst.Structure" +status = "manual" +ref_mode = "ref-mut" + + +[[object]] +name = "GstPlayer.Player" +status = "generate" +trait = false + + [[object.function]] + name = "visualizations_free" + # correct mutability + ignore = true + + [[object.function]] + name = "set_config" + # Pass by value + ignore = true + + [[object.function]] + name = "new" + ignore = true + + [[object.signal]] + name = "buffering" + concurrency = "send" + + [[object.signal]] + name = "duration-changed" + concurrency = "send" + + [[object.signal]] + name = "end-of-stream" + concurrency = "send" + + [[object.signal]] + name = "error" + concurrency = "send" + + [[object.signal]] + name = "media-info-updated" + concurrency = "send" + + [[object.signal]] + name = "mute-changed" + concurrency = "send" + + [[object.signal]] + name = "position-changed" + concurrency = "send" + + [[object.signal]] + name = "seek-done" + concurrency = "send" + + [[object.signal]] + name = "state-changed" + concurrency = "send" + + [[object.signal]] + name = "uri-loaded" + concurrency = "send" + + [[object.signal]] + name = "video-dimensions-changed" + concurrency = "send" + + [[object.signal]] + name = "volume-changed" + concurrency = "send" + + [[object.signal]] + name = "warning" + concurrency = "send" diff --git a/docs/gstreamer-player/docs.md b/docs/gstreamer-player/docs.md new file mode 100644 index 000000000..2ca88519b --- /dev/null +++ b/docs/gstreamer-player/docs.md @@ -0,0 +1,794 @@ + + + + +# Implements + +[`ObjectExt`](trait.ObjectExt.html) + +Creates a new `Player` instance that uses `signal_dispatcher` to dispatch +signals to some event loop system, or emits signals directly if NULL is +passed. See `PlayerGMainContextSignalDispatcher::new`. + +Video is going to be rendered by `video_renderer`, or if `None` is provided +no special video set up will be done and some default handling will be +performed. +## `video_renderer` +GstPlayerVideoRenderer to use +## `signal_dispatcher` +GstPlayerSignalDispatcher to use + +# Returns + +a new `Player` instance + +## `config` +a `Player` configuration + +# Returns + +current position update interval in milliseconds + +Since 1.10 + +## `config` +a `Player` configuration + +# Returns + +`true` if accurate seeking is enabled + +Since 1.12 + +Return the user agent which has been configured using +`Player::config_set_user_agent` if any. +## `config` +a `Player` configuration + +# Returns + +the configured agent, or `None` +Since 1.10 + +set interval in milliseconds between two position-updated signals. +pass 0 to stop updating the position. +Since 1.10 +## `config` +a `Player` configuration +## `interval` +interval in ms + +Set the user agent to pass to the server if `player` needs to connect +to a server during playback. This is typically used when playing HTTP +or RTSP streams. + +Since 1.10 +## `config` +a `Player` configuration +## `agent` +the string to use as user agent + +## `info` +a `PlayerMediaInfo` + +# Returns + +A `glib::List` of +matching `PlayerAudioInfo`. + +## `info` +a `PlayerMediaInfo` + +# Returns + +A `glib::List` of +matching `PlayerSubtitleInfo`. + +## `info` +a `PlayerMediaInfo` + +# Returns + +A `glib::List` of +matching `PlayerVideoInfo`. + +Frees a `None` terminated array of `PlayerVisualization`. +## `viss` +a `None` terminated array of `PlayerVisualization` to free + + +# Returns + + + a `None` terminated array containing all available + visualizations. Use `Player::visualizations_free` after + usage. + +Enable or disable accurate seeking. When enabled, elements will try harder +to seek as accurately as possible to the requested seek position. Generally +it will be slower especially for formats that don't have any indexes or +timestamp markers in the stream. + +If accurate seeking is disabled, elements will seek as close as the request +position without slowing down seeking too much. + +Accurate seeking is disabled by default. + +Feature: `v1_12` + +## `accurate` +accurate seek or not + +Retrieve the current value of audio-video-offset property + +# Returns + +The current value of audio-video-offset in nanoseconds + +Since 1.10 + +Retrieve the current value of the indicated `type_`. +## `type_` +`PlayerColorBalanceType` + +# Returns + +The current value of `type_`, between [0,1]. In case of + error -1 is returned. + +Get a copy of the current configuration of the player. This configuration +can either be modified and used for the `Player::set_config` call +or it must be freed after usage. + +# Returns + +a copy of the current configuration of `self`. Use +`gst::Structure::free` after usage or `Player::set_config`. + +Since 1.10 + +A Function to get current audio `PlayerAudioInfo` instance. + +# Returns + +current audio track. + +The caller should free it with `gobject::ObjectExt::unref` + +A Function to get current subtitle `PlayerSubtitleInfo` instance. + +# Returns + +current subtitle track. + +The caller should free it with `gobject::ObjectExt::unref` + +A Function to get current video `PlayerVideoInfo` instance. + +# Returns + +current video track. + +The caller should free it with `gobject::ObjectExt::unref` + + +# Returns + +Name of the currently enabled visualization. + `g_free` after usage. + +Retrieves the duration of the media stream that self represents. + +# Returns + +the duration of the currently-playing media stream, in +nanoseconds. + +A Function to get the current media info `PlayerMediaInfo` instance. + +# Returns + +media info instance. + +The caller should free it with `gobject::ObjectExt::unref` + +Retrieve the current value of the indicated `type_`. + +# Returns + +The current value of `type_`, Default: 0x00000000 "none + +Retrieve the current value of the indicated `type_`. + +# Returns + +The current value of `type_`, Default: -1 "none" + + +# Returns + +`true` if the currently-playing stream is muted. + + +# Returns + +The internal playbin instance + + +# Returns + +the absolute position time, in nanoseconds, of the +currently-playing stream. + + +# Returns + +current playback rate + +current subtitle URI + +# Returns + +URI of the current external subtitle. + `g_free` after usage. + +Gets the URI of the currently-playing stream. + +# Returns + +a string containing the URI of the +currently-playing stream. `g_free` after usage. + +Get a snapshot of the currently selected video stream, if any. The format can be +selected with `format` and optional configuration is possible with `config` +Currently supported settings are: +- width, height of type G_TYPE_INT +- pixel-aspect-ratio of type GST_TYPE_FRACTION + Except for GST_PLAYER_THUMBNAIL_RAW_NATIVE format, if no config is set, pixel-aspect-ratio would be 1/1 +## `format` +output format of the video snapshot +## `config` +Additional configuration + +# Returns + +Current video snapshot sample or `None` on failure + +Since 1.12 + +Returns the current volume level, as a percentage between 0 and 1. + +# Returns + +the volume as percentage between 0 and 1. + +Checks whether the `self` has color balance support available. + +# Returns + +`true` if `self` has color balance support. Otherwise, + `false`. + +Pauses the current stream. + +Request to play the loaded stream. + +Seeks the currently-playing stream to the absolute `position` time +in nanoseconds. +## `position` +position to seek in nanoseconds + +## `stream_index` +stream index + +# Returns + +`true` or `false` + +Sets the audio track `stream_idex`. + +Enable or disable the current audio track. +## `enabled` +TRUE or FALSE + +Sets audio-video-offset property by value of `offset` + +Since 1.10 +## `offset` +`gint64` in nanoseconds + +Sets the current value of the indicated channel `type_` to the passed +value. +## `type_` +`PlayerColorBalanceType` +## `value` +The new value for the `type_`, ranged [0,1] + +Set the configuration of the player. If the player is already configured, and +the configuration haven't change, this function will return `true`. If the +player is not in the GST_PLAYER_STATE_STOPPED, this method will return `false` +and active configuration will remain. + +`config` is a `gst::Structure` that contains the configuration parameters for +the player. + +This function takes ownership of `config`. +## `config` +a `gst::Structure` + +# Returns + +`true` when the configuration could be set. +Since 1.10 + +Sets the current value of the indicated mode `type_` to the passed +value. +## `flags` +The new value for the `type_` + +Sets the current value of the indicated mode `type_` to the passed +value. +## `mode` +The new value for the `type_` + +`true` if the currently-playing stream should be muted. +## `val` +Mute state the should be set + +Playback at specified rate +## `rate` +playback rate + +## `stream_index` +stream index + +# Returns + +`true` or `false` + +Sets the subtitle strack `stream_index`. + +Enable or disable the current subtitle track. +## `enabled` +TRUE or FALSE + +Sets the external subtitle URI. +## `uri` +subtitle URI + +Sets the next URI to play. +## `uri` +next URI to play. + +## `stream_index` +stream index + +# Returns + +`true` or `false` + +Sets the video track `stream_index`. + +Enable or disable the current video track. +## `enabled` +TRUE or FALSE + +## `name` +visualization element obtained from +`Player::visualizations_get`() + +# Returns + +`true` if the visualizations was set correctly. Otherwise, +`false`. + +Enable or disable the visualization. +## `enabled` +TRUE or FALSE + +Sets the volume level of the stream as a percentage between 0 and 1. +## `val` +the new volume level, as a percentage between 0 and 1 + +Stops playing the current stream and resets to the first position +in the stream. + +`PlayerStreamInfo` specific to audio streams. + +# Implements + +[`PlayerAudioInfoExt`](trait.PlayerAudioInfoExt.html), [`PlayerStreamInfoExt`](trait.PlayerStreamInfoExt.html), [`ObjectExt`](trait.ObjectExt.html) + +Trait containing all `PlayerAudioInfo` methods. + +# Implementors + +[`PlayerAudioInfo`](struct.PlayerAudioInfo.html) + + +# Returns + +the audio bitrate in `PlayerAudioInfo`. + + +# Returns + +the number of audio channels in `PlayerAudioInfo`. + + +# Returns + +the language of the stream, or NULL if unknown. + + +# Returns + +the audio maximum bitrate in `PlayerAudioInfo`. + + +# Returns + +the audio sample rate in `PlayerAudioInfo`. + + +hue or color balance. + +brightness or black level. + +color saturation or chroma +gain. + +contrast or luma gain. + + +generic error. + + + +# Implements + +[`PlayerGMainContextSignalDispatcherExt`](trait.PlayerGMainContextSignalDispatcherExt.html), [`ObjectExt`](trait.ObjectExt.html), [`PlayerSignalDispatcherExt`](trait.PlayerSignalDispatcherExt.html) + +Trait containing all `PlayerGMainContextSignalDispatcher` methods. + +# Implementors + +[`PlayerGMainContextSignalDispatcher`](struct.PlayerGMainContextSignalDispatcher.html) + +Creates a new GstPlayerSignalDispatcher that uses `application_context`, +or the thread default one if `None` is used. See `gst_player_new_full`. +## `application_context` +GMainContext to use or `None` + +# Returns + +the new GstPlayerSignalDispatcher + +Structure containing the media information of a URI. + +# Implements + +[`PlayerMediaInfoExt`](trait.PlayerMediaInfoExt.html), [`ObjectExt`](trait.ObjectExt.html) + +Trait containing all `PlayerMediaInfo` methods. + +# Implementors + +[`PlayerMediaInfo`](struct.PlayerMediaInfo.html) + + +# Returns + +A `glib::List` of +matching `PlayerAudioInfo`. + + +# Returns + +the container format. + + +# Returns + +duration of the media. + +Function to get the image (or preview-image) stored in taglist. +Application can use gst_sample_*`_` API's to get caps, buffer etc. + +# Returns + +GstSample or NULL. + + +Feature: `v1_12` + + +# Returns + +number of audio streams. + + +Feature: `v1_12` + + +# Returns + +number of total streams. + + +Feature: `v1_12` + + +# Returns + +number of subtitle streams. + + +Feature: `v1_12` + + +# Returns + +number of video streams. + + +# Returns + +A `glib::List` of +matching `PlayerStreamInfo`. + + +# Returns + +A `glib::List` of +matching `PlayerSubtitleInfo`. + + +# Returns + +the tags contained in media info. + + +# Returns + +the media title. + + +# Returns + +the URI associated with `PlayerMediaInfo`. + + +# Returns + +A `glib::List` of +matching `PlayerVideoInfo`. + + +# Returns + +`true` if the media is live. + + +# Returns + +`true` if the media is seekable. + + + +# Implements + +[`PlayerSignalDispatcherExt`](trait.PlayerSignalDispatcherExt.html) + +Trait containing all `PlayerSignalDispatcher` methods. + +# Implementors + +[`PlayerGMainContextSignalDispatcher`](struct.PlayerGMainContextSignalDispatcher.html), [`PlayerSignalDispatcher`](struct.PlayerSignalDispatcher.html) + + + +the player is stopped. + +the player is buffering. + +the player is paused. + +the player is currently playing a +stream. + +Base structure for information concering a media stream. Depending on +the stream type, one can find more media-specific information in +`PlayerVideoInfo`, `PlayerAudioInfo`, `PlayerSubtitleInfo`. + +# Implements + +[`PlayerStreamInfoExt`](trait.PlayerStreamInfoExt.html), [`ObjectExt`](trait.ObjectExt.html) + +Trait containing all `PlayerStreamInfo` methods. + +# Implementors + +[`PlayerAudioInfo`](struct.PlayerAudioInfo.html), [`PlayerStreamInfo`](struct.PlayerStreamInfo.html), [`PlayerSubtitleInfo`](struct.PlayerSubtitleInfo.html), [`PlayerVideoInfo`](struct.PlayerVideoInfo.html) + + +# Returns + +the `gst::Caps` of the stream. + +A string describing codec used in `PlayerStreamInfo`. + +# Returns + +codec string or NULL on unknown. + +Function to get stream index from `PlayerStreamInfo` instance. + +# Returns + +the stream index of this stream. + +Function to return human readable name for the stream type +of the given `self` (ex: "audio", "video", "subtitle") + +# Returns + +a human readable name + + +# Returns + +the tags contained in this stream. + +`PlayerStreamInfo` specific to subtitle streams. + +# Implements + +[`PlayerSubtitleInfoExt`](trait.PlayerSubtitleInfoExt.html), [`PlayerStreamInfoExt`](trait.PlayerStreamInfoExt.html), [`ObjectExt`](trait.ObjectExt.html) + +Trait containing all `PlayerSubtitleInfo` methods. + +# Implementors + +[`PlayerSubtitleInfo`](struct.PlayerSubtitleInfo.html) + + +# Returns + +the language of the stream, or NULL if unknown. + +`PlayerStreamInfo` specific to video streams. + +# Implements + +[`PlayerVideoInfoExt`](trait.PlayerVideoInfoExt.html), [`PlayerStreamInfoExt`](trait.PlayerStreamInfoExt.html), [`ObjectExt`](trait.ObjectExt.html) + +Trait containing all `PlayerVideoInfo` methods. + +# Implementors + +[`PlayerVideoInfo`](struct.PlayerVideoInfo.html) + + +# Returns + +the current bitrate of video in `PlayerVideoInfo`. + +## `fps_n` +Numerator of frame rate +## `fps_d` +Denominator of frame rate + + +# Returns + +the height of video in `PlayerVideoInfo`. + + +# Returns + +the maximum bitrate of video in `PlayerVideoInfo`. + +Returns the pixel aspect ratio in `par_n` and `par_d` +## `par_n` +numerator +## `par_d` +denominator + + +# Returns + +the width of video in `PlayerVideoInfo`. + + + +# Implements + +[`PlayerVideoOverlayVideoRendererExt`](trait.PlayerVideoOverlayVideoRendererExt.html), [`ObjectExt`](trait.ObjectExt.html), [`PlayerVideoRendererExt`](trait.PlayerVideoRendererExt.html) + +Trait containing all `PlayerVideoOverlayVideoRenderer` methods. + +# Implementors + +[`PlayerVideoOverlayVideoRenderer`](struct.PlayerVideoOverlayVideoRenderer.html) + +## `window_handle` +Window handle to use or `None` + +## `window_handle` +Window handle to use or `None` +## `video_sink` +the custom video_sink element to be set for the video renderer + +# Returns + + + +Since 1.12 + +Tell an overlay that it has been exposed. This will redraw the current frame +in the drawable even if the pipeline is PAUSED. + +Return the currently configured render rectangle. See `PlayerVideoOverlayVideoRendererExt::set_render_rectangle` +for details. +## `x` +the horizontal offset of the render area inside the window +## `y` +the vertical offset of the render area inside the window +## `width` +the width of the render area inside the window +## `height` +the height of the render area inside the window + + +# Returns + +The currently set, platform specific window +handle + +Configure a subregion as a video target within the window set by +`PlayerVideoOverlayVideoRendererExt::set_window_handle`. If this is not +used or not supported the video will fill the area of the window set as the +overlay to 100%. By specifying the rectangle, the video can be overlaid to +a specific region of that window only. After setting the new rectangle one +should call `PlayerVideoOverlayVideoRendererExt::expose` to force a +redraw. To unset the region pass -1 for the `width` and `height` parameters. + +This method is needed for non fullscreen video overlay in UI toolkits that +do not support subwindows. +## `x` +the horizontal offset of the render area inside the window +## `y` +the vertical offset of the render area inside the window +## `width` +the width of the render area inside the window +## `height` +the height of the render area inside the window + +Sets the platform specific window handle into which the video +should be rendered +## `window_handle` +handle referencing to the platform specific window + + + +# Implements + +[`PlayerVideoRendererExt`](trait.PlayerVideoRendererExt.html) + +Trait containing all `PlayerVideoRenderer` methods. + +# Implementors + +[`PlayerVideoOverlayVideoRenderer`](struct.PlayerVideoOverlayVideoRenderer.html), [`PlayerVideoRenderer`](struct.PlayerVideoRenderer.html) + +A `PlayerVisualization` descriptor. + +Makes a copy of the `PlayerVisualization`. The result must be +freed using `PlayerVisualization::free`. + +# Returns + +an allocated copy of `self`. + +Frees a `PlayerVisualization`. diff --git a/examples/Cargo.toml b/examples/Cargo.toml index eecea99e9..7af393fd8 100644 --- a/examples/Cargo.toml +++ b/examples/Cargo.toml @@ -7,8 +7,13 @@ authors = ["Sebastian Dröge "] glib = { version = "0.1.3", git = "https://github.com/gtk-rs/glib" } gstreamer = { path = "../gstreamer" } gstreamer-app = { path = "../gstreamer-app" } +gstreamer-player = { path = "../gstreamer-player", optional = true } gtk = { version = "0.1.3", git = "https://github.com/gtk-rs/gtk", features = ["v3_6"] } gio = { version = "0.1.3", git = "https://github.com/gtk-rs/gio" } futures = "0.1" tokio-core = "0.1" send-cell = "0.1" + +[features] +gst-player = ["gstreamer-player"] +default-features = [] diff --git a/examples/src/bin/player.rs b/examples/src/bin/player.rs new file mode 100644 index 000000000..b1055c69f --- /dev/null +++ b/examples/src/bin/player.rs @@ -0,0 +1,96 @@ +extern crate gstreamer as gst; + +#[cfg(feature = "gst-player")] +extern crate gstreamer_player as gst_player; + +extern crate glib; + +#[allow(unused_imports)] +use glib::ObjectExt; + +extern crate send_cell; + +use std::env; + +pub mod utils; + + +#[cfg(feature = "gst-player")] +fn main_loop(uri: &str) -> Result<(), utils::ExampleError> { + gst::init().map_err(utils::ExampleError::InitFailed)?; + + let main_loop = glib::MainLoop::new(None, false); + + let dispatcher = gst_player::PlayerGMainContextSignalDispatcher::new(None).unwrap(); + let player = gst_player::Player::new(None, Some(&dispatcher)); + player + .set_property("uri", &glib::Value::from(uri)) + .expect("Can't set uri property"); + + let result = std::cell::RefCell::new(Some(Ok(()))); + let error = std::sync::Arc::new(std::sync::Mutex::new(send_cell::SendCell::new(result))); + let error_clone = error.clone(); + + let player_clone = player.clone(); + let main_loop_clone = main_loop.clone(); + player.connect_end_of_stream(move |_| { + let main_loop = &main_loop_clone; + let player = &player_clone; + player.stop(); + main_loop.quit(); + }); + + let player_clone = player.clone(); + let main_loop_clone = main_loop.clone(); + player.connect_error(move |_, err| { + let main_loop = &main_loop_clone; + let player = &player_clone; + + let error = std::sync::Arc::clone(&error_clone); + let guard = error.lock().unwrap(); + let cell = &*guard; + let refcell = cell.get(); + *refcell.borrow_mut() = Some(Err(utils::ExampleError::ElementError( + "player".to_owned(), + err.clone(), + "".to_owned(), + ))); + + player.stop(); + main_loop.quit(); + }); + + player.play(); + main_loop.run(); + + let guard = error.as_ref().lock().unwrap(); + let cell = &*guard; + let refcell = cell.get(); + let result = refcell.borrow(); + + if let Some(ref e) = *result { + return e.clone(); + } else { + Ok(()) + } +} + +#[cfg(not(feature = "gst-player"))] +#[allow(unused_variables)] +fn main_loop(uri: &str) -> Result<(), utils::ExampleError> { + Err(utils::ExampleError::MissingFeature("gst-player")) +} + +fn main() { + let args: Vec<_> = env::args().collect(); + let uri: &str = if args.len() == 2 { + args[1].as_ref() + } else { + panic!("Usage: player uri"); + }; + + match main_loop(uri) { + Ok(r) => r, + Err(e) => eprintln!("Error! {}", e), + } +} diff --git a/examples/src/bin/utils/mod.rs b/examples/src/bin/utils/mod.rs index 6ea9e5a43..bde22f2df 100644 --- a/examples/src/bin/utils/mod.rs +++ b/examples/src/bin/utils/mod.rs @@ -5,13 +5,14 @@ use gst::*; extern crate glib; use std::fmt; -#[derive(Debug)] +#[derive(Debug, Clone)] pub enum ExampleError { InitFailed(glib::Error), ElementNotFound(&'static str), ElementLinkFailed(::std::string::String, ::std::string::String), SetStateError(::std::string::String), ElementError(::std::string::String, glib::Error, ::std::string::String), + MissingFeature(&'static str), } impl fmt::Display for ExampleError { @@ -30,6 +31,12 @@ impl fmt::Display for ExampleError { ExampleError::ElementError(ref element, ref err, ref debug) => { write!(f, "Error from {}: {} ({:?})", element, err, debug) } + ExampleError::MissingFeature(ref feature) => write!( + f, + "Feature {} is required. Please rebuild with --features {}", + feature, + feature + ), } } } diff --git a/gstreamer-app/Cargo.toml b/gstreamer-app/Cargo.toml index acc0e605c..5846ae3b8 100644 --- a/gstreamer-app/Cargo.toml +++ b/gstreamer-app/Cargo.toml @@ -25,8 +25,8 @@ version = "0.1" optional = true [features] -v1_10 = ["gstreamer-sys/v1_10"] -v1_12 = ["gstreamer-sys/v1_12", "v1_10"] +v1_10 = ["gstreamer-sys/v1_10", "gstreamer-app-sys/v1_10"] +v1_12 = ["gstreamer-sys/v1_12", "gstreamer-app-sys/v1_12", "v1_10"] embed-lgpl-docs = ["rustdoc-stripper"] purge-lgpl-docs = ["rustdoc-stripper"] default-features = [] diff --git a/gstreamer-player/Cargo.toml b/gstreamer-player/Cargo.toml new file mode 100644 index 000000000..19ec340d9 --- /dev/null +++ b/gstreamer-player/Cargo.toml @@ -0,0 +1,30 @@ +[package] +name = "gstreamer-player" +version = "0.1.0" +authors = ["Sebastian Dröge "] +categories = ["api-bindings", "multimedia"] +description = "Rust bindings for GStreamer Player 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_12"] } +gstreamer-player-sys = { version = "0.1.1", git = "https://github.com/sdroege/gstreamer-sys", features = ["v1_12"] } +glib = { version = "0.1.3", git = "https://github.com/gtk-rs/glib" } +gstreamer = { version = "0.1.0", path = "../gstreamer", features = ["v1_12"] } + +[build-dependencies.rustdoc-stripper] +version = "0.1" +optional = true + +[features] +embed-lgpl-docs = ["rustdoc-stripper"] +purge-lgpl-docs = ["rustdoc-stripper"] +default-features = [] diff --git a/gstreamer-player/build.rs b/gstreamer-player/build.rs new file mode 100644 index 000000000..873bf3be6 --- /dev/null +++ b/gstreamer-player/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-player/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-player/src/auto/enums.rs b/gstreamer-player/src/auto/enums.rs index 2528e051c..3cc70186f 100644 --- a/gstreamer-player/src/auto/enums.rs +++ b/gstreamer-player/src/auto/enums.rs @@ -1,4 +1,4 @@ -// This file was generated by gir (f00d658) from gir-files (???) +// This file was generated by gir (3294959) from gir-files (???) // DO NOT EDIT use ffi; diff --git a/gstreamer-player/src/auto/flags.rs b/gstreamer-player/src/auto/flags.rs index 0d24c0bba..17773d34a 100644 --- a/gstreamer-player/src/auto/flags.rs +++ b/gstreamer-player/src/auto/flags.rs @@ -1,4 +1,4 @@ -// This file was generated by gir (f00d658) from gir-files (???) +// This file was generated by gir (3294959) from gir-files (???) // DO NOT EDIT use ffi; diff --git a/gstreamer-player/src/auto/mod.rs b/gstreamer-player/src/auto/mod.rs index 6b8225964..f81b778a2 100644 --- a/gstreamer-player/src/auto/mod.rs +++ b/gstreamer-player/src/auto/mod.rs @@ -1,9 +1,8 @@ -// This file was generated by gir (f00d658) from gir-files (???) +// This file was generated by gir (3294959) from gir-files (???) // DO NOT EDIT mod player; pub use self::player::Player; -pub use self::player::PlayerExt; mod player_audio_info; pub use self::player_audio_info::PlayerAudioInfo; @@ -52,7 +51,6 @@ pub use self::enums::PlayerState; #[doc(hidden)] pub mod traits { - pub use super::PlayerExt; pub use super::PlayerAudioInfoExt; pub use super::PlayerGMainContextSignalDispatcherExt; pub use super::PlayerMediaInfoExt; diff --git a/gstreamer-player/src/auto/player.rs b/gstreamer-player/src/auto/player.rs index e0a78e26b..d32d16347 100644 --- a/gstreamer-player/src/auto/player.rs +++ b/gstreamer-player/src/auto/player.rs @@ -1,22 +1,17 @@ -// This file was generated by gir (f00d658) from gir-files (???) +// This file was generated by gir (3294959) from gir-files (???) // DO NOT EDIT use Error; use PlayerAudioInfo; use PlayerColorBalanceType; use PlayerMediaInfo; -use PlayerSignalDispatcher; use PlayerSnapshotFormat; use PlayerState; use PlayerSubtitleInfo; use PlayerVideoInfo; -use PlayerVideoRenderer; use PlayerVisualization; use ffi; -use glib; use glib::Value; -use glib::object::Downcast; -use glib::object::IsA; use glib::signal::connect; use glib::translate::*; use glib_ffi; @@ -37,17 +32,296 @@ glib_wrapper! { } impl Player { - pub fn new<'a, 'b, P: IsA + 'a, Q: Into>, R: IsA + 'b, S: Into>>(video_renderer: Q, signal_dispatcher: S) -> Player { - assert_initialized_main_thread!(); - let video_renderer = video_renderer.into(); - let video_renderer = video_renderer.to_glib_none(); - let signal_dispatcher = signal_dispatcher.into(); - let signal_dispatcher = signal_dispatcher.to_glib_none(); + pub fn config_set_seek_accurate(&self, accurate: bool) { unsafe { - from_glib_none(ffi::gst_player_new(video_renderer.0, signal_dispatcher.0)) + ffi::gst_player_config_set_seek_accurate(self.to_glib_none().0, accurate.to_glib()); } } + pub fn get_audio_video_offset(&self) -> i64 { + unsafe { + ffi::gst_player_get_audio_video_offset(self.to_glib_none().0) + } + } + + pub fn get_color_balance(&self, type_: PlayerColorBalanceType) -> f64 { + unsafe { + ffi::gst_player_get_color_balance(self.to_glib_none().0, type_.to_glib()) + } + } + + pub fn get_config(&self) -> Option { + unsafe { + from_glib_full(ffi::gst_player_get_config(self.to_glib_none().0)) + } + } + + pub fn get_current_audio_track(&self) -> Option { + unsafe { + from_glib_full(ffi::gst_player_get_current_audio_track(self.to_glib_none().0)) + } + } + + pub fn get_current_subtitle_track(&self) -> Option { + unsafe { + from_glib_none(ffi::gst_player_get_current_subtitle_track(self.to_glib_none().0)) + } + } + + pub fn get_current_video_track(&self) -> Option { + unsafe { + from_glib_full(ffi::gst_player_get_current_video_track(self.to_glib_none().0)) + } + } + + pub fn get_current_visualization(&self) -> Option { + unsafe { + from_glib_full(ffi::gst_player_get_current_visualization(self.to_glib_none().0)) + } + } + + pub fn get_duration(&self) -> gst::ClockTime { + unsafe { + ffi::gst_player_get_duration(self.to_glib_none().0) + } + } + + pub fn get_media_info(&self) -> Option { + unsafe { + from_glib_full(ffi::gst_player_get_media_info(self.to_glib_none().0)) + } + } + + //pub fn get_multiview_flags(&self) -> /*Ignored*/gst_video::VideoMultiviewFlags { + // unsafe { TODO: call ffi::gst_player_get_multiview_flags() } + //} + + //pub fn get_multiview_mode(&self) -> /*Ignored*/gst_video::VideoMultiviewMode { + // unsafe { TODO: call ffi::gst_player_get_multiview_mode() } + //} + + pub fn get_mute(&self) -> bool { + unsafe { + from_glib(ffi::gst_player_get_mute(self.to_glib_none().0)) + } + } + + pub fn get_pipeline(&self) -> Option { + unsafe { + from_glib_full(ffi::gst_player_get_pipeline(self.to_glib_none().0)) + } + } + + pub fn get_position(&self) -> gst::ClockTime { + unsafe { + ffi::gst_player_get_position(self.to_glib_none().0) + } + } + + pub fn get_rate(&self) -> f64 { + unsafe { + ffi::gst_player_get_rate(self.to_glib_none().0) + } + } + + pub fn get_subtitle_uri(&self) -> Option { + unsafe { + from_glib_full(ffi::gst_player_get_subtitle_uri(self.to_glib_none().0)) + } + } + + pub fn get_uri(&self) -> Option { + unsafe { + from_glib_full(ffi::gst_player_get_uri(self.to_glib_none().0)) + } + } + + pub fn get_video_snapshot<'a, P: Into>>(&self, format: PlayerSnapshotFormat, config: P) -> Option { + let config = config.into(); + let config = config.to_glib_none(); + unsafe { + from_glib_full(ffi::gst_player_get_video_snapshot(self.to_glib_none().0, format.to_glib(), config.0)) + } + } + + pub fn get_volume(&self) -> f64 { + unsafe { + ffi::gst_player_get_volume(self.to_glib_none().0) + } + } + + pub fn has_color_balance(&self) -> bool { + unsafe { + from_glib(ffi::gst_player_has_color_balance(self.to_glib_none().0)) + } + } + + pub fn pause(&self) { + unsafe { + ffi::gst_player_pause(self.to_glib_none().0); + } + } + + pub fn play(&self) { + unsafe { + ffi::gst_player_play(self.to_glib_none().0); + } + } + + pub fn seek(&self, position: gst::ClockTime) { + unsafe { + ffi::gst_player_seek(self.to_glib_none().0, position); + } + } + + pub fn set_audio_track(&self, stream_index: i32) -> bool { + unsafe { + from_glib(ffi::gst_player_set_audio_track(self.to_glib_none().0, stream_index)) + } + } + + pub fn set_audio_track_enabled(&self, enabled: bool) { + unsafe { + ffi::gst_player_set_audio_track_enabled(self.to_glib_none().0, enabled.to_glib()); + } + } + + pub fn set_audio_video_offset(&self, offset: i64) { + unsafe { + ffi::gst_player_set_audio_video_offset(self.to_glib_none().0, offset); + } + } + + pub fn set_color_balance(&self, type_: PlayerColorBalanceType, value: f64) { + unsafe { + ffi::gst_player_set_color_balance(self.to_glib_none().0, type_.to_glib(), value); + } + } + + //pub fn set_multiview_flags(&self, flags: /*Ignored*/gst_video::VideoMultiviewFlags) { + // unsafe { TODO: call ffi::gst_player_set_multiview_flags() } + //} + + //pub fn set_multiview_mode(&self, mode: /*Ignored*/gst_video::VideoMultiviewMode) { + // unsafe { TODO: call ffi::gst_player_set_multiview_mode() } + //} + + pub fn set_mute(&self, val: bool) { + unsafe { + ffi::gst_player_set_mute(self.to_glib_none().0, val.to_glib()); + } + } + + pub fn set_rate(&self, rate: f64) { + unsafe { + ffi::gst_player_set_rate(self.to_glib_none().0, rate); + } + } + + pub fn set_subtitle_track(&self, stream_index: i32) -> bool { + unsafe { + from_glib(ffi::gst_player_set_subtitle_track(self.to_glib_none().0, stream_index)) + } + } + + pub fn set_subtitle_track_enabled(&self, enabled: bool) { + unsafe { + ffi::gst_player_set_subtitle_track_enabled(self.to_glib_none().0, enabled.to_glib()); + } + } + + pub fn set_subtitle_uri(&self, uri: &str) { + unsafe { + ffi::gst_player_set_subtitle_uri(self.to_glib_none().0, uri.to_glib_none().0); + } + } + + pub fn set_uri(&self, uri: &str) { + unsafe { + ffi::gst_player_set_uri(self.to_glib_none().0, uri.to_glib_none().0); + } + } + + pub fn set_video_track(&self, stream_index: i32) -> bool { + unsafe { + from_glib(ffi::gst_player_set_video_track(self.to_glib_none().0, stream_index)) + } + } + + pub fn set_video_track_enabled(&self, enabled: bool) { + unsafe { + ffi::gst_player_set_video_track_enabled(self.to_glib_none().0, enabled.to_glib()); + } + } + + pub fn set_visualization(&self, name: &str) -> bool { + unsafe { + from_glib(ffi::gst_player_set_visualization(self.to_glib_none().0, name.to_glib_none().0)) + } + } + + pub fn set_visualization_enabled(&self, enabled: bool) { + unsafe { + ffi::gst_player_set_visualization_enabled(self.to_glib_none().0, enabled.to_glib()); + } + } + + pub fn set_volume(&self, val: f64) { + unsafe { + ffi::gst_player_set_volume(self.to_glib_none().0, val); + } + } + + pub fn stop(&self) { + unsafe { + ffi::gst_player_stop(self.to_glib_none().0); + } + } + + pub fn get_property_suburi(&self) -> Option { + let mut value = Value::from(None::<&str>); + unsafe { + gobject_ffi::g_object_get_property(self.to_glib_none().0, "suburi".to_glib_none().0, value.to_glib_none_mut().0); + } + value.get() + } + + pub fn set_property_suburi(&self, suburi: Option<&str>) { + unsafe { + gobject_ffi::g_object_set_property(self.to_glib_none().0, "suburi".to_glib_none().0, Value::from(suburi).to_glib_none().0); + } + } + + //pub fn get_property_video_multiview_flags(&self) -> /*Ignored*/gst_video::VideoMultiviewFlags { + // let mut value = Value::from(&0u32); + // unsafe { + // gobject_ffi::g_object_get_property(self.to_glib_none().0, "video-multiview-flags".to_glib_none().0, value.to_glib_none_mut().0); + // from_glib(transmute(value.get::().unwrap())) + // } + //} + + //pub fn set_property_video_multiview_flags(&self, video_multiview_flags: /*Ignored*/gst_video::VideoMultiviewFlags) { + // let video_multiview_flags = video_multiview_flags.to_glib().bits() as u32; + // unsafe { + // gobject_ffi::g_object_set_property(self.to_glib_none().0, "video-multiview-flags".to_glib_none().0, Value::from(&video_multiview_flags).to_glib_none().0); + // } + //} + + //pub fn get_property_video_multiview_mode(&self) -> /*Ignored*/gst_video::VideoMultiviewFramePacking { + // let mut value = Value::from(&0); + // unsafe { + // gobject_ffi::g_object_get_property(self.to_glib_none().0, "video-multiview-mode".to_glib_none().0, value.to_glib_none_mut().0); + // from_glib(transmute(value.get::().unwrap())) + // } + //} + + //pub fn set_property_video_multiview_mode(&self, video_multiview_mode: /*Ignored*/gst_video::VideoMultiviewFramePacking) { + // let video_multiview_mode = video_multiview_mode.to_glib() as i32; + // unsafe { + // gobject_ffi::g_object_set_property(self.to_glib_none().0, "video-multiview-mode".to_glib_none().0, Value::from(&video_multiview_mode).to_glib_none().0); + // } + //} + pub fn config_get_position_update_interval(config: &gst::Structure) -> u32 { assert_initialized_main_thread!(); unsafe { @@ -104,640 +378,195 @@ impl Player { } } - pub fn visualizations_free(viss: &mut PlayerVisualization) { - assert_initialized_main_thread!(); - unsafe { - ffi::gst_player_visualizations_free(viss.to_glib_none_mut().0); - } - } - pub fn visualizations_get() -> Vec { assert_initialized_main_thread!(); unsafe { FromGlibPtrContainer::from_glib_full(ffi::gst_player_visualizations_get()) } } + + pub fn connect_buffering(&self, f: F) -> u64 { + unsafe { + let f: Box_> = Box_::new(Box_::new(f)); + connect(self.to_glib_none().0, "buffering", + transmute(buffering_trampoline as usize), Box_::into_raw(f) as *mut _) + } + } + + pub fn connect_duration_changed(&self, f: F) -> u64 { + unsafe { + let f: Box_> = Box_::new(Box_::new(f)); + connect(self.to_glib_none().0, "duration-changed", + transmute(duration_changed_trampoline as usize), Box_::into_raw(f) as *mut _) + } + } + + pub fn connect_end_of_stream(&self, f: F) -> u64 { + unsafe { + let f: Box_> = Box_::new(Box_::new(f)); + connect(self.to_glib_none().0, "end-of-stream", + transmute(end_of_stream_trampoline as usize), Box_::into_raw(f) as *mut _) + } + } + + pub fn connect_error(&self, f: F) -> u64 { + unsafe { + let f: Box_> = Box_::new(Box_::new(f)); + connect(self.to_glib_none().0, "error", + transmute(error_trampoline as usize), Box_::into_raw(f) as *mut _) + } + } + + pub fn connect_media_info_updated(&self, f: F) -> u64 { + unsafe { + let f: Box_> = Box_::new(Box_::new(f)); + connect(self.to_glib_none().0, "media-info-updated", + transmute(media_info_updated_trampoline as usize), Box_::into_raw(f) as *mut _) + } + } + + pub fn connect_mute_changed(&self, f: F) -> u64 { + unsafe { + let f: Box_> = Box_::new(Box_::new(f)); + connect(self.to_glib_none().0, "mute-changed", + transmute(mute_changed_trampoline as usize), Box_::into_raw(f) as *mut _) + } + } + + pub fn connect_position_updated(&self, f: F) -> u64 { + unsafe { + let f: Box_> = Box_::new(Box_::new(f)); + connect(self.to_glib_none().0, "position-updated", + transmute(position_updated_trampoline as usize), Box_::into_raw(f) as *mut _) + } + } + + pub fn connect_seek_done(&self, f: F) -> u64 { + unsafe { + let f: Box_> = Box_::new(Box_::new(f)); + connect(self.to_glib_none().0, "seek-done", + transmute(seek_done_trampoline as usize), Box_::into_raw(f) as *mut _) + } + } + + pub fn connect_state_changed(&self, f: F) -> u64 { + unsafe { + let f: Box_> = Box_::new(Box_::new(f)); + connect(self.to_glib_none().0, "state-changed", + transmute(state_changed_trampoline as usize), Box_::into_raw(f) as *mut _) + } + } + + pub fn connect_uri_loaded(&self, f: F) -> u64 { + unsafe { + let f: Box_> = Box_::new(Box_::new(f)); + connect(self.to_glib_none().0, "uri-loaded", + transmute(uri_loaded_trampoline as usize), Box_::into_raw(f) as *mut _) + } + } + + pub fn connect_video_dimensions_changed(&self, f: F) -> u64 { + unsafe { + let f: Box_> = Box_::new(Box_::new(f)); + connect(self.to_glib_none().0, "video-dimensions-changed", + transmute(video_dimensions_changed_trampoline as usize), Box_::into_raw(f) as *mut _) + } + } + + pub fn connect_volume_changed(&self, f: F) -> u64 { + unsafe { + let f: Box_> = Box_::new(Box_::new(f)); + connect(self.to_glib_none().0, "volume-changed", + transmute(volume_changed_trampoline as usize), Box_::into_raw(f) as *mut _) + } + } + + pub fn connect_warning(&self, f: F) -> u64 { + unsafe { + let f: Box_> = Box_::new(Box_::new(f)); + connect(self.to_glib_none().0, "warning", + transmute(warning_trampoline as usize), Box_::into_raw(f) as *mut _) + } + } } unsafe impl Send for Player {} unsafe impl Sync for Player {} -pub trait PlayerExt { - #[cfg(feature = "v1_12")] - fn config_set_seek_accurate(&self, accurate: bool); - - fn get_audio_video_offset(&self) -> i64; - - fn get_color_balance(&self, type_: PlayerColorBalanceType) -> f64; - - fn get_config(&self) -> Option; - - fn get_current_audio_track(&self) -> Option; - - fn get_current_subtitle_track(&self) -> Option; - - fn get_current_video_track(&self) -> Option; - - fn get_current_visualization(&self) -> Option; - - fn get_duration(&self) -> gst::ClockTime; - - fn get_media_info(&self) -> Option; - - //fn get_multiview_flags(&self) -> /*Ignored*/gst_video::VideoMultiviewFlags; - - //fn get_multiview_mode(&self) -> /*Ignored*/gst_video::VideoMultiviewMode; - - fn get_mute(&self) -> bool; - - fn get_pipeline(&self) -> Option; - - fn get_position(&self) -> gst::ClockTime; - - fn get_rate(&self) -> f64; - - fn get_subtitle_uri(&self) -> Option; - - fn get_uri(&self) -> Option; - - fn get_video_snapshot<'a, P: Into>>(&self, format: PlayerSnapshotFormat, config: P) -> Option; - - fn get_volume(&self) -> f64; - - fn has_color_balance(&self) -> bool; - - fn pause(&self); - - fn play(&self); - - fn seek(&self, position: gst::ClockTime); - - fn set_audio_track(&self, stream_index: i32) -> bool; - - fn set_audio_track_enabled(&self, enabled: bool); - - fn set_audio_video_offset(&self, offset: i64); - - fn set_color_balance(&self, type_: PlayerColorBalanceType, value: f64); - - fn set_config(&self, config: &mut gst::Structure) -> bool; - - //fn set_multiview_flags(&self, flags: /*Ignored*/gst_video::VideoMultiviewFlags); - - //fn set_multiview_mode(&self, mode: /*Ignored*/gst_video::VideoMultiviewMode); - - fn set_mute(&self, val: bool); - - fn set_rate(&self, rate: f64); - - fn set_subtitle_track(&self, stream_index: i32) -> bool; - - fn set_subtitle_track_enabled(&self, enabled: bool); - - fn set_subtitle_uri(&self, uri: &str); - - fn set_uri(&self, uri: &str); - - fn set_video_track(&self, stream_index: i32) -> bool; - - fn set_video_track_enabled(&self, enabled: bool); - - fn set_visualization(&self, name: &str) -> bool; - - fn set_visualization_enabled(&self, enabled: bool); - - fn set_volume(&self, val: f64); - - fn stop(&self); - - fn get_property_suburi(&self) -> Option; - - fn set_property_suburi(&self, suburi: Option<&str>); - - //fn get_property_video_multiview_flags(&self) -> /*Ignored*/gst_video::VideoMultiviewFlags; - - //fn set_property_video_multiview_flags(&self, video_multiview_flags: /*Ignored*/gst_video::VideoMultiviewFlags); - - //fn get_property_video_multiview_mode(&self) -> /*Ignored*/gst_video::VideoMultiviewFramePacking; - - //fn set_property_video_multiview_mode(&self, video_multiview_mode: /*Ignored*/gst_video::VideoMultiviewFramePacking); - - fn connect_buffering(&self, f: F) -> u64; - - fn connect_duration_changed(&self, f: F) -> u64; - - fn connect_end_of_stream(&self, f: F) -> u64; - - fn connect_error(&self, f: F) -> u64; - - fn connect_media_info_updated(&self, f: F) -> u64; - - fn connect_mute_changed(&self, f: F) -> u64; - - fn connect_position_updated(&self, f: F) -> u64; - - fn connect_seek_done(&self, f: F) -> u64; - - fn connect_state_changed(&self, f: F) -> u64; - - fn connect_uri_loaded(&self, f: F) -> u64; - - fn connect_video_dimensions_changed(&self, f: F) -> u64; - - fn connect_volume_changed(&self, f: F) -> u64; - - fn connect_warning(&self, f: F) -> u64; -} - -impl + IsA> PlayerExt for O { - #[cfg(feature = "v1_12")] - fn config_set_seek_accurate(&self, accurate: bool) { - unsafe { - ffi::gst_player_config_set_seek_accurate(self.to_glib_none().0, accurate.to_glib()); - } - } - - fn get_audio_video_offset(&self) -> i64 { - unsafe { - ffi::gst_player_get_audio_video_offset(self.to_glib_none().0) - } - } - - fn get_color_balance(&self, type_: PlayerColorBalanceType) -> f64 { - unsafe { - ffi::gst_player_get_color_balance(self.to_glib_none().0, type_.to_glib()) - } - } - - fn get_config(&self) -> Option { - unsafe { - from_glib_full(ffi::gst_player_get_config(self.to_glib_none().0)) - } - } - - fn get_current_audio_track(&self) -> Option { - unsafe { - from_glib_full(ffi::gst_player_get_current_audio_track(self.to_glib_none().0)) - } - } - - fn get_current_subtitle_track(&self) -> Option { - unsafe { - from_glib_none(ffi::gst_player_get_current_subtitle_track(self.to_glib_none().0)) - } - } - - fn get_current_video_track(&self) -> Option { - unsafe { - from_glib_full(ffi::gst_player_get_current_video_track(self.to_glib_none().0)) - } - } - - fn get_current_visualization(&self) -> Option { - unsafe { - from_glib_full(ffi::gst_player_get_current_visualization(self.to_glib_none().0)) - } - } - - fn get_duration(&self) -> gst::ClockTime { - unsafe { - ffi::gst_player_get_duration(self.to_glib_none().0) - } - } - - fn get_media_info(&self) -> Option { - unsafe { - from_glib_full(ffi::gst_player_get_media_info(self.to_glib_none().0)) - } - } - - //fn get_multiview_flags(&self) -> /*Ignored*/gst_video::VideoMultiviewFlags { - // unsafe { TODO: call ffi::gst_player_get_multiview_flags() } - //} - - //fn get_multiview_mode(&self) -> /*Ignored*/gst_video::VideoMultiviewMode { - // unsafe { TODO: call ffi::gst_player_get_multiview_mode() } - //} - - fn get_mute(&self) -> bool { - unsafe { - from_glib(ffi::gst_player_get_mute(self.to_glib_none().0)) - } - } - - fn get_pipeline(&self) -> Option { - unsafe { - from_glib_full(ffi::gst_player_get_pipeline(self.to_glib_none().0)) - } - } - - fn get_position(&self) -> gst::ClockTime { - unsafe { - ffi::gst_player_get_position(self.to_glib_none().0) - } - } - - fn get_rate(&self) -> f64 { - unsafe { - ffi::gst_player_get_rate(self.to_glib_none().0) - } - } - - fn get_subtitle_uri(&self) -> Option { - unsafe { - from_glib_full(ffi::gst_player_get_subtitle_uri(self.to_glib_none().0)) - } - } - - fn get_uri(&self) -> Option { - unsafe { - from_glib_full(ffi::gst_player_get_uri(self.to_glib_none().0)) - } - } - - fn get_video_snapshot<'a, P: Into>>(&self, format: PlayerSnapshotFormat, config: P) -> Option { - let config = config.into(); - unsafe { - from_glib_full(ffi::gst_player_get_video_snapshot(self.to_glib_none().0, format.to_glib(), config.to_glib_none_mut().0)) - } - } - - fn get_volume(&self) -> f64 { - unsafe { - ffi::gst_player_get_volume(self.to_glib_none().0) - } - } - - fn has_color_balance(&self) -> bool { - unsafe { - from_glib(ffi::gst_player_has_color_balance(self.to_glib_none().0)) - } - } - - fn pause(&self) { - unsafe { - ffi::gst_player_pause(self.to_glib_none().0); - } - } - - fn play(&self) { - unsafe { - ffi::gst_player_play(self.to_glib_none().0); - } - } - - fn seek(&self, position: gst::ClockTime) { - unsafe { - ffi::gst_player_seek(self.to_glib_none().0, position); - } - } - - fn set_audio_track(&self, stream_index: i32) -> bool { - unsafe { - from_glib(ffi::gst_player_set_audio_track(self.to_glib_none().0, stream_index)) - } - } - - fn set_audio_track_enabled(&self, enabled: bool) { - unsafe { - ffi::gst_player_set_audio_track_enabled(self.to_glib_none().0, enabled.to_glib()); - } - } - - fn set_audio_video_offset(&self, offset: i64) { - unsafe { - ffi::gst_player_set_audio_video_offset(self.to_glib_none().0, offset); - } - } - - fn set_color_balance(&self, type_: PlayerColorBalanceType, value: f64) { - unsafe { - ffi::gst_player_set_color_balance(self.to_glib_none().0, type_.to_glib(), value); - } - } - - fn set_config(&self, config: &mut gst::Structure) -> bool { - unsafe { - from_glib(ffi::gst_player_set_config(self.to_glib_none().0, config.to_glib_full())) - } - } - - //fn set_multiview_flags(&self, flags: /*Ignored*/gst_video::VideoMultiviewFlags) { - // unsafe { TODO: call ffi::gst_player_set_multiview_flags() } - //} - - //fn set_multiview_mode(&self, mode: /*Ignored*/gst_video::VideoMultiviewMode) { - // unsafe { TODO: call ffi::gst_player_set_multiview_mode() } - //} - - fn set_mute(&self, val: bool) { - unsafe { - ffi::gst_player_set_mute(self.to_glib_none().0, val.to_glib()); - } - } - - fn set_rate(&self, rate: f64) { - unsafe { - ffi::gst_player_set_rate(self.to_glib_none().0, rate); - } - } - - fn set_subtitle_track(&self, stream_index: i32) -> bool { - unsafe { - from_glib(ffi::gst_player_set_subtitle_track(self.to_glib_none().0, stream_index)) - } - } - - fn set_subtitle_track_enabled(&self, enabled: bool) { - unsafe { - ffi::gst_player_set_subtitle_track_enabled(self.to_glib_none().0, enabled.to_glib()); - } - } - - fn set_subtitle_uri(&self, uri: &str) { - unsafe { - ffi::gst_player_set_subtitle_uri(self.to_glib_none().0, uri.to_glib_none().0); - } - } - - fn set_uri(&self, uri: &str) { - unsafe { - ffi::gst_player_set_uri(self.to_glib_none().0, uri.to_glib_none().0); - } - } - - fn set_video_track(&self, stream_index: i32) -> bool { - unsafe { - from_glib(ffi::gst_player_set_video_track(self.to_glib_none().0, stream_index)) - } - } - - fn set_video_track_enabled(&self, enabled: bool) { - unsafe { - ffi::gst_player_set_video_track_enabled(self.to_glib_none().0, enabled.to_glib()); - } - } - - fn set_visualization(&self, name: &str) -> bool { - unsafe { - from_glib(ffi::gst_player_set_visualization(self.to_glib_none().0, name.to_glib_none().0)) - } - } - - fn set_visualization_enabled(&self, enabled: bool) { - unsafe { - ffi::gst_player_set_visualization_enabled(self.to_glib_none().0, enabled.to_glib()); - } - } - - fn set_volume(&self, val: f64) { - unsafe { - ffi::gst_player_set_volume(self.to_glib_none().0, val); - } - } - - fn stop(&self) { - unsafe { - ffi::gst_player_stop(self.to_glib_none().0); - } - } - - fn get_property_suburi(&self) -> Option { - let mut value = Value::from(None::<&str>); - unsafe { - gobject_ffi::g_object_get_property(self.to_glib_none().0, "suburi".to_glib_none().0, value.to_glib_none_mut().0); - } - value.get() - } - - fn set_property_suburi(&self, suburi: Option<&str>) { - unsafe { - gobject_ffi::g_object_set_property(self.to_glib_none().0, "suburi".to_glib_none().0, Value::from(suburi).to_glib_none().0); - } - } - - //fn get_property_video_multiview_flags(&self) -> /*Ignored*/gst_video::VideoMultiviewFlags { - // let mut value = Value::from(&0u32); - // unsafe { - // gobject_ffi::g_object_get_property(self.to_glib_none().0, "video-multiview-flags".to_glib_none().0, value.to_glib_none_mut().0); - // from_glib(transmute(value.get::().unwrap())) - // } - //} - - //fn set_property_video_multiview_flags(&self, video_multiview_flags: /*Ignored*/gst_video::VideoMultiviewFlags) { - // let video_multiview_flags = video_multiview_flags.to_glib().bits() as u32; - // unsafe { - // gobject_ffi::g_object_set_property(self.to_glib_none().0, "video-multiview-flags".to_glib_none().0, Value::from(&video_multiview_flags).to_glib_none().0); - // } - //} - - //fn get_property_video_multiview_mode(&self) -> /*Ignored*/gst_video::VideoMultiviewFramePacking { - // let mut value = Value::from(&0); - // unsafe { - // gobject_ffi::g_object_get_property(self.to_glib_none().0, "video-multiview-mode".to_glib_none().0, value.to_glib_none_mut().0); - // from_glib(transmute(value.get::().unwrap())) - // } - //} - - //fn set_property_video_multiview_mode(&self, video_multiview_mode: /*Ignored*/gst_video::VideoMultiviewFramePacking) { - // let video_multiview_mode = video_multiview_mode.to_glib() as i32; - // unsafe { - // gobject_ffi::g_object_set_property(self.to_glib_none().0, "video-multiview-mode".to_glib_none().0, Value::from(&video_multiview_mode).to_glib_none().0); - // } - //} - - fn connect_buffering(&self, f: F) -> u64 { - unsafe { - let f: Box_> = Box_::new(Box_::new(f)); - connect(self.to_glib_none().0, "buffering", - transmute(buffering_trampoline:: as usize), Box_::into_raw(f) as *mut _) - } - } - - fn connect_duration_changed(&self, f: F) -> u64 { - unsafe { - let f: Box_> = Box_::new(Box_::new(f)); - connect(self.to_glib_none().0, "duration-changed", - transmute(duration_changed_trampoline:: as usize), Box_::into_raw(f) as *mut _) - } - } - - fn connect_end_of_stream(&self, f: F) -> u64 { - unsafe { - let f: Box_> = Box_::new(Box_::new(f)); - connect(self.to_glib_none().0, "end-of-stream", - transmute(end_of_stream_trampoline:: as usize), Box_::into_raw(f) as *mut _) - } - } - - fn connect_error(&self, f: F) -> u64 { - unsafe { - let f: Box_> = Box_::new(Box_::new(f)); - connect(self.to_glib_none().0, "error", - transmute(error_trampoline:: as usize), Box_::into_raw(f) as *mut _) - } - } - - fn connect_media_info_updated(&self, f: F) -> u64 { - unsafe { - let f: Box_> = Box_::new(Box_::new(f)); - connect(self.to_glib_none().0, "media-info-updated", - transmute(media_info_updated_trampoline:: as usize), Box_::into_raw(f) as *mut _) - } - } - - fn connect_mute_changed(&self, f: F) -> u64 { - unsafe { - let f: Box_> = Box_::new(Box_::new(f)); - connect(self.to_glib_none().0, "mute-changed", - transmute(mute_changed_trampoline:: as usize), Box_::into_raw(f) as *mut _) - } - } - - fn connect_position_updated(&self, f: F) -> u64 { - unsafe { - let f: Box_> = Box_::new(Box_::new(f)); - connect(self.to_glib_none().0, "position-updated", - transmute(position_updated_trampoline:: as usize), Box_::into_raw(f) as *mut _) - } - } - - fn connect_seek_done(&self, f: F) -> u64 { - unsafe { - let f: Box_> = Box_::new(Box_::new(f)); - connect(self.to_glib_none().0, "seek-done", - transmute(seek_done_trampoline:: as usize), Box_::into_raw(f) as *mut _) - } - } - - fn connect_state_changed(&self, f: F) -> u64 { - unsafe { - let f: Box_> = Box_::new(Box_::new(f)); - connect(self.to_glib_none().0, "state-changed", - transmute(state_changed_trampoline:: as usize), Box_::into_raw(f) as *mut _) - } - } - - fn connect_uri_loaded(&self, f: F) -> u64 { - unsafe { - let f: Box_> = Box_::new(Box_::new(f)); - connect(self.to_glib_none().0, "uri-loaded", - transmute(uri_loaded_trampoline:: as usize), Box_::into_raw(f) as *mut _) - } - } - - fn connect_video_dimensions_changed(&self, f: F) -> u64 { - unsafe { - let f: Box_> = Box_::new(Box_::new(f)); - connect(self.to_glib_none().0, "video-dimensions-changed", - transmute(video_dimensions_changed_trampoline:: as usize), Box_::into_raw(f) as *mut _) - } - } - - fn connect_volume_changed(&self, f: F) -> u64 { - unsafe { - let f: Box_> = Box_::new(Box_::new(f)); - connect(self.to_glib_none().0, "volume-changed", - transmute(volume_changed_trampoline:: as usize), Box_::into_raw(f) as *mut _) - } - } - - fn connect_warning(&self, f: F) -> u64 { - unsafe { - let f: Box_> = Box_::new(Box_::new(f)); - connect(self.to_glib_none().0, "warning", - transmute(warning_trampoline:: as usize), Box_::into_raw(f) as *mut _) - } - } -} - -unsafe extern "C" fn buffering_trampoline

(this: *mut ffi::GstPlayer, object: libc::c_int, f: glib_ffi::gpointer) -where P: IsA { +unsafe extern "C" fn buffering_trampoline(this: *mut ffi::GstPlayer, object: libc::c_int, f: glib_ffi::gpointer) { callback_guard!(); - let f: &Box_ = transmute(f); - f(&Player::from_glib_none(this).downcast_unchecked(), object) + let f: &&(Fn(&Player, i32) + Send + 'static) = transmute(f); + f(&from_glib_none(this), object) } -unsafe extern "C" fn duration_changed_trampoline

(this: *mut ffi::GstPlayer, object: u64, f: glib_ffi::gpointer) -where P: IsA { +unsafe extern "C" fn duration_changed_trampoline(this: *mut ffi::GstPlayer, object: u64, f: glib_ffi::gpointer) { callback_guard!(); - let f: &Box_ = transmute(f); - f(&Player::from_glib_none(this).downcast_unchecked(), object) + let f: &&(Fn(&Player, u64) + Send + 'static) = transmute(f); + f(&from_glib_none(this), object) } -unsafe extern "C" fn end_of_stream_trampoline

(this: *mut ffi::GstPlayer, f: glib_ffi::gpointer) -where P: IsA { +unsafe extern "C" fn end_of_stream_trampoline(this: *mut ffi::GstPlayer, f: glib_ffi::gpointer) { callback_guard!(); - let f: &Box_ = transmute(f); - f(&Player::from_glib_none(this).downcast_unchecked()) + let f: &&(Fn(&Player) + Send + 'static) = transmute(f); + f(&from_glib_none(this)) } -unsafe extern "C" fn error_trampoline

(this: *mut ffi::GstPlayer, object: *mut glib_ffi::GError, f: glib_ffi::gpointer) -where P: IsA { +unsafe extern "C" fn error_trampoline(this: *mut ffi::GstPlayer, object: *mut glib_ffi::GError, f: glib_ffi::gpointer) { callback_guard!(); - let f: &Box_ = transmute(f); - f(&Player::from_glib_none(this).downcast_unchecked(), &from_glib_none(object)) + let f: &&(Fn(&Player, &Error) + Send + 'static) = transmute(f); + f(&from_glib_none(this), &from_glib_none(object)) } -unsafe extern "C" fn media_info_updated_trampoline

(this: *mut ffi::GstPlayer, object: *mut ffi::GstPlayerMediaInfo, f: glib_ffi::gpointer) -where P: IsA { +unsafe extern "C" fn media_info_updated_trampoline(this: *mut ffi::GstPlayer, object: *mut ffi::GstPlayerMediaInfo, f: glib_ffi::gpointer) { callback_guard!(); - let f: &Box_ = transmute(f); - f(&Player::from_glib_none(this).downcast_unchecked(), &from_glib_none(object)) + let f: &&(Fn(&Player, &PlayerMediaInfo) + Send + 'static) = transmute(f); + f(&from_glib_none(this), &from_glib_none(object)) } -unsafe extern "C" fn mute_changed_trampoline

(this: *mut ffi::GstPlayer, f: glib_ffi::gpointer) -where P: IsA { +unsafe extern "C" fn mute_changed_trampoline(this: *mut ffi::GstPlayer, f: glib_ffi::gpointer) { callback_guard!(); - let f: &Box_ = transmute(f); - f(&Player::from_glib_none(this).downcast_unchecked()) + let f: &&(Fn(&Player) + Send + 'static) = transmute(f); + f(&from_glib_none(this)) } -unsafe extern "C" fn position_updated_trampoline

(this: *mut ffi::GstPlayer, object: u64, f: glib_ffi::gpointer) -where P: IsA { +unsafe extern "C" fn position_updated_trampoline(this: *mut ffi::GstPlayer, object: u64, f: glib_ffi::gpointer) { callback_guard!(); - let f: &Box_ = transmute(f); - f(&Player::from_glib_none(this).downcast_unchecked(), object) + let f: &&(Fn(&Player, u64) + Send + Sync + 'static) = transmute(f); + f(&from_glib_none(this), object) } -unsafe extern "C" fn seek_done_trampoline

(this: *mut ffi::GstPlayer, object: u64, f: glib_ffi::gpointer) -where P: IsA { +unsafe extern "C" fn seek_done_trampoline(this: *mut ffi::GstPlayer, object: u64, f: glib_ffi::gpointer) { callback_guard!(); - let f: &Box_ = transmute(f); - f(&Player::from_glib_none(this).downcast_unchecked(), object) + let f: &&(Fn(&Player, u64) + Send + 'static) = transmute(f); + f(&from_glib_none(this), object) } -unsafe extern "C" fn state_changed_trampoline

(this: *mut ffi::GstPlayer, object: ffi::GstPlayerState, f: glib_ffi::gpointer) -where P: IsA { +unsafe extern "C" fn state_changed_trampoline(this: *mut ffi::GstPlayer, object: ffi::GstPlayerState, f: glib_ffi::gpointer) { callback_guard!(); - let f: &Box_ = transmute(f); - f(&Player::from_glib_none(this).downcast_unchecked(), from_glib(object)) + let f: &&(Fn(&Player, PlayerState) + Send + 'static) = transmute(f); + f(&from_glib_none(this), from_glib(object)) } -unsafe extern "C" fn uri_loaded_trampoline

(this: *mut ffi::GstPlayer, object: *mut libc::c_char, f: glib_ffi::gpointer) -where P: IsA { +unsafe extern "C" fn uri_loaded_trampoline(this: *mut ffi::GstPlayer, object: *mut libc::c_char, f: glib_ffi::gpointer) { callback_guard!(); - let f: &Box_ = transmute(f); - f(&Player::from_glib_none(this).downcast_unchecked(), &String::from_glib_none(object)) + let f: &&(Fn(&Player, &str) + Send + 'static) = transmute(f); + f(&from_glib_none(this), &String::from_glib_none(object)) } -unsafe extern "C" fn video_dimensions_changed_trampoline

(this: *mut ffi::GstPlayer, object: libc::c_int, p0: libc::c_int, f: glib_ffi::gpointer) -where P: IsA { +unsafe extern "C" fn video_dimensions_changed_trampoline(this: *mut ffi::GstPlayer, object: libc::c_int, p0: libc::c_int, f: glib_ffi::gpointer) { callback_guard!(); - let f: &Box_ = transmute(f); - f(&Player::from_glib_none(this).downcast_unchecked(), object, p0) + let f: &&(Fn(&Player, i32, i32) + Send + 'static) = transmute(f); + f(&from_glib_none(this), object, p0) } -unsafe extern "C" fn volume_changed_trampoline

(this: *mut ffi::GstPlayer, f: glib_ffi::gpointer) -where P: IsA { +unsafe extern "C" fn volume_changed_trampoline(this: *mut ffi::GstPlayer, f: glib_ffi::gpointer) { callback_guard!(); - let f: &Box_ = transmute(f); - f(&Player::from_glib_none(this).downcast_unchecked()) + let f: &&(Fn(&Player) + Send + 'static) = transmute(f); + f(&from_glib_none(this)) } -unsafe extern "C" fn warning_trampoline

(this: *mut ffi::GstPlayer, object: *mut glib_ffi::GError, f: glib_ffi::gpointer) -where P: IsA { +unsafe extern "C" fn warning_trampoline(this: *mut ffi::GstPlayer, object: *mut glib_ffi::GError, f: glib_ffi::gpointer) { callback_guard!(); - let f: &Box_ = transmute(f); - f(&Player::from_glib_none(this).downcast_unchecked(), &from_glib_none(object)) + let f: &&(Fn(&Player, &Error) + Send + 'static) = transmute(f); + f(&from_glib_none(this), &from_glib_none(object)) } diff --git a/gstreamer-player/src/auto/player_audio_info.rs b/gstreamer-player/src/auto/player_audio_info.rs index 1851060bd..bff45b4ab 100644 --- a/gstreamer-player/src/auto/player_audio_info.rs +++ b/gstreamer-player/src/auto/player_audio_info.rs @@ -1,4 +1,4 @@ -// This file was generated by gir (f00d658) from gir-files (???) +// This file was generated by gir (3294959) from gir-files (???) // DO NOT EDIT use PlayerStreamInfo; diff --git a/gstreamer-player/src/auto/player_g_main_context_signal_dispatcher.rs b/gstreamer-player/src/auto/player_g_main_context_signal_dispatcher.rs index 4170f817d..ac361ed86 100644 --- a/gstreamer-player/src/auto/player_g_main_context_signal_dispatcher.rs +++ b/gstreamer-player/src/auto/player_g_main_context_signal_dispatcher.rs @@ -1,4 +1,4 @@ -// This file was generated by gir (f00d658) from gir-files (???) +// This file was generated by gir (3294959) from gir-files (???) // DO NOT EDIT use PlayerSignalDispatcher; diff --git a/gstreamer-player/src/auto/player_media_info.rs b/gstreamer-player/src/auto/player_media_info.rs index d2edc403c..21e342eee 100644 --- a/gstreamer-player/src/auto/player_media_info.rs +++ b/gstreamer-player/src/auto/player_media_info.rs @@ -1,4 +1,4 @@ -// This file was generated by gir (f00d658) from gir-files (???) +// This file was generated by gir (3294959) from gir-files (???) // DO NOT EDIT use PlayerAudioInfo; @@ -34,16 +34,12 @@ pub trait PlayerMediaInfoExt { fn get_image_sample(&self) -> Option; - #[cfg(feature = "v1_12")] fn get_number_of_audio_streams(&self) -> u32; - #[cfg(feature = "v1_12")] fn get_number_of_streams(&self) -> u32; - #[cfg(feature = "v1_12")] fn get_number_of_subtitle_streams(&self) -> u32; - #[cfg(feature = "v1_12")] fn get_number_of_video_streams(&self) -> u32; fn get_stream_list(&self) -> Vec; @@ -88,28 +84,24 @@ impl> PlayerMediaInfoExt for O { } } - #[cfg(feature = "v1_12")] fn get_number_of_audio_streams(&self) -> u32 { unsafe { ffi::gst_player_media_info_get_number_of_audio_streams(self.to_glib_none().0) } } - #[cfg(feature = "v1_12")] fn get_number_of_streams(&self) -> u32 { unsafe { ffi::gst_player_media_info_get_number_of_streams(self.to_glib_none().0) } } - #[cfg(feature = "v1_12")] fn get_number_of_subtitle_streams(&self) -> u32 { unsafe { ffi::gst_player_media_info_get_number_of_subtitle_streams(self.to_glib_none().0) } } - #[cfg(feature = "v1_12")] fn get_number_of_video_streams(&self) -> u32 { unsafe { ffi::gst_player_media_info_get_number_of_video_streams(self.to_glib_none().0) diff --git a/gstreamer-player/src/auto/player_signal_dispatcher.rs b/gstreamer-player/src/auto/player_signal_dispatcher.rs index 93da41bbd..da678c4a5 100644 --- a/gstreamer-player/src/auto/player_signal_dispatcher.rs +++ b/gstreamer-player/src/auto/player_signal_dispatcher.rs @@ -1,4 +1,4 @@ -// This file was generated by gir (f00d658) from gir-files (???) +// This file was generated by gir (3294959) from gir-files (???) // DO NOT EDIT use ffi; diff --git a/gstreamer-player/src/auto/player_stream_info.rs b/gstreamer-player/src/auto/player_stream_info.rs index 6bec6a766..5fb5f243b 100644 --- a/gstreamer-player/src/auto/player_stream_info.rs +++ b/gstreamer-player/src/auto/player_stream_info.rs @@ -1,4 +1,4 @@ -// This file was generated by gir (f00d658) from gir-files (???) +// This file was generated by gir (3294959) from gir-files (???) // DO NOT EDIT use ffi; diff --git a/gstreamer-player/src/auto/player_subtitle_info.rs b/gstreamer-player/src/auto/player_subtitle_info.rs index 0d7e7cfac..3606b6086 100644 --- a/gstreamer-player/src/auto/player_subtitle_info.rs +++ b/gstreamer-player/src/auto/player_subtitle_info.rs @@ -1,4 +1,4 @@ -// This file was generated by gir (f00d658) from gir-files (???) +// This file was generated by gir (3294959) from gir-files (???) // DO NOT EDIT use PlayerStreamInfo; diff --git a/gstreamer-player/src/auto/player_video_info.rs b/gstreamer-player/src/auto/player_video_info.rs index 60b1c86c8..8be9d5bd3 100644 --- a/gstreamer-player/src/auto/player_video_info.rs +++ b/gstreamer-player/src/auto/player_video_info.rs @@ -1,4 +1,4 @@ -// This file was generated by gir (f00d658) from gir-files (???) +// This file was generated by gir (3294959) from gir-files (???) // DO NOT EDIT use PlayerStreamInfo; diff --git a/gstreamer-player/src/auto/player_video_overlay_video_renderer.rs b/gstreamer-player/src/auto/player_video_overlay_video_renderer.rs index 15eb17126..35ca0605b 100644 --- a/gstreamer-player/src/auto/player_video_overlay_video_renderer.rs +++ b/gstreamer-player/src/auto/player_video_overlay_video_renderer.rs @@ -1,4 +1,4 @@ -// This file was generated by gir (f00d658) from gir-files (???) +// This file was generated by gir (3294959) from gir-files (???) // DO NOT EDIT use PlayerVideoRenderer; diff --git a/gstreamer-player/src/auto/player_video_renderer.rs b/gstreamer-player/src/auto/player_video_renderer.rs index 3ac0665cb..15d0d2eb7 100644 --- a/gstreamer-player/src/auto/player_video_renderer.rs +++ b/gstreamer-player/src/auto/player_video_renderer.rs @@ -1,4 +1,4 @@ -// This file was generated by gir (f00d658) from gir-files (???) +// This file was generated by gir (3294959) from gir-files (???) // DO NOT EDIT use ffi; diff --git a/gstreamer-player/src/auto/player_visualization.rs b/gstreamer-player/src/auto/player_visualization.rs index 8d118cd19..d2bf7d404 100644 --- a/gstreamer-player/src/auto/player_visualization.rs +++ b/gstreamer-player/src/auto/player_visualization.rs @@ -1,4 +1,4 @@ -// This file was generated by gir (f00d658) from gir-files (???) +// This file was generated by gir (3294959) from gir-files (???) // DO NOT EDIT use ffi; diff --git a/gstreamer-player/src/lib.rs b/gstreamer-player/src/lib.rs new file mode 100644 index 000000000..15258b9a5 --- /dev/null +++ b/gstreamer-player/src/lib.rs @@ -0,0 +1,46 @@ +// 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. + +extern crate libc; + +extern crate glib_sys as glib_ffi; +extern crate gobject_sys as gobject_ffi; +extern crate gstreamer_sys as gst_ffi; +extern crate gstreamer_player_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 { + () => ( + ) +} + +macro_rules! assert_initialized_main_thread { + () => ( + ) +} + +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 player; diff --git a/gstreamer-player/src/player.rs b/gstreamer-player/src/player.rs new file mode 100644 index 000000000..00bcbed46 --- /dev/null +++ b/gstreamer-player/src/player.rs @@ -0,0 +1,46 @@ +// 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 Player; +use PlayerSignalDispatcher; +use PlayerVideoRenderer; +use ffi; +use glib::translate::*; +use gst; + +impl Player { + pub fn new( + video_renderer: Option<&PlayerVideoRenderer>, + signal_dispatcher: Option<&PlayerSignalDispatcher>, + ) -> Player { + assert_initialized_main_thread!(); + let (major, minor, _, _) = gst::version(); + if (major, minor) > (1, 12) { + let video_renderer = video_renderer.to_glib_full(); + let signal_dispatcher = signal_dispatcher.to_glib_full(); + unsafe { from_glib_full(ffi::gst_player_new(video_renderer, signal_dispatcher)) } + } else { + // Workaround for bad floating reference handling in 1.12. This issue was fixed for 1.13 in + // https://cgit.freedesktop.org/gstreamer/gst-plugins-bad/commit/gst-libs/gst/player/gstplayer.c?id=634cd87c76f58b5e1383715bafd5614db825c7d1 + let video_renderer = video_renderer.to_glib_none(); + let signal_dispatcher = signal_dispatcher.to_glib_none(); + unsafe { from_glib_none(ffi::gst_player_new(video_renderer.0, signal_dispatcher.0)) } + } + + } + + #[allow(dead_code)] + fn set_config(&self, config: gst::Structure) -> bool { + unsafe { + from_glib(ffi::gst_player_set_config( + self.to_glib_none().0, + config.into_ptr(), + )) + } + } +}