369 lines
12 KiB
Rust
369 lines
12 KiB
Rust
// Copyright (c) 2015 T. Okubo
|
|
// This file is part of vlc-rs.
|
|
// Licensed under the MIT license, see the LICENSE file.
|
|
|
|
use crate::sys;
|
|
use crate::Instance;
|
|
use crate::Media;
|
|
use crate::EventManager;
|
|
use libc::{c_void, c_uint};
|
|
use crate::enums::{State, Position};
|
|
use std::mem::transmute;
|
|
|
|
/// A LibVLC media player plays one media (usually in a custom drawable).
|
|
pub struct MediaPlayer {
|
|
pub(crate) ptr: *mut sys::libvlc_media_player_t,
|
|
}
|
|
|
|
impl MediaPlayer {
|
|
/// Create an empty Media Player object
|
|
pub fn new(instance: &Instance) -> Option<MediaPlayer> {
|
|
unsafe{
|
|
let p = sys::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{ sys::libvlc_media_player_set_media(self.ptr, md.ptr) };
|
|
}
|
|
|
|
/// Get the media used by the media_player.
|
|
pub fn get_media(&self) -> Option<Media> {
|
|
let p = unsafe{ sys::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 = sys::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{ sys::libvlc_media_player_is_playing(self.ptr) } == 0 {
|
|
false
|
|
}else{
|
|
true
|
|
}
|
|
}
|
|
|
|
/// Play
|
|
pub fn play(&self) -> Result<(), ()> {
|
|
if unsafe{ sys::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{ sys::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{ sys::libvlc_media_player_pause(self.ptr) };
|
|
}
|
|
|
|
/// Stop (no effect if there is no media)
|
|
pub fn stop(&self) {
|
|
unsafe{ sys::libvlc_media_player_stop(self.ptr) };
|
|
}
|
|
|
|
pub fn set_callbacks<F>(
|
|
&self,
|
|
play: F,
|
|
pause: Option<Box<dyn Fn(i64) + Send + 'static>>,
|
|
resume: Option<Box<dyn Fn(i64) + Send + 'static>>,
|
|
flush: Option<Box<dyn Fn(i64) + Send + 'static>>,
|
|
drain: Option<Box<dyn Fn() + Send + 'static>>)
|
|
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{
|
|
sys::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{ sys::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{ sys::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{ sys::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<u32> {
|
|
let id = unsafe{ sys::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{ sys::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{ sys::libvlc_media_player_get_hwnd(self.ptr) };
|
|
if hwnd.is_null() { None }else{ Some(hwnd) }
|
|
}
|
|
|
|
/// Get the current movie time (in ms).
|
|
pub fn get_time(&self) -> Option<i64> {
|
|
unsafe{
|
|
let t = sys::libvlc_media_player_get_time(self.ptr);
|
|
if t == -1 { None }else{ Some(t) }
|
|
}
|
|
}
|
|
|
|
/// Set the movie time (in ms).
|
|
/// This has no effect if no media is being played. Not all formats and protocols support this.
|
|
pub fn set_time(&self, time: i64) {
|
|
unsafe{ sys::libvlc_media_player_set_time(self.ptr, time); }
|
|
}
|
|
|
|
/// Get movie position as percentage between 0.0 and 1.0.
|
|
pub fn get_position(&self) -> Option<f32> {
|
|
unsafe{
|
|
let pos = sys::libvlc_media_player_get_position(self.ptr);
|
|
if pos == -1f32 { None }else{ Some(pos) }
|
|
}
|
|
}
|
|
|
|
/// Set movie position as percentage between 0.0 and 1.0.
|
|
/// This has no effect if playback is not enabled. This might not work depending on the underlying input format and protocol.
|
|
pub fn set_position(&self, pos: f32) {
|
|
unsafe{ sys::libvlc_media_player_set_position(self.ptr, pos); }
|
|
}
|
|
|
|
/// Set movie chapter (if applicable).
|
|
pub fn set_chapter(&self, chapter: i32) {
|
|
unsafe{ sys::libvlc_media_player_set_chapter(self.ptr, chapter); }
|
|
}
|
|
|
|
/// Get movie chapter.
|
|
pub fn get_chapter(&self) -> Option<i32> {
|
|
unsafe{
|
|
let c = sys::libvlc_media_player_get_chapter(self.ptr);
|
|
if c == -1 { None }else{ Some(c) }
|
|
}
|
|
}
|
|
|
|
/// Get movie chapter count.
|
|
pub fn chapter_count(&self) -> Option<i32> {
|
|
unsafe{
|
|
let c = sys::libvlc_media_player_get_chapter_count(self.ptr);
|
|
if c == -1 { None }else{ Some(c) }
|
|
}
|
|
}
|
|
|
|
/// Is the player able to play.
|
|
pub fn will_play(&self) -> bool {
|
|
unsafe{
|
|
let b = sys::libvlc_media_player_will_play(self.ptr);
|
|
if b == 0 { false }else{ true }
|
|
}
|
|
}
|
|
|
|
/// Get title chapter count.
|
|
pub fn chapter_count_for_title(&self, title: i32) -> Option<i32> {
|
|
unsafe{
|
|
let c = sys::libvlc_media_player_get_chapter_count_for_title(self.ptr, title);
|
|
if c == -1 { None }else{ Some(c) }
|
|
}
|
|
}
|
|
|
|
/// Set movie title.
|
|
pub fn set_title(&self, title: i32) {
|
|
unsafe{ sys::libvlc_media_player_set_title(self.ptr, title); }
|
|
}
|
|
|
|
/// Get movie title.
|
|
pub fn get_title(&self) -> Option<i32> {
|
|
unsafe{
|
|
let t = sys::libvlc_media_player_get_title(self.ptr);
|
|
if t == -1 { None }else{ Some(t) }
|
|
}
|
|
}
|
|
|
|
/// Get movie title count.
|
|
pub fn title_count(&self) -> Option<i32> {
|
|
unsafe{
|
|
let t = sys::libvlc_media_player_get_title_count(self.ptr);
|
|
if t == -1 { Some(t) } else { None }
|
|
}
|
|
}
|
|
|
|
/// Set previous chapter (if applicable)
|
|
pub fn previous_chapter(&self) {
|
|
unsafe{ sys::libvlc_media_player_previous_chapter(self.ptr); }
|
|
}
|
|
|
|
/// Set next chapter (if applicable)
|
|
pub fn next_chapter(&self) {
|
|
unsafe{ sys::libvlc_media_player_next_chapter(self.ptr); }
|
|
}
|
|
|
|
/// Get the requested movie play rate.
|
|
pub fn get_rate(&self) -> f32 {
|
|
unsafe{ sys::libvlc_media_player_get_rate(self.ptr) }
|
|
}
|
|
|
|
/// Set movie play rate.
|
|
pub fn set_rate(&self, rate: f32) -> Result<(),()> {
|
|
unsafe{
|
|
if sys::libvlc_media_player_set_rate(self.ptr, rate) == -1 {
|
|
Err(())
|
|
}else{
|
|
Ok(())
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Get current movie state.
|
|
pub fn state(&self) -> State {
|
|
unsafe{ sys::libvlc_media_player_get_state(self.ptr) }
|
|
}
|
|
|
|
/// How many video outputs does this media player have?
|
|
pub fn has_vout(&self) -> u32 {
|
|
unsafe{ sys::libvlc_media_player_has_vout(self.ptr) }
|
|
}
|
|
|
|
/// Is this media player seekable?
|
|
pub fn is_seekable(&self) -> bool {
|
|
unsafe{
|
|
let b = sys::libvlc_media_player_is_seekable(self.ptr);
|
|
if b == 0 { false }else{ true }
|
|
}
|
|
}
|
|
|
|
/// Can this media player be paused?
|
|
pub fn can_pause(&self) -> bool {
|
|
unsafe{
|
|
let b = sys::libvlc_media_player_can_pause(self.ptr);
|
|
if b == 0 { false }else{ true }
|
|
}
|
|
}
|
|
|
|
/// Check if the current program is scrambled.
|
|
pub fn program_scrambled(&self) -> bool {
|
|
unsafe{
|
|
let b = sys::libvlc_media_player_program_scrambled(self.ptr);
|
|
if b == 0 { false }else{ true }
|
|
}
|
|
}
|
|
|
|
/// Display the next frame (if supported)
|
|
pub fn next_frame(&self) {
|
|
unsafe{ sys::libvlc_media_player_next_frame(self.ptr); }
|
|
}
|
|
|
|
/// Navigate through DVD Menu.
|
|
pub fn navigate(&self, navigate: u32) {
|
|
unsafe{ sys::libvlc_media_player_navigate(self.ptr, navigate); }
|
|
}
|
|
|
|
/// Set if, and how, the video title will be shown when media is played.
|
|
pub fn set_video_title_display(&self, position: Position, timeout: u32) {
|
|
unsafe{ sys::libvlc_media_player_set_video_title_display(self.ptr, position, timeout); }
|
|
}
|
|
|
|
/// Returns raw pointer
|
|
pub fn raw(&self) -> *mut sys::libvlc_media_player_t {
|
|
self.ptr
|
|
}
|
|
}
|
|
|
|
impl Drop for MediaPlayer {
|
|
fn drop(&mut self) {
|
|
unsafe{ sys::libvlc_media_player_release(self.ptr) };
|
|
}
|
|
}
|
|
|
|
// For audio_set_callbacks
|
|
struct AudioCallbacksData {
|
|
play: Box<dyn Fn(*const c_void, u32, i64) + Send + 'static>,
|
|
pause: Option<Box<dyn Fn(i64) + Send + 'static>>,
|
|
resume: Option<Box<dyn Fn(i64) + Send + 'static>>,
|
|
flush: Option<Box<dyn Fn(i64) + Send + 'static>>,
|
|
drain: Option<Box<dyn Fn() + Send + 'static>>,
|
|
}
|
|
|
|
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())();
|
|
}
|
|
|
|
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
|
|
pub struct TrackDescription {
|
|
pub id: i32,
|
|
pub name: Option<String>,
|
|
}
|
|
|