Skip to content
Merged
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
1 change: 0 additions & 1 deletion po/POTFILES
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,3 @@ src/PlaybackManager.vala
src/Views/NowPlayingView.vala
src/Widgets/AlbumImage.vala
src/Widgets/SeekBar.vala
src/Services/M3U.vala
41 changes: 38 additions & 3 deletions src/Application.vala
Original file line number Diff line number Diff line change
Expand Up @@ -163,8 +163,15 @@ public class Music.Application : Gtk.Application {
continue;
}

if ((file_path.ascii_down ().has_suffix (".m3u")) || (file_path.ascii_down ().has_suffix (".m3u8"))) {
foreach (var track in M3U.parse_playlist (file)) {
// Check if the file has M3U suffix: "foo.m3u", "bar.M3U8", etc.
var m3u_suffix = /^.+.m3u8?$/i;
if (m3u_suffix.match (file_path)) {
File[] tracks = M3U.parse_playlist (file);
if (tracks == null) {
continue;
}

foreach (var track in tracks) {
elements += track;
}

Expand Down Expand Up @@ -213,7 +220,35 @@ public class Music.Application : Gtk.Application {
}

private void action_save_m3u_playlist () {
M3U.save_playlist ((MainWindow)active_window, playback_manager.queue_liststore);
var save_dialog = new Gtk.FileDialog () {
initial_name = _("New playlist.m3u")
};

save_dialog.save.begin (active_window, null, (obj, res) => {
File? file;
try {
file = save_dialog.save.end (res);
M3U.save_playlist (playback_manager.queue_liststore, file);
} catch (Error err) {
if (err.matches (Gtk.DialogError.quark (), Gtk.DialogError.DISMISSED)) {
return;
}

warning ("Failed to save playlist: %s", err.message);

var dialog = new Granite.MessageDialog (
_("Couldn't save playlist"),
err.message,
new ThemedIcon ("playlist-queue")
) {
badge_icon = new ThemedIcon ("dialog-error"),
modal = true,
transient_for = active_window
};
dialog.present ();
dialog.response.connect (dialog.destroy);
}
});
}

private void on_bus_acquired (DBusConnection connection, string name) {
Expand Down
75 changes: 28 additions & 47 deletions src/Services/M3U.vala
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
namespace Music.M3U {

// Standard specification here: https://en.wikipedia.org/wiki/M3U
public File[] parse_playlist (File playlist) {
public File[]? parse_playlist (File playlist) {
debug ("Parsing playlist: %s", playlist.get_path ());
File[] list = {};

Expand All @@ -16,71 +16,52 @@ namespace Music.M3U {
string line;

while ((line = dis.read_line ()) != null) {
print ("%s\n", line);
debug ("%s", line);

// Skip extended
// Skip extended
if (line.has_prefix ("#EXT")) {
print ("Skipping EXTM3U: " + line + "\n");

} else {
File target;

if (line.ascii_down ().has_prefix ("file:///")) {
target = File.new_for_uri (line);

//FIXME: URL get skipped.
//} else if (line.ascii_down ().has_prefix ("http")) {
// print ("URL are currently unsupported:" + line + "\n");

} else {
target = File.new_for_path (line);
debug ("Skipping EXTM3U: " + line);
continue;
}

};
File target;

// We do not need to test yet whether files exist
list += target;
if (line.ascii_down ().has_prefix ("file:///")) {
target = File.new_for_uri (line);
//FIXME: URL get skipped.
//} else if (line.ascii_down ().has_prefix ("http")) {
// debug ("URL are currently unsupported:" + line);
} else {
target = File.new_for_path (line);
}
}

// We do not need to test yet whether files exist
list += target;
}
} catch (Error e) {
print ("Error: %s\n", e.message);
warning ("Error: %s", e.message);
return null;
}

return list;

}

public void save_playlist (MainWindow parent, ListStore queue_liststore) {
debug ("Saving queue as playlist" + "\n");
public void save_playlist (ListStore queue_liststore, File playlist) throws Error {
debug ("Saving queue as playlist");
string content = "";

for (var i = 0; i < queue_liststore.n_items; i++) {
var item = (Music.AudioObject)queue_liststore.get_item (i);
content = content + item.uri + "\n";
}

var save_dialog = new Gtk.FileDialog () {
initial_name = _("New playlist.m3u")
};

save_dialog.save.begin (parent, null, (obj, res) => {
try {
var file = save_dialog.save.end (res);
var dostream = new DataOutputStream (
file.replace (
null,
false,
GLib.FileCreateFlags.REPLACE_DESTINATION
)
);

try {
var ostream = playlist.replace (null, false, GLib.FileCreateFlags.REPLACE_DESTINATION);
var dostream = new DataOutputStream (ostream);
dostream.put_string (content);

} catch (Error err) {
warning ("Failed to save file: %s", err.message);
}
});


} catch (Error err) {
warning ("Failed to writing to playlist: %s", err.message);
throw err;
}
}
}