vlc/
core.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 std::ptr::null;
6use std::borrow::Cow;
7use std::marker::PhantomData;
8use sys;
9use ::tools::{to_cstr, from_cstr, from_cstr_ref};
10use ::libc::{c_void, c_char, c_int};
11use ::enums::*;
12
13/// Retrieve libvlc version. 
14pub fn version() -> String {
15    unsafe{
16        from_cstr_ref(sys::libvlc_get_version()).unwrap().into_owned()
17    }
18}
19
20/// Retrieve libvlc compiler version.
21pub fn compiler() -> String {
22    unsafe{
23        from_cstr_ref(sys::libvlc_get_compiler()).unwrap().into_owned()
24    }
25}
26
27pub struct Instance {
28    pub(crate) ptr: *mut sys::libvlc_instance_t,
29}
30
31impl Instance {
32    /// Create and initialize a libvlc instance. 
33    pub fn new() -> Option<Instance> {
34        unsafe{
35            let p = sys::libvlc_new(0, null());
36            
37            if p.is_null() {
38                return None;
39            }
40            
41            Some(Instance{ptr: p})
42        }
43    }
44
45    /// Try to start a user interface for the libvlc instance.
46    pub fn add_intf(&self, name: &str) -> Result<(), ()> {
47        let cstr = to_cstr(name);
48
49        let result = unsafe{
50            sys::libvlc_add_intf(self.ptr, cstr.as_ptr())
51        };
52
53        if result == 0 { Ok(()) }
54        else { Err(()) }
55    }
56
57    /// Sets the application name.
58    /// LibVLC passes this as the user agent string when a protocol requires it.
59    pub fn set_user_agent(&self, name: &str, http: &str) {
60        unsafe{
61            sys::libvlc_set_user_agent(
62                self.ptr, to_cstr(name).as_ptr(), to_cstr(http).as_ptr());
63        }
64    }
65
66    /// Waits until an interface causes the instance to exit.
67    pub fn wait(&self) {
68        unsafe{ sys::libvlc_wait(self.ptr) };
69    }
70
71    /// Sets some meta-information about the application.
72    pub fn set_app_id(&self, id: &str, version: &str, icon: &str) {
73        unsafe{
74            sys::libvlc_set_app_id(
75                self.ptr, to_cstr(id).as_ptr(), to_cstr(version).as_ptr(), to_cstr(icon).as_ptr());
76        }
77    }
78
79    /// Returns a list of audio filters that are available.
80    pub fn audio_filter_list_get(&self) -> Option<ModuleDescriptionList> {
81        unsafe{
82            let p = sys::libvlc_audio_filter_list_get(self.ptr);
83            if p.is_null() { None }
84            else { Some(ModuleDescriptionList{ptr: p}) }
85        }
86    }
87
88    /// Returns a list of video filters that are available.
89    pub fn video_filter_list_get(&self) -> Option<ModuleDescriptionList> {
90        unsafe{
91            let p = sys::libvlc_video_filter_list_get(self.ptr);
92            if p.is_null() { None }
93            else { Some(ModuleDescriptionList{ptr: p}) }
94        }
95    }
96
97    /// Set logging callback
98    pub fn set_log<F: Fn(LogLevel, Log, Cow<str>) + Send + 'static>(&self, f: F) {
99        let cb: Box<Box<Fn(LogLevel, Log, Cow<str>) + Send + 'static>> = Box::new(Box::new(f));
100        
101        unsafe{
102            sys::libvlc_log_set(self.ptr, logging_cb, Box::into_raw(cb) as *mut _);
103        }
104    }
105
106    /// Returns raw pointer
107    pub fn raw(&self) -> *mut sys::libvlc_instance_t {
108        self.ptr
109    }
110}
111
112impl Drop for Instance {
113    fn drop(&mut self) {
114        unsafe{
115            sys::libvlc_release(self.ptr);
116        }
117    }
118}
119
120extern "C" {
121    fn vsnprintf(s: *mut c_char, n: usize, fmt: *const c_char, arg: sys::va_list);
122}
123const BUF_SIZE: usize = 1024; // Write log message to the buffer by vsnprintf.
124unsafe extern "C" fn logging_cb(
125    data: *mut c_void, level: c_int, ctx: *const sys::libvlc_log_t, fmt: *const c_char, args: sys::va_list) {
126
127    let f: &Box<Fn(LogLevel, Log, Cow<str>) + Send + 'static> = ::std::mem::transmute(data);
128    let mut buf: [c_char; BUF_SIZE] = [0; BUF_SIZE];
129
130    vsnprintf(buf.as_mut_ptr(), BUF_SIZE, fmt, args);
131
132    f(::std::mem::transmute(level), Log{ptr: ctx}, from_cstr_ref(buf.as_ptr()).unwrap());
133}
134
135/// List of module description.
136pub struct ModuleDescriptionList {
137    ptr: *mut sys::libvlc_module_description_t,
138}
139
140impl ModuleDescriptionList {
141    /// Returns raw pointer
142    pub fn raw(&self) -> *mut sys::libvlc_module_description_t {
143        self.ptr
144    }
145}
146
147impl Drop for ModuleDescriptionList {
148    fn drop(&mut self) {
149        unsafe{ sys::libvlc_module_description_list_release(self.ptr) };
150    }
151}
152
153impl<'a> IntoIterator for &'a ModuleDescriptionList {
154    type Item = ModuleDescriptionRef<'a>;
155    type IntoIter = ModuleDescriptionListIter<'a>;
156
157    fn into_iter(self) -> Self::IntoIter {
158        ModuleDescriptionListIter{ptr: self.ptr, _phantomdata: PhantomData}
159    }
160}
161
162pub struct ModuleDescriptionListIter<'a> {
163    ptr: *mut sys::libvlc_module_description_t,
164    _phantomdata: PhantomData<&'a sys::libvlc_module_description_t>,
165}
166
167/// Description of a module.
168/// The strings are owned.
169#[derive(Clone, PartialEq, Eq, Hash, Debug)]
170pub struct ModuleDescription {
171    pub name:      Option<String>,
172    pub shortname: Option<String>,
173    pub longname:  Option<String>,
174    pub help:      Option<String>,
175}
176
177/// Description of a module. 
178#[derive(Clone, PartialEq, Eq, Hash, Debug)]
179pub struct ModuleDescriptionRef<'a> {
180    pub name:      Option<Cow<'a, str>>,
181    pub shortname: Option<Cow<'a, str>>,
182    pub longname:  Option<Cow<'a, str>>,
183    pub help:      Option<Cow<'a, str>>,
184}
185
186impl<'a> Iterator for ModuleDescriptionListIter<'a> {
187    type Item = ModuleDescriptionRef<'a>;
188
189    fn next(&mut self) -> Option<Self::Item> {
190        unsafe{
191            if self.ptr.is_null() {
192                return None;
193            }
194            let p = self.ptr;
195            self.ptr = (*p).p_next;
196            Some(ModuleDescriptionRef{
197                name:      from_cstr_ref((*p).psz_name),
198                shortname: from_cstr_ref((*p).psz_shortname),
199                longname:  from_cstr_ref((*p).psz_longname),
200                help:      from_cstr_ref((*p).psz_help),
201            })
202        }
203    }
204}
205
206impl<'a> ModuleDescriptionRef<'a> {
207    /// Convert to owned strings.
208    pub fn into_owned(&'a self) -> ModuleDescription {
209        ModuleDescription {
210            name:      self.name     .as_ref().map(|s| s.clone().into_owned()),
211            shortname: self.shortname.as_ref().map(|s| s.clone().into_owned()),
212            longname:  self.name     .as_ref().map(|s| s.clone().into_owned()),
213            help:      self.shortname.as_ref().map(|s| s.clone().into_owned()),
214        }
215    }
216}
217
218pub fn errmsg() -> Option<String> {
219    unsafe{ from_cstr(sys::libvlc_errmsg()) }
220}
221
222pub fn clearerr() {
223    unsafe{ sys::libvlc_clearerr() };
224}
225
226#[derive(Clone, Debug)]
227pub enum Event {
228    MediaMetaChanged(Meta),
229    MediaSubItemAdded,
230    MediaDurationChanged(i64),
231    MediaParsedChanged(i32),
232    MediaFreed,
233    MediaStateChanged(State),
234    MediaSubItemTreeAdded,
235    
236    MediaPlayerMediaChanged,
237    MediaPlayerNothingSpecial,
238    MediaPlayerOpening,
239    MediaPlayerBuffering(f32),
240    MediaPlayerPlaying,
241    MediaPlayerPaused,
242    MediaPlayerStopped,
243    MediaPlayerForward,
244    MediaPlayerBackward,
245    MediaPlayerEndReached,
246    MediaPlayerEncounteredError,
247    MediaPlayerTimeChanged,
248    MediaPlayerPositionChanged(f32),
249    MediaPlayerSeekableChanged,
250    MediaPlayerPausableChanged,
251    MediaPlayerTitleChanged,
252    MediaPlayerSnapshotTaken,
253    MediaPlayerLengthChanged,
254    MediaPlayerVout,
255    MediaPlayerScrambledChanged,
256
257    MediaListItemAdded,
258    MediaListWillAddItem,
259    MediaListItemDeleted,
260    MediaListWillDeleteItem,
261
262    MediaListViewItemAdded,
263    MediaListViewWillAddItem,
264    MediaListViewItemDeleted,
265    MediaListViewWillDeleteItem,
266
267    MediaListPlayerPlayed,
268    MediaListPlayerNextItemSet,
269    MediaListPlayerStopped,
270
271    MediaDiscovererStarted,
272    MediaDiscovererEnded,
273
274    VlmMediaAdded,
275    VlmMediaRemoved,
276    VlmMediaChanged,
277    VlmMediaInstanceStarted,
278    VlmMediaInstanceStopped,
279    VlmMediaInstanceStatusInit,
280    VlmMediaInstanceStatusOpening,
281    VlmMediaInstanceStatusPlaying,
282    VlmMediaInstanceStatusPause,
283    VlmMediaInstanceStatusEnd,
284    VlmMediaInstanceStatusError
285}
286
287pub struct EventManager<'a> {
288    pub(crate) ptr: *mut sys::libvlc_event_manager_t,
289    pub(crate) _phantomdata: ::std::marker::PhantomData<&'a sys::libvlc_event_manager_t>,
290}
291
292impl<'a> EventManager<'a> {
293    pub fn attach<F>(&self, event_type: EventType, callback: F) -> Result<(), ()>
294        where F: Fn(Event, VLCObject) + Send + 'static
295    {
296        // Explicit type annotation is needed
297        let callback: Box<Box<Fn(Event, VLCObject) + Send + 'static>> =
298            Box::new(Box::new(callback));
299        
300        let result = unsafe{
301            sys::libvlc_event_attach(
302                self.ptr, event_type as i32, event_manager_callback,
303                Box::into_raw(callback) as *mut c_void)
304        };
305
306        if result == 0 {
307            Ok(())
308        }else{
309            Err(())
310        }
311    }
312
313    /// Returns raw pointer
314    pub fn raw(&self) -> *mut sys::libvlc_event_manager_t {
315        self.ptr
316    }
317}
318
319unsafe extern "C" fn event_manager_callback(pe: *const sys::libvlc_event_t, data: *mut c_void) {
320    let f: &Box<Fn(Event, VLCObject) + Send + 'static> = ::std::mem::transmute(data);
321
322    f(conv_event(pe), VLCObject{ ptr: (*pe).p_obj });
323}
324
325// Convert c-style libvlc_event_t to Event
326fn conv_event(pe: *const sys::libvlc_event_t) -> Event {
327    let event_type: EventType = unsafe{ ::std::mem::transmute((*pe)._type) };
328    
329    match event_type {
330        EventType::MediaMetaChanged => {
331            unsafe{
332                Event::MediaMetaChanged((*pe).u.media_meta_changed.meta_type)
333            }
334        },
335        EventType::MediaSubItemAdded => {
336            Event::MediaSubItemAdded
337        },
338        EventType::MediaDurationChanged => {
339            unsafe{
340                Event::MediaDurationChanged((*pe).u.media_duration_changed.new_duration)
341            }
342        },
343        EventType::MediaParsedChanged => {
344            unsafe{
345                Event::MediaParsedChanged((*pe).u.media_parsed_changed.new_status)
346            }
347        },
348        EventType::MediaFreed => {
349            Event::MediaFreed
350        },
351        EventType::MediaStateChanged => {
352            unsafe{
353                Event::MediaStateChanged((*pe).u.media_state_changed.new_state)
354            }
355        },
356        EventType::MediaSubItemTreeAdded => {
357            Event::MediaSubItemTreeAdded
358        },
359        EventType::MediaPlayerMediaChanged => {
360            Event::MediaPlayerMediaChanged
361        },
362        EventType::MediaPlayerNothingSpecial => {
363            Event::MediaPlayerNothingSpecial
364        },
365        EventType::MediaPlayerOpening => {
366            Event::MediaPlayerOpening
367        },
368        EventType::MediaPlayerBuffering => {
369            unsafe{
370                Event::MediaPlayerBuffering((*pe).u.media_player_buffering.new_cache)
371            }
372        },
373        EventType::MediaPlayerPlaying => {
374            Event::MediaPlayerPlaying
375        },
376        EventType::MediaPlayerPaused => {
377            Event::MediaPlayerPaused
378        },
379        EventType::MediaPlayerStopped => {
380            Event::MediaPlayerStopped
381        },
382        EventType::MediaPlayerForward => {
383            Event::MediaPlayerForward
384        },
385        EventType::MediaPlayerBackward => {
386            Event::MediaPlayerBackward
387        },
388        EventType::MediaPlayerEndReached => {
389            Event::MediaPlayerEndReached
390        },
391        EventType::MediaPlayerEncounteredError => {
392            Event::MediaPlayerEncounteredError
393        },
394        EventType::MediaPlayerTimeChanged => {
395            Event::MediaPlayerTimeChanged
396        },
397        EventType::MediaPlayerPositionChanged => {
398            unsafe{
399                Event::MediaPlayerPositionChanged((*pe).u.media_player_position_changed.new_position)
400            }
401        },
402        EventType::MediaPlayerSeekableChanged => {
403            Event::MediaPlayerSeekableChanged
404        },
405        EventType::MediaPlayerPausableChanged => {
406            Event::MediaPlayerPausableChanged
407        },
408        EventType::MediaPlayerTitleChanged => {
409            Event::MediaPlayerTitleChanged
410        },
411        EventType::MediaPlayerSnapshotTaken => {
412            Event::MediaPlayerSnapshotTaken
413        },
414        EventType::MediaPlayerLengthChanged => {
415            Event::MediaPlayerLengthChanged
416        },
417        EventType::MediaPlayerVout => {
418            Event::MediaPlayerVout
419        },
420        EventType::MediaPlayerScrambledChanged => {
421            Event::MediaPlayerScrambledChanged
422        },
423        EventType::MediaListItemAdded => {
424            Event::MediaListItemAdded
425        },
426        EventType::MediaListWillAddItem => {
427            Event::MediaListWillAddItem
428        },
429        EventType::MediaListItemDeleted => {
430            Event::MediaListItemDeleted
431        },
432        EventType::MediaListWillDeleteItem => {
433            Event::MediaListWillDeleteItem
434        },
435        EventType::MediaListViewItemAdded => {
436            Event::MediaListViewItemAdded
437        },
438        EventType::MediaListViewWillAddItem => {
439            Event::MediaListViewWillAddItem
440        },
441        EventType::MediaListViewItemDeleted => {
442            Event::MediaListViewItemDeleted
443        },
444        EventType::MediaListViewWillDeleteItem => {
445            Event::MediaListViewWillDeleteItem
446        },
447        EventType::MediaListPlayerPlayed => {
448            Event::MediaListPlayerPlayed
449        },
450        EventType::MediaListPlayerNextItemSet => {
451            Event::MediaListPlayerNextItemSet
452        },
453        EventType::MediaListPlayerStopped => {
454            Event::MediaListPlayerStopped
455        },
456        EventType::MediaDiscovererStarted => {
457            Event::MediaDiscovererStarted
458        },
459        EventType::MediaDiscovererEnded => {
460            Event::MediaDiscovererEnded
461        },
462        EventType::VlmMediaAdded => {
463            Event::VlmMediaAdded
464        },
465        EventType::VlmMediaRemoved => {
466            Event::VlmMediaRemoved
467        },
468        EventType::VlmMediaChanged => {
469            Event::VlmMediaChanged
470        },
471        EventType::VlmMediaInstanceStarted => {
472            Event::VlmMediaInstanceStarted
473        },
474        EventType::VlmMediaInstanceStopped => {
475            Event::VlmMediaInstanceStopped
476        },
477        EventType::VlmMediaInstanceStatusInit => {
478            Event::VlmMediaInstanceStatusInit
479        },
480        EventType::VlmMediaInstanceStatusOpening => {
481            Event::VlmMediaInstanceStatusOpening
482        },
483        EventType::VlmMediaInstanceStatusPlaying => {
484            Event::VlmMediaInstanceStatusPlaying
485        },
486        EventType::VlmMediaInstanceStatusPause => {
487            Event::VlmMediaInstanceStatusPause
488        },
489        EventType::VlmMediaInstanceStatusEnd => {
490            Event::VlmMediaInstanceStatusEnd
491        },
492        EventType::VlmMediaInstanceStatusError => {
493            Event::VlmMediaInstanceStatusError
494        },
495    }
496}
497
498pub struct VLCObject {
499    ptr: *mut c_void,
500}
501
502impl VLCObject {
503    /// Returns raw pointer
504    pub fn raw(&self) -> *mut c_void {
505        self.ptr
506    }
507}
508
509pub struct Log {
510    pub(crate) ptr: *const sys::libvlc_log_t
511}
512
513impl Log {
514    /// Returns raw pointer
515    pub fn raw(&self) -> *const sys::libvlc_log_t {
516        self.ptr
517    }
518}
519