[gnome-music/wip/jfelder/playlist-export] playlistcontrols: Add a playlist export feature
- From: Jean Felder <jfelder src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-music/wip/jfelder/playlist-export] playlistcontrols: Add a playlist export feature
- Date: Wed, 26 Feb 2020 19:48:23 +0000 (UTC)
commit 151808b98a35003cafcf4df449afc132832851fe
Author: Jean Felder <jfelder src gnome org>
Date: Wed Feb 26 20:33:02 2020 +0100
playlistcontrols: Add a playlist export feature
This allows to export a playlist to an m3u8 file. The export method is
added to the Playlist object in order to create the m3u8 file content
and save it.
data/ui/PlaylistControls.ui | 4 +++
gnomemusic/grilowrappers/grltrackerplaylists.py | 17 ++++++++++
gnomemusic/widgets/playlistcontrols.py | 42 +++++++++++++++++++++++--
3 files changed, 61 insertions(+), 2 deletions(-)
---
diff --git a/data/ui/PlaylistControls.ui b/data/ui/PlaylistControls.ui
index d0db94b0..9591a69d 100644
--- a/data/ui/PlaylistControls.ui
+++ b/data/ui/PlaylistControls.ui
@@ -14,6 +14,10 @@
<attribute name="label" translatable="yes">_Rename…</attribute>
<attribute name="action">win.playlist_rename</attribute>
</item>
+ <item>
+ <attribute name="label" translatable="yes">_Export…</attribute>
+ <attribute name="action">win.playlist_export</attribute>
+ </item>
</menu>
<object class="GtkImage" id="_view_more_image">
<property name="visible">True</property>
diff --git a/gnomemusic/grilowrappers/grltrackerplaylists.py b/gnomemusic/grilowrappers/grltrackerplaylists.py
index f63da4af..f3c507f0 100644
--- a/gnomemusic/grilowrappers/grltrackerplaylists.py
+++ b/gnomemusic/grilowrappers/grltrackerplaylists.py
@@ -690,6 +690,23 @@ class Playlist(GObject.GObject):
query, GLib.PRIORITY_LOW, None, _position_changed_cb,
position)
+ def export(self, playlist_path):
+ """Save playlist to an m3u8 file.
+
+ :param str playlist_path: filename to write playlist content
+ """
+ song_content = ["#EXTINF:{},{} - {}\n{}\n".format(
+ song.props.duration, song.props.artist,
+ song.props.title, song.props.url)
+ for song in self.model]
+ pl_content = "#EXTM3U\n\n" + "\n".join(song_content)
+
+ try:
+ GLib.file_set_contents(playlist_path, pl_content.encode("utf-8"))
+ except GLib.Error as e:
+ self._log.warning(
+ "Unable to save playlist: {}, {}".format(e.domain, e.message))
+
class SmartPlaylist(Playlist):
"""Base class for smart playlists"""
diff --git a/gnomemusic/widgets/playlistcontrols.py b/gnomemusic/widgets/playlistcontrols.py
index f3a9bb81..7a3eeccd 100644
--- a/gnomemusic/widgets/playlistcontrols.py
+++ b/gnomemusic/widgets/playlistcontrols.py
@@ -23,8 +23,9 @@
# delete this exception statement from your version.
import gettext
+from gettext import gettext as _
-from gi.repository import Gdk, GObject, Gio, Gtk
+from gi.repository import Gdk, GLib, GObject, Gio, Gtk
from gnomemusic.grilowrappers.grltrackerplaylists import Playlist
from gnomemusic.widgets.notificationspopup import PlaylistNotification
@@ -59,6 +60,9 @@ class PlaylistControls(Gtk.Grid):
self._rename_action = Gio.SimpleAction.new("playlist_rename", None)
self._rename_action.connect("activate", self._on_rename_action)
+ self._export_action = Gio.SimpleAction.new("playlist_export", None)
+ self._export_action.connect("activate", self._on_export_action)
+
# FIXME: This is a workaround for not being able to pass the application
# object via init when using Gtk.Builder.
@GObject.Property(default=None)
@@ -87,6 +91,38 @@ class PlaylistControls(Gtk.Grid):
self._window.add_action(self._delete_action)
self._window.add_action(self._play_action)
self._window.add_action(self._rename_action)
+ self._window.add_action(self._export_action)
+
+ def _on_export_action(self, action, parameter):
+ export_dialog = Gtk.FileChooserDialog(
+ _("Save Playlist"), self._window, Gtk.FileChooserAction.SAVE,
+ (Gtk.STOCK_CANCEL, Gtk.ResponseType.CANCEL,
+ Gtk.STOCK_SAVE, Gtk.ResponseType.ACCEPT))
+ export_dialog.props.modal = True
+
+ pl_name = self.props.playlist.props.title
+ export_dialog.set_current_name("{}.m3u8".format(pl_name))
+ music_dir = GLib.get_user_special_dir(
+ GLib.UserDirectory.DIRECTORY_MUSIC)
+ export_dialog.set_current_folder_uri(GLib.filename_to_uri(music_dir))
+ export_dialog.set_do_overwrite_confirmation(True)
+
+ filter_pl = Gtk.FileFilter()
+ filter_pl.set_name(_("Playlists"))
+ filter_pl.add_mime_type("audio/x-mpegurl")
+ filter_pl.add_mime_type("audio/mpegurl")
+ export_dialog.add_filter(filter_pl)
+
+ filter_any = Gtk.FileFilter()
+ filter_any.set_name(_("Any files"))
+ filter_any.add_pattern("*")
+ export_dialog.add_filter(filter_any)
+
+ if export_dialog.run() == Gtk.ResponseType.ACCEPT:
+ pl_filename = export_dialog.get_filename()
+ self.props.playlist.export(pl_filename)
+
+ export_dialog.destroy()
def _on_rename_action(self, menuitem, data=None):
self._enable_rename_playlist(self.props.playlist)
@@ -129,7 +165,9 @@ class PlaylistControls(Gtk.Grid):
"{} Song", "{} Songs", self.props.playlist.count).format(
self.props.playlist.count)
- self._play_action.props.enabled = self.props.playlist.props.count > 0
+ not_empty = self.props.playlist.props.count > 0
+ self._play_action.props.enabled = not_empty
+ self._export_action.props.enabled = not_empty
def _enable_rename_playlist(self, pl_torename):
"""Enables rename button and entry
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]