macro to create linked list handling structure
parent
e7d7fe6740
commit
22ee272594
|
@ -20,6 +20,7 @@ crate-type = ["rlib"]
|
||||||
[dependencies]
|
[dependencies]
|
||||||
libc = "0.2"
|
libc = "0.2"
|
||||||
libvlc-sys = "0.2"
|
libvlc-sys = "0.2"
|
||||||
|
paste = "1.0"
|
||||||
|
|
||||||
[target.'cfg(target_os = "windows")'.build-dependencies]
|
[target.'cfg(target_os = "windows")'.build-dependencies]
|
||||||
vswhom = "0.1.0"
|
vswhom = "0.1.0"
|
123
src/core.rs
123
src/core.rs
|
@ -3,14 +3,13 @@
|
||||||
// Licensed under the MIT license, see the LICENSE file.
|
// Licensed under the MIT license, see the LICENSE file.
|
||||||
|
|
||||||
use crate::enums::*;
|
use crate::enums::*;
|
||||||
use crate::tools::{from_cstr, from_cstr_ref, to_cstr};
|
use crate::tools::{from_cstr, from_cstr_ref, linked_list_iter, to_cstr};
|
||||||
use libc::{c_char, c_int, c_void};
|
use libc::{c_char, c_int, c_void};
|
||||||
use std::borrow::Cow;
|
use std::borrow::Cow;
|
||||||
use std::convert::TryInto;
|
use std::convert::TryInto;
|
||||||
use std::ffi::CString;
|
use std::ffi::CString;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::i32;
|
use std::i32;
|
||||||
use std::marker::PhantomData;
|
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
use vlc_sys as sys;
|
use vlc_sys as sys;
|
||||||
|
|
||||||
|
@ -25,6 +24,36 @@ impl fmt::Display for InternalError {
|
||||||
|
|
||||||
impl std::error::Error for InternalError {}
|
impl std::error::Error for InternalError {}
|
||||||
|
|
||||||
|
|
||||||
|
linked_list_iter!(
|
||||||
|
libvlc_module_description, // C raw type
|
||||||
|
module_description, // Rust base struct name
|
||||||
|
{
|
||||||
|
name: (String, str),
|
||||||
|
shortname: (String, str),
|
||||||
|
longname: (String, str),
|
||||||
|
help: (String, str),
|
||||||
|
} // fields
|
||||||
|
);
|
||||||
|
|
||||||
|
linked_list_iter!(
|
||||||
|
libvlc_audio_output, // C raw type
|
||||||
|
audio_output, // Rust base struct name
|
||||||
|
{
|
||||||
|
name: (String, str),
|
||||||
|
description: (String, str),
|
||||||
|
} // fields
|
||||||
|
);
|
||||||
|
|
||||||
|
linked_list_iter!(
|
||||||
|
libvlc_audio_output_device, // C raw type
|
||||||
|
audio_output_device, // Rust base struct name
|
||||||
|
{
|
||||||
|
device: (String, str),
|
||||||
|
description: (String, str),
|
||||||
|
} // fields
|
||||||
|
);
|
||||||
|
|
||||||
/// Retrieve libvlc version.
|
/// Retrieve libvlc version.
|
||||||
pub fn version() -> String {
|
pub fn version() -> String {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -131,7 +160,7 @@ impl Instance {
|
||||||
if p.is_null() {
|
if p.is_null() {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
Some(ModuleDescriptionList { ptr: p })
|
Some(ModuleDescriptionList::new(p))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -143,7 +172,7 @@ impl Instance {
|
||||||
if p.is_null() {
|
if p.is_null() {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
Some(ModuleDescriptionList { ptr: p })
|
Some(ModuleDescriptionList::new(p))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -203,92 +232,6 @@ unsafe extern "C" fn logging_cb(
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// List of module description.
|
|
||||||
pub struct ModuleDescriptionList {
|
|
||||||
ptr: *mut sys::libvlc_module_description_t,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl ModuleDescriptionList {
|
|
||||||
/// Returns raw pointer
|
|
||||||
pub fn raw(&self) -> *mut sys::libvlc_module_description_t {
|
|
||||||
self.ptr
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Drop for ModuleDescriptionList {
|
|
||||||
fn drop(&mut self) {
|
|
||||||
unsafe { sys::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 sys::libvlc_module_description_t,
|
|
||||||
_phantomdata: PhantomData<&'a sys::libvlc_module_description_t>,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Description of a module.
|
|
||||||
/// The strings are owned.
|
|
||||||
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
|
|
||||||
pub struct ModuleDescription {
|
|
||||||
pub name: Option<String>,
|
|
||||||
pub shortname: Option<String>,
|
|
||||||
pub longname: Option<String>,
|
|
||||||
pub help: Option<String>,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Description of a module.
|
|
||||||
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
|
|
||||||
pub struct ModuleDescriptionRef<'a> {
|
|
||||||
pub name: Option<Cow<'a, str>>,
|
|
||||||
pub shortname: Option<Cow<'a, str>>,
|
|
||||||
pub longname: Option<Cow<'a, str>>,
|
|
||||||
pub help: Option<Cow<'a, str>>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> Iterator for ModuleDescriptionListIter<'a> {
|
|
||||||
type Item = ModuleDescriptionRef<'a>;
|
|
||||||
|
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
|
||||||
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<String> {
|
pub fn errmsg() -> Option<String> {
|
||||||
unsafe { from_cstr(sys::libvlc_errmsg()) }
|
unsafe { from_cstr(sys::libvlc_errmsg()) }
|
||||||
}
|
}
|
||||||
|
|
201
src/tools.rs
201
src/tools.rs
|
@ -41,3 +41,204 @@ pub fn path_to_cstr(path: &Path) -> Result<CString, NulError> {
|
||||||
|
|
||||||
Ok(path)
|
Ok(path)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Defines a module with all necessary structures to easily handle a C linked list
|
||||||
|
macro_rules! linked_list_iter {
|
||||||
|
(
|
||||||
|
$c_type:ident,
|
||||||
|
$name:ident,
|
||||||
|
{
|
||||||
|
$($(#[$field_meta:meta])*
|
||||||
|
$field_vis:vis $field_name:ident: ($field_type:ty, $field_b_type:ty)),* $(,)+
|
||||||
|
}
|
||||||
|
) => {
|
||||||
|
paste::item! {
|
||||||
|
mod $name {
|
||||||
|
use std::borrow::Cow;
|
||||||
|
use std::marker::PhantomData;
|
||||||
|
use crate::tools::from_cstr_ref;
|
||||||
|
|
||||||
|
use vlc_sys::[<$c_type _t>];
|
||||||
|
use vlc_sys::[<$c_type _list_release>];
|
||||||
|
|
||||||
|
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
|
||||||
|
pub struct Item {
|
||||||
|
$(
|
||||||
|
$(#[$field_meta:meta])*
|
||||||
|
$field_vis $field_name : Option<$field_type>,
|
||||||
|
)*
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
|
||||||
|
pub struct ItemRef<'a> {
|
||||||
|
$(
|
||||||
|
$(#[$field_meta:meta])*
|
||||||
|
$field_vis $field_name : Option<Cow<'a, $field_b_type>>,
|
||||||
|
)*
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> ItemRef<'a> {
|
||||||
|
/// Convert to owned strings.
|
||||||
|
pub fn into_owned(&'a self) -> Item {
|
||||||
|
Item {
|
||||||
|
$($field_name: self.$field_name.as_ref().map(|s| s.clone().into_owned()),)*
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct ListIter<'a> {
|
||||||
|
ptr: *mut [<$c_type _t>],
|
||||||
|
_phantomdata: PhantomData<&'a [<$c_type _t>]>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Iterator for ListIter<'a> {
|
||||||
|
type Item = ItemRef<'a>;
|
||||||
|
|
||||||
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
|
unsafe {
|
||||||
|
if self.ptr.is_null() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
let p = self.ptr;
|
||||||
|
self.ptr = (*p).p_next;
|
||||||
|
Some(ItemRef {
|
||||||
|
$($field_name: from_cstr_ref((*p).[<psz_ $field_name>]),)*
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct List {
|
||||||
|
ptr: *mut [<$c_type _t>]
|
||||||
|
}
|
||||||
|
|
||||||
|
impl List {
|
||||||
|
pub fn new(ptr: *mut [<$c_type _t>]) -> List {
|
||||||
|
Self { ptr }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns raw pointer
|
||||||
|
pub fn raw(&self) -> *mut [<$c_type _t>] {
|
||||||
|
self.ptr
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Drop for List {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
unsafe{ [<$c_type _list_release>](self.ptr) };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> IntoIterator for &'a List {
|
||||||
|
type Item = ItemRef<'a>;
|
||||||
|
type IntoIter = ListIter<'a>;
|
||||||
|
|
||||||
|
fn into_iter(self) -> Self::IntoIter {
|
||||||
|
ListIter{ptr: self.ptr, _phantomdata: PhantomData}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// backward compatibility types
|
||||||
|
pub type [<$name:camel>] = $name::Item;
|
||||||
|
pub type [<$name:camel Ref>]<'a> = $name::ItemRef<'a>;
|
||||||
|
pub type [<$name:camel List>] = $name::List;
|
||||||
|
pub type [<$name:camel ListIter>]<'a> = $name::ListIter<'a>;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
macro_rules! linked_list_iter {
|
||||||
|
(
|
||||||
|
$namespace:path,
|
||||||
|
$c_type: ident,
|
||||||
|
$name: ident,
|
||||||
|
{
|
||||||
|
$($(#[$field_meta:meta])*
|
||||||
|
$field_vis:vis $field_name:ident: ($field_type:ty, $field_b_type:ty)),* $(,)+
|
||||||
|
}
|
||||||
|
) => {
|
||||||
|
paste::item! {
|
||||||
|
use std::marker::PhantomData;
|
||||||
|
use crate::$namespace::[<$c_type _t>];
|
||||||
|
use crate::$namespace::[<$c_type _list_release>];
|
||||||
|
|
||||||
|
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
|
||||||
|
pub struct $name {
|
||||||
|
$(
|
||||||
|
$(#[$field_meta:meta])*
|
||||||
|
$field_vis $field_name : Option<$field_type>,
|
||||||
|
)*
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, PartialEq, Eq, Hash, Debug)]
|
||||||
|
pub struct [<$name Ref>]<'a> {
|
||||||
|
$(
|
||||||
|
$(#[$field_meta:meta])*
|
||||||
|
$field_vis $field_name : Option<Cow<'a, $field_b_type>>,
|
||||||
|
)*
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> [<$name Ref>]<'a> {
|
||||||
|
/// Convert to owned strings.
|
||||||
|
pub fn into_owned(&'a self) -> $name {
|
||||||
|
$name {
|
||||||
|
$($field_name: self.$field_name.as_ref().map(|s| s.clone().into_owned()),)*
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct [<$name ListIter>]<'a> {
|
||||||
|
ptr: *mut [<$c_type _t>],
|
||||||
|
_phantomdata: PhantomData<&'a [<$c_type _t>]>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> Iterator for [<$name ListIter>]<'a> {
|
||||||
|
type Item = [<$name Ref>]<'a>;
|
||||||
|
|
||||||
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
|
unsafe {
|
||||||
|
if self.ptr.is_null() {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
let p = self.ptr;
|
||||||
|
self.ptr = (*p).p_next;
|
||||||
|
Some([<$name Ref>] {
|
||||||
|
$($field_name: from_cstr_ref((*p).[<psz_ $field_name>]),)*
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct [<$name List>] {
|
||||||
|
ptr: *mut [<$c_type _t>]
|
||||||
|
}
|
||||||
|
|
||||||
|
impl [<$name List>] {
|
||||||
|
/// Returns raw pointer
|
||||||
|
pub fn raw(&self) -> *mut [<$c_type _t>] {
|
||||||
|
self.ptr
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Drop for [<$name List>] {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
unsafe{ [<$c_type _list_release>](self.ptr) };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> IntoIterator for &'a [<$name List>] {
|
||||||
|
type Item = [<$name Ref>]<'a>;
|
||||||
|
type IntoIter = [<$name ListIter>]<'a>;
|
||||||
|
|
||||||
|
fn into_iter(self) -> Self::IntoIter {
|
||||||
|
[<$name ListIter>]{ptr: self.ptr, _phantomdata: PhantomData}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
pub(crate) use linked_list_iter;
|
Loading…
Reference in New Issue