mirror of
https://gitlab.freedesktop.org/dabrain34/GstPipelineStudio.git
synced 2024-12-18 22:16:33 +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
|
||||
- [ ] Offer compatible element to a pad (autorender)
|
||||
- [ ] Display tags/meta/message detected
|
||||
- [ ] Seek to position
|
||||
- [ ] Use one listbox with name, favorites and rank (sort list)
|
||||
- [x] Display position and duration
|
||||
- [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
|
||||
|
||||
### CI/Infra
|
||||
|
|
57
src/app.rs
57
src/app.rs
|
@ -52,7 +52,7 @@ pub struct GPSAppInner {
|
|||
pub builder: Builder,
|
||||
pub pipeline: RefCell<GPS::Pipeline>,
|
||||
pub plugin_list_initialized: OnceCell<bool>,
|
||||
pub menu_signal_handlers: RefCell<HashMap<String, SignalHandlerId>>,
|
||||
pub signal_handlers: RefCell<HashMap<String, SignalHandlerId>>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
|
@ -135,7 +135,7 @@ impl GPSApp {
|
|||
builder,
|
||||
pipeline: RefCell::new(pipeline),
|
||||
plugin_list_initialized: OnceCell::new(),
|
||||
menu_signal_handlers: RefCell::new(HashMap::new()),
|
||||
signal_handlers: RefCell::new(HashMap::new()),
|
||||
}));
|
||||
let app_weak = app.downgrade();
|
||||
app.pipeline.borrow().set_app(app_weak);
|
||||
|
@ -161,7 +161,52 @@ impl GPSApp {
|
|||
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));
|
||||
|
||||
application.connect_shutdown(move |_| {
|
||||
let app = app_container
|
||||
.borrow_mut()
|
||||
|
@ -202,6 +247,9 @@ impl GPSApp {
|
|||
.object("app_pop_menu")
|
||||
.expect("Couldn't get app_pop_menu");
|
||||
pop_menu.unparent();
|
||||
if let Some(timeout_id) = timeout_id.borrow_mut().take() {
|
||||
timeout_id.remove();
|
||||
}
|
||||
|
||||
app.drop();
|
||||
});
|
||||
|
@ -283,8 +331,7 @@ impl GPSApp {
|
|||
fn disconnect_app_menu_action(&self, action_name: &str) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
@ -299,7 +346,7 @@ impl GPSApp {
|
|||
let action = self.app_menu_action(action_name);
|
||||
self.disconnect_app_menu_action(action_name);
|
||||
let signal_handler_id = action.connect_activate(f);
|
||||
self.menu_signal_handlers
|
||||
self.signal_handlers
|
||||
.borrow_mut()
|
||||
.insert(String::from(action_name), signal_handler_id);
|
||||
}
|
||||
|
|
25
src/gps.ui
25
src/gps.ui
|
@ -145,7 +145,7 @@
|
|||
<property name="orientation">vertical</property>
|
||||
<property name="spacing">1</property>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
<object class="GtkPaned">
|
||||
<property name="vexpand">0</property>
|
||||
<child>
|
||||
<object class="GtkBox">
|
||||
|
@ -177,18 +177,25 @@
|
|||
<property name="icon-name">edit-clear</property>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkLabel" id="label-position">
|
||||
<property name="label" translatable="yes">xx:xx:xx</property>
|
||||
<property name="hexpand">1</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkScale" id="scale-position">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="adjustment">scale_adjustment</property>
|
||||
<property name="round-digits">1</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkScale" id="scale-position">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="adjustment">scale_adjustment</property>
|
||||
<property name="round-digits">1</property>
|
||||
</object>
|
||||
</child>
|
||||
|
||||
<!--Graph and DashBoard paned-->
|
||||
<child>
|
||||
<object class="GtkPaned" id="graph_dashboard-paned">
|
||||
|
|
|
@ -180,6 +180,46 @@ impl Pipeline {
|
|||
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 {
|
||||
match state {
|
||||
PipelineState::Playing => AppState::Playing,
|
||||
|
|
Loading…
Reference in a new issue