video: Add GstNavigation interface "subclassing" support

This commit is contained in:
Thibault Saunier 2021-12-22 01:26:20 +00:00
parent 74e70eb580
commit 56dfe0fe59
10 changed files with 1121 additions and 3 deletions

View file

@ -20,6 +20,8 @@ generate = [
"GstVideo.ColorBalance",
"GstVideo.ColorBalanceChannel",
"GstVideo.ColorBalanceType",
"GstVideo.NavigationMessageType",
"GstVideo.NavigationQueryType",
"GstVideo.VideoAFDSpec",
"GstVideo.VideoAFDValue",
"GstVideo.VideoAggregatorParallelConvertPad",
@ -84,6 +86,129 @@ name = "Gst.ClockTime"
status = "manual"
conversion_type = "Option"
[[object]]
name = "Gst.Event"
status = "manual"
ref_mode = "ref"
[[object]]
name = "Gst.Query"
status = "manual"
ref_mode = "ref"
[[object]]
name = "gst.Structure"
status = "manual"
ref_mode = "ref"
[[object]]
name = "GstVideo.Navigation"
status = "generate"
[[object.function]]
name = "event_parse_key_event"
manual = true
[[object.function]]
name = "send_event"
manual = true
[[object.function]]
name = "event_parse_mouse_button_event"
manual = true
[[object.function]]
name = "event_parse_mouse_move_event"
manual = true
[[object.function]]
name = "event_parse_command"
manual = true
[[object.function]]
name = "message_parse_event"
manual = true
[[object.function]]
name = "message_get_type"
manual = true
[[object.function]]
name = "message_new_event"
manual = true
[[object.function]]
name = "event_parse_mouse_scroll_event"
manual = true
[[object.function]]
name = "event_get_type"
manual = true
[[object.function]]
name = "message_new_commands_changed"
ignore = true
[[object.function]]
name = "message_parse_angles_changed"
ignore = true
[[object.function]]
name = "message_new_mouse_over"
ignore = true
[[object.function]]
name = "message_parse_mouse_over"
ignore = true
[[object.function]]
name = "message_new_angles_changed"
ignore = true
[[object.function]]
name = "query_get_type"
ignore = true
[[object.function]]
name = "query_new_angles"
ignore = true
[[object.function]]
name = "query_new_commands"
ignore = true
[[object.function]]
name = "query_parse_angles"
ignore = true
[[object.function]]
name = "query_parse_commands_length"
ignore = true
[[object.function]]
name = "query_parse_commands_nth"
ignore = true
[[object.function]]
name = "query_set_angles"
ignore = true
[[object]]
name = "GstVideo.NavigationCommand"
status = "generate"
[[object.derive]]
name = "serde::Serialize, serde::Deserialize"
cfg_condition = "feature = \"ser_de\""
[[object.derive]]
name = "Debug, Eq, PartialEq, Ord, PartialOrd, Hash"
[[object]]
name = "GstVideo.NavigationEventType"
status = "generate"
[[object.member]]
name = "mouse_scroll"
version = "1.18"
[[object]]
name = "GstVideo.VideoBufferFlags"
status = "generate"

View file

@ -81,6 +81,382 @@ impl ToValue for ColorBalanceType {
}
}
#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Clone, Copy)]
#[non_exhaustive]
#[doc(alias = "GstNavigationCommand")]
pub enum NavigationCommand {
#[doc(alias = "GST_NAVIGATION_COMMAND_INVALID")]
Invalid,
#[doc(alias = "GST_NAVIGATION_COMMAND_MENU1")]
Menu1,
#[doc(alias = "GST_NAVIGATION_COMMAND_MENU2")]
Menu2,
#[doc(alias = "GST_NAVIGATION_COMMAND_MENU3")]
Menu3,
#[doc(alias = "GST_NAVIGATION_COMMAND_MENU4")]
Menu4,
#[doc(alias = "GST_NAVIGATION_COMMAND_MENU5")]
Menu5,
#[doc(alias = "GST_NAVIGATION_COMMAND_MENU6")]
Menu6,
#[doc(alias = "GST_NAVIGATION_COMMAND_MENU7")]
Menu7,
#[doc(alias = "GST_NAVIGATION_COMMAND_LEFT")]
Left,
#[doc(alias = "GST_NAVIGATION_COMMAND_RIGHT")]
Right,
#[doc(alias = "GST_NAVIGATION_COMMAND_UP")]
Up,
#[doc(alias = "GST_NAVIGATION_COMMAND_DOWN")]
Down,
#[doc(alias = "GST_NAVIGATION_COMMAND_ACTIVATE")]
Activate,
#[doc(alias = "GST_NAVIGATION_COMMAND_PREV_ANGLE")]
PrevAngle,
#[doc(alias = "GST_NAVIGATION_COMMAND_NEXT_ANGLE")]
NextAngle,
#[doc(hidden)]
__Unknown(i32),
}
#[doc(hidden)]
impl IntoGlib for NavigationCommand {
type GlibType = ffi::GstNavigationCommand;
fn into_glib(self) -> ffi::GstNavigationCommand {
match self {
Self::Invalid => ffi::GST_NAVIGATION_COMMAND_INVALID,
Self::Menu1 => ffi::GST_NAVIGATION_COMMAND_MENU1,
Self::Menu2 => ffi::GST_NAVIGATION_COMMAND_MENU2,
Self::Menu3 => ffi::GST_NAVIGATION_COMMAND_MENU3,
Self::Menu4 => ffi::GST_NAVIGATION_COMMAND_MENU4,
Self::Menu5 => ffi::GST_NAVIGATION_COMMAND_MENU5,
Self::Menu6 => ffi::GST_NAVIGATION_COMMAND_MENU6,
Self::Menu7 => ffi::GST_NAVIGATION_COMMAND_MENU7,
Self::Left => ffi::GST_NAVIGATION_COMMAND_LEFT,
Self::Right => ffi::GST_NAVIGATION_COMMAND_RIGHT,
Self::Up => ffi::GST_NAVIGATION_COMMAND_UP,
Self::Down => ffi::GST_NAVIGATION_COMMAND_DOWN,
Self::Activate => ffi::GST_NAVIGATION_COMMAND_ACTIVATE,
Self::PrevAngle => ffi::GST_NAVIGATION_COMMAND_PREV_ANGLE,
Self::NextAngle => ffi::GST_NAVIGATION_COMMAND_NEXT_ANGLE,
Self::__Unknown(value) => value,
}
}
}
#[doc(hidden)]
impl FromGlib<ffi::GstNavigationCommand> for NavigationCommand {
unsafe fn from_glib(value: ffi::GstNavigationCommand) -> Self {
skip_assert_initialized!();
match value {
ffi::GST_NAVIGATION_COMMAND_INVALID => Self::Invalid,
ffi::GST_NAVIGATION_COMMAND_MENU1 => Self::Menu1,
ffi::GST_NAVIGATION_COMMAND_MENU2 => Self::Menu2,
ffi::GST_NAVIGATION_COMMAND_MENU3 => Self::Menu3,
ffi::GST_NAVIGATION_COMMAND_MENU4 => Self::Menu4,
ffi::GST_NAVIGATION_COMMAND_MENU5 => Self::Menu5,
ffi::GST_NAVIGATION_COMMAND_MENU6 => Self::Menu6,
ffi::GST_NAVIGATION_COMMAND_MENU7 => Self::Menu7,
ffi::GST_NAVIGATION_COMMAND_LEFT => Self::Left,
ffi::GST_NAVIGATION_COMMAND_RIGHT => Self::Right,
ffi::GST_NAVIGATION_COMMAND_UP => Self::Up,
ffi::GST_NAVIGATION_COMMAND_DOWN => Self::Down,
ffi::GST_NAVIGATION_COMMAND_ACTIVATE => Self::Activate,
ffi::GST_NAVIGATION_COMMAND_PREV_ANGLE => Self::PrevAngle,
ffi::GST_NAVIGATION_COMMAND_NEXT_ANGLE => Self::NextAngle,
value => Self::__Unknown(value),
}
}
}
impl StaticType for NavigationCommand {
fn static_type() -> Type {
unsafe { from_glib(ffi::gst_navigation_command_get_type()) }
}
}
impl glib::value::ValueType for NavigationCommand {
type Type = Self;
}
unsafe impl<'a> FromValue<'a> for NavigationCommand {
type Checker = glib::value::GenericValueTypeChecker<Self>;
unsafe fn from_value(value: &'a glib::Value) -> Self {
skip_assert_initialized!();
from_glib(glib::gobject_ffi::g_value_get_enum(value.to_glib_none().0))
}
}
impl ToValue for NavigationCommand {
fn to_value(&self) -> glib::Value {
let mut value = glib::Value::for_value_type::<Self>();
unsafe {
glib::gobject_ffi::g_value_set_enum(value.to_glib_none_mut().0, self.into_glib());
}
value
}
fn value_type(&self) -> glib::Type {
Self::static_type()
}
}
#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Clone, Copy)]
#[non_exhaustive]
#[doc(alias = "GstNavigationEventType")]
pub enum NavigationEventType {
#[doc(alias = "GST_NAVIGATION_EVENT_INVALID")]
Invalid,
#[doc(alias = "GST_NAVIGATION_EVENT_KEY_PRESS")]
KeyPress,
#[doc(alias = "GST_NAVIGATION_EVENT_KEY_RELEASE")]
KeyRelease,
#[doc(alias = "GST_NAVIGATION_EVENT_MOUSE_BUTTON_PRESS")]
MouseButtonPress,
#[doc(alias = "GST_NAVIGATION_EVENT_MOUSE_BUTTON_RELEASE")]
MouseButtonRelease,
#[doc(alias = "GST_NAVIGATION_EVENT_MOUSE_MOVE")]
MouseMove,
#[doc(alias = "GST_NAVIGATION_EVENT_COMMAND")]
Command,
#[cfg(any(feature = "v1_18", feature = "dox"))]
#[cfg_attr(feature = "dox", doc(cfg(feature = "v1_18")))]
#[doc(alias = "GST_NAVIGATION_EVENT_MOUSE_SCROLL")]
MouseScroll,
#[doc(hidden)]
__Unknown(i32),
}
#[doc(hidden)]
impl IntoGlib for NavigationEventType {
type GlibType = ffi::GstNavigationEventType;
fn into_glib(self) -> ffi::GstNavigationEventType {
match self {
Self::Invalid => ffi::GST_NAVIGATION_EVENT_INVALID,
Self::KeyPress => ffi::GST_NAVIGATION_EVENT_KEY_PRESS,
Self::KeyRelease => ffi::GST_NAVIGATION_EVENT_KEY_RELEASE,
Self::MouseButtonPress => ffi::GST_NAVIGATION_EVENT_MOUSE_BUTTON_PRESS,
Self::MouseButtonRelease => ffi::GST_NAVIGATION_EVENT_MOUSE_BUTTON_RELEASE,
Self::MouseMove => ffi::GST_NAVIGATION_EVENT_MOUSE_MOVE,
Self::Command => ffi::GST_NAVIGATION_EVENT_COMMAND,
#[cfg(any(feature = "v1_18", feature = "dox"))]
Self::MouseScroll => ffi::GST_NAVIGATION_EVENT_MOUSE_SCROLL,
Self::__Unknown(value) => value,
}
}
}
#[doc(hidden)]
impl FromGlib<ffi::GstNavigationEventType> for NavigationEventType {
unsafe fn from_glib(value: ffi::GstNavigationEventType) -> Self {
skip_assert_initialized!();
match value {
ffi::GST_NAVIGATION_EVENT_INVALID => Self::Invalid,
ffi::GST_NAVIGATION_EVENT_KEY_PRESS => Self::KeyPress,
ffi::GST_NAVIGATION_EVENT_KEY_RELEASE => Self::KeyRelease,
ffi::GST_NAVIGATION_EVENT_MOUSE_BUTTON_PRESS => Self::MouseButtonPress,
ffi::GST_NAVIGATION_EVENT_MOUSE_BUTTON_RELEASE => Self::MouseButtonRelease,
ffi::GST_NAVIGATION_EVENT_MOUSE_MOVE => Self::MouseMove,
ffi::GST_NAVIGATION_EVENT_COMMAND => Self::Command,
#[cfg(any(feature = "v1_18", feature = "dox"))]
ffi::GST_NAVIGATION_EVENT_MOUSE_SCROLL => Self::MouseScroll,
value => Self::__Unknown(value),
}
}
}
impl StaticType for NavigationEventType {
fn static_type() -> Type {
unsafe { from_glib(ffi::gst_navigation_event_type_get_type()) }
}
}
impl glib::value::ValueType for NavigationEventType {
type Type = Self;
}
unsafe impl<'a> FromValue<'a> for NavigationEventType {
type Checker = glib::value::GenericValueTypeChecker<Self>;
unsafe fn from_value(value: &'a glib::Value) -> Self {
skip_assert_initialized!();
from_glib(glib::gobject_ffi::g_value_get_enum(value.to_glib_none().0))
}
}
impl ToValue for NavigationEventType {
fn to_value(&self) -> glib::Value {
let mut value = glib::Value::for_value_type::<Self>();
unsafe {
glib::gobject_ffi::g_value_set_enum(value.to_glib_none_mut().0, self.into_glib());
}
value
}
fn value_type(&self) -> glib::Type {
Self::static_type()
}
}
#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Clone, Copy)]
#[non_exhaustive]
#[doc(alias = "GstNavigationMessageType")]
pub enum NavigationMessageType {
#[doc(alias = "GST_NAVIGATION_MESSAGE_INVALID")]
Invalid,
#[doc(alias = "GST_NAVIGATION_MESSAGE_MOUSE_OVER")]
MouseOver,
#[doc(alias = "GST_NAVIGATION_MESSAGE_COMMANDS_CHANGED")]
CommandsChanged,
#[doc(alias = "GST_NAVIGATION_MESSAGE_ANGLES_CHANGED")]
AnglesChanged,
#[doc(alias = "GST_NAVIGATION_MESSAGE_EVENT")]
Event,
#[doc(hidden)]
__Unknown(i32),
}
#[doc(hidden)]
impl IntoGlib for NavigationMessageType {
type GlibType = ffi::GstNavigationMessageType;
fn into_glib(self) -> ffi::GstNavigationMessageType {
match self {
Self::Invalid => ffi::GST_NAVIGATION_MESSAGE_INVALID,
Self::MouseOver => ffi::GST_NAVIGATION_MESSAGE_MOUSE_OVER,
Self::CommandsChanged => ffi::GST_NAVIGATION_MESSAGE_COMMANDS_CHANGED,
Self::AnglesChanged => ffi::GST_NAVIGATION_MESSAGE_ANGLES_CHANGED,
Self::Event => ffi::GST_NAVIGATION_MESSAGE_EVENT,
Self::__Unknown(value) => value,
}
}
}
#[doc(hidden)]
impl FromGlib<ffi::GstNavigationMessageType> for NavigationMessageType {
unsafe fn from_glib(value: ffi::GstNavigationMessageType) -> Self {
skip_assert_initialized!();
match value {
ffi::GST_NAVIGATION_MESSAGE_INVALID => Self::Invalid,
ffi::GST_NAVIGATION_MESSAGE_MOUSE_OVER => Self::MouseOver,
ffi::GST_NAVIGATION_MESSAGE_COMMANDS_CHANGED => Self::CommandsChanged,
ffi::GST_NAVIGATION_MESSAGE_ANGLES_CHANGED => Self::AnglesChanged,
ffi::GST_NAVIGATION_MESSAGE_EVENT => Self::Event,
value => Self::__Unknown(value),
}
}
}
impl StaticType for NavigationMessageType {
fn static_type() -> Type {
unsafe { from_glib(ffi::gst_navigation_message_type_get_type()) }
}
}
impl glib::value::ValueType for NavigationMessageType {
type Type = Self;
}
unsafe impl<'a> FromValue<'a> for NavigationMessageType {
type Checker = glib::value::GenericValueTypeChecker<Self>;
unsafe fn from_value(value: &'a glib::Value) -> Self {
skip_assert_initialized!();
from_glib(glib::gobject_ffi::g_value_get_enum(value.to_glib_none().0))
}
}
impl ToValue for NavigationMessageType {
fn to_value(&self) -> glib::Value {
let mut value = glib::Value::for_value_type::<Self>();
unsafe {
glib::gobject_ffi::g_value_set_enum(value.to_glib_none_mut().0, self.into_glib());
}
value
}
fn value_type(&self) -> glib::Type {
Self::static_type()
}
}
#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Clone, Copy)]
#[non_exhaustive]
#[doc(alias = "GstNavigationQueryType")]
pub enum NavigationQueryType {
#[doc(alias = "GST_NAVIGATION_QUERY_INVALID")]
Invalid,
#[doc(alias = "GST_NAVIGATION_QUERY_COMMANDS")]
Commands,
#[doc(alias = "GST_NAVIGATION_QUERY_ANGLES")]
Angles,
#[doc(hidden)]
__Unknown(i32),
}
#[doc(hidden)]
impl IntoGlib for NavigationQueryType {
type GlibType = ffi::GstNavigationQueryType;
fn into_glib(self) -> ffi::GstNavigationQueryType {
match self {
Self::Invalid => ffi::GST_NAVIGATION_QUERY_INVALID,
Self::Commands => ffi::GST_NAVIGATION_QUERY_COMMANDS,
Self::Angles => ffi::GST_NAVIGATION_QUERY_ANGLES,
Self::__Unknown(value) => value,
}
}
}
#[doc(hidden)]
impl FromGlib<ffi::GstNavigationQueryType> for NavigationQueryType {
unsafe fn from_glib(value: ffi::GstNavigationQueryType) -> Self {
skip_assert_initialized!();
match value {
ffi::GST_NAVIGATION_QUERY_INVALID => Self::Invalid,
ffi::GST_NAVIGATION_QUERY_COMMANDS => Self::Commands,
ffi::GST_NAVIGATION_QUERY_ANGLES => Self::Angles,
value => Self::__Unknown(value),
}
}
}
impl StaticType for NavigationQueryType {
fn static_type() -> Type {
unsafe { from_glib(ffi::gst_navigation_query_type_get_type()) }
}
}
impl glib::value::ValueType for NavigationQueryType {
type Type = Self;
}
unsafe impl<'a> FromValue<'a> for NavigationQueryType {
type Checker = glib::value::GenericValueTypeChecker<Self>;
unsafe fn from_value(value: &'a glib::Value) -> Self {
skip_assert_initialized!();
from_glib(glib::gobject_ffi::g_value_get_enum(value.to_glib_none().0))
}
}
impl ToValue for NavigationQueryType {
fn to_value(&self) -> glib::Value {
let mut value = glib::Value::for_value_type::<Self>();
unsafe {
glib::gobject_ffi::g_value_set_enum(value.to_glib_none_mut().0, self.into_glib());
}
value
}
fn value_type(&self) -> glib::Type {
Self::static_type()
}
}
#[cfg(any(feature = "v1_18", feature = "dox"))]
#[cfg_attr(feature = "dox", doc(cfg(feature = "v1_18")))]
#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Clone, Copy)]

