diff --git a/Gir_GstRtspServer.toml b/Gir_GstRtspServer.toml index 70165319a..502a4075a 100644 --- a/Gir_GstRtspServer.toml +++ b/Gir_GstRtspServer.toml @@ -44,6 +44,9 @@ manual = [ "GObject.Object", "Gio.TlsCertificateFlags", "Gio.TlsCertificate", + "Gio.TlsDatabase", + "Gio.TlsConnection", + "Gio.TlsAuthenticationMode", "Gio.Socket", "Gio.Cancellable", "Gio.SocketFamily", @@ -229,3 +232,17 @@ status="generate" name = "make_basic" [object.function.return] nullable = false + + [[object.function]] + name = "set_default_token" + # gir forgets mut + ignore = true + +[[object]] +name="GstRtspServer.RTSPToken" +status = "generate" +concurrency = "none" + [[object.function]] + name = "writable_structure" + # mutable ref + ignore = true diff --git a/examples/Cargo.toml b/examples/Cargo.toml index 860dba92a..5c0465acf 100644 --- a/examples/Cargo.toml +++ b/examples/Cargo.toml @@ -10,7 +10,9 @@ gstreamer-app = { path = "../gstreamer-app" } gstreamer-audio = { path = "../gstreamer-audio" } gstreamer-video = { path = "../gstreamer-video" } gstreamer-player = { path = "../gstreamer-player", optional = true } +gstreamer-rtsp = { path = "../gstreamer-rtsp", optional = true } gstreamer-rtsp-server = { path = "../gstreamer-rtsp-server", optional = true } +gstreamer-rtsp-server-sys = { git = "https://github.com/sdroege/gstreamer-sys", features = ["v1_8"] } gtk = { git = "https://github.com/gtk-rs/gtk", features = ["v3_6"], optional = true } gdk = { git = "https://github.com/gtk-rs/gdk", optional = true } gio = { git = "https://github.com/gtk-rs/gio", optional = true } @@ -29,6 +31,7 @@ gtkvideooverlay-x11 = ["gtkvideooverlay"] gtkvideooverlay-quartz = ["gtkvideooverlay"] tokio = ["gstreamer/futures", "futures", "tokio-core"] gst-rtsp-server = ["gstreamer-rtsp-server"] +gst-rtsp-server-record = ["gstreamer-rtsp-server", "gstreamer-rtsp", "gio"] default-features = [] v1_10 = ["gstreamer/v1_10"] @@ -96,3 +99,7 @@ name = "toc" [[bin]] name = "tokio" required-features = ["tokio"] + +[[bin]] +name = "rtsp-server-record" +required-features = ["gst-rtsp-server-record"] diff --git a/examples/src/bin/rtsp-server-record.rs b/examples/src/bin/rtsp-server-record.rs new file mode 100644 index 000000000..3068f0a9b --- /dev/null +++ b/examples/src/bin/rtsp-server-record.rs @@ -0,0 +1,113 @@ +extern crate glib; +extern crate failure; +extern crate gio; + +#[macro_use] +extern crate failure_derive; + +extern crate gstreamer_rtsp_server_sys as ffi; +extern crate gstreamer_rtsp_server as gst_rtsp_server; +extern crate gstreamer_rtsp as gst_rtsp; +extern crate gstreamer as gst; + +use std::env; +use std::ptr; +use failure::Error; + +use glib::translate::*; +use gst_rtsp_server::prelude::*; +use gst_rtsp_server::*; +use gst_rtsp::*; + +#[path = "../examples-common.rs"] +mod examples_common; + +#[derive(Debug, Fail)] +#[fail(display = "Could not get mount points")] +struct NoMountPoints; + +#[derive(Debug, Fail)] +#[fail(display = "Usage: {} LAUNCH_LINE", _0)] +struct UsageError(String); + +fn main_loop() -> Result<(), Error> { + let args: Vec<_> = env::args().collect(); + + if args.len() != 2 { + return Err(Error::from(UsageError(args[0].clone()))); + } + + let main_loop = glib::MainLoop::new(None, false); + let server = RTSPServer::new(); + let factory = RTSPMediaFactory::new(); + let mounts = server.get_mount_points().ok_or(NoMountPoints)?; + let auth = RTSPAuth::new(); + let mut token = RTSPToken::new(&[(*RTSP_TOKEN_MEDIA_FACTORY_ROLE, &"user")]); + let basic = RTSPAuth::make_basic("user", "password"); + let cert = gio::TlsCertificate::new_from_pem ( + "-----BEGIN CERTIFICATE-----\ + MIICJjCCAY+gAwIBAgIBBzANBgkqhkiG9w0BAQUFADCBhjETMBEGCgmSJomT8ixk\ + ARkWA0NPTTEXMBUGCgmSJomT8ixkARkWB0VYQU1QTEUxHjAcBgNVBAsTFUNlcnRp\ + ZmljYXRlIEF1dGhvcml0eTEXMBUGA1UEAxMOY2EuZXhhbXBsZS5jb20xHTAbBgkq\ + hkiG9w0BCQEWDmNhQGV4YW1wbGUuY29tMB4XDTExMDExNzE5NDcxN1oXDTIxMDEx\ + NDE5NDcxN1owSzETMBEGCgmSJomT8ixkARkWA0NPTTEXMBUGCgmSJomT8ixkARkW\ + B0VYQU1QTEUxGzAZBgNVBAMTEnNlcnZlci5leGFtcGxlLmNvbTBcMA0GCSqGSIb3\ + DQEBAQUAA0sAMEgCQQDYScTxk55XBmbDM9zzwO+grVySE4rudWuzH2PpObIonqbf\ + hRoAalKVluG9jvbHI81eXxCdSObv1KBP1sbN5RzpAgMBAAGjIjAgMAkGA1UdEwQC\ + MAAwEwYDVR0lBAwwCgYIKwYBBQUHAwEwDQYJKoZIhvcNAQEFBQADgYEAYx6fMqT1\ + Gvo0jq88E8mc+bmp4LfXD4wJ7KxYeadQxt75HFRpj4FhFO3DOpVRFgzHlOEo3Fwk\ + PZOKjvkT0cbcoEq5whLH25dHoQxGoVQgFyAP5s+7Vp5AlHh8Y/vAoXeEVyy/RCIH\ + QkhUlAflfDMcrrYjsmwoOPSjhx6Mm/AopX4=\ + -----END CERTIFICATE-----\ + -----BEGIN PRIVATE KEY-----\ + MIIBVAIBADANBgkqhkiG9w0BAQEFAASCAT4wggE6AgEAAkEA2EnE8ZOeVwZmwzPc\ + 88DvoK1ckhOK7nVrsx9j6TmyKJ6m34UaAGpSlZbhvY72xyPNXl8QnUjm79SgT9bG\ + zeUc6QIDAQABAkBRFJZ32VbqWMP9OVwDJLiwC01AlYLnka0mIQZbT/2xq9dUc9GW\ + U3kiVw4lL8v/+sPjtTPCYYdzHHOyDen6znVhAiEA9qJT7BtQvRxCvGrAhr9MS022\ + tTdPbW829BoUtIeH64cCIQDggG5i48v7HPacPBIH1RaSVhXl8qHCpQD3qrIw3FMw\ + DwIga8PqH5Sf5sHedy2+CiK0V4MRfoU4c3zQ6kArI+bEgSkCIQCLA1vXBiE31B5s\ + bdHoYa1BXebfZVd+1Hd95IfEM5mbRwIgSkDuQwV55BBlvWph3U8wVIMIb4GStaH8\ + W535W8UBbEg=-----END PRIVATE KEY-----")?; + + // Bindable versions were added in b1f515178a363df0322d7adbd5754e1f6e2083c9 + unsafe { + ffi::gst_rtsp_media_factory_add_role(factory.to_glib_none().0, + "user".to_glib_none().0, + RTSP_PERM_MEDIA_FACTORY_ACCESS.to_glib_none().0, + ::static_type().to_glib() as *const u8, + true.to_glib() as *const u8, + RTSP_PERM_MEDIA_FACTORY_CONSTRUCT.as_ptr() as *const u8, + ::static_type().to_glib() as *const u8, + true.to_glib() as *const u8, + ptr::null_mut::()); + } + + auth.set_tls_certificate(&cert); + auth.add_basic(basic.as_str(), &mut token); + server.set_auth(&auth); + factory.set_launch(args[1].as_str()); + factory.set_transport_mode(RTSPTransportMode::RECORD); + factory.set_profiles(RTSPProfile::SAVP | RTSPProfile::SAVPF); + + mounts.add_factory("/test", &factory); + + server.attach(None); + + println!("Stream ready at rtsps://127.0.0.1:{}/test", server.get_bound_port()); + + main_loop.run(); + + Ok(()) +} + +fn example_main() -> Result<(), Error> { + gst::init()?; + main_loop() +} + +fn main() { + match examples_common::run(example_main) { + Ok(r) => r, + Err(e) => eprintln!("Error! {}", e), + } +} diff --git a/gstreamer-rtsp-server/Cargo.toml b/gstreamer-rtsp-server/Cargo.toml index 6e6fac931..1470e62db 100644 --- a/gstreamer-rtsp-server/Cargo.toml +++ b/gstreamer-rtsp-server/Cargo.toml @@ -15,6 +15,7 @@ build = "build.rs" [dependencies] bitflags = "1.0" libc = "0.2" +lazy_static = "1.0" glib-sys = { git = "https://github.com/gtk-rs/sys" } gio-sys = { git = "https://github.com/gtk-rs/sys" } gobject-sys = { git = "https://github.com/gtk-rs/sys" } diff --git a/gstreamer-rtsp-server/src/auto/mod.rs b/gstreamer-rtsp-server/src/auto/mod.rs index 8630d122e..ffa45190d 100644 --- a/gstreamer-rtsp-server/src/auto/mod.rs +++ b/gstreamer-rtsp-server/src/auto/mod.rs @@ -61,6 +61,9 @@ pub use self::r_t_s_p_thread_pool::RTSPThreadPoolExt; mod r_t_s_p_address; pub use self::r_t_s_p_address::RTSPAddress; +mod r_t_s_p_token; +pub use self::r_t_s_p_token::RTSPToken; + mod enums; pub use self::enums::RTSPAddressPoolResult; pub use self::enums::RTSPMediaStatus; diff --git a/gstreamer-rtsp-server/src/auto/r_t_s_p_auth.rs b/gstreamer-rtsp-server/src/auto/r_t_s_p_auth.rs index e44e2f12f..7c3f959a8 100644 --- a/gstreamer-rtsp-server/src/auto/r_t_s_p_auth.rs +++ b/gstreamer-rtsp-server/src/auto/r_t_s_p_auth.rs @@ -2,15 +2,23 @@ // from gir-files (https://github.com/gtk-rs/gir-files @ ???) // DO NOT EDIT +use RTSPToken; use ffi; use gio; +use gio_ffi; +use glib; +use glib::object::Downcast; use glib::object::IsA; +use glib::signal::SignalHandlerId; +use glib::signal::connect; use glib::translate::*; use glib_ffi; use gobject_ffi; #[cfg(any(feature = "v1_12", feature = "dox"))] use gst_rtsp; +use std::boxed::Box as Box_; use std::mem; +use std::mem::transmute; use std::ptr; glib_wrapper! { @@ -54,54 +62,58 @@ unsafe impl Send for RTSPAuth {} unsafe impl Sync for RTSPAuth {} pub trait RTSPAuthExt { - //fn add_basic(&self, basic: &str, token: /*Ignored*/&mut RTSPToken); + fn add_basic(&self, basic: &str, token: &mut RTSPToken); - //#[cfg(any(feature = "v1_12", feature = "dox"))] - //fn add_digest(&self, user: &str, pass: &str, token: /*Ignored*/&mut RTSPToken); + #[cfg(any(feature = "v1_12", feature = "dox"))] + fn add_digest(&self, user: &str, pass: &str, token: &mut RTSPToken); - //fn get_default_token(&self) -> /*Ignored*/Option; + fn get_default_token(&self) -> Option; #[cfg(any(feature = "v1_12", feature = "dox"))] fn get_supported_methods(&self) -> gst_rtsp::RTSPAuthMethod; - //fn get_tls_authentication_mode(&self) -> /*Ignored*/gio::TlsAuthenticationMode; + fn get_tls_authentication_mode(&self) -> gio::TlsAuthenticationMode; fn get_tls_certificate(&self) -> Option; - //fn get_tls_database(&self) -> /*Ignored*/Option; + fn get_tls_database(&self) -> Option; fn remove_basic(&self, basic: &str); #[cfg(any(feature = "v1_12", feature = "dox"))] fn remove_digest(&self, user: &str); - //fn set_default_token<'a, P: Into>>(&self, token: P); - #[cfg(any(feature = "v1_12", feature = "dox"))] fn set_supported_methods(&self, methods: gst_rtsp::RTSPAuthMethod); - //fn set_tls_authentication_mode<'a, P: Into>>(&self, mode: P); + fn set_tls_authentication_mode(&self, mode: gio::TlsAuthenticationMode); fn set_tls_certificate<'a, P: Into>>(&self, cert: P); - //fn set_tls_database<'a, P: IsA + 'a, Q: Into>>(&self, database: Q); + fn set_tls_database<'a, P: IsA + 'a, Q: Into>>(&self, database: Q); - //fn connect_accept_certificate(&self, f: F) -> SignalHandlerId; + fn connect_accept_certificate bool + Send + Sync + 'static>(&self, f: F) -> SignalHandlerId; } -impl> RTSPAuthExt for O { - //fn add_basic(&self, basic: &str, token: /*Ignored*/&mut RTSPToken) { - // unsafe { TODO: call ffi::gst_rtsp_auth_add_basic() } - //} +impl + IsA> RTSPAuthExt for O { + fn add_basic(&self, basic: &str, token: &mut RTSPToken) { + unsafe { + ffi::gst_rtsp_auth_add_basic(self.to_glib_none().0, basic.to_glib_none().0, token.to_glib_none_mut().0); + } + } - //#[cfg(any(feature = "v1_12", feature = "dox"))] - //fn add_digest(&self, user: &str, pass: &str, token: /*Ignored*/&mut RTSPToken) { - // unsafe { TODO: call ffi::gst_rtsp_auth_add_digest() } - //} + #[cfg(any(feature = "v1_12", feature = "dox"))] + fn add_digest(&self, user: &str, pass: &str, token: &mut RTSPToken) { + unsafe { + ffi::gst_rtsp_auth_add_digest(self.to_glib_none().0, user.to_glib_none().0, pass.to_glib_none().0, token.to_glib_none_mut().0); + } + } - //fn get_default_token(&self) -> /*Ignored*/Option { - // unsafe { TODO: call ffi::gst_rtsp_auth_get_default_token() } - //} + fn get_default_token(&self) -> Option { + unsafe { + from_glib_full(ffi::gst_rtsp_auth_get_default_token(self.to_glib_none().0)) + } + } #[cfg(any(feature = "v1_12", feature = "dox"))] fn get_supported_methods(&self) -> gst_rtsp::RTSPAuthMethod { @@ -110,9 +122,11 @@ impl> RTSPAuthExt for O { } } - //fn get_tls_authentication_mode(&self) -> /*Ignored*/gio::TlsAuthenticationMode { - // unsafe { TODO: call ffi::gst_rtsp_auth_get_tls_authentication_mode() } - //} + fn get_tls_authentication_mode(&self) -> gio::TlsAuthenticationMode { + unsafe { + from_glib(ffi::gst_rtsp_auth_get_tls_authentication_mode(self.to_glib_none().0)) + } + } fn get_tls_certificate(&self) -> Option { unsafe { @@ -120,9 +134,11 @@ impl> RTSPAuthExt for O { } } - //fn get_tls_database(&self) -> /*Ignored*/Option { - // unsafe { TODO: call ffi::gst_rtsp_auth_get_tls_database() } - //} + fn get_tls_database(&self) -> Option { + unsafe { + from_glib_full(ffi::gst_rtsp_auth_get_tls_database(self.to_glib_none().0)) + } + } fn remove_basic(&self, basic: &str) { unsafe { @@ -137,10 +153,6 @@ impl> RTSPAuthExt for O { } } - //fn set_default_token<'a, P: Into>>(&self, token: P) { - // unsafe { TODO: call ffi::gst_rtsp_auth_set_default_token() } - //} - #[cfg(any(feature = "v1_12", feature = "dox"))] fn set_supported_methods(&self, methods: gst_rtsp::RTSPAuthMethod) { unsafe { @@ -148,9 +160,11 @@ impl> RTSPAuthExt for O { } } - //fn set_tls_authentication_mode<'a, P: Into>>(&self, mode: P) { - // unsafe { TODO: call ffi::gst_rtsp_auth_set_tls_authentication_mode() } - //} + fn set_tls_authentication_mode(&self, mode: gio::TlsAuthenticationMode) { + unsafe { + ffi::gst_rtsp_auth_set_tls_authentication_mode(self.to_glib_none().0, mode.to_glib()); + } + } fn set_tls_certificate<'a, P: Into>>(&self, cert: P) { let cert = cert.into(); @@ -160,11 +174,25 @@ impl> RTSPAuthExt for O { } } - //fn set_tls_database<'a, P: IsA + 'a, Q: Into>>(&self, database: Q) { - // unsafe { TODO: call ffi::gst_rtsp_auth_set_tls_database() } - //} + fn set_tls_database<'a, P: IsA + 'a, Q: Into>>(&self, database: Q) { + let database = database.into(); + let database = database.to_glib_none(); + unsafe { + ffi::gst_rtsp_auth_set_tls_database(self.to_glib_none().0, database.0); + } + } - //fn connect_accept_certificate(&self, f: F) -> SignalHandlerId { - // Ignored connection: Gio.TlsConnection - //} + fn connect_accept_certificate bool + Send + Sync + 'static>(&self, f: F) -> SignalHandlerId { + unsafe { + let f: Box_ bool + Send + Sync + 'static>> = Box_::new(Box_::new(f)); + connect(self.to_glib_none().0, "accept-certificate", + transmute(accept_certificate_trampoline:: as usize), Box_::into_raw(f) as *mut _) + } + } +} + +unsafe extern "C" fn accept_certificate_trampoline

(this: *mut ffi::GstRTSPAuth, connection: *mut gio_ffi::GTlsConnection, peer_cert: *mut gio_ffi::GTlsCertificate, errors: gio_ffi::GTlsCertificateFlags, f: glib_ffi::gpointer) -> glib_ffi::gboolean +where P: IsA { + let f: &&(Fn(&P, &gio::TlsConnection, &gio::TlsCertificate, gio::TlsCertificateFlags) -> bool + Send + Sync + 'static) = transmute(f); + f(&RTSPAuth::from_glib_borrow(this).downcast_unchecked(), &from_glib_borrow(connection), &from_glib_borrow(peer_cert), from_glib(errors)).to_glib() } diff --git a/gstreamer-rtsp-server/src/auto/r_t_s_p_token.rs b/gstreamer-rtsp-server/src/auto/r_t_s_p_token.rs new file mode 100644 index 000000000..5f00e2951 --- /dev/null +++ b/gstreamer-rtsp-server/src/auto/r_t_s_p_token.rs @@ -0,0 +1,56 @@ +// This file was generated by gir (https://github.com/gtk-rs/gir @ bd67955) +// from gir-files (https://github.com/gtk-rs/gir-files @ ???) +// DO NOT EDIT + +use ffi; +use glib::translate::*; +use glib_ffi; +use gobject_ffi; +use gst; +use std::mem; +use std::ptr; + +glib_wrapper! { + pub struct RTSPToken(Boxed); + + match fn { + copy => |ptr| gobject_ffi::g_boxed_copy(ffi::gst_rtsp_token_get_type(), ptr as *mut _) as *mut ffi::GstRTSPToken, + free => |ptr| gobject_ffi::g_boxed_free(ffi::gst_rtsp_token_get_type(), ptr as *mut _), + get_type => || ffi::gst_rtsp_token_get_type(), + } +} + +impl RTSPToken { + //pub fn new(firstfield: &str, : /*Unknown conversion*//*Unimplemented*/Fundamental: VarArgs) -> RTSPToken { + // unsafe { TODO: call ffi::gst_rtsp_token_new() } + //} + + pub fn new_empty() -> RTSPToken { + assert_initialized_main_thread!(); + unsafe { + from_glib_full(ffi::gst_rtsp_token_new_empty()) + } + } + + //pub fn new_valist(firstfield: &str, var_args: /*Unknown conversion*//*Unimplemented*/Unsupported) -> RTSPToken { + // unsafe { TODO: call ffi::gst_rtsp_token_new_valist() } + //} + + pub fn get_string(&mut self, field: &str) -> Option { + unsafe { + from_glib_none(ffi::gst_rtsp_token_get_string(self.to_glib_none_mut().0, field.to_glib_none().0)) + } + } + + pub fn get_structure(&mut self) -> Option { + unsafe { + from_glib_none(ffi::gst_rtsp_token_get_structure(self.to_glib_none_mut().0)) + } + } + + pub fn is_allowed(&mut self, field: &str) -> bool { + unsafe { + from_glib(ffi::gst_rtsp_token_is_allowed(self.to_glib_none_mut().0, field.to_glib_none().0)) + } + } +} diff --git a/gstreamer-rtsp-server/src/lib.rs b/gstreamer-rtsp-server/src/lib.rs index 9497df88e..317d4c9e2 100644 --- a/gstreamer-rtsp-server/src/lib.rs +++ b/gstreamer-rtsp-server/src/lib.rs @@ -8,10 +8,13 @@ #[macro_use] extern crate bitflags; +#[macro_use] +extern crate lazy_static; extern crate libc; extern crate gio; extern crate gio_sys as gio_ffi; +use std::ffi::CStr; #[macro_use] extern crate glib; extern crate glib_sys as glib_ffi; @@ -51,13 +54,31 @@ mod r_t_s_p_address_pool; mod r_t_s_p_client; mod r_t_s_p_session_pool; mod r_t_s_p_context; +mod r_t_s_p_auth; +mod r_t_s_p_token; pub use r_t_s_p_server::RTSPServerExtManual; pub use r_t_s_p_address_pool::RTSPAddressPoolExtManual; pub use r_t_s_p_client::RTSPClientExtManual; pub use r_t_s_p_session_pool::RTSPSessionPoolExtManual; +pub use r_t_s_p_auth::RTSPAuthExtManual; pub use r_t_s_p_context::*; +pub use r_t_s_p_token::*; + +lazy_static! { + pub static ref RTSP_ADDRESS_POOL_ANY_IPV4: &'static str = unsafe{CStr::from_ptr(ffi::GST_RTSP_ADDRESS_POOL_ANY_IPV4).to_str().unwrap()}; + pub static ref RTSP_ADDRESS_POOL_ANY_IPV6: &'static str = unsafe{CStr::from_ptr(ffi::GST_RTSP_ADDRESS_POOL_ANY_IPV6).to_str().unwrap()}; + pub static ref RTSP_AUTH_CHECK_CONNECT: &'static str = unsafe{CStr::from_ptr(ffi::GST_RTSP_AUTH_CHECK_CONNECT).to_str().unwrap()}; + pub static ref RTSP_AUTH_CHECK_MEDIA_FACTORY_ACCESS: &'static str = unsafe{CStr::from_ptr(ffi::GST_RTSP_AUTH_CHECK_MEDIA_FACTORY_ACCESS).to_str().unwrap()}; + pub static ref RTSP_AUTH_CHECK_MEDIA_FACTORY_CONSTRUCT: &'static str = unsafe{CStr::from_ptr(ffi::GST_RTSP_AUTH_CHECK_MEDIA_FACTORY_CONSTRUCT).to_str().unwrap()}; + pub static ref RTSP_AUTH_CHECK_TRANSPORT_CLIENT_SETTINGS: &'static str = unsafe{CStr::from_ptr(ffi::GST_RTSP_AUTH_CHECK_TRANSPORT_CLIENT_SETTINGS).to_str().unwrap()}; + pub static ref RTSP_AUTH_CHECK_URL: &'static str = unsafe{CStr::from_ptr(ffi::GST_RTSP_AUTH_CHECK_URL).to_str().unwrap()}; + pub static ref RTSP_PERM_MEDIA_FACTORY_ACCESS: &'static str = unsafe{CStr::from_ptr(ffi::GST_RTSP_PERM_MEDIA_FACTORY_ACCESS).to_str().unwrap()}; + pub static ref RTSP_PERM_MEDIA_FACTORY_CONSTRUCT: &'static str = unsafe{CStr::from_ptr(ffi::GST_RTSP_PERM_MEDIA_FACTORY_CONSTRUCT).to_str().unwrap()}; + pub static ref RTSP_TOKEN_MEDIA_FACTORY_ROLE: &'static str = unsafe{CStr::from_ptr(ffi::GST_RTSP_TOKEN_MEDIA_FACTORY_ROLE).to_str().unwrap()}; + pub static ref RTSP_TOKEN_TRANSPORT_CLIENT_SETTINGS: &'static str = unsafe{CStr::from_ptr(ffi::GST_RTSP_TOKEN_TRANSPORT_CLIENT_SETTINGS).to_str().unwrap()}; +} // Re-export all the traits in a prelude module, so that applications // can always "use gst::prelude::*" without getting conflicts @@ -71,4 +92,5 @@ pub mod prelude { pub use r_t_s_p_address_pool::RTSPAddressPoolExtManual; pub use r_t_s_p_client::RTSPClientExtManual; pub use r_t_s_p_session_pool::RTSPSessionPoolExtManual; + pub use r_t_s_p_auth::RTSPAuthExtManual; } diff --git a/gstreamer-rtsp-server/src/r_t_s_p_auth.rs b/gstreamer-rtsp-server/src/r_t_s_p_auth.rs new file mode 100644 index 000000000..909a5b14b --- /dev/null +++ b/gstreamer-rtsp-server/src/r_t_s_p_auth.rs @@ -0,0 +1,19 @@ +use RTSPAuth; +use RTSPToken; +use ffi; +use glib::object::IsA; +use glib::translate::*; + +pub trait RTSPAuthExtManual { + fn set_default_token<'a, P: Into>>(&self, token: P); +} + +impl> RTSPAuthExtManual for O { + + fn set_default_token<'a, P: Into>>(&self, token: P) { + let mut token = token.into(); + unsafe { + ffi::gst_rtsp_auth_set_default_token(self.to_glib_none().0, token.to_glib_none_mut().0); + } + } +} diff --git a/gstreamer-rtsp-server/src/r_t_s_p_token.rs b/gstreamer-rtsp-server/src/r_t_s_p_token.rs new file mode 100644 index 000000000..5463bb1a4 --- /dev/null +++ b/gstreamer-rtsp-server/src/r_t_s_p_token.rs @@ -0,0 +1,32 @@ +use RTSPToken; +use glib::value::ToSendValue; +use gst; +use ffi; +use glib::translate::*; + +impl RTSPToken { + pub fn new(values: &[(&str, &ToSendValue)]) -> RTSPToken { + let mut token = RTSPToken::new_empty(); + + { + let structure = token.writable_structure().unwrap(); + + for &(f, v) in values { + structure.set_value(f, v.to_send_value()); + } + } + + token + } + + pub fn writable_structure(&mut self) -> Option<&mut gst::StructureRef> { + unsafe { + let structure = ffi::gst_rtsp_token_writable_structure(self.to_glib_none_mut().0); + if structure.is_null() { + None + } else { + Some(gst::StructureRef::from_glib_borrow_mut(structure)) + } + } + } +}