diff --git a/src/core.rs b/src/core.rs index 003ad11..236de3c 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 libc::{c_void, c_char, c_int}; use crate::sys; @@ -31,6 +31,8 @@ pub struct Instance { } +unsafe impl Send for Instance {} + impl Instance { /// Create and initialize a libvlc instance with specified args. /// Note: args.len() has to be less or equal to i32::MAX @@ -119,6 +121,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)); @@ -296,17 +307,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> { @@ -485,37 +496,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)) + } }, } } diff --git a/src/lib.rs b/src/lib.rs index 0772446..db9d611 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 crate::enums::*; pub use crate::core::*; @@ -24,3 +25,4 @@ pub use crate::media_list::*; pub use crate::media_library::*; pub use crate::video::*; pub use crate::audio::*; +pub use crate::vlm::*; diff --git a/src/media.rs b/src/media.rs index 4c4a44f..f100d01 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 8bbcc6f..669665f 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 { diff --git a/src/vlm.rs b/src/vlm.rs new file mode 100644 index 0000000..9ad7283 --- /dev/null +++ b/src/vlm.rs @@ -0,0 +1,147 @@ +use std::ffi::CString; +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<(), ()>; + + 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(()) + } + } +}