diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..2610427 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "vlc-rs" +version = "0.1.0" +authors = ["T. Okubo "] + +[lib] +name = "vlc" +crate-type = ["rlib"] + +[dependencies] +libc = "*" diff --git a/src/core.rs b/src/core.rs new file mode 100644 index 0000000..3d05879 --- /dev/null +++ b/src/core.rs @@ -0,0 +1,466 @@ +// Copyright (c) 2015 T. Okubo +// This file is part of vlc-rs. +// Licensed under the MIT license, see the LICENSE file. + +use std::ptr::null; +use std::borrow::Cow; +use std::marker::PhantomData; +use ffi; +use ::tools::{to_cstr, from_cstr, from_cstr_ref}; +use ::libc::c_void; +use ::enums::*; + +/// Retrieve libvlc version. +pub fn version() -> Cow<'static, str> { + unsafe{ + from_cstr_ref(ffi::libvlc_get_version()).unwrap() + } +} + +/// Retrieve libvlc compiler version. +pub fn compiler() -> Cow<'static, str> { + unsafe{ + from_cstr_ref(ffi::libvlc_get_compiler()).unwrap() + } +} + +pub struct Instance { + pub ptr: *mut ffi::libvlc_instance_t, +} + +impl Instance { + /// Create and initialize a libvlc instance. + pub fn new() -> Option { + unsafe{ + let p = ffi::libvlc_new(0, null()); + + if p.is_null() { + return None; + } + + Some(Instance{ptr: p}) + } + } + + /// Try to start a user interface for the libvlc instance. + pub fn add_intf(&self, name: &str) -> Result<(), ()> { + let cstr = to_cstr(name); + + let result = unsafe{ + ffi::libvlc_add_intf(self.ptr, cstr.as_ptr()) + }; + + if result == 0 { Ok(()) } + else { Err(()) } + } + + /// Sets the application name. + /// LibVLC passes this as the user agent string when a protocol requires it. + pub fn set_user_agent(&self, name: &str, http: &str) { + unsafe{ + ffi::libvlc_set_user_agent( + self.ptr, to_cstr(name).as_ptr(), to_cstr(http).as_ptr()); + } + } + + /// Waits until an interface causes the instance to exit. + pub fn wait(&self) { + unsafe{ ffi::libvlc_wait(self.ptr) }; + } + + /// Sets some meta-information about the application. + pub fn set_app_id(&self, id: &str, version: &str, icon: &str) { + unsafe{ + ffi::libvlc_set_app_id( + self.ptr, to_cstr(id).as_ptr(), to_cstr(version).as_ptr(), to_cstr(icon).as_ptr()); + } + } + + /// Returns a list of audio filters that are available. + pub fn audio_filter_list_get(&self) -> Option { + unsafe{ + let p = ffi::libvlc_audio_filter_list_get(self.ptr); + if p.is_null() { None } + else { Some(ModuleDescriptionList{ptr: p}) } + } + } + + /// Returns a list of video filters that are available. + pub fn video_filter_list_get(&self) -> Option { + unsafe{ + let p = ffi::libvlc_video_filter_list_get(self.ptr); + if p.is_null() { None } + else { Some(ModuleDescriptionList{ptr: p}) } + } + } +} + +impl Drop for Instance { + fn drop(&mut self) { + unsafe{ + ffi::libvlc_release(self.ptr); + } + } +} + +/// List of module description. +pub struct ModuleDescriptionList { + ptr: *mut ffi::libvlc_module_description_t, +} + +impl Drop for ModuleDescriptionList { + fn drop(&mut self) { + unsafe{ ffi::libvlc_module_description_list_release(self.ptr) }; + } +} + +impl<'a> IntoIterator for &'a ModuleDescriptionList { + type Item = ModuleDescriptionRef<'a>; + type IntoIter = ModuleDescriptionListIter<'a>; + + fn into_iter(self) -> Self::IntoIter { + ModuleDescriptionListIter{ptr: self.ptr, _phantomdata: PhantomData} + } +} + +pub struct ModuleDescriptionListIter<'a> { + ptr: *mut ffi::libvlc_module_description_t, + _phantomdata: PhantomData<&'a ffi::libvlc_module_description_t>, +} + +/// Description of a module. +/// The strings are owned. +#[derive(Clone, PartialEq, Eq, Hash, Debug)] +pub struct ModuleDescription { + pub name: Option, + pub shortname: Option, + pub longname: Option, + pub help: Option, +} + +/// Description of a module. +#[derive(Clone, PartialEq, Eq, Hash, Debug)] +pub struct ModuleDescriptionRef<'a> { + pub name: Option>, + pub shortname: Option>, + pub longname: Option>, + pub help: Option>, +} + +impl<'a> Iterator for ModuleDescriptionListIter<'a> { + type Item = ModuleDescriptionRef<'a>; + + fn next(&mut self) -> Option { + unsafe{ + if self.ptr.is_null() { + return None; + } + let p = self.ptr; + self.ptr = (*p).p_next; + Some(ModuleDescriptionRef{ + name: from_cstr_ref((*p).psz_name), + shortname: from_cstr_ref((*p).psz_shortname), + longname: from_cstr_ref((*p).psz_longname), + help: from_cstr_ref((*p).psz_help), + }) + } + } +} + +impl<'a> ModuleDescriptionRef<'a> { + /// Convert to owned strings. + pub fn into_owned(&'a self) -> ModuleDescription { + ModuleDescription { + name: self.name .as_ref().map(|s| s.clone().into_owned()), + shortname: self.shortname.as_ref().map(|s| s.clone().into_owned()), + longname: self.name .as_ref().map(|s| s.clone().into_owned()), + help: self.shortname.as_ref().map(|s| s.clone().into_owned()), + } + } +} + +pub fn errmsg() -> Option { + unsafe{ from_cstr(ffi::libvlc_errmsg()) } +} + +pub fn clearerr() { + unsafe{ ffi::libvlc_clearerr() }; +} + +#[derive(Clone, Debug)] +pub enum Event { + MediaMetaChanged(Meta), + MediaSubItemAdded, + MediaDurationChanged(i64), + MediaParsedChanged(i32), + MediaFreed, + MediaStateChanged(State), + MediaSubItemTreeAdded, + + MediaPlayerMediaChanged, + MediaPlayerNothingSpecial, + MediaPlayerOpening, + MediaPlayerBuffering(f32), + MediaPlayerPlaying, + MediaPlayerPaused, + MediaPlayerStopped, + MediaPlayerForward, + MediaPlayerBackward, + MediaPlayerEndReached, + MediaPlayerEncounteredError, + MediaPlayerTimeChanged, + MediaPlayerPositionChanged(f32), + MediaPlayerSeekableChanged, + MediaPlayerPausableChanged, + MediaPlayerTitleChanged, + MediaPlayerSnapshotTaken, + MediaPlayerLengthChanged, + MediaPlayerVout, + MediaPlayerScrambledChanged, + + MediaListItemAdded, + MediaListWillAddItem, + MediaListItemDeleted, + MediaListWillDeleteItem, + + MediaListViewItemAdded, + MediaListViewWillAddItem, + MediaListViewItemDeleted, + MediaListViewWillDeleteItem, + + MediaListPlayerPlayed, + MediaListPlayerNextItemSet, + MediaListPlayerStopped, + + MediaDiscovererStarted, + MediaDiscovererEnded, + + VlmMediaAdded, + VlmMediaRemoved, + VlmMediaChanged, + VlmMediaInstanceStarted, + VlmMediaInstanceStopped, + VlmMediaInstanceStatusInit, + VlmMediaInstanceStatusOpening, + VlmMediaInstanceStatusPlaying, + VlmMediaInstanceStatusPause, + VlmMediaInstanceStatusEnd, + VlmMediaInstanceStatusError +} + +pub struct EventManager<'a> { + pub ptr: *mut ffi::libvlc_event_manager_t, + pub _phantomdata: ::std::marker::PhantomData<&'a ffi::libvlc_event_manager_t>, +} + +impl<'a> EventManager<'a> { + pub fn attach(&self, event_type: EventType, callback: F) -> Result<(), ()> + where F: Fn(Event, VLCObject) + Send + 'static + { + // Explicit type annotation is needed + let callback: Box> = + Box::new(Box::new(callback)); + + let result = unsafe{ + ffi::libvlc_event_attach( + self.ptr, event_type as i32, event_manager_callback, + Box::into_raw(callback) as *mut c_void) + }; + + if result == 0 { + Ok(()) + }else{ + Err(()) + } + } +} + +unsafe extern "C" fn event_manager_callback(pe: *const ffi::libvlc_event_t, data: *mut c_void) { + let f: &Box = ::std::mem::transmute(data); + + f(conv_event(pe), VLCObject{_ptr: (*pe).p_obj}); +} + +// Convert c-style libvlc_event_t to Event +fn conv_event(pe: *const ffi::libvlc_event_t) -> Event { + let event_type: EventType = unsafe{ ::std::mem::transmute((*pe)._type) }; + + match event_type { + EventType::MediaMetaChanged => { + unsafe{ + let p = ffi::libvlc_event_t_union::get_media_meta_changed(pe); + Event::MediaMetaChanged((*p).meta_type) + } + }, + EventType::MediaSubItemAdded => { + Event::MediaSubItemAdded + }, + EventType::MediaDurationChanged => { + unsafe{ + let p = ffi::libvlc_event_t_union::get_media_duration_changed(pe); + Event::MediaDurationChanged((*p).new_duration) + } + }, + EventType::MediaParsedChanged => { + unsafe{ + let p = ffi::libvlc_event_t_union::get_media_parsed_changed(pe); + Event::MediaParsedChanged((*p).new_status) + } + }, + EventType::MediaFreed => { + Event::MediaFreed + }, + EventType::MediaStateChanged => { + unsafe{ + let p = ffi::libvlc_event_t_union::get_media_state_changed(pe); + Event::MediaStateChanged((*p).new_state) + } + }, + EventType::MediaSubItemTreeAdded => { + Event::MediaSubItemTreeAdded + }, + EventType::MediaPlayerMediaChanged => { + Event::MediaPlayerMediaChanged + }, + EventType::MediaPlayerNothingSpecial => { + Event::MediaPlayerNothingSpecial + }, + EventType::MediaPlayerOpening => { + Event::MediaPlayerOpening + }, + EventType::MediaPlayerBuffering => { + unsafe{ + let p = ffi::libvlc_event_t_union::get_media_player_buffering(pe); + Event::MediaPlayerBuffering((*p).new_cache) + } + }, + EventType::MediaPlayerPlaying => { + Event::MediaPlayerPlaying + }, + EventType::MediaPlayerPaused => { + Event::MediaPlayerPaused + }, + EventType::MediaPlayerStopped => { + Event::MediaPlayerStopped + }, + EventType::MediaPlayerForward => { + Event::MediaPlayerForward + }, + EventType::MediaPlayerBackward => { + Event::MediaPlayerBackward + }, + EventType::MediaPlayerEndReached => { + Event::MediaPlayerEndReached + }, + EventType::MediaPlayerEncounteredError => { + Event::MediaPlayerEncounteredError + }, + EventType::MediaPlayerTimeChanged => { + Event::MediaPlayerTimeChanged + }, + EventType::MediaPlayerPositionChanged => { + unsafe{ + let p = ffi::libvlc_event_t_union::get_media_player_position_changed(pe); + Event::MediaPlayerPositionChanged((*p).new_position) + } + }, + EventType::MediaPlayerSeekableChanged => { + Event::MediaPlayerSeekableChanged + }, + EventType::MediaPlayerPausableChanged => { + Event::MediaPlayerPausableChanged + }, + EventType::MediaPlayerTitleChanged => { + Event::MediaPlayerTitleChanged + }, + EventType::MediaPlayerSnapshotTaken => { + Event::MediaPlayerSnapshotTaken + }, + EventType::MediaPlayerLengthChanged => { + Event::MediaPlayerLengthChanged + }, + EventType::MediaPlayerVout => { + Event::MediaPlayerVout + }, + EventType::MediaPlayerScrambledChanged => { + Event::MediaPlayerScrambledChanged + }, + EventType::MediaListItemAdded => { + Event::MediaListItemAdded + }, + EventType::MediaListWillAddItem => { + Event::MediaListWillAddItem + }, + EventType::MediaListItemDeleted => { + Event::MediaListItemDeleted + }, + EventType::MediaListWillDeleteItem => { + Event::MediaListWillDeleteItem + }, + EventType::MediaListViewItemAdded => { + Event::MediaListViewItemAdded + }, + EventType::MediaListViewWillAddItem => { + Event::MediaListViewWillAddItem + }, + EventType::MediaListViewItemDeleted => { + Event::MediaListViewItemDeleted + }, + EventType::MediaListViewWillDeleteItem => { + Event::MediaListViewWillDeleteItem + }, + EventType::MediaListPlayerPlayed => { + Event::MediaListPlayerPlayed + }, + EventType::MediaListPlayerNextItemSet => { + Event::MediaListPlayerNextItemSet + }, + EventType::MediaListPlayerStopped => { + Event::MediaListPlayerStopped + }, + EventType::MediaDiscovererStarted => { + Event::MediaDiscovererStarted + }, + EventType::MediaDiscovererEnded => { + Event::MediaDiscovererEnded + }, + EventType::VlmMediaAdded => { + Event::VlmMediaAdded + }, + EventType::VlmMediaRemoved => { + Event::VlmMediaRemoved + }, + EventType::VlmMediaChanged => { + Event::VlmMediaChanged + }, + EventType::VlmMediaInstanceStarted => { + Event::VlmMediaInstanceStarted + }, + EventType::VlmMediaInstanceStopped => { + Event::VlmMediaInstanceStopped + }, + EventType::VlmMediaInstanceStatusInit => { + Event::VlmMediaInstanceStatusInit + }, + EventType::VlmMediaInstanceStatusOpening => { + Event::VlmMediaInstanceStatusOpening + }, + EventType::VlmMediaInstanceStatusPlaying => { + Event::VlmMediaInstanceStatusPlaying + }, + EventType::VlmMediaInstanceStatusPause => { + Event::VlmMediaInstanceStatusPause + }, + EventType::VlmMediaInstanceStatusEnd => { + Event::VlmMediaInstanceStatusEnd + }, + EventType::VlmMediaInstanceStatusError => { + Event::VlmMediaInstanceStatusError + }, + } +} + +pub struct VLCObject { + _ptr: *mut c_void, +} + diff --git a/src/enums.rs b/src/enums.rs new file mode 100644 index 0000000..f1deac0 --- /dev/null +++ b/src/enums.rs @@ -0,0 +1,133 @@ +// Copyright (c) 2015 T. Okubo +// This file is part of vlc-rs. +// Licensed under the MIT license, see the LICENSE file. + +#[repr(C)] +#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] +pub enum LogLevel { + Debug = 0, + Notice = 2, + Warning = 3, + Error = 4, +} + +#[repr(C)] +#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] +pub enum Meta { + Title, + Artist, + Genre, + Copyright, + Album, + TrackNumber, + Description, + Rating, + Date, + Setting, + URL, + Language, + NowPlaying, + Publisher, + EncodedBy, + ArtworkURL, + TrackID, + TrackTotal, + Director, + Season, + Episode, + ShowName, + Actors +} + +#[repr(C)] +#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] +pub enum State { + NothingSpecial = 0, + Opening, + Buffering, + Playing, + Paused, + Stopped, + Ended, + Error +} + +#[repr(C)] +#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] +pub enum TrackType { + Unknown = -1, + Audio = 0, + Video = 1, + Text = 2 +} + +// #[repr(C)] +// #[derive(Clone, Copy, PartialEq, Eq, Debug)] +// pub enum ParseFlag { +// ParseLocal, +// ParseNetwork, +// FetchLocal, +// FetchNetwork, +// } + +#[repr(C)] +#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] +pub enum EventType { + MediaMetaChanged = 0, + MediaSubItemAdded, + MediaDurationChanged, + MediaParsedChanged, + MediaFreed, + MediaStateChanged, + MediaSubItemTreeAdded, + + MediaPlayerMediaChanged = 0x100, + MediaPlayerNothingSpecial, + MediaPlayerOpening, + MediaPlayerBuffering, + MediaPlayerPlaying, + MediaPlayerPaused, + MediaPlayerStopped, + MediaPlayerForward, + MediaPlayerBackward, + MediaPlayerEndReached, + MediaPlayerEncounteredError, + MediaPlayerTimeChanged, + MediaPlayerPositionChanged, + MediaPlayerSeekableChanged, + MediaPlayerPausableChanged, + MediaPlayerTitleChanged, + MediaPlayerSnapshotTaken, + MediaPlayerLengthChanged, + MediaPlayerVout, + MediaPlayerScrambledChanged, + + MediaListItemAdded = 0x200, + MediaListWillAddItem, + MediaListItemDeleted, + MediaListWillDeleteItem, + + MediaListViewItemAdded = 0x300, + MediaListViewWillAddItem, + MediaListViewItemDeleted, + MediaListViewWillDeleteItem, + + MediaListPlayerPlayed = 0x400, + MediaListPlayerNextItemSet, + MediaListPlayerStopped, + + MediaDiscovererStarted = 0x500, + MediaDiscovererEnded, + + VlmMediaAdded = 0x600, + VlmMediaRemoved, + VlmMediaChanged, + VlmMediaInstanceStarted, + VlmMediaInstanceStopped, + VlmMediaInstanceStatusInit, + VlmMediaInstanceStatusOpening, + VlmMediaInstanceStatusPlaying, + VlmMediaInstanceStatusPause, + VlmMediaInstanceStatusEnd, + VlmMediaInstanceStatusError +} diff --git a/src/ffi.rs b/src/ffi.rs new file mode 100644 index 0000000..0ccbff7 --- /dev/null +++ b/src/ffi.rs @@ -0,0 +1,829 @@ +// Copyright (c) 2015 T. Okubo +// This file is part of vlc-rs. +// Licensed under the MIT license, see the LICENSE file. + +#![allow(non_camel_case_types, non_upper_case_globals)] + +use libc::{c_void, c_int, c_uint, c_char, c_float, uintptr_t, FILE}; +use std::mem::transmute; + +pub type c_bool = u8; + +pub type libvlc_event_type_t = c_int; + +// From libvlc_structures.h +pub enum libvlc_instance_t {} +pub enum libvlc_log_iterator_t {} + +pub type libvlc_time_t = i64; + +#[repr(C)] +pub struct libvlc_log_message_t { + pub i_severity: c_int, + pub psz_type: *const c_char, + pub psz_name: *const c_char, + pub psz_header: *const c_char, + pub psz_message: *const c_char, +} + +// From libvlc.h +pub enum libvlc_event_manager_t {} +pub enum libvlc_log_t {} +pub enum vlc_log_t {} + +pub type libvlc_callback_t = unsafe extern "C" fn(*const libvlc_event_t, *mut c_void); + +pub use LogLevel as libvlc_log_level; + +#[repr(C)] +pub struct libvlc_module_description_t +{ + pub psz_name: *const c_char, + pub psz_shortname: *const c_char, + pub psz_longname: *const c_char, + pub psz_help: *const c_char, + pub p_next: *mut libvlc_module_description_t, +} + +#[link(name = "vlc")] +extern "C" { + pub fn libvlc_errmsg() -> *const c_char; + pub fn libvlc_clearerr(); + pub fn libvlc_new(argc: c_int, argv: *const *const c_char) -> *mut libvlc_instance_t; + pub fn libvlc_release(p_instance: *mut libvlc_instance_t); + pub fn libvlc_retain(p_instance: *mut libvlc_instance_t); + pub fn libvlc_add_intf(p_instance: *mut libvlc_instance_t, name: *const c_char) -> c_int; + pub fn libvlc_set_exit_handler( + p_instance: *mut libvlc_instance_t, + cb: extern "C" fn(*mut c_void), opaque: *mut c_void); + pub fn libvlc_wait(p_instance: *mut libvlc_instance_t); + pub fn libvlc_set_user_agent( + p_instance: *mut libvlc_instance_t, name: *const c_char, http: *const c_char); + pub fn libvlc_set_app_id( + p_instance: *mut libvlc_instance_t, id: *const c_char, version: *const c_char, + icon: *const c_char); + pub fn libvlc_get_version() -> *const c_char; + pub fn libvlc_get_compiler() -> *const c_char; + pub fn libvlc_get_changeset() -> *const c_char; + pub fn libvlc_free(ptr: *mut c_void); + pub fn libvlc_event_attach( + p_event_manager: *mut libvlc_event_manager_t, i_event_type: libvlc_event_type_t, + f_callback: libvlc_callback_t, user_data: *mut c_void) -> c_int; + pub fn libvlc_event_type_name(event_type: libvlc_event_type_t) -> *const c_char; + pub fn libvlc_log_get_context( + ctx: *const libvlc_log_t, module: *const *const c_char, file: *const *const c_char, + line: *mut c_uint); + pub fn libvlc_log_get_object( + ctx: *const libvlc_log_t, name: *const *const c_char, + header: *const *const c_char, id: *mut uintptr_t); + pub fn libvlc_log_unset(_: *mut libvlc_instance_t); + // pub fn libvlc_log_set + pub fn libvlc_log_set_file(_: *mut libvlc_instance_t, stream: *mut FILE); + pub fn libvlc_module_description_list_release(p_list: *mut libvlc_module_description_t); + pub fn libvlc_audio_filter_list_get( + p_instance: *mut libvlc_instance_t) -> *mut libvlc_module_description_t; + pub fn libvlc_video_filter_list_get( + p_instance: *mut libvlc_instance_t) -> *mut libvlc_module_description_t; + pub fn libvlc_clock() -> i64; +} + +pub unsafe fn libvlc_delay(pts: i64) -> i64 { + pts - libvlc_clock() +} + +// From libvlc_media.h +pub enum libvlc_media_t {} + +pub use Meta as libvlc_meta_t; +pub use State as libvlc_state_t; + +pub const libvlc_media_option_trusted: u32 = 0x2; +pub const libvlc_media_option_unique: u32 = 0x100; + +pub use TrackType as libvlc_track_type_t; + +#[repr(C)] +#[derive(Clone, Copy)] +pub struct libvlc_media_stats_t { + /* Input */ + pub i_read_bytes: c_int, + pub f_input_bitrate: c_float, + /* Demux */ + pub i_demux_read_bytes: c_int, + pub f_demux_bitrate: c_float, + pub i_demux_corrupted: c_int, + pub i_demux_discontinuity: c_int, + /* Decoders */ + pub i_decoded_video: c_int, + pub i_decoded_audio: c_int, + /* Video Output */ + pub i_displayed_pictures: c_int, + pub i_lost_pictures: c_int, + /* Audio output */ + pub i_played_abuffers: c_int, + pub i_lost_abuffers: c_int, + /* Stream output */ + pub i_sent_packets: c_int, + pub i_sent_bytes: c_int, + pub f_send_bitrate: c_float, +} + +#[repr(C)] +#[derive(Clone, Copy)] +pub struct libvlc_media_track_info_t { + /* Codec fourcc */ + pub i_codec: u32, + pub i_id: c_int, + pub i_type: libvlc_track_type_t, + /* Codec specific */ + pub i_profile: c_int, + pub i_level: c_int, + + pub _union0: [c_uint; 2] +} + +impl libvlc_media_track_info_t { + pub fn audio_i_channnels(&self) -> c_uint { + self._union0[0] + } + pub fn audio_i_rate(&self) -> c_uint { + self._union0[1] + } + pub fn video_i_height(&self) -> c_uint { + self._union0[0] + } + pub fn video_i_width(&self) -> c_uint { + self._union0[1] + } +} + +#[repr(C)] +#[derive(Clone, Copy)] +pub struct libvlc_audio_track_t +{ + pub i_channels: c_uint, + pub i_rate: c_uint, +} + +#[derive(Clone, Copy)] +pub struct libvlc_video_track_t +{ + pub i_height: c_uint, + pub i_width: c_uint, + pub i_sar_num: c_uint, + pub i_sar_den: c_uint, + pub i_frame_rate_num: c_uint, + pub i_frame_rate_den: c_uint, +} + +pub struct libvlc_subtitle_track_t { + pub psz_encoding: *const c_char, +} + +#[repr(C)] +pub struct libvlc_media_track_t { + pub i_codec: u32, + pub i_original_fourcc: u32, + pub i_id: c_int, + pub i_type: libvlc_track_type_t, + pub i_profile: c_int, + pub i_level: c_int, + pub _union0: *mut c_void, + pub i_bitrate: c_uint, + pub psz_language: *mut c_char, + pub psz_description: *mut c_char, +} + +impl libvlc_media_track_t { + pub unsafe fn audio(&mut self) -> *mut libvlc_audio_track_t { + transmute(self._union0) + } + pub unsafe fn video(&mut self) -> *mut libvlc_audio_track_t { + transmute(self._union0) + } + pub unsafe fn subtitle(&mut self) -> *mut libvlc_subtitle_track_t { + transmute(self._union0) + } +} + +#[link(name = "vlc")] +extern "C" { + pub fn libvlc_media_new_location(p_instance: *mut libvlc_instance_t, psz_mrl: *const c_char) + -> *mut libvlc_media_t; + pub fn libvlc_media_new_path(p_instance: *mut libvlc_instance_t, path: *const c_char) + -> *mut libvlc_media_t; + pub fn libvlc_media_new_fd(p_instance: *mut libvlc_instance_t, fd: c_int) + -> *mut libvlc_media_t; + pub fn libvlc_media_as_node(p_instance: *mut libvlc_instance_t, psz_name: *const c_char) + -> *mut libvlc_media_t; + pub fn libvlc_media_add_option(p_md: *mut libvlc_media_t, psz_options: *const c_char); + pub fn libvlc_media_add_option_flag( + p_md: *mut libvlc_media_t, psz_options: *const c_char, i_flags: c_uint); + pub fn libvlc_media_retain(p_md: *mut libvlc_media_t); + pub fn libvlc_media_release(p_md: *mut libvlc_media_t); + pub fn libvlc_media_get_mrl(p_md: *mut libvlc_media_t) -> *mut c_char; + pub fn libvlc_media_duplicate(p_md: *mut libvlc_media_t) -> *mut libvlc_media_t; + pub fn libvlc_media_get_meta(p_md: *mut libvlc_media_t, e_meta: libvlc_meta_t) -> *mut c_char; + pub fn libvlc_media_set_meta(p_md: *mut libvlc_media_t, e_meta: libvlc_meta_t, + psz_value: *const c_char); + pub fn libvlc_media_save_meta(p_md: *mut libvlc_media_t) -> c_int; + pub fn libvlc_media_get_state(p_md: *mut libvlc_media_t) -> libvlc_state_t; + pub fn libvlc_media_get_stats(p_md: *mut libvlc_media_t, p_stats: *mut libvlc_media_stats_t) + -> c_int; + pub fn libvlc_media_subitems(p_md: *mut libvlc_media_t) + -> *mut libvlc_media_list_t; + pub fn libvlc_media_event_manager(p_md: *mut libvlc_media_t) + -> *mut libvlc_event_manager_t; + pub fn libvlc_media_get_duration(p_md: *mut libvlc_media_t) + -> libvlc_time_t; + pub fn libvlc_media_parse(p_md: *mut libvlc_media_t); + pub fn libvlc_media_parse_async(p_md: *mut libvlc_media_t); + pub fn libvlc_media_is_parsed(p_md: *mut libvlc_media_t) -> c_int; + pub fn libvlc_media_set_user_data(p_md: *mut libvlc_media_t, + p_new_user_data: *mut c_void); + pub fn libvlc_media_get_user_data(p_md: *mut libvlc_media_t) -> *mut c_void; + pub fn libvlc_media_tracks_get(p_md: *mut libvlc_media_t, + tracks: *mut *mut *mut libvlc_media_track_t) -> c_uint; + pub fn libvlc_media_tracks_release(p_tracks: *mut *mut libvlc_media_track_t, i_count: c_uint); +} + +// From libvlc_media_player.h + +pub enum libvlc_media_player_t {} +pub enum libvlc_equalizer_t {} + +#[repr(C)] +pub struct libvlc_track_description_t { + i_id: c_int, + psz_name: *mut c_char, + p_next: *mut libvlc_track_description_t, +} + +#[repr(C)] +pub struct libvlc_audio_output_t { + psz_name: *mut c_char, + psz_description: *mut c_char, + p_next: *mut libvlc_audio_output_t, +} + +#[repr(C)] +pub struct libvlc_audio_output_device_t { + p_next: *mut libvlc_audio_output_device_t, + psz_device: *mut c_char, + psz_description: *mut c_char, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub struct libvlc_rectangle_t { + top: c_int, left: c_int, bottom: c_int, right: c_int, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub enum libvlc_video_marquee_option_t { + libvlc_marquee_Enable = 0, + libvlc_marquee_Text, + libvlc_marquee_Color, + libvlc_marquee_Opacity, + libvlc_marquee_Position, + libvlc_marquee_Refresh, + libvlc_marquee_Size, + libvlc_marquee_Timeout, + libvlc_marquee_X, + libvlc_marquee_Y, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub enum libvlc_navigate_mode_t { + libvlc_navigate_activate = 0, + libvlc_navigate_up, + libvlc_navigate_down, + libvlc_navigate_left, + libvlc_navigate_right, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub enum libvlc_position_t { + libvlc_position_disable = -1, + libvlc_position_center, + libvlc_position_left, + libvlc_position_right, + libvlc_position_top, + libvlc_position_top_left, + libvlc_position_top_right, + libvlc_position_bottom, + libvlc_position_bottom_left, + libvlc_position_bottom_right, +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub enum libvlc_video_logo_option_t { + libvlc_logo_enable, + libvlc_logo_file, + libvlc_logo_x, + libvlc_logo_y, + libvlc_logo_delay, + libvlc_logo_repeat, + libvlc_logo_opacity, + libvlc_logo_position +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub enum libvlc_video_adjust_option_t { + libvlc_adjust_Enable = 0, + libvlc_adjust_Contrast, + libvlc_adjust_Brightness, + libvlc_adjust_Hue, + libvlc_adjust_Saturation, + libvlc_adjust_Gamma +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub enum libvlc_audio_output_device_types_t { + libvlc_AudioOutputDevice_Error = -1, + libvlc_AudioOutputDevice_Mono = 1, + libvlc_AudioOutputDevice_Stereo = 2, + libvlc_AudioOutputDevice_2F2R = 4, + libvlc_AudioOutputDevice_3F2R = 5, + libvlc_AudioOutputDevice_5_1 = 6, + libvlc_AudioOutputDevice_6_1 = 7, + libvlc_AudioOutputDevice_7_1 = 8, + libvlc_AudioOutputDevice_SPDIF = 10 +} + +#[repr(C)] +#[derive(Clone, Copy, Debug)] +pub enum libvlc_audio_output_channel_t { + libvlc_AudioChannel_Error = -1, + libvlc_AudioChannel_Stereo = 1, + libvlc_AudioChannel_RStereo = 2, + libvlc_AudioChannel_Left = 3, + libvlc_AudioChannel_Right = 4, + libvlc_AudioChannel_Dolbys = 5 +} + +pub type libvlc_video_lock_cb = Option *mut c_void>; +pub type libvlc_video_unlock_cb = Option; +pub type libvlc_video_display_cb = Option; +pub type libvlc_video_format_cb = Option; +pub type libvlc_video_cleanup_cb = Option; +pub type libvlc_audio_play_cb = Option; +pub type libvlc_audio_pause_cb = Option; +pub type libvlc_audio_resume_cb = Option; +pub type libvlc_audio_flush_cb = Option; +pub type libvlc_audio_drain_cb = Option; +pub type libvlc_audio_set_volume_cb = Option; +pub type libvlc_audio_setup_cb = Option; +pub type libvlc_audio_cleanup_cb = Option; + +#[link(name = "vlc")] +extern "C" { + pub fn libvlc_media_player_new(p_libvlc_instance: *mut libvlc_instance_t) + -> *mut libvlc_media_player_t; + pub fn libvlc_media_player_new_from_media(p_md: *mut libvlc_media_t) + -> *mut libvlc_media_player_t; + pub fn libvlc_media_player_release(p_mi: *mut libvlc_media_player_t); + pub fn libvlc_media_player_retain(p_mi: *mut libvlc_media_player_t); + pub fn libvlc_media_player_set_media(p_mi: *mut libvlc_media_player_t, + p_md: *mut libvlc_media_t); + pub fn libvlc_media_player_get_media(p_mi: *mut libvlc_media_player_t) -> *mut libvlc_media_t; + pub fn libvlc_media_player_event_manager(p_mi: *mut libvlc_media_player_t) + -> *mut libvlc_event_manager_t; + pub fn libvlc_media_player_is_playing(p_mi: *mut libvlc_media_player_t) -> c_int; + pub fn libvlc_media_player_play(p_mi: *mut libvlc_media_player_t) -> c_int; + pub fn libvlc_media_player_set_pause(mp: *mut libvlc_media_player_t, do_pause: c_int); + pub fn libvlc_media_player_pause(p_mi: *mut libvlc_media_player_t); + pub fn libvlc_media_player_stop(p_mi: *mut libvlc_media_player_t); + pub fn libvlc_video_set_callbacks( + mp: *mut libvlc_media_player_t, lock: libvlc_video_lock_cb, + unlock: libvlc_video_unlock_cb, display: libvlc_video_display_cb, + opaque: *mut c_void); + pub fn libvlc_video_set_format( + mp: *mut libvlc_media_player_t, chroma: *const c_char, width: c_uint, height: c_uint, + pitch: c_uint); + pub fn libvlc_video_set_format_callbacks( + mp: *mut libvlc_media_player_t, setup: libvlc_video_format_cb, + cleanup: libvlc_video_cleanup_cb); + pub fn libvlc_media_player_set_nsobject( + p_mi: *mut libvlc_media_player_t, drawable: *mut c_void); + pub fn libvlc_media_player_get_nsobject(p_mi: *mut libvlc_media_player_t) -> *mut c_void; + pub fn libvlc_media_player_set_xwindow( + p_mi: *mut libvlc_media_player_t, drawable: u32); + pub fn libvlc_media_player_get_xwindow(p_mi: *mut libvlc_media_player_t) -> u32; + pub fn libvlc_media_player_set_hwnd( + p_mi: *mut libvlc_media_player_t, drawable: *mut c_void); + pub fn libvlc_media_player_get_hwnd(p_mi: *mut libvlc_media_player_t) -> *mut c_void; + pub fn libvlc_audio_set_callbacks( + mp: *mut libvlc_media_player_t, play: libvlc_audio_play_cb, pause: libvlc_audio_pause_cb, + resume: libvlc_audio_resume_cb, flush: libvlc_audio_flush_cb, + drain: libvlc_audio_drain_cb, opaque: *mut c_void); + pub fn libvlc_audio_set_volume_callback( + mp: *mut libvlc_media_player_t, set_volume: libvlc_audio_set_volume_cb); + pub fn libvlc_audio_set_format_callbacks( + mp: *mut libvlc_media_player_t, setup: libvlc_audio_setup_cb, + cleanup: libvlc_audio_cleanup_cb); + pub fn libvlc_audio_set_format( + mp: *mut libvlc_media_player_t, format: *const c_char, rate: c_uint, channels: c_uint); + pub fn libvlc_media_player_get_length(p_mi: *mut libvlc_media_player_t) -> libvlc_time_t; + pub fn libvlc_media_player_get_time(p_mi: *mut libvlc_media_player_t) -> libvlc_time_t; + pub fn libvlc_media_player_set_time( + p_mi: *mut libvlc_media_player_t, i_time: libvlc_time_t); + pub fn libvlc_media_player_get_position(p_mi: *mut libvlc_media_player_t) -> c_float; + pub fn libvlc_media_player_set_position(p_mi: *mut libvlc_media_player_t, f_pos: c_float); + pub fn libvlc_media_player_set_chapter(p_mi: *mut libvlc_media_player_t, i_chapter: c_int); + pub fn libvlc_media_player_get_chapter(p_mi: *mut libvlc_media_player_t) -> c_int; + pub fn libvlc_media_player_get_chapter_count(p_mi: *mut libvlc_media_player_t) -> c_int; + pub fn libvlc_media_player_set_title(p_mi: *mut libvlc_media_player_t, i_title: c_int); + pub fn libvlc_media_player_get_title(p_mi: *mut libvlc_media_player_t) -> c_int; + pub fn libvlc_media_player_get_title_count(p_mi: *mut libvlc_media_player_t) -> c_int; + pub fn libvlc_media_player_previous_chapter(p_mi: *mut libvlc_media_player_t); + pub fn libvlc_media_player_next_chapter(p_mi: *mut libvlc_media_player_t); + pub fn libvlc_media_player_get_rate(p_mi: *mut libvlc_media_player_t) -> c_float; + pub fn libvlc_media_player_set_rate(p_mi: *mut libvlc_media_player_t, rate: c_float) -> c_int; + pub fn libvlc_media_player_get_state(p_mi: *mut libvlc_media_player_t) -> libvlc_state_t; + pub fn libvlc_media_player_get_fps(p_mi: *mut libvlc_media_player_t) -> c_float; + pub fn libvlc_media_player_has_vout(p_mi: *mut libvlc_media_player_t) -> c_uint; + pub fn libvlc_media_player_is_seekable(p_mi: *mut libvlc_media_player_t) -> c_int; + pub fn libvlc_media_player_can_pause(p_mi: *mut libvlc_media_player_t) -> c_int; + pub fn libvlc_media_player_program_scrambled(p_mi: *mut libvlc_media_player_t) -> c_int; + pub fn libvlc_media_player_next_frame(p_mi: *mut libvlc_media_player_t); + pub fn libvlc_media_player_navigate(p_mi: *mut libvlc_media_player_t, navigate: c_uint); + pub fn libvlc_media_player_set_video_title_display( + p_mi: *mut libvlc_media_player_t, position: libvlc_position_t, timeout: c_uint); + pub fn libvlc_track_description_list_release(p_track_description: *mut libvlc_track_description_t); + pub fn libvlc_toggle_fullscreen(p_mi: *mut libvlc_media_player_t); + pub fn libvlc_set_fullscreen(p_mi: *mut libvlc_media_player_t, b_fullscreen: c_int); + pub fn libvlc_get_fullscreen(p_mi: *mut libvlc_media_player_t) -> c_int; + pub fn libvlc_video_set_key_input(p_mi: *mut libvlc_media_player_t, on: c_uint); + pub fn libvlc_video_set_mouse_input(p_mi: *mut libvlc_media_player_t, on: c_uint); + pub fn libvlc_video_get_size( + p_mi: *mut libvlc_media_player_t, num: c_uint, px: *mut c_uint, py: *mut c_uint) -> c_int; + pub fn libvlc_video_get_cursor( + p_mi: *mut libvlc_media_player_t, num: c_uint, px: *mut c_int, py: *mut c_int) -> c_int; + pub fn libvlc_video_get_scale(p_mi: *mut libvlc_media_player_t) -> c_float; + pub fn libvlc_video_set_scale(p_mi: *mut libvlc_media_player_t, f_factor: c_float); + pub fn libvlc_video_get_aspect_ratio(p_mi: *mut libvlc_media_player_t) -> *mut c_char; + pub fn libvlc_video_set_aspect_ratio(p_mi: *mut libvlc_media_player_t, psz_aspect: *const c_char); + pub fn libvlc_video_get_spu(p_mi: *mut libvlc_media_player_t) -> c_int; + pub fn libvlc_video_get_spu_count(p_mi: *mut libvlc_media_player_t) -> c_int; + pub fn libvlc_video_get_spu_description(p_mi: *mut libvlc_media_player_t) + -> *mut libvlc_track_description_t; + pub fn libvlc_video_set_spu(p_mi: *mut libvlc_media_player_t, i_spu: c_int) -> c_int; + pub fn libvlc_video_set_subtitle_file( + p_mi: *mut libvlc_media_player_t, psz_subtitle: *const c_char) -> c_int; + pub fn libvlc_video_get_spu_delay(p_mi: *mut libvlc_media_player_t) -> i64; + pub fn libvlc_video_set_spu_delay( + p_mi: *mut libvlc_media_player_t, i_delay: i64) -> c_int; + pub fn libvlc_video_get_title_description( + p_mi: *mut libvlc_media_player_t) -> *mut libvlc_track_description_t; + pub fn libvlc_video_get_chapter_description( + p_mi: *mut libvlc_media_player_t, i_title: c_int) -> *mut libvlc_track_description_t; + pub fn libvlc_video_get_crop_geometry(p_mi: *mut libvlc_media_player_t) -> *mut c_char; + pub fn libvlc_video_set_crop_geometry( + p_mi: *mut libvlc_media_player_t, psz_geometry: *const c_char); + pub fn libvlc_video_get_teletext(p_mi: *mut libvlc_media_player_t) -> c_int; + pub fn libvlc_video_set_teletext(p_mi: *mut libvlc_media_player_t, i_page: c_int); + pub fn libvlc_toggle_teletext(p_mi: *mut libvlc_media_player_t); + pub fn libvlc_video_get_track_count(p_mi: *mut libvlc_media_player_t) -> c_int; + pub fn libvlc_video_get_track_description( + p_mi: *mut libvlc_media_player_t) -> *mut libvlc_track_description_t; + pub fn libvlc_video_get_track(p_mi: *mut libvlc_media_player_t) -> c_int; + pub fn libvlc_video_set_track(p_mi: *mut libvlc_media_player_t, i_track: c_int) -> c_int; + pub fn libvlc_video_take_snapshot( + p_mi: *mut libvlc_media_player_t, num: c_uint, psz_filepath: *const c_char, + i_width: c_uint, i_height: c_uint) -> c_int; + pub fn libvlc_video_set_deinterlace(p_mi: *mut libvlc_media_player_t, psz_mode: *const c_char); + pub fn libvlc_video_get_marquee_int(p_mi: *mut libvlc_media_player_t, option: c_uint) -> c_int; + pub fn libvlc_video_get_marquee_string( + p_mi: *mut libvlc_media_player_t, option: c_uint) -> *mut c_char; + pub fn libvlc_video_set_marquee_int( + p_mi: *mut libvlc_media_player_t, option: c_uint, i_val: c_int); + pub fn libvlc_video_set_marquee_string( + p_mi: *mut libvlc_media_player_t, option: c_uint, psz_text: *const c_char); + pub fn libvlc_video_get_logo_int(p_mi: *mut libvlc_media_player_t, option: c_uint) -> c_int; + pub fn libvlc_video_set_logo_int(p_mi: *mut libvlc_media_player_t, option: c_uint, value: c_int); + pub fn libvlc_video_set_logo_string( + p_mi: *mut libvlc_media_player_t, option: c_uint, psz_value: *const c_char); + pub fn libvlc_video_get_adjust_int( + p_mi: *mut libvlc_media_player_t, option: c_uint) -> c_int; + pub fn libvlc_video_set_adjust_int( + p_mi: *mut libvlc_media_player_t, option: c_uint, value: c_int); + pub fn libvlc_video_get_adjust_float( + p_mi: *mut libvlc_media_player_t, option: c_uint) -> c_float; + pub fn libvlc_video_set_adjust_float( + p_mi: *mut libvlc_media_player_t, option: c_uint, value: c_float); + pub fn libvlc_audio_output_list_get(p_instance: *mut libvlc_instance_t) + -> *mut libvlc_audio_output_t; + pub fn libvlc_audio_output_list_release(p_list: *mut libvlc_audio_output_t); + pub fn libvlc_audio_output_set(p_mi: *mut libvlc_media_player_t, psz_name: *const c_char) -> c_int; + pub fn libvlc_audio_output_device_enum( + mp: *mut libvlc_media_player_t) -> *mut libvlc_audio_output_device_t; + pub fn libvlc_audio_output_device_list_get( + p_instance: *mut libvlc_instance_t, aout: *const c_char) -> *mut libvlc_audio_output_device_t; + pub fn libvlc_audio_output_device_list_release(p_list: *mut libvlc_audio_output_device_t); + pub fn libvlc_audio_output_device_set( + mp: *mut libvlc_media_player_t, module: *const c_char, device_id: *const c_char); + pub fn libvlc_audio_toggle_mute(p_mi: *mut libvlc_media_player_t); + pub fn libvlc_audio_get_mute(p_mi: *mut libvlc_media_player_t) -> c_int; + pub fn libvlc_audio_set_mute(p_mi: *mut libvlc_media_player_t, status: c_int); + pub fn libvlc_audio_get_volume(p_mi: *mut libvlc_media_player_t) -> c_int; + pub fn libvlc_audio_set_volume(p_mi: *mut libvlc_media_player_t, i_volume: c_int) -> c_int; + pub fn libvlc_audio_get_track_count(p_mi: *mut libvlc_media_player_t) -> c_int; + pub fn libvlc_audio_get_track_description( + p_mi: *mut libvlc_media_player_t) -> *mut libvlc_track_description_t; + pub fn libvlc_audio_get_track(p_mi: *mut libvlc_media_player_t) -> c_int; + pub fn libvlc_audio_set_track(p_mi: *mut libvlc_media_player_t, i_track: c_int) -> c_int; + pub fn libvlc_audio_get_channel(p_mi: *mut libvlc_media_player_t) -> c_int; + pub fn libvlc_audio_set_channel(p_mi: *mut libvlc_media_player_t, channel: c_int) -> c_int; + pub fn libvlc_audio_get_delay(p_mi: *mut libvlc_media_player_t) -> i64; + pub fn libvlc_audio_set_delay(p_mi: *mut libvlc_media_player_t, i_delay: i64) -> c_int; + pub fn libvlc_audio_equalizer_get_preset_count() -> c_uint; + pub fn libvlc_audio_equalizer_get_preset_name(u_index: c_uint) -> *const c_char; + pub fn libvlc_audio_equalizer_get_band_count() -> c_uint; + pub fn libvlc_audio_equalizer_get_band_frequency(u_index: c_uint) -> c_float; + pub fn libvlc_audio_equalizer_new() -> *mut libvlc_equalizer_t; + pub fn libvlc_audio_equalizer_new_from_preset(u_index: c_uint) -> *mut libvlc_equalizer_t; + pub fn libvlc_audio_equalizer_release(p_equalizer: *mut libvlc_equalizer_t); + pub fn libvlc_audio_equalizer_set_preamp( + p_equalizer: *mut libvlc_equalizer_t, f_preamp: c_float) -> c_int; + pub fn libvlc_audio_equalizer_get_preamp(p_equalizer: *mut libvlc_equalizer_t) -> c_float; + pub fn libvlc_audio_equalizer_set_amp_at_index( + p_equalizer: *mut libvlc_equalizer_t, f_amp: c_float, u_band: c_uint) -> c_int; + pub fn libvlc_audio_equalizer_get_amp_at_index( + p_equalizer: *mut libvlc_equalizer_t, u_band: c_uint) -> c_float; + pub fn libvlc_media_player_set_equalizer( + p_mi: *mut libvlc_media_player_t, p_equalizer: *mut libvlc_equalizer_t) -> c_int; +} + +// From libvlc_events.h +pub use EventType as libvlc_event_e; + +#[repr(C)] +pub struct libvlc_event_t { + pub _type: c_int, + pub p_obj: *mut c_void, + pub data: [u64; 2], +} + +pub mod libvlc_event_t_union { + use super::*; + use libc::{c_int, c_char, c_float}; + #[repr(C)] + pub struct media_meta_changed { + pub meta_type: libvlc_meta_t, + } + #[repr(C)] + pub struct media_subitem_added { + pub new_child: *mut libvlc_media_t, + } + #[repr(C)] + pub struct media_duration_changed { + pub new_duration: i64, + } + #[repr(C)] + pub struct media_parsed_changed { + pub new_status: c_int, + } + #[repr(C)] + pub struct media_freed { + pub md: *mut libvlc_media_t, + } + #[repr(C)] + pub struct media_state_changed { + pub new_state: libvlc_state_t, + } + #[repr(C)] + pub struct media_subitemtree_added { + pub item: *mut libvlc_media_t, + } + #[repr(C)] + pub struct media_player_buffering { + pub new_cache: c_float, + } + #[repr(C)] + pub struct media_player_position_changed { + pub new_position: c_float, + } + #[repr(C)] + pub struct media_player_time_changed { + pub new_time: libvlc_time_t, + } + #[repr(C)] + pub struct media_player_title_changed { + pub new_titie: c_int, + } + #[repr(C)] + pub struct media_player_seekable_changed { + pub new_seekable: c_int, + } + #[repr(C)] + pub struct media_player_pausable_changed { + pub new_pausable: c_int, + } + #[repr(C)] + pub struct media_player_scrambled_changed { + pub new_scrambled: c_int, + } + #[repr(C)] + pub struct media_player_vout { + pub new_count: c_int, + } + #[repr(C)] + pub struct media_list_item_added { + pub item: *mut libvlc_media_t, + pub index: c_int, + } + #[repr(C)] + pub struct media_list_will_add_item { + pub item: *mut libvlc_media_t, + pub index: c_int, + } + #[repr(C)] + pub struct media_list_item_deleted { + pub item: *mut libvlc_media_t, + pub index: c_int, + } + #[repr(C)] + pub struct media_list_will_delete_item { + pub item: *mut libvlc_media_t, + pub index: c_int, + } + #[repr(C)] + pub struct media_list_player_next_item_set { + pub item: *mut libvlc_media_t, + } + #[repr(C)] + pub struct media_player_snapshot_taken { + pub psz_filename: *mut c_char, + } + #[repr(C)] + pub struct media_player_length_changed { + pub new_length: libvlc_time_t, + } + #[repr(C)] + pub struct vlm_media_event { + pub psz_media_name: *mut c_char, + pub psz_instance_name: *mut c_char, + } + #[repr(C)] + pub struct media_player_media_changed { + pub new_media: *mut libvlc_media_t, + } + + macro_rules! union_func { + ($name:ident, $ty:ty) => { + pub unsafe fn $name(p: *const libvlc_event_t) -> *const $ty { + let p: *const _ = &((*p).data); + p as *const $ty + } + } + } + + union_func!(get_media_meta_changed, media_meta_changed); + union_func!(get_media_subitem_added, media_subitem_added); + union_func!(get_media_duration_changed, media_duration_changed); + union_func!(get_media_parsed_changed, media_parsed_changed); + union_func!(get_media_freed, media_freed); + union_func!(get_media_state_changed, media_state_changed); + union_func!(get_media_subitemtree_added, media_subitemtree_added); + union_func!(get_media_player_buffering, media_player_buffering); + union_func!(get_media_player_position_changed, media_player_position_changed); + union_func!(get_media_player_time_changed, media_player_time_changed); + union_func!(get_media_player_title_changed, media_player_title_changed); + union_func!(get_media_player_seekable_changed, media_player_seekable_changed); + union_func!(get_media_player_pausable_changed, media_player_pausable_changed); + union_func!(get_media_player_scrambled_changed, media_player_scrambled_changed); + union_func!(get_media_player_vout, media_player_vout); + union_func!(get_media_list_item_added, media_list_item_added); + union_func!(get_media_list_will_add_item, media_list_will_add_item); + union_func!(get_media_list_item_deleted, media_list_item_deleted); + union_func!(get_media_list_will_delete_item, media_list_will_delete_item); + union_func!(get_media_list_player_next_item_set, media_list_player_next_item_set); + union_func!(get_media_player_snapshot_taken, media_player_snapshot_taken); + union_func!(get_media_player_length_changed, media_player_length_changed); + union_func!(get_vlm_media_event, vlm_media_event); + union_func!(get_media_player_media_changed, media_player_media_changed); + +} + +// From libvlc_media_list.h + +pub enum libvlc_media_list_t {} + +#[link(name = "vlc")] +extern "C" { + pub fn libvlc_media_list_new(p_instance: *mut libvlc_instance_t) -> *mut libvlc_media_list_t; + pub fn libvlc_media_list_release(p_ml: *mut libvlc_media_list_t); + pub fn libvlc_media_list_retain(p_ml: *mut libvlc_media_list_t); + pub fn libvlc_media_list_set_media(p_ml: *mut libvlc_media_list_t, p_md: *mut libvlc_media_t); + pub fn libvlc_media_list_media(p_ml: *mut libvlc_media_list_t) -> *mut libvlc_media_t; + pub fn libvlc_media_list_add_media( + p_ml: *mut libvlc_media_list_t, p_md: *mut libvlc_media_t) -> c_int; + pub fn libvlc_media_list_insert_media( + p_ml: *mut libvlc_media_list_t, p_md: *mut libvlc_media_t, i_pos: c_int) -> c_int; + pub fn libvlc_media_list_remove_index(p_ml: *mut libvlc_media_list_t, i_pos: c_int) -> c_int; + pub fn libvlc_media_list_count(p_ml: *mut libvlc_media_list_t) -> c_int; + pub fn libvlc_media_list_item_at_index( + p_ml: *mut libvlc_media_list_t, i_pos: c_int) -> *mut libvlc_media_t; + pub fn libvlc_media_list_index_of_item( + p_ml: *mut libvlc_media_list_t, p_md: *mut libvlc_media_t) -> c_int; + pub fn libvlc_media_list_is_readonly(p_ml: *mut libvlc_media_list_t) -> c_int; + pub fn libvlc_media_list_lock(p_ml: *mut libvlc_media_list_t); + pub fn libvlc_media_list_unlock(p_ml: *mut libvlc_media_list_t); + pub fn libvlc_media_list_event_manager( + p_ml: *mut libvlc_media_list_t) -> *mut libvlc_event_manager_t; +} + +// From libvlc_media_library.h + +pub enum libvlc_media_library_t {} + +#[link(name = "vlc")] +extern "C" { + pub fn libvlc_media_library_new(p_instance: *mut libvlc_instance_t) -> *mut libvlc_media_library_t; + pub fn libvlc_media_library_release(p_mlib: *mut libvlc_media_library_t); + pub fn libvlc_media_library_retain(p_mlib: *mut libvlc_media_library_t); + pub fn libvlc_media_library_load(p_mlib: *mut libvlc_media_library_t) -> c_int; + pub fn libvlc_media_library_media_list( + p_mlib: *mut libvlc_media_library_t) -> *mut libvlc_media_list_t; +} + +// From libvlc_media_discoverer.h + +pub enum libvlc_media_discoverer_t {} + +#[link(name = "vlc")] +extern "C" { + pub fn libvlc_media_discoverer_new_from_name( + p_inst: *mut libvlc_instance_t, psz_name: *const c_char) -> *mut libvlc_media_discoverer_t; + pub fn libvlc_media_discoverer_release(p_mdis: *mut libvlc_media_discoverer_t); + pub fn libvlc_media_discoverer_localized_name( + p_mdis: *mut libvlc_media_discoverer_t) -> *mut c_char; + pub fn libvlc_media_discoverer_media_list( + p_mdis: *mut libvlc_media_discoverer_t) -> *mut libvlc_media_list_t; + pub fn libvlc_media_discoverer_event_manager( + p_mdis: *mut libvlc_media_discoverer_t) -> *mut libvlc_event_manager_t; + pub fn libvlc_media_discoverer_is_running(p_mdis: *mut libvlc_media_discoverer_t) -> c_int; +} + +// From libvlc_vlm.h + +#[link(name = "vlc")] +extern "C" { + pub fn libvlc_vlm_release(p_instance: *mut libvlc_instance_t); + pub fn libvlc_vlm_add_broadcast( + p_instance: *mut libvlc_instance_t, psz_name: *const c_char, psz_input: *const c_char, + psz_output: *const c_char, i_options: c_int, ppsz_options: *const *const c_char, + b_enabled: c_int, b_loop: c_int) -> c_int; + pub fn libvlc_vlm_add_vod( + p_instance: *mut libvlc_instance_t, psz_name: *const c_char, psz_input: *const c_char, + i_options: c_int, ppsz_options: *const *const c_char, b_enabled: c_int, + psz_mux: *const c_char) -> c_int; + pub fn libvlc_vlm_del_media( + p_instance: *mut libvlc_instance_t, psz_name: *const c_char) -> c_int; + pub fn libvlc_vlm_set_enabled( + p_instance: *mut libvlc_instance_t, psz_name: *const c_char, b_enabled: c_int) -> c_int; + pub fn libvlc_vlm_set_output( + p_instance: *mut libvlc_instance_t, psz_name: *const c_char, psz_output: *const c_char) -> c_int; + pub fn libvlc_vlm_set_input( + p_instance: *mut libvlc_instance_t, psz_name: *const c_char, psz_input: *const c_char) -> c_int; + pub fn libvlc_vlm_add_input( + p_instance: *mut libvlc_instance_t, psz_name: *const c_char, psz_input: *const c_char) -> c_int; + pub fn libvlc_vlm_set_loop( + p_instance: *mut libvlc_instance_t, psz_name: *const c_char, b_loop: c_int) -> c_int; + pub fn libvlc_vlm_set_mux( + p_instance: *mut libvlc_instance_t, psz_name: *const c_char, psz_mux: *const c_char) -> c_int; + pub fn libvlc_vlm_change_media( + p_instance: *mut libvlc_instance_t, psz_name: *const c_char, psz_input: *const c_char, + psz_output: *const c_char, i_options: c_int, ppsz_options: *const *const c_char, + b_enabled: c_int, b_loop: c_int) -> c_int; + pub fn libvlc_vlm_play_media( + p_instance: *mut libvlc_instance_t, psz_name: *const c_char) -> c_int; + pub fn libvlc_vlm_stop_media( + p_instance: *mut libvlc_instance_t, psz_name: *const c_char) -> c_int; + pub fn libvlc_vlm_pause_media( + p_instance: *mut libvlc_instance_t, psz_name: *const c_char) -> c_int; + pub fn libvlc_vlm_seek_media( + p_instance: *mut libvlc_instance_t, psz_name: *const c_char, f_percentage: c_float) -> c_int; + pub fn libvlc_vlm_show_media( + p_instance: *mut libvlc_instance_t, psz_name: *const c_char) -> *const c_char; + pub fn libvlc_vlm_get_media_instance_position( + p_instance: *mut libvlc_instance_t, psz_name: *const c_char, i_instance: c_int) -> c_float; + pub fn libvlc_vlm_get_media_instance_time( + p_instance: *mut libvlc_instance_t, psz_name: *const c_char, i_instance: c_int) -> c_int; + pub fn libvlc_vlm_get_media_instance_length( + p_instance: *mut libvlc_instance_t, psz_name: *const c_char, i_instance: c_int) -> c_int; + pub fn libvlc_vlm_get_media_instance_rate( + p_instance: *mut libvlc_instance_t, psz_name: *const c_char, i_instance: c_int) -> c_int; + pub fn libvlc_vlm_get_event_manager( + p_instance: *mut libvlc_instance_t) -> *mut libvlc_event_manager_t; +} diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..a75a6b3 --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,19 @@ +// Copyright (c) 2015 T. Okubo +// This file is part of vlc-rs. +// Licensed under the MIT license, see the LICENSE file. + +extern crate libc; + +pub mod ffi; + +mod tools; +mod core; +mod media; +mod media_player; +mod enums; + +pub use enums::*; +pub use core::*; +pub use media::*; +pub use media_player::*; + diff --git a/src/media.rs b/src/media.rs new file mode 100644 index 0000000..31de332 --- /dev/null +++ b/src/media.rs @@ -0,0 +1,171 @@ +// 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, EventManager}; +use ::enums::{State, Meta, TrackType}; +use ::tools::{to_cstr, from_cstr}; + +pub struct Media { + pub ptr: *mut ffi::libvlc_media_t, +} + +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 { + let cstr = to_cstr(mrl); + + unsafe{ + let p = ffi::libvlc_media_new_location(instance.ptr, cstr.as_ptr()); + if p.is_null() { + return None; + } + + Some(Media{ptr: p}) + } + } + + /// Create a media for a certain file path. + pub fn new_path(instance: &Instance, path: &str) -> Option { + let cstr = to_cstr(path); + + unsafe{ + let p = ffi::libvlc_media_new_path(instance.ptr, cstr.as_ptr()); + if p.is_null() { + return None; + } + + Some(Media{ptr: p}) + } + } + + pub fn new_fd(instance: &Instance, fd: i32) -> Option { + unsafe{ + let p = ffi::libvlc_media_new_fd(instance.ptr, fd); + if p.is_null() { + return None; + } + + Some(Media{ptr: p}) + } + } + + pub fn mrl(&self) -> Option { + unsafe{ + let p_str = ffi::libvlc_media_get_mrl(self.ptr); + let s = from_cstr(p_str); + ffi::libvlc_free(p_str as *mut ::libc::c_void); + s + } + } + + pub fn event_manager<'a>(&'a self) -> EventManager<'a> { + unsafe{ + let p = ffi::libvlc_media_event_manager(self.ptr); + assert!(!p.is_null()); + EventManager{ptr: p, _phantomdata: ::std::marker::PhantomData} + } + } + + /// Read the meta of the media. + /// If the media has not yet been parsed this will return None. + pub fn get_meta(&self, meta: Meta) -> Option { + unsafe{ + let p_str = ffi::libvlc_media_get_meta(self.ptr, meta); + let s = from_cstr(p_str); + ffi::libvlc_free(p_str as *mut ::libc::c_void); + s + } + } + + /// Set the meta of the media. + /// (This function will not save the meta, call save_meta in order to save the meta) + pub fn set_meta(&self, meta: Meta, value: &str) { + unsafe{ + ffi::libvlc_media_set_meta(self.ptr, meta, to_cstr(value).as_ptr()); + } + } + + /// Save the meta previously set. + pub fn save_meta(&self) -> bool { + if unsafe{ ffi::libvlc_media_save_meta(self.ptr) } == 0 { false }else{ true } + } + + /// Get current state of media descriptor object. + pub fn state(&self) -> State { + unsafe{ ffi::libvlc_media_get_state(self.ptr) } + } + + /// Get duration (in ms) of media descriptor object item. + pub fn duration(&self) -> Option { + let time = unsafe{ + ffi::libvlc_media_get_duration(self.ptr) + }; + if time != -1 { Some(time) }else{ None } + } + + /// Parse a media. + pub fn parse(&self) { + unsafe{ ffi::libvlc_media_parse(self.ptr) }; + } + + /// Parse a media. + pub fn parse_async(&self) { + unsafe{ ffi::libvlc_media_parse_async(self.ptr) }; + } + + /// Get Parsed status for media descriptor object. + pub fn is_parsed(&self) -> bool { + if unsafe{ ffi::libvlc_media_is_parsed(self.ptr) } == 0 { false }else{ true } + } +} + +impl Drop for Media { + fn drop(&mut self) { + unsafe{ ffi::libvlc_media_release(self.ptr) }; + } +} + +#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] +pub struct MediaTrackInfo { + pub codec: u32, + pub id: i32, + pub track_type: TrackType, + + pub profile: i32, + pub level: i32, + + audio: MediaTrackInfoAudio, + video: MediaTrackInfoVideo, +} + +#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] +pub struct MediaTrackInfoAudio { + pub channels: i32, + pub rate: i32, +} + +#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] +pub struct MediaTrackInfoVideo { + pub height: i32, + pub width: i32, +} + +impl MediaTrackInfo { + pub fn audio(&self) -> Option { + if self.track_type == TrackType::Audio { + Some(self.audio) + }else{ + None + } + } + + pub fn video(&self) -> Option { + if self.track_type == TrackType::Video { + Some(self.video) + }else{ + None + } + } +} diff --git a/src/media_player.rs b/src/media_player.rs new file mode 100644 index 0000000..6c980db --- /dev/null +++ b/src/media_player.rs @@ -0,0 +1,195 @@ +// 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())(); +} + diff --git a/src/tools.rs b/src/tools.rs new file mode 100644 index 0000000..1d27451 --- /dev/null +++ b/src/tools.rs @@ -0,0 +1,35 @@ +// Copyright (c) 2015 T. Okubo +// This file is part of vlc-rs. +// Licensed under the MIT license, see the LICENSE file. + +use std::ffi::{CString, CStr}; +use std::borrow::Cow; +use libc::c_char; + +// Convert String to CString. +// Panic if the string includes null bytes. +pub fn to_cstr(s: &str) -> CString { + CString::new(s.to_owned()).expect("Error: Unexpected null byte") +} + +// Convert *const c_char to String +pub unsafe fn from_cstr(p: *const c_char) -> Option { + if p.is_null() { + None + }else{ + let cstr = CStr::from_ptr(p); + + Some(cstr.to_string_lossy().into_owned()) + } +} + +// Convert *const c_char to &str +pub unsafe fn from_cstr_ref<'a>(p: *const c_char) -> Option> { + if p.is_null() { + None + }else{ + let cstr = CStr::from_ptr(p); + + Some(cstr.to_string_lossy()) + } +}