/* * Copyright (C) 2014 Fastboot Mobile, LLC. * * This program is free software; you can redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; either version 3 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See * the GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along with this program; * if not, see <http://www.gnu.org/licenses>. */ package com.fastbootmobile.encore.app.fragments; import android.app.AlertDialog; import android.app.Dialog; import android.content.DialogInterface; import android.os.Bundle; import android.support.annotation.NonNull; import android.support.v4.app.DialogFragment; import android.util.Log; import android.widget.Toast; import com.fastbootmobile.encore.app.R; import com.fastbootmobile.encore.framework.PluginsLookup; import com.fastbootmobile.encore.model.Album; import com.fastbootmobile.encore.model.BoundEntity; import com.fastbootmobile.encore.model.Playlist; import com.fastbootmobile.encore.model.Song; import com.fastbootmobile.encore.providers.IMusicProvider; import com.fastbootmobile.encore.providers.ProviderAggregator; import com.fastbootmobile.encore.providers.ProviderConnection; import com.fastbootmobile.encore.providers.ProviderIdentifier; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.Iterator; import java.util.List; /** * Dialog fragment allowing the user to select a playlist to which add a song or an album */ public class PlaylistChooserFragment extends DialogFragment { private static final String TAG = "PlaylistChooserFragment"; private static final String KEY_SONG = "song"; private static final String KEY_ALBUM = "album"; private static final String KEY_PLAYLIST = "playlist"; private Song mSong; private Album mAlbum; private Playlist mPlaylist; /** * Creates the fragment in the perspective of adding a song to a playlist * @param song The song to add * @return The fragment generated */ public static PlaylistChooserFragment newInstance(Song song) { PlaylistChooserFragment fragment = new PlaylistChooserFragment(); Bundle bundle = new Bundle(); bundle.putParcelable(KEY_SONG, song); fragment.setArguments(bundle); return fragment; } /** * Creates the fragment in the perspective of adding an album to a playlist * @param album The album of which tracks will be added * @return The fragment generated */ public static PlaylistChooserFragment newInstance(Album album) { PlaylistChooserFragment fragment = new PlaylistChooserFragment(); Bundle bundle = new Bundle(); bundle.putParcelable(KEY_ALBUM, album); fragment.setArguments(bundle); return fragment; } /** * Creates the fragment in the perspective of appending a playlist to another one * @param playlist The playlist that should be appended to the selection * @return The fragment generated */ public static PlaylistChooserFragment newInstance(Playlist playlist) { PlaylistChooserFragment fragment = new PlaylistChooserFragment(); Bundle bundle = new Bundle(); bundle.putParcelable(KEY_PLAYLIST, playlist); fragment.setArguments(bundle); return fragment; } @Override public void onCreate(Bundle savedInstance) { super.onCreate(savedInstance); Bundle args = getArguments(); if (args == null) { throw new IllegalArgumentException("This fragment requires a song or album"); } // Get the cached entity to have updated copy final ProviderAggregator aggregator = ProviderAggregator.getDefault(); if (args.containsKey(KEY_SONG)) { mSong = args.getParcelable(KEY_SONG); mSong = aggregator.retrieveSong(mSong.getRef(), mSong.getProvider()); } else if (args.containsKey(KEY_ALBUM)) { mAlbum = args.getParcelable(KEY_ALBUM); mAlbum = aggregator.retrieveAlbum(mAlbum.getRef(), mAlbum.getProvider()); } else if (args.containsKey(KEY_PLAYLIST)) { mPlaylist = args.getParcelable(KEY_PLAYLIST); mPlaylist = aggregator.retrievePlaylist(mPlaylist.getRef(), mPlaylist.getProvider()); } else { throw new IllegalArgumentException("No song, album or playlist parameters were found"); } } @NonNull @Override public Dialog onCreateDialog(Bundle savedInstance) { AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); final ProviderAggregator aggregator = ProviderAggregator.getDefault(); // Get and sort the playlists available List<Playlist> playlistList = aggregator.getAllPlaylists(); Collections.sort(playlistList, new Comparator<Playlist>() { @Override public int compare(Playlist lhs, Playlist rhs) { if (lhs.getName() != null && rhs.getName() != null) { return lhs.getName().compareTo(rhs.getName()); } else if (lhs.getName() == null && rhs.getName() == null) { return 0; } else if (lhs.getName() == null) { return 1; } else { return -1; } } }); List<String> choices = new ArrayList<>(); choices.add(getString(R.string.new_playlist)); final List<Playlist> playlistChoices = new ArrayList<>(); final ProviderConnection mppp = PluginsLookup.getDefault().getMultiProviderPlaylistProvider(); // Decide what entity we are using BoundEntity ent; if (mSong != null) { ent = mSong; } else if (mAlbum != null) { ent = mAlbum; } else if (mPlaylist != null) { ent = mPlaylist; } else { Log.e(TAG, "No entity attached for source checking!"); builder.setTitle(getString(R.string.add_to)); return builder.create(); } for (Playlist playlist : playlistList) { ProviderIdentifier providerIdentifier = playlist.getProvider(); // Allow adding to a playlist from the same provider, or from the MultiProvider if (ent.getProvider().equals(providerIdentifier) || mppp.getIdentifier().equals(providerIdentifier)) { String decoration = ""; choices.add(playlist.getName() + decoration); playlistChoices.add(playlist); } } builder.setTitle(getString(R.string.add_to)) .setItems(choices.toArray(new String[choices.size()]), new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { if (which == 0) { NewPlaylistFragment fragment; String ref; if (mSong != null) { fragment = NewPlaylistFragment.newInstance(mSong); ref = mSong.getRef(); } else if (mAlbum != null) { fragment = NewPlaylistFragment.newInstance(mAlbum); ref = mAlbum.getRef(); } else if (mPlaylist != null) { fragment = NewPlaylistFragment.newInstance(mPlaylist); ref = mPlaylist.getRef(); } else { throw new RuntimeException("Shouldn't be here"); } fragment.show(getFragmentManager(), ref + "-newplaylist"); } else { final Playlist playlistChosen = playlistChoices.get(which - 1); ProviderIdentifier playlistChosenId = aggregator.getCache().getRefProvider(playlistChosen.getRef()); try { final IMusicProvider provider = PluginsLookup.getDefault().getProvider(playlistChosenId).getBinder(); int totalCount = 0; int successCount = 0; if (mSong != null) { ++totalCount; if (provider.addSongToPlaylist(mSong.getRef(), playlistChosen.getRef(), mSong.getProvider())) { ++successCount; } } else if (mAlbum != null) { Iterator<String> songs = mAlbum.songs(); while (songs.hasNext()) { if (provider.addSongToPlaylist(songs.next(), playlistChosen.getRef(), mAlbum.getProvider())) { ++successCount; } ++totalCount; } } else if (mPlaylist != null) { Iterator<String> songs = mPlaylist.songs(); while (songs.hasNext()) { // TODO: This might cause issues if we add a playlist // from a multi-provider playlist to another one ++totalCount; if (provider.addSongToPlaylist(songs.next(), playlistChosen.getRef(), mPlaylist.getProvider())) { ++successCount; } } } if (totalCount == successCount) { Toast.makeText(getActivity(), getString(R.string.toast_playlist_track_add_success, successCount, playlistChosen.getName()), Toast.LENGTH_SHORT).show(); } else if (successCount > 0) { Toast.makeText(getActivity(), getString(R.string.toast_playlist_track_add_partial, successCount, totalCount, playlistChosen.getName()), Toast.LENGTH_SHORT).show(); } else { Toast.makeText(getActivity(), getString(R.string.toast_playlist_track_add_error, playlistChosen.getName()), Toast.LENGTH_SHORT).show(); } } catch (Exception e) { Log.e(TAG, "Unable to add to playlist", e); Toast.makeText(getActivity(), getString(R.string.toast_playlist_track_add_error, playlistChosen.getName()), Toast.LENGTH_SHORT).show(); } } } }); return builder.create(); } }