Commit 7dc2e43d authored by Sebastian Dröge's avatar Sebastian Dröge 🍵

Clean-up GstPlayer bindings

Various nullability, types and usability fixes. The player configuration
is a new type now that can deref to a structure
parent d3b03de9
......@@ -19,7 +19,6 @@ generate = [
"GstPlayer.PlayerSignalDispatcher",
"GstPlayer.PlayerSnapshotFormat",
"GstPlayer.PlayerState",
"GstPlayer.PlayerStreamInfo",
"GstPlayer.PlayerVideoRenderer",
"GstPlayer.PlayerVisualization",
]
......@@ -29,6 +28,8 @@ manual = [
"GLib.MainContext",
"GObject.Object",
"Gst.Element",
"GstVideo.VideoMultiviewFlags",
"GstVideo.VideoMultiviewFramePacking",
]
[[object]]
......@@ -64,13 +65,52 @@ trait = false
[[object.function]]
name = "set_config"
# Pass by value
# Custom type
ignore = true
[[object.function]]
name = "new"
ignore = true
[[object.function]]
name = "get_config"
# Custom type
ignore = true
[[object.function]]
pattern = "config_.*"
# Custom type
ignore = true
[[object.function]]
name = "get_pipeline"
[object.function.return]
nullable = false
[[object.function]]
name = "set_audio_track"
[object.function.return]
bool_return_is_error = "Failed to set audio track"
[[object.function]]
name = "set_subtitle_track"
[object.function.return]
bool_return_is_error = "Failed to set subtitle track"
[[object.function]]
name = "set_video_track"
[object.function.return]
bool_return_is_error = "Failed to set video track"
[[object.function]]
name = "set_visualization"
[[object.function.parameter]]
name = "name"
nullable = true
[object.function.return]
bool_return_is_error = "Failed to set visualization"
[[object.signal]]
name = "buffering"
concurrency = "send"
......@@ -129,6 +169,16 @@ trait = false
name = "warning"
concurrency = "send"
[[object]]
name = "GstPlayer.PlayerStreamInfo"
status = "generate"
[[object.function]]
name = "get_stream_type"
[object.function.return]
nullable = false
[[object]]
name = "GstPlayer.PlayerAudioInfo"
status = "generate"
......@@ -139,6 +189,16 @@ name = "GstPlayer.PlayerVideoInfo"
status = "generate"
trait = false
[[object.function]]
name = "get_framerate"
# Fraction
ignore = true
[[object.function]]
name = "get_pixel_aspect_ratio"
# Fraction
ignore = true
[[object]]
name = "GstPlayer.PlayerSubtitleInfo"
status = "generate"
......@@ -149,6 +209,11 @@ name = "GstPlayer.PlayerMediaInfo"
status = "generate"
trait = false
[[object.function]]
name = "get_uri"
[object.function.return]
nullable = false
[[object]]
name = "GstPlayer.PlayerVideoOverlayVideoRenderer"
status = "generate"
......
......@@ -405,8 +405,8 @@ The caller should free it with g_object_unref()</doc>
<doc xml:space="preserve">Retrieve the current value of the indicated @type.</doc>
<return-value transfer-ownership="none">
<doc xml:space="preserve">The current value of @type, Default: -1 "none"</doc>
<type name="GstVideo.VideoMultiviewMode"
c:type="GstVideoMultiviewMode"/>
<type name="GstVideo.VideoMultiviewFramePacking"
c:type="GstVideoMultiviewFramePacking"/>
</return-value>
<parameters>
<instance-parameter name="player" transfer-ownership="none">
......@@ -733,8 +733,8 @@ value.</doc>
</instance-parameter>
<parameter name="mode" transfer-ownership="none">
<doc xml:space="preserve">The new value for the @type</doc>
<type name="GstVideo.VideoMultiviewMode"
c:type="GstVideoMultiviewMode"/>
<type name="GstVideo.VideoMultiviewFramePacking"
c:type="GstVideoMultiviewFramePacking"/>
</parameter>
</parameters>
</method>
......
......@@ -17,9 +17,11 @@ bitflags = "1.0"
libc = "0.2"
glib-sys = { git = "https://github.com/gtk-rs/sys" }
gobject-sys = { git = "https://github.com/gtk-rs/sys" }
gstreamer-sys = { git = "https://github.com/sdroege/gstreamer-sys", features = ["v1_12"] }
gstreamer-player-sys = { git = "https://github.com/sdroege/gstreamer-sys", features = ["v1_12"] }
glib = { git = "https://github.com/gtk-rs/glib" }
gstreamer = { path = "../gstreamer", features = ["v1_12"] }
gstreamer-video = { path = "../gstreamer-video", features = ["v1_12"] }
[build-dependencies.rustdoc-stripper]
version = "0.1"
......
......@@ -11,6 +11,7 @@ use PlayerSubtitleInfo;
use PlayerVideoInfo;
use PlayerVisualization;
use ffi;
use glib;
use glib::StaticType;
use glib::Value;
use glib::signal::SignalHandlerId;
......@@ -19,6 +20,7 @@ use glib::translate::*;
use glib_ffi;
use gobject_ffi;
use gst;
use gst_video;
use libc;
use std::boxed::Box as Box_;
use std::mem;
......@@ -34,12 +36,6 @@ glib_wrapper! {
}
impl Player {
pub fn config_set_seek_accurate(&self, accurate: bool) {
unsafe {
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)
......@@ -52,12 +48,6 @@ impl Player {
}
}
pub fn get_config(&self) -> Option<gst::Structure> {
unsafe {
from_glib_full(ffi::gst_player_get_config(self.to_glib_none().0))
}
}
pub fn get_current_audio_track(&self) -> Option<PlayerAudioInfo> {
unsafe {
from_glib_full(ffi::gst_player_get_current_audio_track(self.to_glib_none().0))
......@@ -94,13 +84,17 @@ impl Player {
}
}
//pub fn get_multiview_flags(&self) -> /*Ignored*/gst_video::VideoMultiviewFlags {
// unsafe { TODO: call ffi::gst_player_get_multiview_flags() }
//}
pub fn get_multiview_flags(&self) -> gst_video::VideoMultiviewFlags {
unsafe {
from_glib(ffi::gst_player_get_multiview_flags(self.to_glib_none().0))
}
}
//pub fn get_multiview_mode(&self) -> /*Ignored*/gst_video::VideoMultiviewMode {
// unsafe { TODO: call ffi::gst_player_get_multiview_mode() }
//}
pub fn get_multiview_mode(&self) -> gst_video::VideoMultiviewFramePacking {
unsafe {
from_glib(ffi::gst_player_get_multiview_mode(self.to_glib_none().0))
}
}
pub fn get_mute(&self) -> bool {
unsafe {
......@@ -108,7 +102,7 @@ impl Player {
}
}
pub fn get_pipeline(&self) -> Option<gst::Element> {
pub fn get_pipeline(&self) -> gst::Element {
unsafe {
from_glib_full(ffi::gst_player_get_pipeline(self.to_glib_none().0))
}
......@@ -176,9 +170,9 @@ impl Player {
}
}
pub fn set_audio_track(&self, stream_index: i32) -> bool {
pub fn set_audio_track(&self, stream_index: i32) -> Result<(), glib::error::BoolError> {
unsafe {
from_glib(ffi::gst_player_set_audio_track(self.to_glib_none().0, stream_index))
glib::error::BoolError::from_glib(ffi::gst_player_set_audio_track(self.to_glib_none().0, stream_index), "Failed to set audio track")
}
}
......@@ -200,13 +194,17 @@ impl Player {
}
}
//pub fn set_multiview_flags(&self, flags: /*Ignored*/gst_video::VideoMultiviewFlags) {
// unsafe { TODO: call ffi::gst_player_set_multiview_flags() }
//}
pub fn set_multiview_flags(&self, flags: gst_video::VideoMultiviewFlags) {
unsafe {
ffi::gst_player_set_multiview_flags(self.to_glib_none().0, flags.to_glib());
}
}
//pub fn set_multiview_mode(&self, mode: /*Ignored*/gst_video::VideoMultiviewMode) {
// unsafe { TODO: call ffi::gst_player_set_multiview_mode() }
//}
pub fn set_multiview_mode(&self, mode: gst_video::VideoMultiviewFramePacking) {
unsafe {
ffi::gst_player_set_multiview_mode(self.to_glib_none().0, mode.to_glib());
}
}
pub fn set_mute(&self, val: bool) {
unsafe {
......@@ -220,9 +218,9 @@ impl Player {
}
}
pub fn set_subtitle_track(&self, stream_index: i32) -> bool {
pub fn set_subtitle_track(&self, stream_index: i32) -> Result<(), glib::error::BoolError> {
unsafe {
from_glib(ffi::gst_player_set_subtitle_track(self.to_glib_none().0, stream_index))
glib::error::BoolError::from_glib(ffi::gst_player_set_subtitle_track(self.to_glib_none().0, stream_index), "Failed to set subtitle track")
}
}
......@@ -244,9 +242,9 @@ impl Player {
}
}
pub fn set_video_track(&self, stream_index: i32) -> bool {
pub fn set_video_track(&self, stream_index: i32) -> Result<(), glib::error::BoolError> {
unsafe {
from_glib(ffi::gst_player_set_video_track(self.to_glib_none().0, stream_index))
glib::error::BoolError::from_glib(ffi::gst_player_set_video_track(self.to_glib_none().0, stream_index), "Failed to set video track")
}
}
......@@ -256,9 +254,11 @@ impl Player {
}
}
pub fn set_visualization(&self, name: &str) -> bool {
pub fn set_visualization<'a, P: Into<Option<&'a str>>>(&self, name: P) -> Result<(), glib::error::BoolError> {
let name = name.into();
let name = name.to_glib_none();
unsafe {
from_glib(ffi::gst_player_set_visualization(self.to_glib_none().0, name.to_glib_none().0))
glib::error::BoolError::from_glib(ffi::gst_player_set_visualization(self.to_glib_none().0, name.0), "Failed to set visualization")
}
}
......@@ -295,68 +295,33 @@ impl Player {
}
}
//pub fn get_property_video_multiview_flags(&self) -> /*Ignored*/gst_video::VideoMultiviewFlags {
// unsafe {
// let mut value = Value::uninitialized();
// gobject_ffi::g_value_init(value.to_glib_none_mut().0, </*Unknown type*/ as StaticType>::static_type().to_glib());
// gobject_ffi::g_object_get_property(self.to_glib_none().0, "video-multiview-flags".to_glib_none().0, value.to_glib_none_mut().0);
// value.get().unwrap()
// }
//}
//pub fn set_property_video_multiview_flags(&self, video_multiview_flags: /*Ignored*/gst_video::VideoMultiviewFlags) {
// 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 {
// unsafe {
// let mut value = Value::uninitialized();
// gobject_ffi::g_value_init(value.to_glib_none_mut().0, </*Unknown type*/ as StaticType>::static_type().to_glib());
// gobject_ffi::g_object_get_property(self.to_glib_none().0, "video-multiview-mode".to_glib_none().0, value.to_glib_none_mut().0);
// value.get().unwrap()
// }
//}
//pub fn set_property_video_multiview_mode(&self, video_multiview_mode: /*Ignored*/gst_video::VideoMultiviewFramePacking) {
// 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!();
pub fn get_property_video_multiview_flags(&self) -> gst_video::VideoMultiviewFlags {
unsafe {
ffi::gst_player_config_get_position_update_interval(config.to_glib_none().0)
}
}
pub fn config_get_seek_accurate(config: &gst::Structure) -> bool {
assert_initialized_main_thread!();
unsafe {
from_glib(ffi::gst_player_config_get_seek_accurate(config.to_glib_none().0))
let mut value = Value::uninitialized();
gobject_ffi::g_value_init(value.to_glib_none_mut().0, <gst_video::VideoMultiviewFlags as StaticType>::static_type().to_glib());
gobject_ffi::g_object_get_property(self.to_glib_none().0, "video-multiview-flags".to_glib_none().0, value.to_glib_none_mut().0);
value.get().unwrap()
}
}
pub fn config_get_user_agent(config: &gst::Structure) -> Option<String> {
assert_initialized_main_thread!();
pub fn set_property_video_multiview_flags(&self, video_multiview_flags: gst_video::VideoMultiviewFlags) {
unsafe {
from_glib_full(ffi::gst_player_config_get_user_agent(config.to_glib_none().0))
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 config_set_position_update_interval(config: &mut gst::Structure, interval: u32) {
assert_initialized_main_thread!();
pub fn get_property_video_multiview_mode(&self) -> gst_video::VideoMultiviewFramePacking {
unsafe {
ffi::gst_player_config_set_position_update_interval(config.to_glib_none_mut().0, interval);
let mut value = Value::uninitialized();
gobject_ffi::g_value_init(value.to_glib_none_mut().0, <gst_video::VideoMultiviewFramePacking as StaticType>::static_type().to_glib());
gobject_ffi::g_object_get_property(self.to_glib_none().0, "video-multiview-mode".to_glib_none().0, value.to_glib_none_mut().0);
value.get().unwrap()
}
}
pub fn config_set_user_agent(config: &mut gst::Structure, agent: &str) {
assert_initialized_main_thread!();
pub fn set_property_video_multiview_mode(&self, video_multiview_mode: gst_video::VideoMultiviewFramePacking) {
unsafe {
ffi::gst_player_config_set_user_agent(config.to_glib_none_mut().0, agent.to_glib_none().0);
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);
}
}
......
......@@ -94,7 +94,7 @@ impl PlayerMediaInfo {
}
}
pub fn get_uri(&self) -> Option<String> {
pub fn get_uri(&self) -> String {
unsafe {
from_glib_none(ffi::gst_player_media_info_get_uri(self.to_glib_none().0))
}
......
......@@ -28,7 +28,7 @@ pub trait PlayerStreamInfoExt {
fn get_index(&self) -> i32;
fn get_stream_type(&self) -> Option<String>;
fn get_stream_type(&self) -> String;
fn get_tags(&self) -> Option<gst::TagList>;
}
......@@ -52,7 +52,7 @@ impl<O: IsA<PlayerStreamInfo>> PlayerStreamInfoExt for O {
}
}
fn get_stream_type(&self) -> Option<String> {
fn get_stream_type(&self) -> String {
unsafe {
from_glib_none(ffi::gst_player_stream_info_get_stream_type(self.to_glib_none().0))
}
......
......@@ -24,15 +24,6 @@ impl PlayerVideoInfo {
}
}
pub fn get_framerate(&self) -> (i32, i32) {
unsafe {
let mut fps_n = mem::uninitialized();
let mut fps_d = mem::uninitialized();
ffi::gst_player_video_info_get_framerate(self.to_glib_none().0, &mut fps_n, &mut fps_d);
(fps_n, fps_d)
}
}
pub fn get_height(&self) -> i32 {
unsafe {
ffi::gst_player_video_info_get_height(self.to_glib_none().0)
......@@ -45,15 +36,6 @@ impl PlayerVideoInfo {
}
}
pub fn get_pixel_aspect_ratio(&self) -> (u32, u32) {
unsafe {
let mut par_n = mem::uninitialized();
let mut par_d = mem::uninitialized();
ffi::gst_player_video_info_get_pixel_aspect_ratio(self.to_glib_none().0, &mut par_n, &mut par_d);
(par_n, par_d)
}
}
pub fn get_width(&self) -> i32 {
unsafe {
ffi::gst_player_video_info_get_width(self.to_glib_none().0)
......
// Copyright (C) 2017 Sebastian Dröge <sebastian@centricular.com>
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use ffi;
use gst_ffi;
use glib::translate::*;
use gst;
use std::mem;
use std::ops;
#[derive(Debug, PartialEq, Eq)]
pub struct PlayerConfig(gst::Structure);
impl ops::Deref for PlayerConfig {
type Target = gst::StructureRef;
fn deref(&self) -> &gst::StructureRef {
self.0.deref()
}
}
impl ops::DerefMut for PlayerConfig {
fn deref_mut(&mut self) -> &mut gst::StructureRef {
self.0.deref_mut()
}
}
impl AsRef<gst::StructureRef> for PlayerConfig {
fn as_ref(&self) -> &gst::StructureRef {
self.0.as_ref()
}
}
impl AsMut<gst::StructureRef> for PlayerConfig {
fn as_mut(&mut self) -> &mut gst::StructureRef {
self.0.as_mut()
}
}
impl PlayerConfig {
pub fn get_position_update_interval(&self) -> u32 {
assert_initialized_main_thread!();
unsafe { ffi::gst_player_config_get_position_update_interval(self.0.to_glib_none().0) }
}
pub fn get_seek_accurate(&self) -> bool {
assert_initialized_main_thread!();
unsafe {
from_glib(ffi::gst_player_config_get_seek_accurate(
self.0.to_glib_none().0,
))
}
}
pub fn get_user_agent(&self) -> Option<String> {
assert_initialized_main_thread!();
unsafe {
from_glib_full(ffi::gst_player_config_get_user_agent(
self.0.to_glib_none().0,
))
}
}
pub fn set_position_update_interval(&mut self, interval: u32) {
assert_initialized_main_thread!();
unsafe {
ffi::gst_player_config_set_position_update_interval(
self.0.to_glib_none_mut().0,
interval,
);
}
}
pub fn set_seek_accurate(&mut self, accurate: bool) {
assert_initialized_main_thread!();
// FIXME: Work-around for
// http://cgit.freedesktop.org/gstreamer/gst-plugins-bad/commit/?id=cc58bd6ae071dec4ea7b4be626034accd0372755
self.set("accurate-seek", &accurate);
}
pub fn set_user_agent(&mut self, agent: &str) {
assert_initialized_main_thread!();
unsafe {
ffi::gst_player_config_set_user_agent(
self.0.to_glib_none_mut().0,
agent.to_glib_none().0,
);
}
}
pub unsafe fn into_ptr(mut self) -> *mut gst_ffi::GstStructure {
let ptr = self.0.to_glib_none_mut().0;
mem::forget(self);
ptr
}
}
impl FromGlibPtrFull<*mut gst_ffi::GstStructure> for PlayerConfig {
unsafe fn from_glib_full(ptr: *mut gst_ffi::GstStructure) -> Self {
PlayerConfig(from_glib_full(ptr))
}
}
......@@ -10,7 +10,9 @@ 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 as gst;
extern crate gstreamer_video as gst_video;
extern crate gstreamer_player_sys as ffi;
#[macro_use]
......@@ -44,9 +46,12 @@ mod auto;
pub use auto::*;
mod player;
mod config;
pub use config::*;
mod player_video_info;
mod player_video_overlay_video_renderer;
pub use player_video_overlay_video_renderer::PlayerVideoOverlayVideoRendererExtManual;
mod player_g_main_context_signal_dispatcher;
// Re-export all the traits in a prelude module, so that applications
......@@ -56,5 +61,4 @@ pub mod prelude {
pub use gst::prelude::*;
pub use auto::traits::*;
pub use player_video_overlay_video_renderer::PlayerVideoOverlayVideoRendererExtManual;
}
......@@ -11,6 +11,7 @@ use PlayerSignalDispatcher;
use PlayerVideoRenderer;
use ffi;
use glib_ffi;
use glib;
use glib::signal::SignalHandlerId;
use glib::signal::connect;
use glib::translate::*;
......@@ -37,55 +38,94 @@ impl Player {
}
}
pub fn set_config(&self, config: gst::Structure) -> bool {
pub fn get_config(&self) -> ::PlayerConfig {
unsafe { from_glib_full(ffi::gst_player_get_config(self.to_glib_none().0)) }
}
pub fn set_config(&self, config: ::PlayerConfig) -> Result<(), glib::error::BoolError> {
unsafe {
from_glib(ffi::gst_player_set_config(
self.to_glib_none().0,
config.into_ptr(),
))
glib::error::BoolError::from_glib(
ffi::gst_player_set_config(self.to_glib_none().0, config.into_ptr()),
"Failed to set config",
)
}
}
pub fn connect_duration_changed<F: Fn(&Player, gst::ClockTime) + Send + 'static>(&self, f: F) -> SignalHandlerId {
pub fn connect_duration_changed<F: Fn(&Player, gst::ClockTime) + Send + 'static>(
&self,
f: F,
) -> SignalHandlerId {
unsafe {
let f: Box_<Box_<Fn(&Player, gst::ClockTime) + Send + 'static>> = 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 _)
let f: Box_<Box_<Fn(&Player, gst::ClockTime) + Send + 'static>> =
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_position_updated<F: Fn(&Player, gst::ClockTime) + Send + 'static>(&self, f: F) -> SignalHandlerId {
pub fn connect_position_updated<F: Fn(&Player, gst::ClockTime) + Send + 'static>(
&self,
f: F,
) -> SignalHandlerId {
unsafe {
let f: Box_<Box_<Fn(&Player, gst::ClockTime) + Send + 'static>> = 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 _)
let f: Box_<Box_<Fn(&Player, gst::ClockTime) + Send + 'static>> =
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<F: Fn(&Player, gst::ClockTime) + Send + 'static>(&self, f: F) -> SignalHandlerId {
pub fn connect_seek_done<F: Fn(&Player, gst::ClockTime) + Send + 'static>(
&self,
f: F,
) -> SignalHandlerId {
unsafe {
let f: Box_<Box_<Fn(&Player, gst::ClockTime) + Send + 'static>> = 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 _)
let f: Box_<Box_<Fn(&Player, gst::ClockTime) + Send + 'static>> =
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 _,
)
}
}
}
unsafe extern "C" fn duration_changed_trampoline(this: *mut ffi::GstPlayer, object: u64, f: glib_ffi::gpointer) {
unsafe extern "C" fn duration_changed_trampoline(
this: *mut ffi::GstPlayer,
object: u64,
f: glib_ffi::gpointer,
) {
callback_guard!();
let f: &&(Fn(&Player, gst::ClockTime) + Send + 'static) = transmute(f);
f(&from_glib_borrow(this), gst::ClockTime(Some(object)))
}
unsafe extern "C" fn position_updated_trampoline(this: *mut ffi::GstPlayer, object: u64, f: glib_ffi::gpointer) {
unsafe extern "C" fn position_updated_trampoline(
this: *mut ffi::GstPlayer,
object: u64,
f: glib_ffi::gpointer,
) {
callback_guard!();
let f: &&(Fn(&Player, gst::ClockTime) + Send + Sync + 'static) = transmute(f);
f(&from_glib_borrow(this), gst::ClockTime(Some(object)))
}
unsafe extern "C" fn seek_done_trampoline(this: *mut ffi::GstPlayer, object: u64, f: glib_ffi::gpointer) {
unsafe extern "C" fn seek_done_trampoline(
this: *mut ffi::GstPlayer,
object: u64,
f: glib_ffi::gpointer,
) {
callback_guard!();
let f: &&(Fn(&Player, gst::ClockTime) + Send + 'static) = transmute(f);
f(&from_glib_borrow(this), gst::ClockTime(Some(object)))
......
// Copyright (C) 2017 Sebastian Dröge <sebastian@centricular.com>
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
use ffi;
use glib::translate::*;
use gst;
use PlayerVideoInfo;
use std::mem;
impl PlayerVideoInfo {
pub fn get_framerate(&self) -> gst::Fraction {
unsafe {
let mut fps_n = mem::uninitialized