diff --git a/src/playbin.vala b/src/playbin.vala index f789bba..0d4a9bc 100644 --- a/src/playbin.vala +++ b/src/playbin.vala @@ -166,6 +166,10 @@ class Playbin : GLib.Object { assert (this.playbin.query_duration (Gst.Format.TIME, out duration)); this.duration = duration; + // cancel any queued seeks + this.queued_seek = -1; + this.update_position = true; + this.position = 0; bool continues = this.next_gapless; @@ -202,7 +206,17 @@ class Playbin : GLib.Object { Gst.State new_state; message.parse_state_changed (null, out new_state, null); - this.update_position = new_state == Gst.State.PLAYING; + if (new_state == Gst.State.PLAYING) { + if (queued_seek != -1) { + if (this.playbin.seek_simple (Gst.Format.TIME, Gst.SeekFlags.FLUSH | Gst.SeekFlags.ACCURATE, this.queued_seek)) { + this.queued_seek = -1; + } else { + warning ("could not reapply queued seek after state changed changed to playing, retrying later"); + } + } else { + this.update_position = true; + } + } }); bus.message["eos"].connect ((message) => { @@ -210,9 +224,14 @@ class Playbin : GLib.Object { }); } + private int64 queued_seek = -1; + public void seek (int64 position) { + this.position = position; + this.update_position = false; if (!this.playbin.seek_simple (Gst.Format.TIME, Gst.SeekFlags.FLUSH | Gst.SeekFlags.ACCURATE, position)) { - warning ("could not seek"); + // try to queue this seek for later + queued_seek = position; } } diff --git a/src/ui/window.blp b/src/ui/window.blp index af97d78..3bf3376 100644 --- a/src/ui/window.blp +++ b/src/ui/window.blp @@ -136,7 +136,7 @@ template $UiWindow: Adw.ApplicationWindow { "numeric", ] - label: bind $format_timestamp (template.position) as ; + label: bind $format_timestamp (template.playbin as <$Playbin>.position) as ; } [center] @@ -148,7 +148,7 @@ template $UiWindow: Adw.ApplicationWindow { adjustment: Adjustment { lower: 0; - value: bind template.position; + value: bind template.playbin as <$Playbin>.position; upper: bind template.playbin as <$Playbin>.duration; }; diff --git a/src/ui/window.vala b/src/ui/window.vala index 862670a..b0dcba6 100644 --- a/src/ui/window.vala +++ b/src/ui/window.vala @@ -10,8 +10,6 @@ class Ui.Window : Adw.ApplicationWindow { private Setup setup; private Subsonic.Client api; - - public int64 position { get; private set; } public double volume { get { return this.playbin.volume; } @@ -114,13 +112,6 @@ class Ui.Window : Adw.ApplicationWindow { }); } }); - - this.playbin.notify["position"].connect (() => { - // only set if we aren't seeking - if (this.seek_timeout_id == 0) { - this.position = this.playbin.position; - } - }); } [GtkCallback] private void on_sidebar_row_activated (Gtk.ListBoxRow row) { @@ -137,22 +128,9 @@ class Ui.Window : Adw.ApplicationWindow { int s = (int) (ns / Gst.SECOND); return "%02d:%02d".printf (s/60, s%60); } - - private void seek_impl (int64 position) { - this.position = position; - if (this.seek_timeout_id == 0) { - this.seek_timeout_id = Timeout.add (500, () => { - playbin.seek(this.position); - this.seek_timeout_id = 0; - return false; - }); - } - } - // same timeout logic as https://code.videolan.org/videolan/npapi-vlc/blob/6eae0ffb9cbaf8f6e04423de2ff38daabdf7cae3/npapi/vlcplugin_gtk.cpp#L312 - private uint seek_timeout_id = 0; [GtkCallback] private bool on_play_position_seek (Gtk.Range range, Gtk.ScrollType scroll_type, double value) { - this.seek_impl((int64) value); + this.playbin.seek ((int64) value); return false; } @@ -202,16 +180,16 @@ class Ui.Window : Adw.ApplicationWindow { [GtkCallback] private void seek_backward () { // 10 seconds - int64 new_position = position - 10 * Gst.SECOND; + int64 new_position = playbin.position - 10 * Gst.SECOND; if (new_position < 0) new_position = 0; - this.seek_impl (new_position); + this.playbin.seek (new_position); } [GtkCallback] private void seek_forward () { // 10 seconds - int64 new_position = position + 10 * Gst.SECOND; + int64 new_position = playbin.position + 10 * Gst.SECOND; if (new_position > this.playbin.duration) new_position = this.playbin.duration; - this.seek_impl (new_position); + this.playbin.seek (new_position); } [GtkCallback] private string song_title (Subsonic.Song? song) {