Fix track description traversal
parent
90729e2bd4
commit
4b17ac7336
11
src/audio.rs
11
src/audio.rs
|
|
@ -5,7 +5,7 @@
|
|||
use vlc_sys as sys;
|
||||
use crate::MediaPlayer;
|
||||
use crate::TrackDescription;
|
||||
use crate::tools::from_cstr;
|
||||
use crate::tools::track_descriptions_from_raw;
|
||||
|
||||
pub trait MediaPlayerAudioEx {
|
||||
fn get_mute(&self) -> Option<bool>;
|
||||
|
|
@ -44,16 +44,9 @@ impl MediaPlayerAudioEx for MediaPlayer {
|
|||
unsafe{
|
||||
let p0 = sys::libvlc_audio_get_track_description(self.ptr);
|
||||
if p0.is_null() { return None; }
|
||||
let mut td = Vec::new();
|
||||
let mut p = p0;
|
||||
|
||||
while !(*p).p_next.is_null() {
|
||||
td.push(TrackDescription{ id: (*p).i_id, name: from_cstr((*p).psz_name) });
|
||||
p = (*p).p_next;
|
||||
}
|
||||
let td = track_descriptions_from_raw(p0);
|
||||
sys::libvlc_track_description_list_release(p0);
|
||||
Some(td)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
91
src/tools.rs
91
src/tools.rs
|
|
@ -2,10 +2,12 @@
|
|||
// This file is part of vlc-rs.
|
||||
// Licensed under the MIT license, see the LICENSE file.
|
||||
|
||||
use std::ffi::{CString, CStr, NulError};
|
||||
use std::path::Path;
|
||||
use std::borrow::Cow;
|
||||
use crate::TrackDescription;
|
||||
use libc::c_char;
|
||||
use std::borrow::Cow;
|
||||
use std::ffi::{CStr, CString, NulError};
|
||||
use std::path::Path;
|
||||
use vlc_sys as sys;
|
||||
|
||||
// Convert String to CString.
|
||||
// Panic if the string includes null bytes.
|
||||
|
|
@ -41,3 +43,86 @@ pub fn path_to_cstr(path: &Path) -> Result<CString, NulError> {
|
|||
|
||||
Ok(path)
|
||||
}
|
||||
|
||||
/// Convert a libVLC track-description linked list into owned Rust values.
|
||||
///
|
||||
/// The caller retains ownership of the list and must release it using
|
||||
/// `libvlc_track_description_list_release` when appropriate.
|
||||
pub unsafe fn track_descriptions_from_raw(
|
||||
mut track: *mut sys::libvlc_track_description_t,
|
||||
) -> Vec<TrackDescription> {
|
||||
let mut descriptions = Vec::new();
|
||||
|
||||
while !track.is_null() {
|
||||
descriptions.push(TrackDescription {
|
||||
id: (*track).i_id,
|
||||
name: from_cstr((*track).psz_name),
|
||||
});
|
||||
track = (*track).p_next;
|
||||
}
|
||||
|
||||
descriptions
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::track_descriptions_from_raw;
|
||||
use std::ffi::CString;
|
||||
use std::ptr;
|
||||
use vlc_sys::libvlc_track_description_t;
|
||||
|
||||
fn track(
|
||||
id: i32,
|
||||
name: &CString,
|
||||
next: *mut libvlc_track_description_t,
|
||||
) -> libvlc_track_description_t {
|
||||
libvlc_track_description_t {
|
||||
i_id: id,
|
||||
psz_name: name.as_ptr() as *mut _,
|
||||
p_next: next,
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn track_descriptions_from_raw_handles_a_null_list() {
|
||||
let descriptions = unsafe { track_descriptions_from_raw(ptr::null_mut()) };
|
||||
|
||||
assert!(descriptions.is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn track_descriptions_from_raw_includes_a_singleton() {
|
||||
let name = CString::new("English").unwrap();
|
||||
let mut node = track(1, &name, ptr::null_mut());
|
||||
|
||||
let descriptions = unsafe { track_descriptions_from_raw(&mut node) };
|
||||
|
||||
assert_eq!(descriptions.len(), 1);
|
||||
assert_eq!(descriptions[0].id, 1);
|
||||
assert_eq!(descriptions[0].name.as_deref(), Some("English"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn track_descriptions_from_raw_includes_the_final_node() {
|
||||
let first_name = CString::new("English").unwrap();
|
||||
let second_name = CString::new("French").unwrap();
|
||||
let mut second = track(2, &second_name, ptr::null_mut());
|
||||
let mut first = track(1, &first_name, &mut second);
|
||||
|
||||
let descriptions = unsafe { track_descriptions_from_raw(&mut first) };
|
||||
|
||||
assert_eq!(
|
||||
descriptions,
|
||||
vec![
|
||||
crate::TrackDescription {
|
||||
id: 1,
|
||||
name: Some("English".to_owned()),
|
||||
},
|
||||
crate::TrackDescription {
|
||||
id: 2,
|
||||
name: Some("French".to_owned()),
|
||||
},
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
10
src/video.rs
10
src/video.rs
|
|
@ -6,7 +6,7 @@ use vlc_sys as sys;
|
|||
use crate::MediaPlayer;
|
||||
use crate::TrackDescription;
|
||||
use crate::enums::VideoAdjustOption;
|
||||
use crate::tools::{to_cstr, from_cstr};
|
||||
use crate::tools::{to_cstr, from_cstr, track_descriptions_from_raw};
|
||||
use libc::c_void;
|
||||
|
||||
pub trait MediaPlayerVideoEx {
|
||||
|
|
@ -98,13 +98,7 @@ impl MediaPlayerVideoEx for MediaPlayer {
|
|||
unsafe{
|
||||
let p0 = sys::libvlc_video_get_track_description(self.ptr);
|
||||
if p0.is_null() { return None; }
|
||||
let mut td = Vec::new();
|
||||
let mut p = p0;
|
||||
|
||||
while !(*p).p_next.is_null() {
|
||||
td.push(TrackDescription{ id: (*p).i_id, name: from_cstr((*p).psz_name) });
|
||||
p = (*p).p_next;
|
||||
}
|
||||
let td = track_descriptions_from_raw(p0);
|
||||
sys::libvlc_track_description_list_release(p0);
|
||||
Some(td)
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue