Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions data/music.gschema.xml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,16 @@
<summary>An index representing the repeat mode</summary>
<description>An index representing the repeat mode</description>
</key>
<key type="as" name="previous-queue">
<default>['']</default>
<summary>The queue from last session to restore</summary>
<description>An array of strings representing the files played last</description>
</key>
<key type="s" name="uri-last-played">
<default>''</default>
<summary>The item that was playing when the user closed Music</summary>
<description>A string representing the uri of the last played music file</description>
</key>

<key name="window-height" type="i">
<default>475</default>
Expand Down
11 changes: 11 additions & 0 deletions src/Application.vala
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,17 @@ public class Music.Application : Gtk.Application {
}

settings.bind ("window-maximized", main_window, "maximized", SettingsBindFlags.SET);

// Restoring the queue overwrites the last played. So we need to retrieve it before
var? uri_last_played = settings.get_string ("uri-last-played");

// This needs to be done after window is constructed
// Else music plays but the queue seems empty
PlaybackManager.get_default ().restore_queue ();

settings.set_string ("uri-last-played", uri_last_played);
PlaybackManager.get_default ().restore_last_played ();
Comment on lines +123 to +126
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is there a reason to have this be two separate functions? We always want to restore both the previous queue and the previously played audio right?

Copy link
Copy Markdown
Contributor Author

@teamcons teamcons May 28, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No
If the user double-click on a music file with the app closed, they want to play it - not play last week's track

restoring previous queue without previous played makes sense in this case, before adding the new track, but the expected behaviour is not to play another totally unrelated track.
this is kind of a problem introduced by restoring sessions, because before the queue would have always been empty, unless the app was already started

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh yeah that makes sense. Thanks for clarifying!


}

private static File[] list_directory (string directory) {
Expand Down
98 changes: 70 additions & 28 deletions src/PlaybackManager.vala
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ 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");
Expand All @@ -54,35 +56,9 @@ public class Music.PlaybackManager : Object {
critical ("Unable to start Gstreamer Discoverer: %s", e.message);
}

queue_liststore.items_changed.connect (() => {
var shuffle_action_action = (SimpleAction) GLib.Application.get_default ().lookup_action (Application.ACTION_SHUFFLE);
has_items = queue_liststore.get_n_items () > 0;
shuffle_action_action.set_enabled (queue_liststore.get_n_items () > 1);
update_next_previous_sensitivity ();
});

notify["current-audio"].connect (() => {
playbin.set_state (Gst.State.NULL);
if (current_audio != null) {
playbin.uri = current_audio.uri;
playbin.set_state (Gst.State.PLAYING);
} else {
playbin.uri = "";
playback_position = 0;

if (progress_timer != 0) {
Source.remove (progress_timer);
progress_timer = 0;
}
}
queue_liststore.items_changed.connect (on_items_changed);

update_next_previous_sensitivity ();

var play_pause_action = (SimpleAction) GLib.Application.get_default ().lookup_action (Application.ACTION_PLAY_PAUSE);
play_pause_action.set_enabled (current_audio != null);
});

settings = new Settings ("io.elementary.music");
notify["current-audio"].connect (on_audio_changed);
}

public void seek_to_progress (double percent) {
Expand Down Expand Up @@ -451,4 +427,70 @@ public class Music.PlaybackManager : Object {

return pix;
}

public void restore_queue () {
var last_session_uri = settings.get_strv ("previous-queue");
var last_session_files = new File[last_session_uri.length];

for (var i = 0; i < last_session_uri.length; i++) {
var uri = last_session_uri[i];
var file = File.new_for_uri (uri);
last_session_files[i] = file;
}

var files_to_play = Application.loop_through_files (last_session_files);
queue_files (files_to_play);
}

public void restore_last_played () {
var? uri_last_played = settings.get_string ("uri-last-played");
var file_last_played = File.new_for_uri (uri_last_played);

if (( uri_last_played != "" ) && (file_last_played.query_exists ())) {
uint position = -1;
var audio_object = new AudioObject (uri_last_played);
queue_liststore.find (audio_object, out position);
current_audio = (AudioObject) queue_liststore.get_item (position);
}
}

private void on_items_changed () {
var shuffle_action_action = (SimpleAction) GLib.Application.get_default ().lookup_action (Application.ACTION_SHUFFLE);
has_items = queue_liststore.get_n_items () > 0;
shuffle_action_action.set_enabled (queue_liststore.get_n_items () > 1);
update_next_previous_sensitivity ();

// Save current queue in gsettings
string[] list_uri = new string[queue_liststore.n_items];

for (var i = 0; i < queue_liststore.n_items; i++) {
var item = (Music.AudioObject)queue_liststore.get_item (i);
list_uri[i] = item.uri;
}

settings.set_strv ("previous-queue", list_uri);
}

private void on_audio_changed () {
playbin.set_state (Gst.State.NULL);
if (current_audio != null) {
playbin.uri = current_audio.uri;
playbin.set_state (Gst.State.PLAYING);
} else {
playbin.uri = "";
playback_position = 0;

if (progress_timer != 0) {
Source.remove (progress_timer);
progress_timer = 0;
}
}

update_next_previous_sensitivity ();

var play_pause_action = (SimpleAction) GLib.Application.get_default ().lookup_action (Application.ACTION_PLAY_PAUSE);
play_pause_action.set_enabled (current_audio != null);

settings.set_string ("uri-last-played", current_audio.uri);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shouldn't we just bind this instead of getting and setting in different places?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"uri-last-played" gets overwritten before being used. But apart from that, yes i suppose, but do not forget this is a draft - i want first to have something that works (im failing at it), before making it clean.

}
}