vlc/
media_player.rs

1// Copyright (c) 2015 T. Okubo
2// This file is part of vlc-rs.
3// Licensed under the MIT license, see the LICENSE file.
4
5use sys;
6use ::Instance;
7use ::Media;
8use ::EventManager;
9use ::libc::{c_void, c_uint};
10use ::enums::{State, Position};
11use std::mem::transmute;
12
13/// A LibVLC media player plays one media (usually in a custom drawable).
14pub struct MediaPlayer {
15    pub(crate) ptr: *mut sys::libvlc_media_player_t,
16}
17
18impl MediaPlayer {
19    /// Create an empty Media Player object
20    pub fn new(instance: &Instance) -> Option<MediaPlayer> {
21        unsafe{
22            let p = sys::libvlc_media_player_new(instance.ptr);
23
24            if p.is_null() {
25                return None;
26            }
27            Some(MediaPlayer{ptr: p})
28        }
29    }
30
31    /// Set the media that will be used by the media_player. If any, previous md will be released.
32    pub fn set_media(&self, md: &Media) {
33        unsafe{ sys::libvlc_media_player_set_media(self.ptr, md.ptr) };
34    }
35
36    /// Get the media used by the media_player.
37    pub fn get_media(&self) -> Option<Media> {
38        let p = unsafe{ sys::libvlc_media_player_get_media(self.ptr) };
39        if p.is_null() {
40            None
41        }else{
42            Some(Media{ptr: p})
43        }
44    }
45
46    /// Get the Event Manager from which the media player send event.
47    pub fn event_manager<'a>(&'a self) -> EventManager<'a> {
48        unsafe{
49            let p = sys::libvlc_media_player_event_manager(self.ptr);
50            assert!(!p.is_null());
51            EventManager{ptr: p, _phantomdata: ::std::marker::PhantomData}
52        }
53    }
54
55    /// is_playing
56    pub fn is_playing(&self) -> bool {
57        if unsafe{ sys::libvlc_media_player_is_playing(self.ptr) } == 0 {
58            false
59        }else{
60            true
61        }
62    }
63
64    /// Play
65    pub fn play(&self) -> Result<(), ()> {
66        if unsafe{ sys::libvlc_media_player_play(self.ptr) } == 0 {
67            Ok(())
68        }else{
69            Err(())
70        }
71    }
72
73    /// Pause or resume (no effect if there is no media)
74    pub fn set_pause(&self, do_pause: bool) {
75        unsafe{ sys::libvlc_media_player_set_pause(self.ptr, if do_pause {1} else {0}) };
76    }
77
78    /// Toggle pause (no effect if there is no media)
79    pub fn pause(&self) {
80        unsafe{ sys::libvlc_media_player_pause(self.ptr) };
81    }
82
83    /// Stop (no effect if there is no media)
84    pub fn stop(&self) {
85        unsafe{ sys::libvlc_media_player_stop(self.ptr) };
86    }
87
88    pub fn set_callbacks<F>(
89        &self,
90        play: F,
91        pause: Option<Box<Fn(i64) + Send + 'static>>,
92        resume: Option<Box<Fn(i64) + Send + 'static>>,
93        flush: Option<Box<Fn(i64) + Send + 'static>>,
94        drain: Option<Box<Fn() + Send + 'static>>)
95        where F: Fn(*const c_void, u32, i64) + Send + 'static,
96    {
97        let flag_pause = pause.is_some();
98        let flag_resume = resume.is_some();
99        let flag_flush = flush.is_some();
100        let flag_drain = drain.is_some();
101        
102        let data = AudioCallbacksData {
103            play: Box::new(play), pause: pause, resume: resume,
104            flush: flush, drain: drain,
105        };
106        let data = Box::into_raw(Box::new(data));
107
108        unsafe{
109            sys::libvlc_audio_set_callbacks(
110                self.ptr,
111                Some(audio_cb_play),
112                if flag_pause {Some(audio_cb_pause)} else {None},
113                if flag_resume {Some(audio_cb_resume)} else {None},
114                if flag_flush {Some(audio_cb_flush)} else {None},
115                if flag_drain {Some(audio_cb_drain)} else {None},
116                data as *mut c_void);
117        }
118    }
119
120    /// Set the NSView handler where the media player should render its video output. 
121    pub fn set_nsobject(&self, drawable: *mut c_void) {
122        unsafe{ sys::libvlc_media_player_set_nsobject(self.ptr, drawable) };
123    }
124
125    /// Get the NSView handler previously set with set_nsobject(). 
126    pub fn get_nsobject(&self) -> Option<*mut c_void> {
127        let nso = unsafe{ sys::libvlc_media_player_get_nsobject(self.ptr) };
128        if nso.is_null() { None }else{ Some(nso) }
129    }
130
131    /// Set an X Window System drawable where the media player should render its video output.
132    pub fn set_xwindow(&self, drawable: u32) {
133        unsafe{ sys::libvlc_media_player_set_xwindow(self.ptr, drawable) };
134    }
135
136    /// Get the X Window System window identifier previously set with set_xwindow(). 
137    pub fn get_xwindow(&self) -> Option<u32> {
138        let id = unsafe{ sys::libvlc_media_player_get_xwindow(self.ptr) };
139        if id == 0 { None }else{ Some(id) }
140    }
141
142    /// Set a Win32/Win64 API window handle (HWND) where the media player should render its video output.
143    /// If LibVLC was built without Win32/Win64 API output support, then this has no effects.
144    pub fn set_hwnd(&self, drawable: *mut c_void) {
145        unsafe{ sys::libvlc_media_player_set_hwnd(self.ptr, drawable) };
146    }
147
148    /// Get the Windows API window handle (HWND) previously set with set_hwnd().
149    pub fn get_hwnd(&self) -> Option<*mut c_void> {
150        let hwnd = unsafe{ sys::libvlc_media_player_get_hwnd(self.ptr) };
151        if hwnd.is_null() { None }else{ Some(hwnd) }
152    }
153
154    /// Get the current movie time (in ms).
155    pub fn get_time(&self) -> Option<i64> {
156        unsafe{
157            let t = sys::libvlc_media_player_get_time(self.ptr);
158            if t == -1 { None }else{ Some(t) }
159        }
160    }
161
162    /// Set the movie time (in ms).
163    /// This has no effect if no media is being played. Not all formats and protocols support this.
164    pub fn set_time(&self, time: i64) {
165        unsafe{ sys::libvlc_media_player_set_time(self.ptr, time); }
166    }
167
168    /// Get movie position as percentage between 0.0 and 1.0.
169    pub fn get_position(&self) -> Option<f32> {
170        unsafe{
171            let pos = sys::libvlc_media_player_get_position(self.ptr);
172            if pos == -1f32 { None }else{ Some(pos) }
173        }
174    }
175
176    /// Set movie position as percentage between 0.0 and 1.0.
177    /// This has no effect if playback is not enabled. This might not work depending on the underlying input format and protocol.
178    pub fn set_position(&self, pos: f32) {
179        unsafe{ sys::libvlc_media_player_set_position(self.ptr, pos); }
180    }
181
182    /// Set movie chapter (if applicable).
183    pub fn set_chapter(&self, chapter: i32) {
184        unsafe{ sys::libvlc_media_player_set_chapter(self.ptr, chapter); }
185    }
186
187    /// Get movie chapter.
188    pub fn get_chapter(&self) -> Option<i32> {
189        unsafe{
190            let c = sys::libvlc_media_player_get_chapter(self.ptr);
191            if c == -1 { None }else{ Some(c) }
192        }
193    }
194
195    /// Get movie chapter count.
196    pub fn chapter_count(&self) -> Option<i32> {
197        unsafe{
198            let c = sys::libvlc_media_player_get_chapter_count(self.ptr);
199            if c == -1 { None }else{ Some(c) }
200        }
201    }
202
203    /// Is the player able to play.
204    pub fn will_play(&self) -> bool {
205        unsafe{
206            let b = sys::libvlc_media_player_will_play(self.ptr);
207            if b == 0 { false }else{ true }
208        }
209    }
210
211    /// Get title chapter count.
212    pub fn chapter_count_for_title(&self, title: i32) -> Option<i32> {
213        unsafe{
214            let c = sys::libvlc_media_player_get_chapter_count_for_title(self.ptr, title);
215            if c == -1 { None }else{ Some(c) }
216        }
217    }
218
219    /// Set movie title.
220    pub fn set_title(&self, title: i32) {
221        unsafe{ sys::libvlc_media_player_set_title(self.ptr, title); }
222    }
223
224    /// Get movie title.
225    pub fn get_title(&self) -> Option<i32> {
226        unsafe{
227            let t = sys::libvlc_media_player_get_title(self.ptr);
228            if t == -1 { None }else{ Some(t) }
229        }
230    }
231
232    /// Get movie title count.
233    pub fn title_count(&self) -> Option<i32> {
234        unsafe{
235            let t = sys::libvlc_media_player_get_title_count(self.ptr);
236            if t == -1 { Some(t) } else { None }
237        }
238    }
239
240    /// Set previous chapter (if applicable)
241    pub fn previous_chapter(&self) {
242        unsafe{ sys::libvlc_media_player_previous_chapter(self.ptr); }
243    }
244
245    /// Set next chapter (if applicable)
246    pub fn next_chapter(&self) {
247        unsafe{ sys::libvlc_media_player_next_chapter(self.ptr); }
248    }
249
250    /// Get the requested movie play rate.
251    pub fn get_rate(&self) -> f32 {
252        unsafe{ sys::libvlc_media_player_get_rate(self.ptr) }
253    }
254
255    /// Set movie play rate.
256    pub fn set_rate(&self, rate: f32) -> Result<(),()> {
257        unsafe{
258            if sys::libvlc_media_player_set_rate(self.ptr, rate) == -1 {
259                Err(())
260            }else{
261                Ok(())
262            }
263        }
264    }
265
266    /// Get current movie state.
267    pub fn state(&self) -> State {
268        unsafe{ sys::libvlc_media_player_get_state(self.ptr) }
269    }
270
271    /// How many video outputs does this media player have?
272    pub fn has_vout(&self) -> u32 {
273        unsafe{ sys::libvlc_media_player_has_vout(self.ptr) }
274    }
275
276    /// Is this media player seekable?
277    pub fn is_seekable(&self) -> bool {
278        unsafe{
279            let b = sys::libvlc_media_player_is_seekable(self.ptr);
280            if b == 0 { false }else{ true }
281        }
282    }
283
284    /// Can this media player be paused?
285    pub fn can_pause(&self) -> bool {
286        unsafe{
287            let b = sys::libvlc_media_player_can_pause(self.ptr);
288            if b == 0 { false }else{ true }
289        }
290    }
291
292    /// Check if the current program is scrambled.
293    pub fn program_scrambled(&self) -> bool {
294        unsafe{
295            let b = sys::libvlc_media_player_program_scrambled(self.ptr);
296            if b == 0 { false }else{ true }
297        }
298    }
299
300    /// Display the next frame (if supported)
301    pub fn next_frame(&self) {
302        unsafe{ sys::libvlc_media_player_next_frame(self.ptr); }
303    }
304
305    /// Navigate through DVD Menu.
306    pub fn navigate(&self, navigate: u32) {
307        unsafe{ sys::libvlc_media_player_navigate(self.ptr, navigate); }
308    }
309
310    /// Set if, and how, the video title will be shown when media is played.
311    pub fn set_video_title_display(&self, position: Position, timeout: u32) {
312        unsafe{ sys::libvlc_media_player_set_video_title_display(self.ptr, position, timeout); }
313    }
314
315    /// Returns raw pointer
316    pub fn raw(&self) -> *mut sys::libvlc_media_player_t {
317        self.ptr
318    }
319}
320
321impl Drop for MediaPlayer {
322    fn drop(&mut self) {
323        unsafe{ sys::libvlc_media_player_release(self.ptr) };
324    }
325}
326
327// For audio_set_callbacks
328struct AudioCallbacksData {
329    play: Box<Fn(*const c_void, u32, i64) + Send + 'static>,
330    pause: Option<Box<Fn(i64) + Send + 'static>>,
331    resume: Option<Box<Fn(i64) + Send + 'static>>,
332    flush: Option<Box<Fn(i64) + Send + 'static>>,
333    drain: Option<Box<Fn() + Send + 'static>>,
334}
335
336unsafe extern "C" fn audio_cb_play(
337    data: *mut c_void, samples: *const c_void, count: c_uint, pts: i64) {
338    let data: &AudioCallbacksData = transmute(data as *mut AudioCallbacksData);
339    (data.play)(samples, count, pts);
340    
341}
342
343unsafe extern "C" fn audio_cb_pause(data: *mut c_void, pts: i64) {
344    let data: &AudioCallbacksData = transmute(data as *mut AudioCallbacksData);
345    (data.pause.as_ref().unwrap())(pts);
346}
347
348unsafe extern "C" fn audio_cb_resume(data: *mut c_void, pts: i64) {
349    let data: &AudioCallbacksData = transmute(data as *mut AudioCallbacksData);
350    (data.resume.as_ref().unwrap())(pts);
351}
352
353unsafe extern "C" fn audio_cb_flush(data: *mut c_void, pts: i64) {
354    let data: &AudioCallbacksData = transmute(data as *mut AudioCallbacksData);
355    (data.flush.as_ref().unwrap())(pts);
356}
357
358unsafe extern "C" fn audio_cb_drain(data: *mut c_void) {
359    let data: &AudioCallbacksData = transmute(data as *mut AudioCallbacksData);
360    (data.drain.as_ref().unwrap())();
361}
362
363#[derive(Clone, PartialEq, Eq, Hash, Debug)]
364pub struct TrackDescription {
365    pub id: i32,
366    pub name: Option<String>,
367}
368