diff --git a/.idea/gradle.xml b/.idea/gradle.xml index db835c9430..a63673e627 100644 --- a/.idea/gradle.xml +++ b/.idea/gradle.xml @@ -3,8 +3,9 @@ diff --git a/JMPDComm/src/main/java/org/a0z/mpd/MPD.java b/JMPDComm/src/main/java/org/a0z/mpd/MPD.java index 7fab1c89b4..635383b24e 100644 --- a/JMPDComm/src/main/java/org/a0z/mpd/MPD.java +++ b/JMPDComm/src/main/java/org/a0z/mpd/MPD.java @@ -113,44 +113,36 @@ public MPD(final String server, final int port, final String password) connect(server, port, password); } - private static MPDCommand getAlbumDetailsCommand(final Album album) { + private static String[] getAlbumArtistPair(final Album album) { final Artist artist = album.getArtist(); - String artistCommand = null; - String artistName = null; - - if (artist != null) { - artistName = artist.getName(); + final String[] artistPair; + if (artist == null) { + artistPair = new String[]{null, null}; + } else { if (album.hasAlbumArtist()) { - artistCommand = MPDCommand.MPD_TAG_ALBUM_ARTIST; + artistPair = new String[]{MPDCommand.MPD_TAG_ALBUM_ARTIST, artist.getName()}; } else { - artistCommand = MPDCommand.MPD_FIND_ARTIST; + artistPair = new String[]{MPDCommand.MPD_TAG_ARTIST, artist.getName()}; } } + return artistPair; + } + + private static MPDCommand getAlbumDetailsCommand(final Album album) { + final String[] artistPair = getAlbumArtistPair(album); + return new MPDCommand(MPDCommand.MPD_CMD_COUNT, MPDCommand.MPD_TAG_ALBUM, album.getName(), - artistCommand, artistName); + artistPair[0], artistPair[1]); } private static MPDCommand getSongsCommand(final Album album) { - final String albumName = album.getName(); - final Artist artist = album.getArtist(); - String artistName = null; - String artistCommand = null; + final String[] artistPair = getAlbumArtistPair(album); - if (artist != null) { - artistName = artist.getName(); - - if (album.hasAlbumArtist()) { - artistCommand = MPDCommand.MPD_TAG_ALBUM_ARTIST; - } else { - artistCommand = MPDCommand.MPD_TAG_ARTIST; - } - } - - return new MPDCommand(MPDCommand.MPD_CMD_FIND, MPDCommand.MPD_TAG_ALBUM, albumName, - artistCommand, artistName); + return new MPDCommand(MPDCommand.MPD_CMD_FIND, MPDCommand.MPD_TAG_ALBUM, album.getName(), + artistPair[0], artistPair[1]); } /* @@ -213,8 +205,20 @@ public void add(final Album album) throws IOException, MPDException { */ public void add(final Album album, final boolean replace, final boolean play) throws IOException, MPDException { - final List songs = getSongs(album); - final CommandQueue commandQueue = MPDPlaylist.addAllCommand(songs); + final CommandQueue commandQueue; + + if (isCommandAvailable(MPDCommand.MPD_CMD_FIND_ADD)) { + final String[] artistPair = getAlbumArtistPair(album); + + commandQueue = new CommandQueue(); + + commandQueue + .add(MPDCommand.MPD_CMD_FIND_ADD, MPDCommand.MPD_TAG_ALBUM, album.getName(), + artistPair[0], artistPair[1]); + } else { + final List songs = getSongs(album); + commandQueue = MPDPlaylist.addAllCommand(songs); + } add(commandQueue, replace, play); } @@ -241,8 +245,17 @@ public void add(final Artist artist) throws IOException, MPDException { */ public void add(final Artist artist, final boolean replace, final boolean play) throws IOException, MPDException { - final List songs = getSongs(artist); - final CommandQueue commandQueue = MPDPlaylist.addAllCommand(songs); + final CommandQueue commandQueue; + + if (isCommandAvailable(MPDCommand.MPD_CMD_FIND_ADD)) { + commandQueue = new CommandQueue(); + + commandQueue + .add(MPDCommand.MPD_CMD_FIND_ADD, MPDCommand.MPD_TAG_ARTIST, artist.getName()); + } else { + final List songs = getSongs(artist); + commandQueue = MPDPlaylist.addAllCommand(songs); + } add(commandQueue, replace, play); } @@ -261,7 +274,11 @@ public void add(final FilesystemTreeEntry music, final boolean replace, final bo throws IOException, MPDException { final CommandQueue commandQueue = new CommandQueue(); - commandQueue.add(MPDPlaylist.addCommand(music.getFullPath())); + if (music instanceof PlaylistFile) { + commandQueue.add(MPDPlaylist.loadCommand(music.getFullPath())); + } else { + commandQueue.add(MPDPlaylist.addCommand(music.getFullPath())); + } add(commandQueue, replace, play); } @@ -277,6 +294,24 @@ public void add(final FilesystemTreeEntry music) throws IOException, MPDExceptio add(music, false, false); } + public void add(final Genre genre, final boolean replace, final boolean play) + throws IOException, MPDException { + final CommandQueue commandQueue; + + if (isCommandAvailable(MPDCommand.MPD_CMD_FIND_ADD)) { + commandQueue = new CommandQueue(); + + commandQueue + .add(MPDCommand.MPD_CMD_FIND_ADD, MPDCommand.MPD_TAG_GENRE, genre.getName()); + } else { + final Collection music = find(MPDCommand.MPD_TAG_GENRE, genre.getName()); + + commandQueue = MPDPlaylist.addAllCommand(music); + } + + add(commandQueue, replace, play); + } + /** * Adds songs to the queue. Optionally, clears the queue prior to the addition. Optionally, * play the added songs afterward. @@ -394,12 +429,24 @@ public void addStream(final String stream, final boolean replace, final boolean public void addToPlaylist(final String playlistName, final Album album) throws IOException, MPDException { - addToPlaylist(playlistName, new ArrayList<>(getSongs(album))); + if (mIdleConnection.isCommandAvailable(MPDCommand.MPD_CMD_SEARCH_ADD_PLAYLIST)) { + final String[] artistPair = getAlbumArtistPair(album); + + mConnection.sendCommand(MPDCommand.MPD_CMD_SEARCH_ADD_PLAYLIST, playlistName, + MPDCommand.MPD_SEARCH_ALBUM, album.getName(), artistPair[0], artistPair[1]); + } else { + addToPlaylist(playlistName, new ArrayList<>(getSongs(album))); + } } public void addToPlaylist(final String playlistName, final Artist artist) throws IOException, MPDException { - addToPlaylist(playlistName, new ArrayList<>(getSongs(artist))); + if (mIdleConnection.isCommandAvailable(MPDCommand.MPD_CMD_SEARCH_ADD_PLAYLIST)) { + mConnection.sendCommand(MPDCommand.MPD_CMD_SEARCH_ADD_PLAYLIST, playlistName, + MPDCommand.MPD_SEARCH_ARTIST, artist.getName()); + } else { + addToPlaylist(playlistName, new ArrayList<>(getSongs(artist))); + } } public void addToPlaylist(final String playlistName, final Collection musicCollection) @@ -421,6 +468,18 @@ public void addToPlaylist(final String playlistName, final FilesystemTreeEntry e entry.getFullPath()); } + public void addToPlaylist(final String playlistName, final Genre genre) + throws IOException, MPDException { + if (mIdleConnection.isCommandAvailable(MPDCommand.MPD_CMD_SEARCH_ADD_PLAYLIST)) { + mConnection.sendCommand(MPDCommand.MPD_CMD_SEARCH_ADD_PLAYLIST, playlistName, + MPDCommand.MPD_SEARCH_GENRE, genre.getName()); + } else { + final Collection music = find(MPDCommand.MPD_TAG_GENRE, genre.getName()); + + addToPlaylist(playlistName, music); + } + } + public void addToPlaylist(final String playlistName, final Music music) throws IOException, MPDException { final Collection songs = new ArrayList<>(1); @@ -1547,6 +1606,26 @@ public void refreshDirectory(final Directory directory) throws IOException, MPDE directory.refresh(mConnection); } + /** + * Removes a list of tracks from a playlist file, by position. + * + * @param playlistName The playlist file to remove tracks from. + * @param positions The positions of the tracks to remove from the playlist file. + * @throws IOException Thrown upon a communication error with the server. + * @throws MPDException Thrown if an error occurs as a result of command execution. + */ + public void removeFromPlaylist(final String playlistName, final List positions) + throws IOException, MPDException { + Collections.sort(positions, Collections.reverseOrder()); + final CommandQueue commandQueue = new CommandQueue(positions.size()); + + for (final Integer position : positions) { + commandQueue.add(MPDCommand.MPD_CMD_PLAYLIST_DEL, playlistName, position.toString()); + } + + commandQueue.send(mConnection); + } + public void removeFromPlaylist(final String playlistName, final Integer pos) throws IOException, MPDException { mConnection.sendCommand(MPDCommand.MPD_CMD_PLAYLIST_DEL, playlistName, diff --git a/JMPDComm/src/main/java/org/a0z/mpd/MPDCommand.java b/JMPDComm/src/main/java/org/a0z/mpd/MPDCommand.java index 628cd5f68e..195507c915 100644 --- a/JMPDComm/src/main/java/org/a0z/mpd/MPDCommand.java +++ b/JMPDComm/src/main/java/org/a0z/mpd/MPDCommand.java @@ -56,6 +56,9 @@ public class MPDCommand { public static final String MPD_CMD_FIND = "find"; + /** Added in MPD protocol 0.16.0 */ + public static final String MPD_CMD_FIND_ADD = "findadd"; + public static final String MPD_CMD_GROUP = "group"; public static final String MPD_CMD_IDLE = "idle"; @@ -115,6 +118,9 @@ public class MPDCommand { public static final String MPD_CMD_SEARCH = "search"; + /** Added in MPD protocol 0.17.0. */ + public static final String MPD_CMD_SEARCH_ADD_PLAYLIST = "searchaddpl"; + public static final String MPD_CMD_SEEK = "seek"; public static final String MPD_CMD_SEEK_ID = "seekid"; @@ -132,10 +138,6 @@ public class MPDCommand { // deprecated commands public static final String MPD_CMD_VOLUME = "volume"; - public static final String MPD_FIND_ALBUM = "album"; - - public static final String MPD_FIND_ARTIST = "artist"; - public static final String MPD_LIST_RESPONSE_ARTIST = "Artist"; public static final String MPD_SEARCH_ALBUM = "album"; diff --git a/JMPDComm/src/main/java/org/a0z/mpd/MPDPlaylist.java b/JMPDComm/src/main/java/org/a0z/mpd/MPDPlaylist.java index 68a9d58286..68869df24f 100644 --- a/JMPDComm/src/main/java/org/a0z/mpd/MPDPlaylist.java +++ b/JMPDComm/src/main/java/org/a0z/mpd/MPDPlaylist.java @@ -390,6 +390,23 @@ public void removeById(final int... songIds) throws IOException, MPDException { commandQueue.send(mConnection); } + /** + * Removes entries from playlist. + * + * @param songIds Playlist songIDs to remove. + * @throws IOException Thrown upon a communication error with the server. + * @throws MPDException Thrown if an error occurs as a result of command execution. + */ + public void removeById(final Collection songIds) throws IOException, MPDException { + final CommandQueue commandQueue = new CommandQueue(songIds.size()); + + for (final Integer id : songIds) { + commandQueue.add(MPD_CMD_PLAYLIST_REMOVE_ID, id.toString()); + } + + commandQueue.send(mConnection); + } + /** * Removes entries from playlist. * diff --git a/MPDroid/build.gradle b/MPDroid/build.gradle index 9412ba48d7..549137fca4 100644 --- a/MPDroid/build.gradle +++ b/MPDroid/build.gradle @@ -27,8 +27,8 @@ android { defaultConfig { minSdkVersion 14 targetSdkVersion 21 - versionCode 51 - versionName "1.07 RC3 " + gitShortHash() + versionCode 52 + versionName "1.07 RC4 " + gitShortHash() } lintOptions { diff --git a/MPDroid/src/main/java/com/namelessdev/mpdroid/fragments/FSFragment.java b/MPDroid/src/main/java/com/namelessdev/mpdroid/fragments/FSFragment.java index fe0016b729..8fbc1e4143 100644 --- a/MPDroid/src/main/java/com/namelessdev/mpdroid/fragments/FSFragment.java +++ b/MPDroid/src/main/java/com/namelessdev/mpdroid/fragments/FSFragment.java @@ -69,7 +69,11 @@ protected void add(final Item item, final boolean replace, final boolean play) { final Directory toAdd = mCurrentDirectory.getDirectory(item.getName()); if (toAdd == null) { mApp.oMPDAsyncHelper.oMPD.add((FilesystemTreeEntry) item, replace, play); - Tools.notifyUser(R.string.songAdded, item); + if (item instanceof PlaylistFile) { + Tools.notifyUser(R.string.playlistAdded, item); + } else { + Tools.notifyUser(R.string.songAdded, item); + } } else { // Valid directory mApp.oMPDAsyncHelper.oMPD.add(toAdd, replace, play); diff --git a/MPDroid/src/main/java/com/namelessdev/mpdroid/fragments/GenresFragment.java b/MPDroid/src/main/java/com/namelessdev/mpdroid/fragments/GenresFragment.java index 0b67d0ebf0..a16689622a 100644 --- a/MPDroid/src/main/java/com/namelessdev/mpdroid/fragments/GenresFragment.java +++ b/MPDroid/src/main/java/com/namelessdev/mpdroid/fragments/GenresFragment.java @@ -43,8 +43,7 @@ public GenresFragment() { @Override protected void add(final Item item, final boolean replace, final boolean play) { try { - mApp.oMPDAsyncHelper.oMPD.getPlaylist().addAll( - mApp.oMPDAsyncHelper.oMPD.find("genre", item.getName())); + mApp.oMPDAsyncHelper.oMPD.add((Genre) item, replace, play); Tools.notifyUser(mIrAdded, item); } catch (final IOException | MPDException e) { Log.e(TAG, "Failed to add all from playlist.", e); @@ -54,8 +53,7 @@ protected void add(final Item item, final boolean replace, final boolean play) { @Override protected void add(final Item item, final String playlist) { try { - mApp.oMPDAsyncHelper.oMPD.addToPlaylist(playlist, - mApp.oMPDAsyncHelper.oMPD.find("genre", item.getName())); + mApp.oMPDAsyncHelper.oMPD.addToPlaylist(playlist, (Genre) item); Tools.notifyUser(mIrAdded, item); } catch (final IOException | MPDException e) { Log.e(TAG, "Failed to add all genre to playlist.", e); diff --git a/MPDroid/src/main/java/com/namelessdev/mpdroid/fragments/StoredPlaylistFragment.java b/MPDroid/src/main/java/com/namelessdev/mpdroid/fragments/StoredPlaylistFragment.java index f5ba84e8b8..6a616bc432 100644 --- a/MPDroid/src/main/java/com/namelessdev/mpdroid/fragments/StoredPlaylistFragment.java +++ b/MPDroid/src/main/java/com/namelessdev/mpdroid/fragments/StoredPlaylistFragment.java @@ -163,6 +163,13 @@ public boolean onOptionsItemSelected(final MenuItem item) { } + @Override + public void onResume() { + super.onResume(); + + updateList(); + } + @Override public void onSaveInstanceState(final Bundle outState) { outState.putString(EXTRA_PLAYLIST_NAME, mPlaylistName); diff --git a/MPDroid/src/main/java/com/namelessdev/mpdroid/library/PlaylistEditActivity.java b/MPDroid/src/main/java/com/namelessdev/mpdroid/library/PlaylistEditActivity.java index 9212ac75ad..6faa58d8ba 100644 --- a/MPDroid/src/main/java/com/namelessdev/mpdroid/library/PlaylistEditActivity.java +++ b/MPDroid/src/main/java/com/namelessdev/mpdroid/library/PlaylistEditActivity.java @@ -42,7 +42,7 @@ import java.io.IOException; import java.util.AbstractMap; import java.util.ArrayList; -import java.util.Collections; +import java.util.Collection; import java.util.HashMap; import java.util.LinkedList; import java.util.List; @@ -109,27 +109,20 @@ public void onClick(final View v) { int count = 0; try { - final ArrayList> copy = new ArrayList<>(mSongList); + final Collection> copy = new ArrayList<>(mSongList); final List positions = new LinkedList<>(); - for (final HashMap item : copy) { + for (final AbstractMap item : copy) { if (item.get("marked").equals(Boolean.TRUE)) { positions.add((Integer) item.get("songid")); - mSongList.remove(copy.indexOf(item) - count); count++; } } - Collections.sort(positions); if (mIsPlayQueue) { - for (count = 0; count < positions.size(); ++count) { - mApp.oMPDAsyncHelper.oMPD.getPlaylist().removeById(positions.get(count)); - } + mApp.oMPDAsyncHelper.oMPD.getPlaylist().removeById(positions); } else { - for (count = 0; count < positions.size(); ++count) { - mApp.oMPDAsyncHelper.oMPD.removeFromPlaylist(mPlaylistName, - positions.get(count) - count); - } + mApp.oMPDAsyncHelper.oMPD.removeFromPlaylist(mPlaylistName, positions); } if (copy.size() != mSongList.size()) { ((BaseAdapter) getListAdapter()).notifyDataSetChanged(); @@ -137,8 +130,8 @@ public void onClick(final View v) { Tools.notifyUser(R.string.removeCountSongs, count); } catch (final Exception e) { Log.e(TAG, "General Error.", e); - update(); } + update(); } } @@ -284,10 +277,17 @@ protected void update() { final View view = null == getListView() ? null : getListView().getChildAt(0); final int top = null == view ? -1 : view.getTop(); int listPlayingId = 0; + int playlistPosition = 0; + // Copy list to avoid concurrent exception for (final Music music : new ArrayList<>(musics)) { final HashMap item = new HashMap<>(); - item.put("songid", music.getSongId()); + if (mIsPlayQueue) { + item.put("songid", music.getSongId()); + } else { + item.put("songid", playlistPosition); + } + playlistPosition++; item.put("artist", music.getArtist()); item.put("title", music.getTitle()); item.put("marked", false); diff --git a/MPDroid/src/main/java/com/namelessdev/mpdroid/service/MPDroidService.java b/MPDroid/src/main/java/com/namelessdev/mpdroid/service/MPDroidService.java index da2f87a7ff..0405d5a95c 100644 --- a/MPDroid/src/main/java/com/namelessdev/mpdroid/service/MPDroidService.java +++ b/MPDroid/src/main/java/com/namelessdev/mpdroid/service/MPDroidService.java @@ -435,6 +435,7 @@ public int onStartCommand(final Intent intent, final int flags, final int startI initializeAsyncHelper(); } MPDControl.run(MPD_ASYNC_HELPER.oMPD, MPDControl.ACTION_PAUSE); + stopStream(); } break; case Intent.ACTION_BOOT_COMPLETED: diff --git a/MPDroid/src/main/java/com/namelessdev/mpdroid/service/StreamHandler.java b/MPDroid/src/main/java/com/namelessdev/mpdroid/service/StreamHandler.java index a296216963..d33f45005c 100644 --- a/MPDroid/src/main/java/com/namelessdev/mpdroid/service/StreamHandler.java +++ b/MPDroid/src/main/java/com/namelessdev/mpdroid/service/StreamHandler.java @@ -475,7 +475,7 @@ public void onPrepared(final MediaPlayer mp) { Log.d(TAG, "StreamHandler.onPrepared()"); } - if (mIsPlaying) { + if (mIsPlaying && mIsActive) { focusResult = mAudioManager.requestAudioFocus(this, AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN); } else { @@ -486,7 +486,9 @@ public void onPrepared(final MediaPlayer mp) { mServiceHandler.sendEmptyMessage(BUFFERING_END); mMediaPlayer.start(); } else { - showErrorToUser(R.string.audioFocusFailed); + if (mIsActive && mIsPlaying) { + showErrorToUser(R.string.audioFocusFailed); + } /** Because mPreparingStream is still set, this will reset the stream. */ windDownResources(STREAMING_STOP); diff --git a/MPDroid/src/main/res/drawable-xxxhdpi/icon.png b/MPDroid/src/main/res/drawable-xxxhdpi/icon.png index 58284f029d..ceb6124a1f 100644 Binary files a/MPDroid/src/main/res/drawable-xxxhdpi/icon.png and b/MPDroid/src/main/res/drawable-xxxhdpi/icon.png differ diff --git a/dmix.iml b/dmix.iml index 0bb6048ae0..62553dc526 100644 --- a/dmix.iml +++ b/dmix.iml @@ -7,12 +7,14 @@ - + + + - + diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 716e0f257b..52bf988e77 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Fri Oct 31 13:25:32 PDT 2014 +#Wed Nov 26 12:20:56 PST 2014 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-2.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-2.2.1-all.zip