mirror of
https://gitlab.freedesktop.org/gstreamer/gst-plugins-rs.git
synced 2025-02-16 12:55:13 +00:00
textahead: generate a buffer with ahead text at segment start
This is useful for karaoke use cases where the first text may appear after a while but you want to already display the upcoming lyrics to users.
This commit is contained in:
parent
5606111345
commit
b5d5cf25fe
1 changed files with 51 additions and 10 deletions
|
@ -27,6 +27,7 @@ struct Settings {
|
||||||
separator: String,
|
separator: String,
|
||||||
current_attributes: String,
|
current_attributes: String,
|
||||||
ahead_attributes: String,
|
ahead_attributes: String,
|
||||||
|
buffer_start_segment: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for Settings {
|
impl Default for Settings {
|
||||||
|
@ -36,6 +37,7 @@ impl Default for Settings {
|
||||||
separator: "\n".to_string(),
|
separator: "\n".to_string(),
|
||||||
current_attributes: "size=\"larger\"".to_string(),
|
current_attributes: "size=\"larger\"".to_string(),
|
||||||
ahead_attributes: "size=\"smaller\"".to_string(),
|
ahead_attributes: "size=\"smaller\"".to_string(),
|
||||||
|
buffer_start_segment: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -50,6 +52,8 @@ struct Input {
|
||||||
struct State {
|
struct State {
|
||||||
pending: Vec<Input>,
|
pending: Vec<Input>,
|
||||||
done: bool,
|
done: bool,
|
||||||
|
/// Segment for which we should send a buffer with ahead text. Only set if `Settings.buffer_start_segment` is set.
|
||||||
|
pending_segment: Option<gst::FormattedSegment<gst::format::Time>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct TextAhead {
|
pub struct TextAhead {
|
||||||
|
@ -128,6 +132,12 @@ impl ObjectImpl for TextAhead {
|
||||||
.default_value(Some(&default.ahead_attributes))
|
.default_value(Some(&default.ahead_attributes))
|
||||||
.mutable_playing()
|
.mutable_playing()
|
||||||
.build(),
|
.build(),
|
||||||
|
glib::ParamSpecBoolean::builder("buffer-start-segment")
|
||||||
|
.nick("Buffer start segment")
|
||||||
|
.blurb("Generate a buffer at the start of the segment with ahead text")
|
||||||
|
.default_value(default.buffer_start_segment)
|
||||||
|
.mutable_playing()
|
||||||
|
.build(),
|
||||||
]
|
]
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -156,6 +166,9 @@ impl ObjectImpl for TextAhead {
|
||||||
"ahead-attributes" => {
|
"ahead-attributes" => {
|
||||||
settings.ahead_attributes = value.get().expect("type checked upstream");
|
settings.ahead_attributes = value.get().expect("type checked upstream");
|
||||||
}
|
}
|
||||||
|
"buffer-start-segment" => {
|
||||||
|
settings.buffer_start_segment = value.get().expect("type checked upstream");
|
||||||
|
}
|
||||||
_ => unimplemented!(),
|
_ => unimplemented!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -168,6 +181,7 @@ impl ObjectImpl for TextAhead {
|
||||||
"separator" => settings.separator.to_value(),
|
"separator" => settings.separator.to_value(),
|
||||||
"current-attributes" => settings.current_attributes.to_value(),
|
"current-attributes" => settings.current_attributes.to_value(),
|
||||||
"ahead-attributes" => settings.ahead_attributes.to_value(),
|
"ahead-attributes" => settings.ahead_attributes.to_value(),
|
||||||
|
"buffer-start-segment" => settings.buffer_start_segment.to_value(),
|
||||||
_ => unimplemented!(),
|
_ => unimplemented!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -305,6 +319,21 @@ impl TextAhead {
|
||||||
let _ = self.src_pad.push_event(gst::event::Caps::new(templ.caps()));
|
let _ = self.src_pad.push_event(gst::event::Caps::new(templ.caps()));
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
gst::EventView::Segment(segment) => {
|
||||||
|
if let Ok(segment) = segment.segment().clone().downcast::<gst::format::Time>() {
|
||||||
|
let buffer_start_segment = {
|
||||||
|
let settings = self.settings.lock().unwrap();
|
||||||
|
settings.buffer_start_segment
|
||||||
|
};
|
||||||
|
|
||||||
|
if buffer_start_segment {
|
||||||
|
let mut state = self.state.lock().unwrap();
|
||||||
|
state.pending_segment = Some(segment);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pad.event_default(Some(element), event)
|
||||||
|
}
|
||||||
_ => pad.event_default(Some(element), event),
|
_ => pad.event_default(Some(element), event),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -320,14 +349,26 @@ impl TextAhead {
|
||||||
}
|
}
|
||||||
let settings = self.settings.lock().unwrap();
|
let settings = self.settings.lock().unwrap();
|
||||||
|
|
||||||
let first = state.pending.remove(0);
|
let (mut text, pts, duration) = if let Some(pending_segment) = state.pending_segment.take()
|
||||||
let mut text = if settings.current_attributes.is_empty() {
|
{
|
||||||
first.text
|
let duration = match (pending_segment.start(), state.pending[0].pts) {
|
||||||
|
(Some(start), Some(first_pts)) => Some(first_pts - start),
|
||||||
|
_ => None,
|
||||||
|
};
|
||||||
|
|
||||||
|
("".to_string(), pending_segment.start(), duration)
|
||||||
} else {
|
} else {
|
||||||
format!(
|
let first = state.pending.remove(0);
|
||||||
"<span {}>{}</span>",
|
let text = if settings.current_attributes.is_empty() {
|
||||||
settings.current_attributes, first.text
|
first.text
|
||||||
)
|
} else {
|
||||||
|
format!(
|
||||||
|
"<span {}>{}</span>",
|
||||||
|
settings.current_attributes, first.text
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
(text, first.pts, first.duration)
|
||||||
};
|
};
|
||||||
|
|
||||||
for input in state.pending.iter() {
|
for input in state.pending.iter() {
|
||||||
|
@ -349,14 +390,14 @@ impl TextAhead {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
gst::log!(CAT, obj: element, "output {:?}: {}", first.pts, text);
|
gst::log!(CAT, obj: element, "output {:?}: {}", pts, text);
|
||||||
|
|
||||||
let mut output = gst::Buffer::from_mut_slice(text.into_bytes());
|
let mut output = gst::Buffer::from_mut_slice(text.into_bytes());
|
||||||
{
|
{
|
||||||
let output = output.get_mut().unwrap();
|
let output = output.get_mut().unwrap();
|
||||||
|
|
||||||
output.set_pts(first.pts);
|
output.set_pts(pts);
|
||||||
output.set_duration(first.duration);
|
output.set_duration(duration);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.src_pad.push(output)
|
self.src_pad.push(output)
|
||||||
|
|
Loading…
Reference in a new issue