From 1aa6aec9cb8c51bd4e318b039c70567489be868a Mon Sep 17 00:00:00 2001 From: Karim Abou Zeid Date: Fri, 29 Jan 2016 11:57:37 +0100 Subject: [PATCH] Added option to save a playlist as m3u file. --- .../gramophone/helper/M3UConstants.java | 8 ++++ .../gramophone/helper/M3UWriter.java | 42 +++++++++++++++++++ .../helper/menu/PlaylistMenuHelper.java | 37 +++++++++++++++- .../gramophone/util/PlaylistsUtil.java | 8 ++++ app/src/main/res/menu/menu_item_playlist.xml | 8 +++- app/src/main/res/values/strings.xml | 6 +++ 6 files changed, 106 insertions(+), 3 deletions(-) create mode 100644 app/src/main/java/com/kabouzeid/gramophone/helper/M3UConstants.java create mode 100644 app/src/main/java/com/kabouzeid/gramophone/helper/M3UWriter.java diff --git a/app/src/main/java/com/kabouzeid/gramophone/helper/M3UConstants.java b/app/src/main/java/com/kabouzeid/gramophone/helper/M3UConstants.java new file mode 100644 index 00000000..a6c6124f --- /dev/null +++ b/app/src/main/java/com/kabouzeid/gramophone/helper/M3UConstants.java @@ -0,0 +1,8 @@ +package com.kabouzeid.gramophone.helper; + +public interface M3UConstants { + String EXTENSION = "m3u"; + String HEADER = "#EXTM3U"; + String ENTRY = "#EXTINF:"; + String DURATION_SEPARATOR = ","; +} \ No newline at end of file diff --git a/app/src/main/java/com/kabouzeid/gramophone/helper/M3UWriter.java b/app/src/main/java/com/kabouzeid/gramophone/helper/M3UWriter.java new file mode 100644 index 00000000..e15ad94c --- /dev/null +++ b/app/src/main/java/com/kabouzeid/gramophone/helper/M3UWriter.java @@ -0,0 +1,42 @@ +package com.kabouzeid.gramophone.helper; + +import android.content.Context; + +import com.kabouzeid.gramophone.loader.PlaylistSongLoader; +import com.kabouzeid.gramophone.model.Playlist; +import com.kabouzeid.gramophone.model.PlaylistSong; +import com.kabouzeid.gramophone.model.Song; + +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.util.ArrayList; + +public class M3UWriter implements M3UConstants { + public static final String TAG = M3UWriter.class.getSimpleName(); + + public static File write(Context context, File dir, Playlist playlist) throws IOException { + if (!dir.exists()) //noinspection ResultOfMethodCallIgnored + dir.mkdirs(); + File file = new File(dir, playlist.name.concat("." + EXTENSION)); + + ArrayList songs = PlaylistSongLoader.getPlaylistSongList(context, playlist.id); + + if (songs.size() > 0) { + BufferedWriter bw = new BufferedWriter(new FileWriter(file)); + + bw.write(HEADER); + for (Song song : songs) { + bw.newLine(); + bw.write(ENTRY + song.duration + DURATION_SEPARATOR + song.artistName + " - " + song.title); + bw.newLine(); + bw.write(song.data); + } + + bw.close(); + } + + return file; + } +} \ No newline at end of file diff --git a/app/src/main/java/com/kabouzeid/gramophone/helper/menu/PlaylistMenuHelper.java b/app/src/main/java/com/kabouzeid/gramophone/helper/menu/PlaylistMenuHelper.java index 922647cd..6e37b020 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/helper/menu/PlaylistMenuHelper.java +++ b/app/src/main/java/com/kabouzeid/gramophone/helper/menu/PlaylistMenuHelper.java @@ -1,9 +1,13 @@ package com.kabouzeid.gramophone.helper.menu; +import android.annotation.SuppressLint; import android.app.Activity; +import android.content.Context; +import android.os.AsyncTask; import android.support.annotation.NonNull; import android.support.v7.app.AppCompatActivity; import android.view.MenuItem; +import android.widget.Toast; import com.kabouzeid.gramophone.R; import com.kabouzeid.gramophone.dialogs.DeletePlaylistDialog; @@ -13,7 +17,9 @@ import com.kabouzeid.gramophone.loader.PlaylistSongLoader; import com.kabouzeid.gramophone.model.Playlist; import com.kabouzeid.gramophone.model.Song; import com.kabouzeid.gramophone.model.smartplaylist.AbsSmartPlaylist; +import com.kabouzeid.gramophone.util.PlaylistsUtil; +import java.io.IOException; import java.util.ArrayList; /** @@ -22,7 +28,7 @@ import java.util.ArrayList; public class PlaylistMenuHelper { public static final int MENU_RES = R.menu.menu_item_playlist; - public static boolean handleMenuClick(@NonNull AppCompatActivity activity, @NonNull Playlist playlist, @NonNull MenuItem item) { + public static boolean handleMenuClick(@NonNull AppCompatActivity activity, @NonNull final Playlist playlist, @NonNull MenuItem item) { switch (item.getItemId()) { case R.id.action_play: MusicPlayerRemote.openQueue(new ArrayList<>(getPlaylistSongs(activity, playlist)), 0, true); @@ -36,6 +42,35 @@ public class PlaylistMenuHelper { case R.id.action_delete_playlist: DeletePlaylistDialog.create(playlist).show(activity.getSupportFragmentManager(), "DELETE_PLAYLIST"); return true; + case R.id.action_save_playlist: + @SuppressLint("ShowToast") final Toast toast = Toast.makeText(activity, R.string.saving_to_file, Toast.LENGTH_SHORT); + new AsyncTask() { + @Override + protected void onPreExecute() { + super.onPreExecute(); + toast.show(); + } + + @Override + protected String doInBackground(Context... params) { + try { + return String.format(params[0].getString(R.string.saved_playlist_to), PlaylistsUtil.savePlaylist(params[0], playlist)); + } catch (IOException e) { + e.printStackTrace(); + return String.format(params[0].getString(R.string.failed_to_save_playlist), e); + } + } + + @Override + protected void onPostExecute(String string) { + super.onPostExecute(string); + if (toast != null) { + toast.setText(string); + toast.show(); + } + } + }.execute(activity.getApplicationContext()); + return true; } return false; } diff --git a/app/src/main/java/com/kabouzeid/gramophone/util/PlaylistsUtil.java b/app/src/main/java/com/kabouzeid/gramophone/util/PlaylistsUtil.java index bb4a2f9e..0e1f83f3 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/util/PlaylistsUtil.java +++ b/app/src/main/java/com/kabouzeid/gramophone/util/PlaylistsUtil.java @@ -5,6 +5,7 @@ import android.content.ContentValues; import android.content.Context; import android.database.Cursor; import android.net.Uri; +import android.os.Environment; import android.provider.BaseColumns; import android.provider.MediaStore; import android.support.annotation.NonNull; @@ -12,10 +13,13 @@ import android.support.annotation.Nullable; import android.widget.Toast; import com.kabouzeid.gramophone.R; +import com.kabouzeid.gramophone.helper.M3UWriter; import com.kabouzeid.gramophone.model.Playlist; import com.kabouzeid.gramophone.model.PlaylistSong; import com.kabouzeid.gramophone.model.Song; +import java.io.File; +import java.io.IOException; import java.util.ArrayList; import java.util.List; @@ -224,4 +228,8 @@ public class PlaylistsUtil { } return ""; } + + public static File savePlaylist(Context context, Playlist playlist) throws IOException { + return M3UWriter.write(context, new File(Environment.getExternalStorageDirectory(), "Playlists"), playlist); + } } \ No newline at end of file diff --git a/app/src/main/res/menu/menu_item_playlist.xml b/app/src/main/res/menu/menu_item_playlist.xml index b13d1de4..ef1ea9bb 100644 --- a/app/src/main/res/menu/menu_item_playlist.xml +++ b/app/src/main/res/menu/menu_item_playlist.xml @@ -9,8 +9,12 @@ android:title="@string/action_add_to_playing_queue" /> + android:title="@string/action_rename" /> + android:title="@string/action_delete" /> + + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 318a5dd4..c67f077d 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -26,6 +26,8 @@ Tag editor Delete from device Details + Rename + Delete Albums Artists Songs @@ -44,6 +46,7 @@ The title or artist is empty. Writing file Saving changes… + Saving to file… Details File name File path @@ -86,6 +89,7 @@ Delete playlist Delete playlists Clear playlist + Save as file "Add to playlist" Shuffle all Shuffle album @@ -230,4 +234,6 @@ The storage permission is required for Phonograph to read your music library. Library Folders + Saved playlist to %s. + Failed to save playlist (%s).