View file

@ -9,6 +9,9 @@ pub use self::color_balance::ColorBalance;
mod color_balance_channel;
pub use self::color_balance_channel::ColorBalanceChannel;
mod navigation;
pub use self::navigation::Navigation;
#[cfg(any(feature = "v1_20", feature = "dox"))]
#[cfg_attr(feature = "dox", doc(cfg(feature = "v1_20")))]
mod video_aggregator_parallel_convert_pad;
@ -39,6 +42,10 @@ pub use self::video_sink::VideoSink;
mod enums;
pub use self::enums::ColorBalanceType;
pub use self::enums::NavigationCommand;
pub use self::enums::NavigationEventType;
pub use self::enums::NavigationMessageType;
pub use self::enums::NavigationQueryType;
#[cfg(any(feature = "v1_18", feature = "dox"))]
#[cfg_attr(feature = "dox", doc(cfg(feature = "v1_18")))]
pub use self::enums::VideoAFDSpec;
@ -91,6 +98,7 @@ pub use self::flags::VideoTimeCodeFlags;
pub mod traits {
pub use super::color_balance::ColorBalanceExt;
pub use super::color_balance_channel::ColorBalanceChannelExt;
pub use super::navigation::NavigationExt;
pub use super::video_decoder::VideoDecoderExt;
pub use super::video_encoder::VideoEncoderExt;
pub use super::video_orientation::VideoOrientationExt;

View file

@ -0,0 +1,94 @@
// This file was generated by gir (https://github.com/gtk-rs/gir)
// from gir-files (https://github.com/gtk-rs/gir-files)
// from gst-gir-files (https://gitlab.freedesktop.org/gstreamer/gir-files-rs.git)
// DO NOT EDIT
use crate::NavigationCommand;
use glib::object::IsA;
use glib::translate::*;
glib::wrapper! {
#[doc(alias = "GstNavigation")]
pub struct Navigation(Interface<ffi::GstNavigation, ffi::GstNavigationInterface>);
match fn {
type_ => || ffi::gst_navigation_get_type(),
}
}
impl Navigation {
pub const NONE: Option<&'static Navigation> = None;
//#[doc(alias = "gst_navigation_query_set_commands")]
//pub fn query_set_commands(query: &gst::Query, n_cmds: i32, : /*Unknown conversion*//*Unimplemented*/Fundamental: VarArgs) {
// unsafe { TODO: call ffi:gst_navigation_query_set_commands() }
//}
//#[doc(alias = "gst_navigation_query_set_commandsv")]
//pub fn query_set_commandsv(query: &gst::Query, cmds: /*Unimplemented*/&CArray TypeId { ns_id: 1, id: 6 }) {
// unsafe { TODO: call ffi:gst_navigation_query_set_commandsv() }
//}
}
unsafe impl Send for Navigation {}
unsafe impl Sync for Navigation {}
pub trait NavigationExt: 'static {
#[doc(alias = "gst_navigation_send_command")]
fn send_command(&self, command: NavigationCommand);
#[doc(alias = "gst_navigation_send_key_event")]
fn send_key_event(&self, event: &str, key: &str);
#[doc(alias = "gst_navigation_send_mouse_event")]
fn send_mouse_event(&self, event: &str, button: i32, x: f64, y: f64);
#[cfg(any(feature = "v1_18", feature = "dox"))]
#[cfg_attr(feature = "dox", doc(cfg(feature = "v1_18")))]
#[doc(alias = "gst_navigation_send_mouse_scroll_event")]
fn send_mouse_scroll_event(&self, x: f64, y: f64, delta_x: f64, delta_y: f64);
}
impl<O: IsA<Navigation>> NavigationExt for O {
fn send_command(&self, command: NavigationCommand) {
unsafe {
ffi::gst_navigation_send_command(self.as_ref().to_glib_none().0, command.into_glib());
}
}
fn send_key_event(&self, event: &str, key: &str) {
unsafe {
ffi::gst_navigation_send_key_event(
self.as_ref().to_glib_none().0,
event.to_glib_none().0,
key.to_glib_none().0,
);
}
}
fn send_mouse_event(&self, event: &str, button: i32, x: f64, y: f64) {
unsafe {
ffi::gst_navigation_send_mouse_event(
self.as_ref().to_glib_none().0,
event.to_glib_none().0,
button,
x,
y,
);
}
}
#[cfg(any(feature = "v1_18", feature = "dox"))]
#[cfg_attr(feature = "dox", doc(cfg(feature = "v1_18")))]
fn send_mouse_scroll_event(&self, x: f64, y: f64, delta_x: f64, delta_y: f64) {
unsafe {
ffi::gst_navigation_send_mouse_scroll_event(
self.as_ref().to_glib_none().0,
x,
y,
delta_x,
delta_y,
);
}
}
}

