mirror of
				https://github.com/johrpan/musicus.git
				synced 2025-10-26 11:47:25 +01:00 
			
		
		
		
	playerbar: Improve seeking
This commit is contained in:
		
							parent
							
								
									0d0d8e668f
								
							
						
					
					
						commit
						e4940d693b
					
				
					 2 changed files with 62 additions and 51 deletions
				
			
		|  | @ -33,9 +33,7 @@ mod imp { | ||||||
|         #[property(get, set)] |         #[property(get, set)] | ||||||
|         pub duration_ms: Cell<u64>, |         pub duration_ms: Cell<u64>, | ||||||
|         #[property(get, set)] |         #[property(get, set)] | ||||||
|         pub current_time_ms: Cell<u64>, |         pub position_ms: Cell<u64>, | ||||||
|         #[property(get, set = Self::set_position)] |  | ||||||
|         pub position: Cell<f64>, |  | ||||||
|         #[property(get, construct_only)] |         #[property(get, construct_only)] | ||||||
|         pub player: OnceCell<gstreamer_player::Player>, |         pub player: OnceCell<gstreamer_player::Player>, | ||||||
| 
 | 
 | ||||||
|  | @ -74,15 +72,6 @@ mod imp { | ||||||
|                 item.set_is_playing(true); |                 item.set_is_playing(true); | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
| 
 |  | ||||||
|         pub fn set_position(&self, position: f64) { |  | ||||||
|             self.player |  | ||||||
|                 .get() |  | ||||||
|                 .unwrap() |  | ||||||
|                 .seek(gst::ClockTime::from_mseconds( |  | ||||||
|                     (position * self.duration_ms.get() as f64) as u64, |  | ||||||
|                 )); |  | ||||||
|         } |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     #[glib::object_subclass] |     #[glib::object_subclass] | ||||||
|  | @ -140,23 +129,11 @@ mod imp { | ||||||
|             }); |             }); | ||||||
| 
 | 
 | ||||||
|             let obj = Fragile::new(self.obj().to_owned()); |             let obj = Fragile::new(self.obj().to_owned()); | ||||||
|             player.connect_position_updated(move |_, current_time| { |             player.connect_position_updated(move |_, position| { | ||||||
|                 if let Some(current_time) = current_time { |                 if let Some(position) = position { | ||||||
|                     let obj = obj.get(); |                     let obj = obj.get(); | ||||||
|                     let imp = obj.imp(); |                     obj.imp().position_ms.set(position.mseconds()); | ||||||
| 
 |                     obj.notify_position_ms(); | ||||||
|                     let current_time_ms = current_time.mseconds(); |  | ||||||
|                     let duration_ms = imp.duration_ms.get(); |  | ||||||
|                     let mut position = current_time_ms as f64 / duration_ms as f64; |  | ||||||
|                     if position > 1.0 { |  | ||||||
|                         position = 1.0 |  | ||||||
|                     } |  | ||||||
| 
 |  | ||||||
|                     imp.current_time_ms.set(current_time_ms); |  | ||||||
|                     obj.notify_current_time_ms(); |  | ||||||
| 
 |  | ||||||
|                     imp.position.set(position); |  | ||||||
|                     obj.notify_position(); |  | ||||||
|                 } |                 } | ||||||
|             }); |             }); | ||||||
| 
 | 
 | ||||||
