mirror of
https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs.git
synced 2024-11-22 11:30:59 +00:00
uriplaylistbin: add properties reporting the current state of the playlist
This commit is contained in:
parent
9783d01a35
commit
b7c08933aa
2 changed files with 134 additions and 25 deletions
|
@ -7,7 +7,7 @@
|
||||||
// SPDX-License-Identifier: MPL-2.0
|
// SPDX-License-Identifier: MPL-2.0
|
||||||
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::sync::Mutex;
|
use std::sync::{Mutex, MutexGuard};
|
||||||
|
|
||||||
use gst::glib;
|
use gst::glib;
|
||||||
use gst::prelude::*;
|
use gst::prelude::*;
|
||||||
|
@ -123,6 +123,10 @@ struct State {
|
||||||
streaming: Vec<Item>,
|
streaming: Vec<Item>,
|
||||||
// items which have been fully played, waiting to be cleaned up
|
// items which have been fully played, waiting to be cleaned up
|
||||||
done: Vec<Item>,
|
done: Vec<Item>,
|
||||||
|
|
||||||
|
// read-only properties
|
||||||
|
current_iteration: u32,
|
||||||
|
current_uri_index: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl State {
|
impl State {
|
||||||
|
@ -141,6 +145,8 @@ impl State {
|
||||||
blocked: None,
|
blocked: None,
|
||||||
streaming: vec![],
|
streaming: vec![],
|
||||||
done: vec![],
|
done: vec![],
|
||||||
|
current_iteration: 0,
|
||||||
|
current_uri_index: 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -717,6 +723,24 @@ impl ObjectImpl for UriPlaylistBin {
|
||||||
1,
|
1,
|
||||||
glib::ParamFlags::READWRITE | gst::PARAM_FLAG_MUTABLE_READY,
|
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();
|
let settings = self.settings.lock().unwrap();
|
||||||
settings.iterations.to_value()
|
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!(),
|
_ => unimplemented!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -980,6 +1020,8 @@ impl UriPlaylistBin {
|
||||||
// unblock last item
|
// unblock last item
|
||||||
state.unblock_item(element);
|
state.unblock_item(element);
|
||||||
|
|
||||||
|
self.update_current(state_guard);
|
||||||
|
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -1115,6 +1157,8 @@ impl UriPlaylistBin {
|
||||||
}
|
}
|
||||||
|
|
||||||
state.waiting_for_stream_collection = None;
|
state.waiting_for_stream_collection = None;
|
||||||
|
|
||||||
|
self.update_current(state_guard);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -1431,6 +1475,8 @@ impl UriPlaylistBin {
|
||||||
item.set_blocked();
|
item.set_blocked();
|
||||||
state.blocked = Some(item);
|
state.blocked = Some(item);
|
||||||
|
|
||||||
|
self.update_current(state_guard);
|
||||||
|
|
||||||
true
|
true
|
||||||
} else {
|
} else {
|
||||||
false
|
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");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -76,7 +76,7 @@ fn test(
|
||||||
n_streams: u32,
|
n_streams: u32,
|
||||||
iterations: u32,
|
iterations: u32,
|
||||||
check_streams: bool,
|
check_streams: bool,
|
||||||
) -> Vec<gst::Message> {
|
) -> (Vec<gst::Message>, u32, u64) {
|
||||||
init();
|
init();
|
||||||
|
|
||||||
let playlist_len = medias.len() * (iterations as usize);
|
let playlist_len = medias.len() * (iterations as usize);
|
||||||
|
@ -99,6 +99,9 @@ fn test(
|
||||||
playlist.set_property("uris", &uris);
|
playlist.set_property("uris", &uris);
|
||||||
playlist.set_property("iterations", &iterations);
|
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();
|
let mq_clone = mq.clone();
|
||||||
playlist.connect_pad_added(move |_playlist, src_pad| {
|
playlist.connect_pad_added(move |_playlist, src_pad| {
|
||||||
let mq_sink = mq_clone.request_pad_simple("sink_%u").unwrap();
|
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();
|
pipeline.set_state(gst::State::Null).unwrap();
|
||||||
|
|
||||||
events
|
(events, current_iteration, current_uri_index)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn assert_eos(msg: gst::Message) {
|
fn assert_eos(msg: gst::Message) {
|
||||||
|
@ -234,66 +240,88 @@ fn assert_stream_selected(msg: gst::Message, n_streams: usize) -> gst::Object {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn single_audio() {
|
fn single_audio() {
|
||||||
let events = test(vec![TestMedia::ogg()], 1, 1, true).into_iter();
|
let (events, current_iteration, current_uri_index) = test(vec![TestMedia::ogg()], 1, 1, true);
|
||||||
assert_eos(events.last().unwrap());
|
assert_eos(events.into_iter().last().unwrap());
|
||||||
|
assert_eq!(current_iteration, 0);
|
||||||
|
assert_eq!(current_uri_index, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn single_video() {
|
fn single_video() {
|
||||||
let events = test(vec![TestMedia::mkv()], 2, 1, true).into_iter();
|
let (events, current_iteration, current_uri_index) = test(vec![TestMedia::mkv()], 2, 1, true);
|
||||||
assert_eos(events.last().unwrap());
|
assert_eos(events.into_iter().last().unwrap());
|
||||||
|
assert_eq!(current_iteration, 0);
|
||||||
|
assert_eq!(current_uri_index, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn multi_audio() {
|
fn multi_audio() {
|
||||||
let events = test(
|
let (events, current_iteration, current_uri_index) = test(
|
||||||
vec![TestMedia::ogg(), TestMedia::ogg(), TestMedia::ogg()],
|
vec![TestMedia::ogg(), TestMedia::ogg(), TestMedia::ogg()],
|
||||||
1,
|
1,
|
||||||
1,
|
1,
|
||||||
true,
|
true,
|
||||||
)
|
);
|
||||||
.into_iter();
|
assert_eos(events.into_iter().last().unwrap());
|
||||||
assert_eos(events.last().unwrap());
|
assert_eq!(current_iteration, 0);
|
||||||
|
assert_eq!(current_uri_index, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn multi_audio_video() {
|
fn multi_audio_video() {
|
||||||
let events = test(vec![TestMedia::mkv(), TestMedia::mkv()], 2, 1, true).into_iter();
|
let (events, current_iteration, current_uri_index) =
|
||||||
assert_eos(events.last().unwrap());
|
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]
|
#[test]
|
||||||
fn iterations() {
|
fn iterations() {
|
||||||
let events = test(vec![TestMedia::mkv(), TestMedia::mkv()], 2, 2, true).into_iter();
|
let (events, current_iteration, current_uri_index) =
|
||||||
assert_eos(events.last().unwrap());
|
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]
|
#[test]
|
||||||
fn nb_streams_increasing() {
|
fn nb_streams_increasing() {
|
||||||
let events = test(vec![TestMedia::ogg(), TestMedia::mkv()], 2, 1, false).into_iter();
|
let (events, current_iteration, current_uri_index) =
|
||||||
assert_eos(events.last().unwrap());
|
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]
|
#[test]
|
||||||
fn missing_file() {
|
fn missing_file() {
|
||||||
let events = test(
|
let (events, current_iteration, current_uri_index) = test(
|
||||||
vec![TestMedia::ogg(), TestMedia::missing_file()],
|
vec![TestMedia::ogg(), TestMedia::missing_file()],
|
||||||
1,
|
1,
|
||||||
1,
|
1,
|
||||||
false,
|
false,
|
||||||
)
|
);
|
||||||
.into_iter();
|
assert_error(
|
||||||
assert_error(events.last().unwrap(), TestMedia::missing_file());
|
events.into_iter().last().unwrap(),
|
||||||
|
TestMedia::missing_file(),
|
||||||
|
);
|
||||||
|
assert_eq!(current_iteration, 0);
|
||||||
|
assert_eq!(current_uri_index, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn missing_http() {
|
fn missing_http() {
|
||||||
let events = test(
|
let (events, current_iteration, current_uri_index) = test(
|
||||||
vec![TestMedia::ogg(), TestMedia::missing_http()],
|
vec![TestMedia::ogg(), TestMedia::missing_http()],
|
||||||
1,
|
1,
|
||||||
1,
|
1,
|
||||||
false,
|
false,
|
||||||
)
|
);
|
||||||
.into_iter();
|
assert_error(
|
||||||
assert_error(events.last().unwrap(), TestMedia::missing_http());
|
events.into_iter().last().unwrap(),
|
||||||
|
TestMedia::missing_http(),
|
||||||
|
);
|
||||||
|
assert_eq!(current_iteration, 0);
|
||||||
|
assert_eq!(current_uri_index, 0);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue