diff --git a/docs/plugins/gst_plugins_cache.json b/docs/plugins/gst_plugins_cache.json
index eadaf329..c8e51e37 100644
--- a/docs/plugins/gst_plugins_cache.json
+++ b/docs/plugins/gst_plugins_cache.json
@@ -6268,6 +6268,32 @@
"type": "guint",
"writable": true
},
+ "n-previous": {
+ "blurb": "The number of previous text buffers to display before the current one",
+ "conditionally-available": false,
+ "construct": false,
+ "construct-only": false,
+ "controllable": false,
+ "default": "0",
+ "max": "-1",
+ "min": "0",
+ "mutable": "playing",
+ "readable": true,
+ "type": "guint",
+ "writable": true
+ },
+ "previous-attributes": {
+ "blurb": "Pango span attributes to set on the previous text",
+ "conditionally-available": false,
+ "construct": false,
+ "construct-only": false,
+ "controllable": false,
+ "default": "size=\"smaller\"",
+ "mutable": "playing",
+ "readable": true,
+ "type": "gchararray",
+ "writable": true
+ },
"separator": {
"blurb": "Text inserted between each text buffers",
"conditionally-available": false,
diff --git a/text/ahead/src/textahead/imp.rs b/text/ahead/src/textahead/imp.rs
index cec37423..82dc1f1b 100644
--- a/text/ahead/src/textahead/imp.rs
+++ b/text/ahead/src/textahead/imp.rs
@@ -28,6 +28,8 @@ struct Settings {
current_attributes: String,
ahead_attributes: String,
buffer_start_segment: bool,
+ n_previous: u32,
+ previous_attributes: String,
}
impl Default for Settings {
@@ -38,6 +40,8 @@ impl Default for Settings {
current_attributes: "size=\"larger\"".to_string(),
ahead_attributes: "size=\"smaller\"".to_string(),
buffer_start_segment: false,
+ n_previous: 0,
+ previous_attributes: "size=\"smaller\"".to_string(),
}
}
}
@@ -50,6 +54,7 @@ struct Input {
#[derive(Default)]
struct State {
+ previous: Vec,
pending: Vec,
done: bool,
/// Segment for which we should send a buffer with ahead text. Only set if `Settings.buffer_start_segment` is set.
@@ -138,6 +143,18 @@ impl ObjectImpl for TextAhead {
.default_value(default.buffer_start_segment)
.mutable_playing()
.build(),
+ glib::ParamSpecUInt::builder("n-previous")
+ .nick("n-previous")
+ .blurb("The number of previous text buffers to display before the current one")
+ .default_value(default.n_previous)
+ .mutable_playing()
+ .build(),
+ glib::ParamSpecString::builder("previous-attributes")
+ .nick("Previous attributes")
+ .blurb("Pango span attributes to set on the previous text")
+ .default_value(&*default.previous_attributes)
+ .mutable_playing()
+ .build(),
]
});
@@ -163,6 +180,12 @@ impl ObjectImpl for TextAhead {
"buffer-start-segment" => {
settings.buffer_start_segment = value.get().expect("type checked upstream");
}
+ "n-previous" => {
+ settings.n_previous = value.get().expect("type checked upstream");
+ }
+ "previous-attributes" => {
+ settings.previous_attributes = value.get().expect("type checked upstream");
+ }
_ => unimplemented!(),
}
}
@@ -176,6 +199,8 @@ impl ObjectImpl for TextAhead {
"current-attributes" => settings.current_attributes.to_value(),
"ahead-attributes" => settings.ahead_attributes.to_value(),
"buffer-start-segment" => settings.buffer_start_segment.to_value(),
+ "n-previous" => settings.n_previous.to_value(),
+ "previous-attributes" => settings.previous_attributes.to_value(),
_ => unimplemented!(),
}
}
@@ -351,19 +376,66 @@ impl TextAhead {
("".to_string(), pending_segment.start(), duration)
} else {
- let first = state.pending.remove(0);
- let text = if settings.current_attributes.is_empty() {
- first.text
- } else {
- format!(
- "{}",
- settings.current_attributes, first.text
- )
- };
+ let mut text = String::new();
+ let mut first_buffer = true;
- (text, first.pts, first.duration)
+ // previous buffers
+ for previous in state.previous.iter() {
+ if !first_buffer && !settings.separator.is_empty() {
+ text.push_str(&settings.separator);
+ }
+
+ if settings.ahead_attributes.is_empty() {
+ text.push_str(&previous.text);
+ } else {
+ use std::fmt::Write;
+
+ write!(
+ &mut text,
+ "{}",
+ settings.previous_attributes, previous.text,
+ )
+ .unwrap();
+ }
+
+ first_buffer = false;
+ }
+
+ // current buffer
+ let current = state.pending.remove(0);
+
+ if !first_buffer && !settings.separator.is_empty() {
+ text.push_str(&settings.separator);
+ }
+
+ if settings.current_attributes.is_empty() {
+ text.push_str(¤t.text);
+ } else {
+ use std::fmt::Write;
+
+ write!(
+ &mut text,
+ "{}",
+ settings.current_attributes, current.text
+ )
+ .unwrap();
+ }
+
+ let pts = current.pts;
+ let duration = current.duration;
+
+ if settings.n_previous > 0 {
+ state.previous.push(current);
+
+ if state.previous.len() > settings.n_previous as usize {
+ state.previous.pop();
+ }
+ }
+
+ (text, pts, duration)
};
+ // ahead buffers
for input in state.pending.iter() {
if !settings.separator.is_empty() {
text.push_str(&settings.separator);