From 4c5a4b2edc97990fa2a1b844d75b043628e8f102 Mon Sep 17 00:00:00 2001 From: flodavid Date: Sun, 29 Mar 2026 05:05:04 +0200 Subject: [PATCH] Save and restore playback progress - Add progress in seconds to the gschema to save it every 2 seconds --- data/music.gschema.xml | 5 +++++ src/PlaybackManager.vala | 35 +++++++++++++++++++++++++++++++++-- 2 files changed, 38 insertions(+), 2 deletions(-) diff --git a/data/music.gschema.xml b/data/music.gschema.xml index e4ffeab87..bbb08d850 100644 --- a/data/music.gschema.xml +++ b/data/music.gschema.xml @@ -22,6 +22,11 @@ The last song played by Music A string representing the uri of the last played music file + + 0 + Playback progression of the last song played by Music + Number of seconds elapsed since the beginning of the last track that was played + 475 diff --git a/src/PlaybackManager.vala b/src/PlaybackManager.vala index d9c20c76d..8dc303e9e 100644 --- a/src/PlaybackManager.vala +++ b/src/PlaybackManager.vala @@ -42,7 +42,6 @@ public class Music.PlaybackManager : Object { private PlaybackManager () {} construct { - settings = new Settings ("io.elementary.music"); queue_liststore = new ListStore (typeof (AudioObject)); playbin = Gst.ElementFactory.make ("playbin", "playbin"); @@ -87,8 +86,12 @@ public class Music.PlaybackManager : Object { bind_property ("has-items", clear_action, "enabled", SYNC_CREATE); } + public void seek_to_progress_nano_seconds (int64 progress) { + playbin.seek_simple (Gst.Format.TIME, Gst.SeekFlags.FLUSH, progress); + } + public void seek_to_progress (double percent) { - playbin.seek_simple (Gst.Format.TIME, Gst.SeekFlags.FLUSH, (int64)(percent * current_audio.duration)); + seek_to_progress_nano_seconds ((int64)(percent * current_audio.duration)); } // Files[] must not contain any null entries @@ -185,6 +188,13 @@ public class Music.PlaybackManager : Object { playbin.query_position (Gst.Format.TIME, out position); playback_position = position.clamp (0, current_audio.duration); + int playback_position_seconds = (int)(playback_position / 1000000000); + // Save progress every other second, to reduce disk writes + if (playback_position_seconds % 2 == 0) { + debug ("setting progress: " + (playback_position_seconds).to_string () + "s"); + settings.set_int ("progression-last-played", playback_position_seconds); + } + return Source.CONTINUE; }); } else { @@ -380,6 +390,27 @@ public class Music.PlaybackManager : Object { } current_audio = (AudioObject) queue_liststore.get_item (position); + + // Read then restore saved progress + var progression_last_played_seconds = settings.get_int ("progression-last-played"); + if (progression_last_played_seconds > 0) { + int64 progression_last_played = (int64)progression_last_played_seconds * 1000000000; + + // Wait for current_audio.duration to be set by the object responsible for setting it + GLib.Timeout.add (50, () => { + if (current_audio.duration != 0) { + // Do not seek if duration is inferior to seeking position + if (current_audio.duration > progression_last_played) { + info ("saved progress found and valid, restoring it: %i", progression_last_played_seconds); + seek_to_progress_nano_seconds (progression_last_played); + } + return Source.REMOVE; + } + + // Track metadata are not set yet, continue to wait before restoring playback position + return Source.CONTINUE; + }); + } } } }