// Copyright (c) 2015 T. Okubo // This file is part of vlc-rs. // Licensed under the MIT license, see the LICENSE file. use ffi; use ::Instance; use ::Media; use ::EventManager; use ::libc::{c_void, c_uint}; use std::mem::transmute; /// A LibVLC media player plays one media (usually in a custom drawable). pub struct MediaPlayer { pub ptr: *mut ffi::libvlc_media_player_t, } impl MediaPlayer { /// Create an empty Media Player object pub fn new(instance: &Instance) -> Option { unsafe{ let p = ffi::libvlc_media_player_new(instance.ptr); if p.is_null() { return None; } Some(MediaPlayer{ptr: p}) } } /// Set the media that will be used by the media_player. If any, previous md will be released. pub fn set_media(&self, md: &Media) { unsafe{ ffi::libvlc_media_player_set_media(self.ptr, md.ptr) }; } /// Get the media used by the media_player. pub fn get_media(&self) -> Option { let p = unsafe{ ffi::libvlc_media_player_get_media(self.ptr) }; if p.is_null() { None }else{ Some(Media{ptr: p}) } } /// Get the Event Manager from which the media player send event. pub fn event_manager<'a>(&'a self) -> EventManager<'a> { unsafe{ let p = ffi::libvlc_media_player_event_manager(self.ptr); assert!(!p.is_null()); EventManager{ptr: p, _phantomdata: ::std::marker::PhantomData} } } /// is_playing pub fn is_playing(&self) -> bool { if unsafe{ ffi::libvlc_media_player_is_playing(self.ptr) } == 0 { false }else{ true } } /// Play pub fn play(&self) -> Result<(), ()> { if unsafe{ ffi::libvlc_media_player_play(self.ptr) } == 0 { Ok(()) }else{ Err(()) } } /// Pause or resume (no effect if there is no media) pub fn set_pause(&self, do_pause: bool) { unsafe{ ffi::libvlc_media_player_set_pause(self.ptr, if do_pause {1} else {0}) }; } /// Toggle pause (no effect if there is no media) pub fn pause(&self) { unsafe{ ffi::libvlc_media_player_pause(self.ptr) }; } /// Stop (no effect if there is no media) pub fn stop(&self) { unsafe{ ffi::libvlc_media_player_stop(self.ptr) }; } pub fn set_callbacks( &self, play: F, pause: Option>, resume: Option>, flush: Option>, drain: Option>) where F: Fn(*const c_void, u32, i64) + Send + 'static, { let flag_pause = pause.is_some(); let flag_resume = resume.is_some(); let flag_flush = flush.is_some(); let flag_drain = drain.is_some(); let data = AudioCallbacksData { play: Box::new(play), pause: pause, resume: resume, flush: flush, drain: drain, }; let data = Box::into_raw(Box::new(data)); unsafe{ ffi::libvlc_audio_set_callbacks( self.ptr, Some(audio_cb_play), if flag_pause {Some(audio_cb_pause)} else {None}, if flag_resume {Some(audio_cb_resume)} else {None}, if flag_flush {Some(audio_cb_flush)} else {None}, if flag_drain {Some(audio_cb_drain)} else {None}, data as *mut c_void); } } /// Set the NSView handler where the media player should render its video output. pub fn set_nsobject(&self, drawable: *mut c_void) { unsafe{ ffi::libvlc_media_player_set_nsobject(self.ptr, drawable) }; } /// Get the NSView handler previously set with set_nsobject(). pub fn get_nsobject(&self) -> Option<*mut c_void> { let nso = unsafe{ ffi::libvlc_media_player_get_nsobject(self.ptr) }; if nso.is_null() { None }else{ Some(nso) } } /// Set an X Window System drawable where the media player should render its video output. pub fn set_xwindow(&self, drawable: u32) { unsafe{ ffi::libvlc_media_player_set_xwindow(self.ptr, drawable) }; } /// Get the X Window System window identifier previously set with set_xwindow(). pub fn get_xwindow(&self) -> Option { let id = unsafe{ ffi::libvlc_media_player_get_xwindow(self.ptr) }; if id == 0 { None }else{ Some(id) } } /// Set a Win32/Win64 API window handle (HWND) where the media player should render its video output. /// If LibVLC was built without Win32/Win64 API output support, then this has no effects. pub fn set_hwnd(&self, drawable: *mut c_void) { unsafe{ ffi::libvlc_media_player_set_hwnd(self.ptr, drawable) }; } /// Get the Windows API window handle (HWND) previously set with set_hwnd(). pub fn get_hwnd(&self) -> Option<*mut c_void> { let hwnd = unsafe{ ffi::libvlc_media_player_get_hwnd(self.ptr) }; if hwnd.is_null() { None }else{ Some(hwnd) } } } impl Drop for MediaPlayer { fn drop(&mut self) { unsafe{ ffi::libvlc_media_player_release(self.ptr) }; } } // For audio_set_callbacks struct AudioCallbacksData { play: Box, pause: Option>, resume: Option>, flush: Option>, drain: Option>, } unsafe extern "C" fn audio_cb_play( data: *mut c_void, samples: *const c_void, count: c_uint, pts: i64) { let data: &AudioCallbacksData = transmute(data as *mut AudioCallbacksData); (data.play)(samples, count, pts); } unsafe extern "C" fn audio_cb_pause(data: *mut c_void, pts: i64) { let data: &AudioCallbacksData = transmute(data as *mut AudioCallbacksData); (data.pause.as_ref().unwrap())(pts); } unsafe extern "C" fn audio_cb_resume(data: *mut c_void, pts: i64) { let data: &AudioCallbacksData = transmute(data as *mut AudioCallbacksData); (data.resume.as_ref().unwrap())(pts); } unsafe extern "C" fn audio_cb_flush(data: *mut c_void, pts: i64) { let data: &AudioCallbacksData = transmute(data as *mut AudioCallbacksData); (data.flush.as_ref().unwrap())(pts); } unsafe extern "C" fn audio_cb_drain(data: *mut c_void) { let data: &AudioCallbacksData = transmute(data as *mut AudioCallbacksData); (data.drain.as_ref().unwrap())(); }