View file

@ -30,6 +30,8 @@ macro_rules! skip_assert_initialized {
mod auto;
pub use crate::auto::*;
mod navigation;
mod caps_features;
#[cfg(any(feature = "v1_16", feature = "dox"))]
#[cfg_attr(feature = "dox", doc(cfg(feature = "v1_16")))]
@ -54,10 +56,19 @@ pub mod video_frame;
pub use crate::video_frame::{VideoFrame, VideoFrameRef};
mod video_overlay;
pub use crate::video_overlay::is_video_overlay_prepare_window_handle_message;
pub mod video_event;
#[cfg(any(feature = "v1_18", feature = "dox"))]
#[cfg_attr(feature = "dox", doc(cfg(feature = "v1_18")))]
pub use crate::video_event::MouseScrollEvent;
pub use crate::video_event::{
DownstreamForceKeyUnitEvent, ForceKeyUnitEvent, StillFrameEvent, UpstreamForceKeyUnitEvent,
CommandEvent, DownstreamForceKeyUnitEvent, ForceKeyUnitEvent, KeyEvent, MouseButtonEvent,
MouseMoveEvent, NavigationEvent, StillFrameEvent, UpstreamForceKeyUnitEvent,
};
pub mod video_message;
pub use crate::video_message::{NavigationEventMessage, NavigationMessage};
mod functions;
pub use crate::functions::*;
mod video_rectangle;
@ -126,6 +137,7 @@ pub mod prelude {
pub use gst_base::prelude::*;
pub use crate::auto::traits::*;
pub use crate::navigation::NavigationExtManual;
pub use crate::video_buffer_pool::VideoBufferPoolConfig;
pub use crate::video_decoder::VideoDecoderExtManual;
pub use crate::video_encoder::VideoEncoderExtManual;

View file

@ -0,0 +1,16 @@
use crate::auto::Navigation;
use glib::object::IsA;
use glib::translate::ToGlibPtr;
pub trait NavigationExtManual: 'static {
#[doc(alias = "gst_navigation_send_event")]
fn send_event(&self, structure: gst::Structure);
}
impl<O: IsA<Navigation>> NavigationExtManual for O {
fn send_event(&self, structure: gst::Structure) {
unsafe {
ffi::gst_navigation_send_event(self.as_ref().to_glib_none().0, structure.into_ptr());
}
}
}

View file

@ -2,6 +2,7 @@
#![allow(clippy::cast_ptr_alignment)]
mod navigation;
mod video_decoder;
mod video_encoder;
mod video_filter;
@ -11,6 +12,7 @@ pub mod prelude {
#[doc(hidden)]
pub use gst_base::subclass::prelude::*;
pub use super::navigation::NavigationImpl;
pub use super::video_decoder::{VideoDecoderImpl, VideoDecoderImplExt};
pub use super::video_encoder::{VideoEncoderImpl, VideoEncoderImplExt};
pub use super::video_filter::{VideoFilterImpl, VideoFilterImplExt};

View file

@ -0,0 +1,59 @@
// Take a look at the license at the top of the repository in the LICENSE file.
use glib::prelude::*;
use glib::translate::*;
use glib::subclass::prelude::*;
use gst::ffi::GstStructure;
use crate::Navigation;
pub trait NavigationImpl: ObjectImpl {
fn send_event(&self, nav: &Self::Type, structure: gst::Structure);
}
pub trait NavigationImplExt: ObjectSubclass {
fn parent_send_event(&self, nav: &Self::Type, structure: gst::Structure);
}
impl<T: NavigationImpl> NavigationImplExt for T {
fn parent_send_event(&self, nav: &Self::Type, structure: gst::Structure) {
unsafe {
let type_data = Self::type_data();
let parent_iface = type_data.as_ref().parent_interface::<Navigation>()
as *const ffi::GstNavigationInterface;
let func = match (*parent_iface).send_event {
Some(func) => func,
None => return,
};
func(
nav.unsafe_cast_ref::<Navigation>().to_glib_none().0,
structure.into_ptr(),
);
}
}
}
unsafe impl<T: NavigationImpl> IsImplementable<T> for Navigation {
fn interface_init(iface: &mut glib::Interface<Self>) {
let iface = iface.as_mut();
iface.send_event = Some(navigation_send_event::<T>);
}
}
unsafe extern "C" fn navigation_send_event<T: NavigationImpl>(
nav: *mut ffi::GstNavigation,
structure: *mut GstStructure,
) {
let instance = &*(nav as *mut T::Instance);
let imp = instance.impl_();
imp.send_event(
from_glib_borrow::<_, Navigation>(nav).unsafe_cast_ref(),
from_glib_full(structure),
);
}

View file

@ -1,8 +1,9 @@
// Take a look at the license at the top of the repository in the LICENSE file.
use glib::translate::{from_glib, from_glib_full, IntoGlib};
use crate::{NavigationCommand, NavigationEventType};
use glib::translate::{from_glib, from_glib_none, from_glib_full, IntoGlib};
use glib::ToSendValue;
use std::mem;
use std::{mem, ptr};
// FIXME: Copy from gstreamer/src/event.rs
macro_rules! event_builder_generic_impl {
@ -349,3 +350,213 @@ impl StillFrameEvent {
}
}
}
#[derive(Clone, PartialEq, Debug)]
pub struct KeyEvent {
pub key: String,
}
impl KeyEvent {
#[doc(alias = "gst_navigation_event_parse_key_event")]
pub fn parse(event: &gst::EventRef) -> Result<Self, glib::error::BoolError> {
assert_initialized_main_thread!();
unsafe {
let mut key = ptr::null();
let ret = from_glib(ffi::gst_navigation_event_parse_key_event(
event.as_mut_ptr(),
&mut key,
));
if ret {
Ok(Self {
key: from_glib_none(key),
})
} else {
Err(glib::bool_error!("Invalid key event"))
}
}
}
}
#[derive(Clone, PartialEq, Debug)]
pub struct MouseButtonEvent {
pub button: i32,
pub x: f64,
pub y: f64,
}
impl MouseButtonEvent {
#[doc(alias = "gst_navigation_event_parse_mouse_button_event")]
pub fn parse(event: &gst::EventRef) -> Result<Self, glib::error::BoolError> {
assert_initialized_main_thread!();
unsafe {
let mut button = mem::MaybeUninit::uninit();
let mut x = mem::MaybeUninit::uninit();
let mut y = mem::MaybeUninit::uninit();
let ret = from_glib(ffi::gst_navigation_event_parse_mouse_button_event(
event.as_mut_ptr(),
button.as_mut_ptr(),
x.as_mut_ptr(),
y.as_mut_ptr(),
));
let button = button.assume_init();
let x = x.assume_init();
let y = y.assume_init();
if ret {
Ok(Self { button, x, y })
} else {
Err(glib::bool_error!("Invalid mouse button event"))
}
}
}
}
#[derive(Clone, PartialEq, Debug)]
pub struct MouseMoveEvent {
pub x: f64,
pub y: f64,
}
impl MouseMoveEvent {
#[doc(alias = "gst_navigation_event_parse_mouse_move_event")]
pub fn parse(event: &gst::EventRef) -> Result<Self, glib::error::BoolError> {
assert_initialized_main_thread!();
unsafe {
let mut x = mem::MaybeUninit::uninit();
let mut y = mem::MaybeUninit::uninit();
let ret = from_glib(ffi::gst_navigation_event_parse_mouse_move_event(
event.as_mut_ptr(),
x.as_mut_ptr(),
y.as_mut_ptr(),
));
let x = x.assume_init();
let y = y.assume_init();
if ret {
Ok(Self { x, y })
} else {
Err(glib::bool_error!("Invalid mouse move event"))
}
}
}
}
#[cfg(any(feature = "v1_18", feature = "dox"))]
#[cfg_attr(feature = "dox", doc(cfg(feature = "v1_18")))]
#[derive(Clone, PartialEq, Debug)]
pub struct MouseScrollEvent {
pub x: f64,
pub y: f64,
pub delta_x: f64,
pub delta_y: f64,
}
#[cfg(any(feature = "v1_18", feature = "dox"))]
#[cfg_attr(feature = "dox", doc(cfg(feature = "v1_18")))]
impl MouseScrollEvent {
#[doc(alias = "gst_navigation_event_parse_mouse_scroll_event")]
pub fn parse(event: &gst::EventRef) -> Result<Self, glib::error::BoolError> {
assert_initialized_main_thread!();
unsafe {
let mut x = mem::MaybeUninit::uninit();
let mut y = mem::MaybeUninit::uninit();
let mut delta_x = mem::MaybeUninit::uninit();
let mut delta_y = mem::MaybeUninit::uninit();
let ret = from_glib(ffi::gst_navigation_event_parse_mouse_scroll_event(
event.as_mut_ptr(),
x.as_mut_ptr(),
y.as_mut_ptr(),
delta_x.as_mut_ptr(),
delta_y.as_mut_ptr(),
));
let x = x.assume_init();
let y = y.assume_init();
let delta_x = delta_x.assume_init();
let delta_y = delta_y.assume_init();
if ret {
Ok(Self {
x,
y,
delta_x,
delta_y,
})
} else {
Err(glib::bool_error!("Invalid mouse button event"))
}
}
}
}
#[derive(Clone, PartialEq, Debug)]
pub struct CommandEvent {
cmd: NavigationCommand,
}
impl CommandEvent {
#[doc(alias = "gst_navigation_event_parse_command")]
pub fn parse(event: &gst::EventRef) -> Result<Self, glib::error::BoolError> {
assert_initialized_main_thread!();
unsafe {
let mut command = mem::MaybeUninit::uninit();
let ret = from_glib(ffi::gst_navigation_event_parse_command(
event.as_mut_ptr(),
command.as_mut_ptr(),
));
let command = command.assume_init();
if ret {
Ok(Self {
cmd: from_glib(command),
})
} else {
Err(glib::bool_error!("Invalid navigation command event"))
}
}
}
}
#[derive(Clone, PartialEq, Debug)]
pub enum NavigationEvent {
KeyPress(KeyEvent),
KeyRelease(KeyEvent),
MouseMove(MouseMoveEvent),
MouseButtonPress(MouseButtonEvent),
MouseButtonRelease(MouseButtonEvent),
Command(CommandEvent),
#[cfg(any(feature = "v1_18", feature = "dox"))]
#[cfg_attr(feature = "dox", doc(cfg(feature = "v1_18")))]
MouseScroll(MouseScrollEvent),
}
impl NavigationEvent {
#[doc(alias = "gst_navigation_event_get_type")]
pub fn type_(event: &gst::EventRef) -> NavigationEventType {
assert_initialized_main_thread!();
unsafe { from_glib(ffi::gst_navigation_event_get_type(event.as_mut_ptr())) }
}
pub fn parse(event: &gst::EventRef) -> Result<Self, glib::error::BoolError> {
skip_assert_initialized!();
let event_type: NavigationEventType = Self::type_(event);
match event_type {
NavigationEventType::MouseMove => MouseMoveEvent::parse(event).map(Self::MouseMove),
NavigationEventType::KeyPress => KeyEvent::parse(event).map(Self::KeyPress),
NavigationEventType::KeyRelease => KeyEvent::parse(event).map(Self::KeyRelease),
#[cfg(any(feature = "v1_18", feature = "dox"))]
#[cfg_attr(feature = "dox", doc(cfg(feature = "v1_18")))]
NavigationEventType::MouseScroll => {
MouseScrollEvent::parse(event).map(Self::MouseScroll)
}
NavigationEventType::MouseButtonPress => {
MouseButtonEvent::parse(event).map(Self::MouseButtonPress)
}
NavigationEventType::MouseButtonRelease => {
MouseButtonEvent::parse(event).map(Self::MouseButtonRelease)
}
NavigationEventType::Command => CommandEvent::parse(event).map(Self::Command),
NavigationEventType::Invalid | NavigationEventType::__Unknown(_) => {
return Err(glib::bool_error!("Invalid navigation event"))
}
}
}
}

View file

@ -0,0 +1,215 @@
// Take a look at the license at the top of the repository in the LICENSE file.
use crate::NavigationMessageType;
use glib::translate::{from_glib, from_glib_full, IntoGlib, ToGlibPtr};
#[cfg(any(feature = "v1_14", feature = "dox"))]
#[cfg_attr(feature = "dox", doc(cfg(feature = "v1_14")))]
use glib::ToSendValue;
use gst::ffi as gst_ffi;
use gst::{prelude::*, Message, Object, Seqnum};
use std::ptr;
macro_rules! message_builder_generic_impl {
($new_fn:expr) => {
#[allow(clippy::needless_update)]
pub fn src<O: IsA<Object> + Cast + Clone>(self, src: &O) -> Self {
Self {
builder: self.builder.src(src),
..self
}
}
#[doc(alias = "gst_message_set_seqnum")]
#[allow(clippy::needless_update)]
pub fn seqnum(self, seqnum: Seqnum) -> Self {
Self {
builder: self.builder.seqnum(seqnum),
..self
}
}
#[cfg(any(feature = "v1_14", feature = "dox"))]
#[cfg_attr(feature = "dox", doc(cfg(feature = "v1_14")))]
#[allow(clippy::needless_update)]
pub fn other_fields(
self,
other_fields: &[(&'a str, &'a (dyn ToSendValue + Sync))],
) -> Self {
Self {
builder: self.builder.other_fields(other_fields),
..self
}
}
#[must_use = "Building the message without using it has no effect"]
pub fn build(mut self) -> Message {
assert_initialized_main_thread!();
unsafe {
let src = self.builder.src.to_glib_none().0;
let msg = $new_fn(&mut self, src);
if let Some(seqnum) = self.builder.seqnum {
gst_ffi::gst_message_set_seqnum(msg, seqnum.into_glib());
}
#[cfg(any(feature = "v1_14", feature = "dox"))]
if !self.builder.other_fields.is_empty() {
let structure = gst_ffi::gst_message_writable_structure(msg);
if !structure.is_null() {
let structure =
gst::StructureRef::from_glib_borrow_mut(structure as *mut _);
for (k, v) in self.builder.other_fields {
structure.set_value(k, v.to_send_value());
}
}
}
from_glib_full(msg)
}
}
};
}
struct MessageBuilder<'a> {
pub src: Option<Object>,
pub seqnum: Option<Seqnum>,
#[allow(unused)]
pub other_fields: Vec<(&'a str, &'a (dyn ToSendValue + Sync))>,
}
impl<'a> MessageBuilder<'a> {
pub fn new() -> Self {
assert_initialized_main_thread!();
Self {
src: None,
seqnum: None,
other_fields: Vec::new(),
}
}
pub fn src<O: IsA<Object> + Cast + Clone>(self, src: &O) -> Self {
Self {
src: Some(src.clone().upcast::<Object>()),
..self
}
}
pub fn seqnum(self, seqnum: Seqnum) -> Self {
Self {
seqnum: Some(seqnum),
..self
}
}
#[cfg(any(feature = "v1_14", feature = "dox"))]
#[cfg_attr(feature = "dox", doc(cfg(feature = "v1_14")))]
pub fn other_fields(self, other_fields: &[(&'a str, &'a (dyn ToSendValue + Sync))]) -> Self {
Self {
other_fields: self
.other_fields
.iter()
.cloned()
.chain(other_fields.iter().cloned())
.collect(),
..self
}
}
}
#[must_use = "The builder must be built to be used"]
pub struct NavigationEventMessageBuilder<'a> {
builder: MessageBuilder<'a>,
event: gst::Event,
}
impl<'a> NavigationEventMessageBuilder<'a> {
fn new(event: gst::Event) -> Self {
skip_assert_initialized!();
Self {
builder: MessageBuilder::new(),
event,
}
}
message_builder_generic_impl!(|s: &Self, src| ffi::gst_navigation_message_new_event(
src,
s.event.to_glib_none().0
));
}
#[derive(Clone, Debug)]
pub struct NavigationEventMessage {
pub event: gst::Event,
}
impl PartialEq for NavigationEventMessage {
fn eq(&self, other: &Self) -> bool {
unsafe { self.event.as_ptr() == other.event.as_ptr() }
}
}
impl Eq for NavigationEventMessage {}
impl NavigationEventMessage {
#[doc(alias = "gst_navigation_message_new_event")]
#[allow(clippy::new_ret_no_self)]
pub fn new(event: gst::Event) -> gst::Message {
assert_initialized_main_thread!();
NavigationEventMessageBuilder::new(event).build()
}
pub fn builder<'a>(event: gst::Event) -> NavigationEventMessageBuilder<'a> {
assert_initialized_main_thread!();
NavigationEventMessageBuilder::new(event)
}
#[doc(alias = "gst_navigation_message_parse_event")]
pub fn parse(msg: &gst::MessageRef) -> Result<Self, glib::error::BoolError> {
assert_initialized_main_thread!();
unsafe {
let mut event = ptr::null_mut();
let ret = from_glib(ffi::gst_navigation_message_parse_event(
msg.as_mut_ptr(),
&mut event,
));
if ret {
Ok(Self {
event: from_glib_full(event),
})
} else {
Err(glib::bool_error!("Invalid navigation event msg"))
}
}
}
}
#[derive(Clone, PartialEq, Debug)]
pub enum NavigationMessage {
Event(NavigationEventMessage),
}
impl NavigationMessage {
#[doc(alias = "gst_navigation_message_get_type")]
pub fn type_(msg: &gst::MessageRef) -> NavigationMessageType {
assert_initialized_main_thread!();
unsafe { from_glib(ffi::gst_navigation_message_get_type(msg.as_mut_ptr())) }
}
#[doc(alias = "gst_navigation_message_parse_event")]
pub fn parse(msg: &gst::MessageRef) -> Result<Self, glib::error::BoolError> {
skip_assert_initialized!();
let event_type: NavigationMessageType = Self::type_(msg);
match event_type {
NavigationMessageType::Event => NavigationEventMessage::parse(msg).map(Self::Event),
_ => {
return Err(glib::bool_error!(
"Unsupported navigation msg {:?}",
event_type
))
}
}
}
}