|  | @ -166,16 +143,11 @@ mod imp { | ||||||
|                     let obj = obj.get(); |                     let obj = obj.get(); | ||||||
|                     let imp = obj.imp(); |                     let imp = obj.imp(); | ||||||
|                     
 |                     
 | ||||||
|                     let duration_ms = duration.mseconds(); |                     imp.position_ms.set(0); | ||||||
|  |                     obj.notify_position_ms(); | ||||||
|                     
 |                     
 | ||||||
|                     imp.duration_ms.set(duration_ms); |                     imp.duration_ms.set(duration.mseconds()); | ||||||
|                     obj.notify_duration_ms(); |                     obj.notify_duration_ms(); | ||||||
| 
 |  | ||||||
|                     imp.current_time_ms.set(0); |  | ||||||
|                     obj.notify_current_time_ms(); |  | ||||||
| 
 |  | ||||||
|                     imp.position.set(0.0); |  | ||||||
|                     obj.notify_position(); |  | ||||||
|                 } |                 } | ||||||
|             }); |             }); | ||||||
|         } |         } | ||||||
|  | @ -200,9 +172,8 @@ impl MusicusPlayer { | ||||||
|             .property("playing", false) |             .property("playing", false) | ||||||
|             .property("playlist", gio::ListStore::new::<PlaylistItem>()) |             .property("playlist", gio::ListStore::new::<PlaylistItem>()) | ||||||
|             .property("current-index", 0u32) |             .property("current-index", 0u32) | ||||||
|             .property("current-time-ms", 0u64) |             .property("position-ms", 0u64) | ||||||
|             .property("duration-ms", 60_000u64) |             .property("duration-ms", 60_000u64) | ||||||
|             .property("position", 0.0) |  | ||||||
|             .property("player", player) |             .property("player", player) | ||||||
|             .build() |             .build() | ||||||
|     } |     } | ||||||
|  | @ -257,6 +228,10 @@ impl MusicusPlayer { | ||||||
|             .set_playback_status(PlaybackStatus::Paused); |             .set_playback_status(PlaybackStatus::Paused); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     pub fn seek_to(&self, time_ms: u64) { | ||||||
|  |         self.player().seek(gst::ClockTime::from_mseconds(time_ms)); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     pub fn current_item(&self) -> Option<PlaylistItem> { |     pub fn current_item(&self) -> Option<PlaylistItem> { | ||||||
|         let imp = self.imp(); |         let imp = self.imp(); | ||||||
|         imp.playlist |         imp.playlist | ||||||
|  |  | ||||||
|  | @ -1,11 +1,12 @@ | ||||||
| use crate::player::MusicusPlayer; | use crate::player::MusicusPlayer; | ||||||
| use gtk::{ | use gtk::{ | ||||||
|  |     gdk, | ||||||
|     glib::{self, clone, subclass::Signal, Properties}, |     glib::{self, clone, subclass::Signal, Properties}, | ||||||
|     prelude::*, |     prelude::*, | ||||||
|     subclass::prelude::*, |     subclass::prelude::*, | ||||||
| }; | }; | ||||||
| use once_cell::sync::Lazy; | use once_cell::sync::Lazy; | ||||||
| use std::cell::RefCell; | use std::cell::{Cell, RefCell}; | ||||||
| 
 | 
 | ||||||
| mod imp { | mod imp { | ||||||
|     use super::*; |     use super::*; | ||||||
|  | @ -17,6 +18,8 @@ mod imp { | ||||||
|         #[property(get, construct_only)] |         #[property(get, construct_only)] | ||||||
|         pub player: RefCell<MusicusPlayer>, |         pub player: RefCell<MusicusPlayer>, | ||||||
| 
 | 
 | ||||||
|  |         pub seeking: Cell<bool>, | ||||||
|  | 
 | ||||||
|         #[template_child] |         #[template_child] | ||||||
|         pub title_label: TemplateChild<gtk::Label>, |         pub title_label: TemplateChild<gtk::Label>, | ||||||
|         #[template_child] |         #[template_child] | ||||||
|  | @ -54,13 +57,22 @@ mod imp { | ||||||
|         fn update_time(&self) { |         fn update_time(&self) { | ||||||
|             let player = self.player.borrow(); |             let player = self.player.borrow(); | ||||||
| 
 | 
 | ||||||
|  |             let current_time_ms = if self.seeking.get() { | ||||||
|  |                 (self.slider.value() * player.duration_ms() as f64) as u64 | ||||||
|  |             } else { | ||||||
|  |                 let current_time_ms = player.position_ms(); | ||||||
|  |                 self.slider | ||||||
|  |                     .set_value(current_time_ms as f64 / player.duration_ms() as f64); | ||||||
|  |                 current_time_ms | ||||||
|  |             }; | ||||||
|  | 
 | ||||||
|             self.current_time_label |             self.current_time_label | ||||||
|                 .set_label(&format_time(player.current_time_ms())); |                 .set_label(&format_time(current_time_ms)); | ||||||
| 
 | 
 | ||||||
|             self.remaining_time_label.set_label(&format_time( |             self.remaining_time_label.set_label(&format_time( | ||||||
|                 player |                 player | ||||||
|                     .duration_ms() |                     .duration_ms() | ||||||
|                     .checked_sub(player.current_time_ms()) |                     .checked_sub(current_time_ms) | ||||||
|                     .unwrap_or(0), |                     .unwrap_or(0), | ||||||
|             )); |             )); | ||||||
|         } |         } | ||||||
|  | @ -120,17 +132,41 @@ mod imp { | ||||||
|                 clone!(@weak obj => move |_, _, _, _| obj.imp().update_item()), |                 clone!(@weak obj => move |_, _, _, _| obj.imp().update_item()), | ||||||
|             ); |             ); | ||||||
| 
 | 
 | ||||||
|             player.connect_current_time_ms_notify( |             player | ||||||
|                 clone!(@weak obj => move |_| obj.imp().update_time()), |                 .connect_position_ms_notify(clone!(@weak obj => move |_| obj.imp().update_time())); | ||||||
|             ); |  | ||||||
|             player |             player | ||||||
|                 .connect_duration_ms_notify(clone!(@weak obj => move |_| obj.imp().update_time())); |                 .connect_duration_ms_notify(clone!(@weak obj => move |_| obj.imp().update_time())); | ||||||
| 
 | 
 | ||||||
|             player |             let seeking_controller = gtk::EventControllerLegacy::new(); | ||||||
|                 .bind_property("position", &self.slider.adjustment(), "value") | 
 | ||||||
|                 .sync_create() |             seeking_controller.connect_event( | ||||||
|                 .bidirectional() |                 clone!(@weak obj => @default-return glib::Propagation::Proceed, move |_, event| { | ||||||
|                 .build(); |                     if let Some(event) = event.downcast_ref::<gdk::ButtonEvent>() { | ||||||
|  |                         let imp = obj.imp(); | ||||||
|  |                         if event.button() == gdk::BUTTON_PRIMARY { | ||||||
|  |                             match event.event_type() { | ||||||
|  |                                 gdk::EventType::ButtonPress => { | ||||||
|  |                                     imp.seeking.set(true); | ||||||
|  |                                 } | ||||||
|  |                                 gdk::EventType::ButtonRelease => { | ||||||
|  |                                     let player = obj.player(); | ||||||
|  |                                     player.seek_to((imp.slider.value() * player.duration_ms() as f64) as u64); | ||||||
|  |                                     imp.seeking.set(false); | ||||||
|  |                                 } | ||||||
|  |                                 _ => (), | ||||||
|  |                             } | ||||||
|  |                         } | ||||||
|  | 
 | ||||||
|  |                     } | ||||||
|  | 
 | ||||||
|  |                     glib::Propagation::Proceed | ||||||
|  |                 }), | ||||||
|  |             ); | ||||||
|  | 
 | ||||||
|  |             self.slider.add_controller(seeking_controller); | ||||||
|  | 
 | ||||||
|  |             self.slider | ||||||
|  |                 .connect_value_changed(clone!(@weak obj => move |_| obj.imp().update_time())); | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue