uriplaylistbin: add properties reporting the current state of the playlist

This commit is contained in:
Guillaume Desmottes 2021-12-22 11:38:43 +01:00
parent 9783d01a35
commit b7c08933aa
2 changed files with 134 additions and 25 deletions

View file

@ -7,7 +7,7 @@
// SPDX-License-Identifier: MPL-2.0
use std::sync::Arc;
use std::sync::Mutex;
use std::sync::{Mutex, MutexGuard};
use gst::glib;
use gst::prelude::*;
@ -123,6 +123,10 @@ struct State {
streaming: Vec<Item>,
// items which have been fully played, waiting to be cleaned up
done: Vec<Item>,
// read-only properties
current_iteration: u32,
current_uri_index: u64,
}
impl State {
@ -141,6 +145,8 @@ impl State {
blocked: None,
streaming: vec![],
done: vec![],
current_iteration: 0,
current_uri_index: 0,
}
}
@ -717,6 +723,24 @@ impl ObjectImpl for UriPlaylistBin {
1,
glib::ParamFlags::READWRITE | gst::PARAM_FLAG_MUTABLE_READY,
),
glib::ParamSpecUInt::new(
"current-iteration",
"Current iteration",
"The index of the current playlist iteration, or 0 if the iterations property is 0 (unlimited playlist)",
0,
u32::MAX,
0,
glib::ParamFlags::READABLE,
),
glib::ParamSpecUInt64::new(
"current-uri-index",
"Current URI",
"The index from the uris property of the current URI being played",
0,
u64::MAX,
0,
glib::ParamFlags::READABLE,
),
]
});
@ -769,6 +793,22 @@ impl ObjectImpl for UriPlaylistBin {
let settings = self.settings.lock().unwrap();
settings.iterations.to_value()
}
"current-iteration" => {
let state = self.state.lock().unwrap();
state
.as_ref()
.map(|state| state.current_iteration)
.unwrap_or(0)
.to_value()
}
"current-uri-index" => {
let state = self.state.lock().unwrap();
state
.as_ref()
.map(|state| state.current_uri_index)
.unwrap_or(0)
.to_value()
}
_ => unimplemented!(),
}
}
@ -980,6 +1020,8 @@ impl UriPlaylistBin {
// unblock last item
state.unblock_item(element);
self.update_current(state_guard);
return Ok(());
}
};
@ -1115,6 +1157,8 @@ impl UriPlaylistBin {
}
state.waiting_for_stream_collection = None;
self.update_current(state_guard);
}
}
Ok(())
@ -1431,6 +1475,8 @@ impl UriPlaylistBin {
item.set_blocked();
state.blocked = Some(item);
self.update_current(state_guard);
true
} else {
false
@ -1571,5 +1617,40 @@ impl UriPlaylistBin {
);
}
}
self.update_current(self.state.lock().unwrap());
}
fn update_current(&self, mut state_guard: MutexGuard<Option<State>>) {
let (uris_len, infinite) = {
let settings = self.settings.lock().unwrap();
(settings.uris.len(), settings.iterations == 0)
};
if let Some(state) = state_guard.as_mut() {
// first streaming item is the one actually being played
if let Some(current) = state.streaming.get(0) {
let (mut current_iteration, current_uri_index) = (
(current.index() / uris_len) as u32,
(current.index() % uris_len) as u64,
);
if infinite {
current_iteration = 0;
}
let element = self.instance();
if current_iteration != state.current_iteration {
state.current_iteration = current_iteration;
element.notify("current-iteration");
}
if current_uri_index != state.current_uri_index {
state.current_uri_index = current_uri_index;
element.notify("current-uri-index");
}
}
}
}
}

View file

@ -76,7 +76,7 @@ fn test(
n_streams: u32,
iterations: u32,
check_streams: bool,
) -> Vec<gst::Message> {
) -> (Vec<gst::Message>, u32, u64) {
init();
let playlist_len = medias.len() * (iterations as usize);
@ -99,6 +99,9 @@ fn test(
playlist.set_property("uris", &uris);
playlist.set_property("iterations", &iterations);
assert_eq!(playlist.property::<u32>("current-iteration"), 0);
assert_eq!(playlist.property::<u64>("current-uri-index"), 0);
let mq_clone = mq.clone();
playlist.connect_pad_added(move |_playlist, src_pad| {
let mq_sink = mq_clone.request_pad_simple("sink_%u").unwrap();
@ -185,9 +188,12 @@ fn test(
}
}
let current_iteration = playlist.property::<u32>("current-iteration");
let current_uri_index = playlist.property::<u64>("current-uri-index");
pipeline.set_state(gst::State::Null).unwrap();
events
(events, current_iteration, current_uri_index)
}
fn assert_eos(msg: gst::Message) {
@ -234,66 +240,88 @@ fn assert_stream_selected(msg: gst::Message, n_streams: usize) -> gst::Object {
#[test]
fn single_audio() {
let events = test(vec![TestMedia::ogg()], 1, 1, true).into_iter();
assert_eos(events.last().unwrap());
let (events, current_iteration, current_uri_index) = test(vec![TestMedia::ogg()], 1, 1, true);
assert_eos(events.into_iter().last().unwrap());
assert_eq!(current_iteration, 0);
assert_eq!(current_uri_index, 0);
}
#[test]
fn single_video() {
let events = test(vec![TestMedia::mkv()], 2, 1, true).into_iter();
assert_eos(events.last().unwrap());
let (events, current_iteration, current_uri_index) = test(vec![TestMedia::mkv()], 2, 1, true);
assert_eos(events.into_iter().last().unwrap());
assert_eq!(current_iteration, 0);
assert_eq!(current_uri_index, 0);
}
#[test]
fn multi_audio() {
let events = test(
let (events, current_iteration, current_uri_index) = test(
vec![TestMedia::ogg(), TestMedia::ogg(), TestMedia::ogg()],
1,
1,
true,
)
.into_iter();
assert_eos(events.last().unwrap());
);
assert_eos(events.into_iter().last().unwrap());
assert_eq!(current_iteration, 0);
assert_eq!(current_uri_index, 2);
}
#[test]
fn multi_audio_video() {
let events = test(vec![TestMedia::mkv(), TestMedia::mkv()], 2, 1, true).into_iter();
assert_eos(events.last().unwrap());
let (events, current_iteration, current_uri_index) =
test(vec![TestMedia::mkv(), TestMedia::mkv()], 2, 1, true);
assert_eos(events.into_iter().last().unwrap());
assert_eq!(current_iteration, 0);
assert_eq!(current_uri_index, 1);
}
#[test]
fn iterations() {
let events = test(vec![TestMedia::mkv(), TestMedia::mkv()], 2, 2, true).into_iter();
assert_eos(events.last().unwrap());
let (events, current_iteration, current_uri_index) =
test(vec![TestMedia::mkv(), TestMedia::mkv()], 2, 2, true);
assert_eos(events.into_iter().last().unwrap());
assert_eq!(current_iteration, 1);
assert_eq!(current_uri_index, 1);
}
#[test]
fn nb_streams_increasing() {
let events = test(vec![TestMedia::ogg(), TestMedia::mkv()], 2, 1, false).into_iter();
assert_eos(events.last().unwrap());
let (events, current_iteration, current_uri_index) =
test(vec![TestMedia::ogg(), TestMedia::mkv()], 2, 1, false);
assert_eos(events.into_iter().last().unwrap());
assert_eq!(current_iteration, 0);
assert_eq!(current_uri_index, 1);
}
#[test]
fn missing_file() {
let events = test(
let (events, current_iteration, current_uri_index) = test(
vec![TestMedia::ogg(), TestMedia::missing_file()],
1,
1,
false,
)
.into_iter();
assert_error(events.last().unwrap(), TestMedia::missing_file());
);
assert_error(
events.into_iter().last().unwrap(),
TestMedia::missing_file(),
);
assert_eq!(current_iteration, 0);
assert_eq!(current_uri_index, 0);
}
#[test]
fn missing_http() {
let events = test(
let (events, current_iteration, current_uri_index) = test(
vec![TestMedia::ogg(), TestMedia::missing_http()],
1,
1,
false,
)
.into_iter();
assert_error(events.last().unwrap(), TestMedia::missing_http());
);
assert_error(
events.into_iter().last().unwrap(),
TestMedia::missing_http(),
);
assert_eq!(current_iteration, 0);
assert_eq!(current_uri_index, 0);
}