From 7238e34869f6398d6c6823c84915933fb1d28ea7 Mon Sep 17 00:00:00 2001 From: Aron Heinecke Date: Sun, 25 Nov 2018 03:19:01 +0100 Subject: [PATCH 1/6] Implement Send to allow for shared state Signed-off-by: Aron Heinecke --- src/core.rs | 2 ++ src/media.rs | 2 ++ src/media_player.rs | 2 ++ 3 files changed, 6 insertions(+) diff --git a/src/core.rs b/src/core.rs index eb9f924..078919b 100644 --- a/src/core.rs +++ b/src/core.rs @@ -28,6 +28,8 @@ pub struct Instance { pub(crate) ptr: *mut sys::libvlc_instance_t, } +unsafe impl Send for Instance {} + impl Instance { /// Create and initialize a libvlc instance. pub fn new() -> Option { diff --git a/src/media.rs b/src/media.rs index 60e4656..b3f32a8 100644 --- a/src/media.rs +++ b/src/media.rs @@ -12,6 +12,8 @@ pub struct Media { pub(crate) ptr: *mut sys::libvlc_media_t, } +unsafe impl Send for Media {} + impl Media { /// Create a media with a certain given media resource location, for instance a valid URL. pub fn new_location(instance: &Instance, mrl: &str) -> Option { diff --git a/src/media_player.rs b/src/media_player.rs index 15aebf0..56e0448 100644 --- a/src/media_player.rs +++ b/src/media_player.rs @@ -15,6 +15,8 @@ pub struct MediaPlayer { pub(crate) ptr: *mut sys::libvlc_media_player_t, } +unsafe impl Send for MediaPlayer {} + impl MediaPlayer { /// Create an empty Media Player object pub fn new(instance: &Instance) -> Option { From b13d7ead4bf8f6cfd7963deb054c9fb5c1b923e8 Mon Sep 17 00:00:00 2001 From: Raniz Date: Mon, 18 Nov 2019 13:49:40 +0100 Subject: [PATCH 2/6] Add methods for handling VLM broadcasts to Instance --- src/core.rs | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/src/core.rs b/src/core.rs index 955dc3d..b04f096 100644 --- a/src/core.rs +++ b/src/core.rs @@ -79,6 +79,50 @@ impl Instance { else { Err(()) } } + pub fn add_broadcast(&self, name: &str, input: &str, output: &str, options: Option>, enabled: bool, loop_broadcast: bool,) -> Result<(), ()> { + let name= to_cstr(name); + let input = to_cstr(input); + let output = to_cstr(output); + let opts_c_ptr: Vec<*const c_char> ; + let opts_c: Vec; + let enabled = if enabled { 1 } else { 0 }; + let loop_broadcast = if loop_broadcast { 1 } else { 0 }; + if let Some(vec) = options { + opts_c = vec.into_iter() + .map(|x| CString::new(x).expect("Error: Unexpected null byte")).collect(); + opts_c_ptr = opts_c.iter().map(|x| x.as_ptr()).collect(); + } else { + opts_c_ptr = Vec::new(); + } + let result = unsafe { + if opts_c_ptr.is_empty() { + sys::libvlc_vlm_add_broadcast(self.ptr, name.as_ptr(), input.as_ptr(), output.as_ptr(), 0, ptr::null(), enabled, loop_broadcast) + } else { + sys::libvlc_vlm_add_broadcast(self.ptr, name.as_ptr(), input.as_ptr(), output.as_ptr(), opts_c_ptr.len() as i32, opts_c_ptr.as_ptr(), enabled, loop_broadcast) + } + }; + if result == 0 { Ok(()) } + else { Err(()) } + } + + pub fn play_media(&self, name: &str) -> Result<(), ()> { + let name = to_cstr(name); + let result = unsafe { + sys::libvlc_vlm_play_media(self.ptr, name.as_ptr()) + }; + if result == 0 { Ok(()) } + else { Err(()) } + } + + pub fn stop_media(&self, name: &str) -> Result<(), ()> { + let name = to_cstr(name); + let result = unsafe { + sys::libvlc_vlm_stop_media(self.ptr, name.as_ptr()) + }; + if result == 0 { Ok(()) } + else { Err(()) } + } + /// Sets the application name. /// LibVLC passes this as the user agent string when a protocol requires it. pub fn set_user_agent(&self, name: &str, http: &str) { From a5499802ab83cd42f016dc5453680b88a5e83bfb Mon Sep 17 00:00:00 2001 From: Raniz Date: Tue, 19 Nov 2019 07:26:29 +0100 Subject: [PATCH 3/6] Add method for adding VODs to VLM --- src/core.rs | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/core.rs b/src/core.rs index b04f096..ef8c141 100644 --- a/src/core.rs +++ b/src/core.rs @@ -105,6 +105,31 @@ impl Instance { else { Err(()) } } + pub fn add_vod(&self, name: &str, input: &str, mux: &str, options: Option>, enabled: bool) -> Result<(), ()> { + let name= to_cstr(name); + let input = to_cstr(input); + let mux = to_cstr(mux); + let opts_c_ptr: Vec<*const c_char> ; + let opts_c: Vec; + let enabled = if enabled { 1 } else { 0 }; + if let Some(vec) = options { + opts_c = vec.into_iter() + .map(|x| CString::new(x).expect("Error: Unexpected null byte")).collect(); + opts_c_ptr = opts_c.iter().map(|x| x.as_ptr()).collect(); + } else { + opts_c_ptr = Vec::new(); + } + let result = unsafe { + if opts_c_ptr.is_empty() { + sys::libvlc_vlm_add_vod(self.ptr, name.as_ptr(), input.as_ptr(), 0, ptr::null(), enabled, mux.as_ptr()) + } else { + sys::libvlc_vlm_add_vod(self.ptr, name.as_ptr(), input.as_ptr(), opts_c_ptr.len() as i32, opts_c_ptr.as_ptr(), enabled, mux.as_ptr()) + } + }; + if result == 0 { Ok(()) } + else { Err(()) } + } + pub fn play_media(&self, name: &str) -> Result<(), ()> { let name = to_cstr(name); let result = unsafe { From cd3b94f83b8e20b085aabcddbe60b6ec38fe5e3b Mon Sep 17 00:00:00 2001 From: Raniz Date: Tue, 19 Nov 2019 15:20:05 +0100 Subject: [PATCH 4/6] Add support for VLM events --- src/core.rs | 77 +++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 54 insertions(+), 23 deletions(-) diff --git a/src/core.rs b/src/core.rs index aa0fe3a..f1b21f0 100644 --- a/src/core.rs +++ b/src/core.rs @@ -5,7 +5,7 @@ use std::ptr; use std::borrow::Cow; use std::marker::PhantomData; -use std::ffi::CString; +use std::ffi::{CString, CStr}; use std::i32; use sys; use ::tools::{to_cstr, from_cstr, from_cstr_ref}; @@ -190,6 +190,15 @@ impl Instance { } } + /// Returns the VLM event manager + pub fn vlm_event_manager<'a>(&'a self) -> EventManager<'a> { + unsafe{ + let p = sys::libvlc_vlm_get_event_manager(self.ptr); + assert!(!p.is_null()); + EventManager{ptr: p, _phantomdata: ::std::marker::PhantomData} + } + } + /// Set logging callback pub fn set_log) + Send + 'static>(&self, f: F) { let cb: Box) + Send + 'static>> = Box::new(Box::new(f)); @@ -367,17 +376,17 @@ pub enum Event { MediaDiscovererStarted, MediaDiscovererEnded, - VlmMediaAdded, - VlmMediaRemoved, - VlmMediaChanged, - VlmMediaInstanceStarted, - VlmMediaInstanceStopped, - VlmMediaInstanceStatusInit, - VlmMediaInstanceStatusOpening, - VlmMediaInstanceStatusPlaying, - VlmMediaInstanceStatusPause, - VlmMediaInstanceStatusEnd, - VlmMediaInstanceStatusError + VlmMediaAdded(Option, Option), + VlmMediaRemoved(Option, Option), + VlmMediaChanged(Option, Option), + VlmMediaInstanceStarted(Option, Option), + VlmMediaInstanceStopped(Option, Option), + VlmMediaInstanceStatusInit(Option, Option), + VlmMediaInstanceStatusOpening(Option, Option), + VlmMediaInstanceStatusPlaying(Option, Option), + VlmMediaInstanceStatusPause(Option, Option), + VlmMediaInstanceStatusEnd(Option, Option), + VlmMediaInstanceStatusError(Option, Option) } pub struct EventManager<'a> { @@ -556,37 +565,59 @@ fn conv_event(pe: *const sys::libvlc_event_t) -> Event { Event::MediaDiscovererEnded }, EventType::VlmMediaAdded => { - Event::VlmMediaAdded + unsafe { + Event::VlmMediaAdded(from_cstr((*pe).u.vlm_media_event.psz_instance_name), from_cstr((*pe).u.vlm_media_event.psz_media_name)) + } }, EventType::VlmMediaRemoved => { - Event::VlmMediaRemoved + unsafe { + Event::VlmMediaRemoved(from_cstr((*pe).u.vlm_media_event.psz_instance_name), from_cstr((*pe).u.vlm_media_event.psz_media_name)) + } }, EventType::VlmMediaChanged => { - Event::VlmMediaChanged + unsafe { + Event::VlmMediaChanged(from_cstr((*pe).u.vlm_media_event.psz_instance_name), from_cstr((*pe).u.vlm_media_event.psz_media_name)) + } }, EventType::VlmMediaInstanceStarted => { - Event::VlmMediaInstanceStarted + unsafe { + Event::VlmMediaInstanceStarted(from_cstr((*pe).u.vlm_media_event.psz_instance_name), from_cstr((*pe).u.vlm_media_event.psz_media_name)) + } }, EventType::VlmMediaInstanceStopped => { - Event::VlmMediaInstanceStopped + unsafe { + Event::VlmMediaInstanceStopped(from_cstr((*pe).u.vlm_media_event.psz_instance_name), from_cstr((*pe).u.vlm_media_event.psz_media_name)) + } }, EventType::VlmMediaInstanceStatusInit => { - Event::VlmMediaInstanceStatusInit + unsafe { + Event::VlmMediaInstanceStatusInit(from_cstr((*pe).u.vlm_media_event.psz_instance_name), from_cstr((*pe).u.vlm_media_event.psz_media_name)) + } }, EventType::VlmMediaInstanceStatusOpening => { - Event::VlmMediaInstanceStatusOpening + unsafe { + Event::VlmMediaInstanceStatusOpening(from_cstr((*pe).u.vlm_media_event.psz_instance_name), from_cstr((*pe).u.vlm_media_event.psz_media_name)) + } }, EventType::VlmMediaInstanceStatusPlaying => { - Event::VlmMediaInstanceStatusPlaying + unsafe { + Event::VlmMediaInstanceStatusPlaying(from_cstr((*pe).u.vlm_media_event.psz_instance_name), from_cstr((*pe).u.vlm_media_event.psz_media_name)) + } }, EventType::VlmMediaInstanceStatusPause => { - Event::VlmMediaInstanceStatusPause + unsafe { + Event::VlmMediaInstanceStatusPause(from_cstr((*pe).u.vlm_media_event.psz_instance_name), from_cstr((*pe).u.vlm_media_event.psz_media_name)) + } }, EventType::VlmMediaInstanceStatusEnd => { - Event::VlmMediaInstanceStatusEnd + unsafe { + Event::VlmMediaInstanceStatusEnd(from_cstr((*pe).u.vlm_media_event.psz_instance_name), from_cstr((*pe).u.vlm_media_event.psz_media_name)) + } }, EventType::VlmMediaInstanceStatusError => { - Event::VlmMediaInstanceStatusError + unsafe { + Event::VlmMediaInstanceStatusError(from_cstr((*pe).u.vlm_media_event.psz_instance_name), from_cstr((*pe).u.vlm_media_event.psz_media_name)) + } }, } } From d379d70a1cccd37659c1406543c62ad04525f36d Mon Sep 17 00:00:00 2001 From: Raniz Date: Mon, 25 Nov 2019 11:34:57 +0100 Subject: [PATCH 5/6] VLM as a separate module * Refactored VLM methods into a VLM trait in it's own module * Added more VLM methods --- src/core.rs | 69 ------------------------- src/lib.rs | 2 + src/vlm.rs | 146 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 148 insertions(+), 69 deletions(-) create mode 100644 src/vlm.rs diff --git a/src/core.rs b/src/core.rs index f1b21f0..2ef6c7c 100644 --- a/src/core.rs +++ b/src/core.rs @@ -81,75 +81,6 @@ impl Instance { else { Err(()) } } - pub fn add_broadcast(&self, name: &str, input: &str, output: &str, options: Option>, enabled: bool, loop_broadcast: bool,) -> Result<(), ()> { - let name= to_cstr(name); - let input = to_cstr(input); - let output = to_cstr(output); - let opts_c_ptr: Vec<*const c_char> ; - let opts_c: Vec; - let enabled = if enabled { 1 } else { 0 }; - let loop_broadcast = if loop_broadcast { 1 } else { 0 }; - if let Some(vec) = options { - opts_c = vec.into_iter() - .map(|x| CString::new(x).expect("Error: Unexpected null byte")).collect(); - opts_c_ptr = opts_c.iter().map(|x| x.as_ptr()).collect(); - } else { - opts_c_ptr = Vec::new(); - } - let result = unsafe { - if opts_c_ptr.is_empty() { - sys::libvlc_vlm_add_broadcast(self.ptr, name.as_ptr(), input.as_ptr(), output.as_ptr(), 0, ptr::null(), enabled, loop_broadcast) - } else { - sys::libvlc_vlm_add_broadcast(self.ptr, name.as_ptr(), input.as_ptr(), output.as_ptr(), opts_c_ptr.len() as i32, opts_c_ptr.as_ptr(), enabled, loop_broadcast) - } - }; - if result == 0 { Ok(()) } - else { Err(()) } - } - - pub fn add_vod(&self, name: &str, input: &str, mux: &str, options: Option>, enabled: bool) -> Result<(), ()> { - let name= to_cstr(name); - let input = to_cstr(input); - let mux = to_cstr(mux); - let opts_c_ptr: Vec<*const c_char> ; - let opts_c: Vec; - let enabled = if enabled { 1 } else { 0 }; - if let Some(vec) = options { - opts_c = vec.into_iter() - .map(|x| CString::new(x).expect("Error: Unexpected null byte")).collect(); - opts_c_ptr = opts_c.iter().map(|x| x.as_ptr()).collect(); - } else { - opts_c_ptr = Vec::new(); - } - let result = unsafe { - if opts_c_ptr.is_empty() { - sys::libvlc_vlm_add_vod(self.ptr, name.as_ptr(), input.as_ptr(), 0, ptr::null(), enabled, mux.as_ptr()) - } else { - sys::libvlc_vlm_add_vod(self.ptr, name.as_ptr(), input.as_ptr(), opts_c_ptr.len() as i32, opts_c_ptr.as_ptr(), enabled, mux.as_ptr()) - } - }; - if result == 0 { Ok(()) } - else { Err(()) } - } - - pub fn play_media(&self, name: &str) -> Result<(), ()> { - let name = to_cstr(name); - let result = unsafe { - sys::libvlc_vlm_play_media(self.ptr, name.as_ptr()) - }; - if result == 0 { Ok(()) } - else { Err(()) } - } - - pub fn stop_media(&self, name: &str) -> Result<(), ()> { - let name = to_cstr(name); - let result = unsafe { - sys::libvlc_vlm_stop_media(self.ptr, name.as_ptr()) - }; - if result == 0 { Ok(()) } - else { Err(()) } - } - /// Sets the application name. /// LibVLC passes this as the user agent string when a protocol requires it. pub fn set_user_agent(&self, name: &str, http: &str) { diff --git a/src/lib.rs b/src/lib.rs index 6825be0..4bf0ad4 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -15,6 +15,7 @@ mod media_library; mod enums; mod video; mod audio; +mod vlm; pub use enums::*; pub use core::*; @@ -24,3 +25,4 @@ pub use media_list::*; pub use media_library::*; pub use video::*; pub use audio::*; +pub use vlm::*; diff --git a/src/vlm.rs b/src/vlm.rs new file mode 100644 index 0000000..09b31e7 --- /dev/null +++ b/src/vlm.rs @@ -0,0 +1,146 @@ +use ::{sys, Instance}; +use std::ffi::CString; +use tools::{to_cstr, from_cstr}; +use std::os::raw::c_char; +use std::ptr; + +pub trait Vlm { + fn add_broadcast(&self, name: &str, input: &str, output: &str, options: Option>, enabled: bool, loop_broadcast: bool, ) -> Result<(), ()>; + + fn add_vod(&self, name: &str, input: &str, mux: &str, options: Option>, enabled: bool) -> Result<(), ()>; + + fn play_media(&self, name: &str) -> Result<(), ()>; + + fn pause_media(&self, name: &str) -> Result<(), ()>; + + fn stop_media(&self, name: &str) -> Result<(), ()>; + + fn get_media_instance_position(&self, name: &str, instance: i32) -> Result; + + fn get_media_instance_length(&self, name: &str, instance: i32) -> Result; + + fn get_media_instance_time(&self, name: &str, instance: i32) -> Result; + + fn get_media_instance_rate(&self, name: &str, instance: i32) -> Result; + + fn show_media(&self, name: &str) -> Result; +} + +impl Vlm for Instance { + fn add_broadcast(&self, name: &str, input: &str, output: &str, options: Option>, enabled: bool, loop_broadcast: bool, ) -> Result<(), ()> { + let name = to_cstr(name); + let input = to_cstr(input); + let output = to_cstr(output); + let opts_c_ptr: Vec<*const c_char>; + let opts_c: Vec; + let enabled = if enabled { 1 } else { 0 }; + let loop_broadcast = if loop_broadcast { 1 } else { 0 }; + if let Some(vec) = options { + opts_c = vec.into_iter() + .map(|x| CString::new(x).expect("Error: Unexpected null byte")).collect(); + opts_c_ptr = opts_c.iter().map(|x| x.as_ptr()).collect(); + } else { + opts_c_ptr = Vec::new(); + } + let result = unsafe { + if opts_c_ptr.is_empty() { + sys::libvlc_vlm_add_broadcast(self.ptr, name.as_ptr(), input.as_ptr(), output.as_ptr(), 0, ptr::null(), enabled, loop_broadcast) + } else { + sys::libvlc_vlm_add_broadcast(self.ptr, name.as_ptr(), input.as_ptr(), output.as_ptr(), opts_c_ptr.len() as i32, opts_c_ptr.as_ptr(), enabled, loop_broadcast) + } + }; + if result == 0 { Ok(()) } else { Err(()) } + } + + fn add_vod(&self, name: &str, input: &str, mux: &str, options: Option>, enabled: bool) -> Result<(), ()> { + let name = to_cstr(name); + let input = to_cstr(input); + let mux = to_cstr(mux); + let opts_c_ptr: Vec<*const c_char>; + let opts_c: Vec; + let enabled = if enabled { 1 } else { 0 }; + if let Some(vec) = options { + opts_c = vec.into_iter() + .map(|x| CString::new(x).expect("Error: Unexpected null byte")).collect(); + opts_c_ptr = opts_c.iter().map(|x| x.as_ptr()).collect(); + } else { + opts_c_ptr = Vec::new(); + } + let result = unsafe { + if opts_c_ptr.is_empty() { + sys::libvlc_vlm_add_vod(self.ptr, name.as_ptr(), input.as_ptr(), 0, ptr::null(), enabled, mux.as_ptr()) + } else { + sys::libvlc_vlm_add_vod(self.ptr, name.as_ptr(), input.as_ptr(), opts_c_ptr.len() as i32, opts_c_ptr.as_ptr(), enabled, mux.as_ptr()) + } + }; + if result == 0 { Ok(()) } else { Err(()) } + } + + fn play_media(&self, name: &str) -> Result<(), ()> { + let name = to_cstr(name); + let result = unsafe { + sys::libvlc_vlm_play_media(self.ptr, name.as_ptr()) + }; + if result == 0 { Ok(()) } else { Err(()) } + } + + fn pause_media(&self, name: &str) -> Result<(), ()> { + let name = to_cstr(name); + let result = unsafe { + sys::libvlc_vlm_pause_media(self.ptr, name.as_ptr()) + }; + if result == 0 { Ok(()) } else { Err(()) } + } + + fn stop_media(&self, name: &str) -> Result<(), ()> { + let name = to_cstr(name); + let result = unsafe { + sys::libvlc_vlm_stop_media(self.ptr, name.as_ptr()) + }; + if result == 0 { Ok(()) } else { Err(()) } + } + + fn get_media_instance_position(&self, name: &str, instance: i32) -> Result { + let name = to_cstr(name); + let result = unsafe { + sys::libvlc_vlm_get_media_instance_position(self.ptr, name.as_ptr(), instance) + }; + if result != -1f32 { Ok(result) } else { Err(()) } + } + + fn get_media_instance_length(&self, name: &str, instance: i32) -> Result { + let name = to_cstr(name); + let result = unsafe { + sys::libvlc_vlm_get_media_instance_length(self.ptr, name.as_ptr(), instance) + }; + if result != -1 { Ok(result) } else { Err(()) } + } + + fn get_media_instance_time(&self, name: &str, instance: i32) -> Result { + let name = to_cstr(name); + let result = unsafe { + sys::libvlc_vlm_get_media_instance_time(self.ptr, name.as_ptr(), instance) + }; + if result != -1 { Ok(result) } else { Err(()) } + } + + fn get_media_instance_rate(&self, name: &str, instance: i32) -> Result { + let name = to_cstr(name); + let result = unsafe { + sys::libvlc_vlm_get_media_instance_rate(self.ptr, name.as_ptr(), instance) + }; + if result != -1 { Ok(result) } else { Err(()) } + } + + fn show_media(&self, name: &str) -> Result { + let name = to_cstr(name); + let result = unsafe { + from_cstr(sys::libvlc_vlm_show_media(self.ptr, name.as_ptr())) + }; + if let Some(data) = result { + Ok(data.to_string()) + } else { + Err(()) + } + } +} From 93560d3e10493b27871ab0f7c1d089b94e0758a6 Mon Sep 17 00:00:00 2001 From: Raniz Date: Mon, 25 Nov 2019 11:48:12 +0100 Subject: [PATCH 6/6] Update for Rust 2018 --- src/vlm.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/vlm.rs b/src/vlm.rs index 09b31e7..9ad7283 100644 --- a/src/vlm.rs +++ b/src/vlm.rs @@ -1,9 +1,10 @@ -use ::{sys, Instance}; use std::ffi::CString; -use tools::{to_cstr, from_cstr}; use std::os::raw::c_char; use std::ptr; +use crate::{Instance, sys}; +use crate::tools::{from_cstr, to_cstr}; + pub trait Vlm { fn add_broadcast(&self, name: &str, input: &str, output: &str, options: Option>, enabled: bool, loop_broadcast: bool, ) -> Result<(), ()>;