mirror of
https://gitlab.freedesktop.org/dabrain34/GstPipelineStudio.git
synced 2024-12-24 08:50:29 +00:00
app: display position/duration and seek scale
The user can now see the position and duration of the playback The slider can now seek to the given position.
This commit is contained in:
parent
8f72b9ac79
commit
9b768b7d56
4 changed files with 111 additions and 16 deletions
5
TODO.md
5
TODO.md
|
@ -61,8 +61,9 @@
|
||||||
- [ ] Render a media file
|
- [ ] Render a media file
|
||||||
- [ ] Offer compatible element to a pad (autorender)
|
- [ ] Offer compatible element to a pad (autorender)
|
||||||
- [ ] Display tags/meta/message detected
|
- [ ] Display tags/meta/message detected
|
||||||
- [ ] Seek to position
|
- [x] Display position and duration
|
||||||
- [ ] Use one listbox with name, favorites and rank (sort list)
|
- [x] Seek to position
|
||||||
|
- [x] One listbox with elements and one listbox with favorites in the app dashboard
|
||||||
- [x] See the link creation with a dashed line
|
- [x] See the link creation with a dashed line
|
||||||
|
|
||||||
### CI/Infra
|
### CI/Infra
|
||||||
|
|
57
src/app.rs
57
src/app.rs
|
@ -52,7 +52,7 @@ pub struct GPSAppInner {
|
||||||
pub builder: Builder,
|
pub builder: Builder,
|
||||||
pub pipeline: RefCell<GPS::Pipeline>,
|
pub pipeline: RefCell<GPS::Pipeline>,
|
||||||
pub plugin_list_initialized: OnceCell<bool>,
|
pub plugin_list_initialized: OnceCell<bool>,
|
||||||
pub menu_signal_handlers: RefCell<HashMap<String, SignalHandlerId>>,
|
pub signal_handlers: RefCell<HashMap<String, SignalHandlerId>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -135,7 +135,7 @@ impl GPSApp {
|
||||||
builder,
|
builder,
|
||||||
pipeline: RefCell::new(pipeline),
|
pipeline: RefCell::new(pipeline),
|
||||||
plugin_list_initialized: OnceCell::new(),
|
plugin_list_initialized: OnceCell::new(),
|
||||||
menu_signal_handlers: RefCell::new(HashMap::new()),
|
signal_handlers: RefCell::new(HashMap::new()),
|
||||||
}));
|
}));
|
||||||
let app_weak = app.downgrade();
|
let app_weak = app.downgrade();
|
||||||
app.pipeline.borrow().set_app(app_weak);
|
app.pipeline.borrow().set_app(app_weak);
|
||||||
|
@ -161,7 +161,52 @@ impl GPSApp {
|
||||||
app.build_ui(&application);
|
app.build_ui(&application);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
let app_weak = app.downgrade();
|
||||||
|
let slider: gtk::Scale = app
|
||||||
|
.builder
|
||||||
|
.object("scale-position")
|
||||||
|
.expect("Couldn't get status_bar");
|
||||||
|
let slider_update_signal_id = slider.connect_value_changed(move |slider| {
|
||||||
|
let app = upgrade_weak!(app_weak);
|
||||||
|
let pipeline = app.pipeline.borrow();
|
||||||
|
let value = slider.value() as u64;
|
||||||
|
GPS_TRACE!("Seeking to {} s", value);
|
||||||
|
if pipeline.set_position(value).is_err() {
|
||||||
|
GPS_ERROR!("Seeking to {} failed", value);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
let app_weak = app.downgrade();
|
||||||
|
let timeout_id =
|
||||||
|
glib::timeout_add_local(std::time::Duration::from_millis(500), move || {
|
||||||
|
let app = upgrade_weak!(app_weak, glib::Continue(false));
|
||||||
|
let pipeline = app.pipeline.borrow();
|
||||||
|
|
||||||
|
let label: gtk::Label = app
|
||||||
|
.builder
|
||||||
|
.object("label-position")
|
||||||
|
.expect("Couldn't get status_bar");
|
||||||
|
let slider: gtk::Scale = app
|
||||||
|
.builder
|
||||||
|
.object("scale-position")
|
||||||
|
.expect("Couldn't get status_bar");
|
||||||
|
let position = pipeline.position();
|
||||||
|
let duration = pipeline.duration();
|
||||||
|
slider.set_range(0.0, duration as f64 / 1000_f64);
|
||||||
|
slider.block_signal(&slider_update_signal_id);
|
||||||
|
slider.set_value(position as f64 / 1000_f64);
|
||||||
|
slider.unblock_signal(&slider_update_signal_id);
|
||||||
|
|
||||||
|
// Query the current playing position from the underlying pipeline.
|
||||||
|
let position_desc = pipeline.position_description();
|
||||||
|
// Display the playing position in the gui.
|
||||||
|
label.set_text(&position_desc);
|
||||||
|
// Tell the callback to continue calling this closure.
|
||||||
|
glib::Continue(true)
|
||||||
|
});
|
||||||
|
|
||||||
|
let timeout_id = RefCell::new(Some(timeout_id));
|
||||||
let app_container = RefCell::new(Some(app));
|
let app_container = RefCell::new(Some(app));
|
||||||
|
|
||||||
application.connect_shutdown(move |_| {
|
application.connect_shutdown(move |_| {
|
||||||
let app = app_container
|
let app = app_container
|
||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
|
@ -202,6 +247,9 @@ impl GPSApp {
|
||||||
.object("app_pop_menu")
|
.object("app_pop_menu")
|
||||||
.expect("Couldn't get app_pop_menu");
|
.expect("Couldn't get app_pop_menu");
|
||||||
pop_menu.unparent();
|
pop_menu.unparent();
|
||||||
|
if let Some(timeout_id) = timeout_id.borrow_mut().take() {
|
||||||
|
timeout_id.remove();
|
||||||
|
}
|
||||||
|
|
||||||
app.drop();
|
app.drop();
|
||||||
});
|
});
|
||||||
|
@ -283,8 +331,7 @@ impl GPSApp {
|
||||||
fn disconnect_app_menu_action(&self, action_name: &str) {
|
fn disconnect_app_menu_action(&self, action_name: &str) {
|
||||||
let action = self.app_menu_action(action_name);
|
let action = self.app_menu_action(action_name);
|
||||||
|
|
||||||
if let Some(signal_handler_id) = self.menu_signal_handlers.borrow_mut().remove(action_name)
|
if let Some(signal_handler_id) = self.signal_handlers.borrow_mut().remove(action_name) {
|
||||||
{
|
|
||||||
action.disconnect(signal_handler_id);
|
action.disconnect(signal_handler_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -299,7 +346,7 @@ impl GPSApp {
|
||||||
let action = self.app_menu_action(action_name);
|
let action = self.app_menu_action(action_name);
|
||||||
self.disconnect_app_menu_action(action_name);
|
self.disconnect_app_menu_action(action_name);
|
||||||
let signal_handler_id = action.connect_activate(f);
|
let signal_handler_id = action.connect_activate(f);
|
||||||
self.menu_signal_handlers
|
self.signal_handlers
|
||||||
.borrow_mut()
|
.borrow_mut()
|
||||||
.insert(String::from(action_name), signal_handler_id);
|
.insert(String::from(action_name), signal_handler_id);
|
||||||
}
|
}
|
||||||
|
|
|
@ -145,7 +145,7 @@
|
||||||
<property name="orientation">vertical</property>
|
<property name="orientation">vertical</property>
|
||||||
<property name="spacing">1</property>
|
<property name="spacing">1</property>
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkBox">
|
<object class="GtkPaned">
|
||||||
<property name="vexpand">0</property>
|
<property name="vexpand">0</property>
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkBox">
|
<object class="GtkBox">
|
||||||
|
@ -177,6 +177,10 @@
|
||||||
<property name="icon-name">edit-clear</property>
|
<property name="icon-name">edit-clear</property>
|
||||||
</object>
|
</object>
|
||||||
</child>
|
</child>
|
||||||
|
<child>
|
||||||
|
<object class="GtkLabel" id="label-position">
|
||||||
|
<property name="label" translatable="yes">xx:xx:xx</property>
|
||||||
|
<property name="hexpand">1</property>
|
||||||
</object>
|
</object>
|
||||||
</child>
|
</child>
|
||||||
</object>
|
</object>
|
||||||
|
@ -189,6 +193,9 @@
|
||||||
<property name="round-digits">1</property>
|
<property name="round-digits">1</property>
|
||||||
</object>
|
</object>
|
||||||
</child>
|
</child>
|
||||||
|
</object>
|
||||||
|
</child>
|
||||||
|
|
||||||
<!--Graph and DashBoard paned-->
|
<!--Graph and DashBoard paned-->
|
||||||
<child>
|
<child>
|
||||||
<object class="GtkPaned" id="graph_dashboard-paned">
|
<object class="GtkPaned" id="graph_dashboard-paned">
|
||||||
|
|
|
@ -180,6 +180,46 @@ impl Pipeline {
|
||||||
self.current_state.get()
|
self.current_state.get()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn set_position(&self, position: u64) -> anyhow::Result<()> {
|
||||||
|
if let Some(pipeline) = self.pipeline.borrow().to_owned() {
|
||||||
|
pipeline.seek_simple(
|
||||||
|
gst::SeekFlags::FLUSH | gst::SeekFlags::KEY_UNIT,
|
||||||
|
position * gst::ClockTime::SECOND,
|
||||||
|
)?;
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn position(&self) -> u64 {
|
||||||
|
let mut position = gst::ClockTime::NONE;
|
||||||
|
if let Some(pipeline) = self.pipeline.borrow().to_owned() {
|
||||||
|
position = pipeline.query_position::<gst::ClockTime>();
|
||||||
|
}
|
||||||
|
position.unwrap_or_default().mseconds()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn duration(&self) -> u64 {
|
||||||
|
let mut duration = gst::ClockTime::NONE;
|
||||||
|
if let Some(pipeline) = self.pipeline.borrow().to_owned() {
|
||||||
|
duration = pipeline.query_duration::<gst::ClockTime>();
|
||||||
|
}
|
||||||
|
duration.unwrap_or_default().mseconds()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn position_description(&self) -> String {
|
||||||
|
let mut position = gst::ClockTime::NONE;
|
||||||
|
let mut duration = gst::ClockTime::NONE;
|
||||||
|
if let Some(pipeline) = self.pipeline.borrow().to_owned() {
|
||||||
|
position = pipeline.query_position::<gst::ClockTime>();
|
||||||
|
duration = pipeline.query_duration::<gst::ClockTime>();
|
||||||
|
}
|
||||||
|
format!(
|
||||||
|
"{:.0}/{:.0}",
|
||||||
|
position.unwrap_or_default().display(),
|
||||||
|
duration.unwrap_or_default().display(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
fn state_to_app_state(state: PipelineState) -> AppState {
|
fn state_to_app_state(state: PipelineState) -> AppState {
|
||||||
match state {
|
match state {
|
||||||
PipelineState::Playing => AppState::Playing,
|
PipelineState::Playing => AppState::Playing,
|
||||||
|
|
Loading…
Reference in a new issue