diff options
Diffstat (limited to 'app/src/main/java')
13 files changed, 210 insertions, 83 deletions
diff --git a/app/src/main/java/github/daneren2005/dsub/activity/SubsonicActivity.java b/app/src/main/java/github/daneren2005/dsub/activity/SubsonicActivity.java index f1dd21e9..cd746516 100644 --- a/app/src/main/java/github/daneren2005/dsub/activity/SubsonicActivity.java +++ b/app/src/main/java/github/daneren2005/dsub/activity/SubsonicActivity.java @@ -805,6 +805,15 @@ public class SubsonicActivity extends AppCompatActivity implements OnItemSelecte } recreateSpinner(); } + public void replaceExistingFragment(SubsonicFragment fragment, int tag) { + FragmentTransaction trans = getSupportFragmentManager().beginTransaction(); + trans.remove(currentFragment); + trans.add(R.id.fragment_container, fragment, tag + ""); + trans.commit(); + + currentFragment = fragment; + currentFragment.setPrimaryFragment(true); + } public void invalidate() { if(currentFragment != null) { diff --git a/app/src/main/java/github/daneren2005/dsub/domain/Artist.java b/app/src/main/java/github/daneren2005/dsub/domain/Artist.java index f30147e6..f48dd2f9 100644 --- a/app/src/main/java/github/daneren2005/dsub/domain/Artist.java +++ b/app/src/main/java/github/daneren2005/dsub/domain/Artist.java @@ -108,6 +108,12 @@ public class Artist implements Serializable { } public int compare(Artist lhsArtist, Artist rhsArtist) { + if("root".equals(lhsArtist.getId())) { + return 1; + } else if("root".equals(rhsArtist.getId())) { + return -1; + } + String lhs = lhsArtist.getName().toLowerCase(); String rhs = rhsArtist.getName().toLowerCase(); diff --git a/app/src/main/java/github/daneren2005/dsub/fragments/AdminFragment.java b/app/src/main/java/github/daneren2005/dsub/fragments/AdminFragment.java index 69164036..d4afa67e 100644 --- a/app/src/main/java/github/daneren2005/dsub/fragments/AdminFragment.java +++ b/app/src/main/java/github/daneren2005/dsub/fragments/AdminFragment.java @@ -117,7 +117,12 @@ public class AdminFragment extends SelectRecyclerFragment<User> { List<User> users = new ArrayList<User>(); User user = musicService.getUser(refresh, UserUtil.getCurrentUsername(context), context, listener); if(user != null) { - users.add(user); + SubsonicFragment fragment = new UserFragment(); + Bundle args = new Bundle(); + args.putSerializable(Constants.INTENT_EXTRA_NAME_ID, user); + fragment.setArguments(args); + + replaceExistingFragment(fragment); } UserUtil.refreshCurrentUser(context, false); diff --git a/app/src/main/java/github/daneren2005/dsub/fragments/DownloadFragment.java b/app/src/main/java/github/daneren2005/dsub/fragments/DownloadFragment.java index b4e4be93..edbeff43 100644 --- a/app/src/main/java/github/daneren2005/dsub/fragments/DownloadFragment.java +++ b/app/src/main/java/github/daneren2005/dsub/fragments/DownloadFragment.java @@ -42,6 +42,7 @@ import github.daneren2005.dsub.domain.MusicDirectory; import github.daneren2005.dsub.service.DownloadFile; import github.daneren2005.dsub.service.DownloadService; import github.daneren2005.dsub.service.MusicService; +import github.daneren2005.dsub.util.DownloadFileItemHelperCallback; import github.daneren2005.dsub.util.ProgressListener; import github.daneren2005.dsub.util.SilentBackgroundTask; import github.daneren2005.dsub.util.Util; @@ -62,41 +63,7 @@ public class DownloadFragment extends SelectRecyclerFragment<DownloadFile> imple public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle bundle) { super.onCreateView(inflater, container, bundle); - ItemTouchHelper touchHelper = new ItemTouchHelper(new ItemTouchHelper.SimpleCallback(ItemTouchHelper.UP | ItemTouchHelper.DOWN, ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT) { - @Override - public boolean onMove(RecyclerView recyclerView, final RecyclerView.ViewHolder fromHolder, final RecyclerView.ViewHolder toHolder) { - new SilentBackgroundTask<Void>(context) { - private int from; - private int to; - - @Override - protected Void doInBackground() throws Throwable { - from = fromHolder.getAdapterPosition(); - to = toHolder.getAdapterPosition(); - getDownloadService().swap(false, from, to); - return null; - } - - @Override - protected void done(Void result) { - adapter.notifyItemMoved(from, to); - } - }.execute(); - - return true; - } - - @Override - public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) { - SongView songView = (SongView) ((UpdateView.UpdateViewHolder) viewHolder).getUpdateView(); - DownloadFile downloadFile = songView.getDownloadFile(); - - DownloadService downloadService = getDownloadService(); - downloadService.removeBackground(downloadFile); - adapter.removeItem(downloadFile); - currentRevision = downloadService.getDownloadListUpdateRevision(); - } - }); + ItemTouchHelper touchHelper = new ItemTouchHelper(new DownloadFileItemHelperCallback(this, false)); touchHelper.attachToRecyclerView(recyclerView); return rootView; diff --git a/app/src/main/java/github/daneren2005/dsub/fragments/NowPlayingFragment.java b/app/src/main/java/github/daneren2005/dsub/fragments/NowPlayingFragment.java index 8af8a26b..68ade3cc 100644 --- a/app/src/main/java/github/daneren2005/dsub/fragments/NowPlayingFragment.java +++ b/app/src/main/java/github/daneren2005/dsub/fragments/NowPlayingFragment.java @@ -188,40 +188,7 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis FastScroller fastScroller = (FastScroller) rootView.findViewById(R.id.download_fast_scroller); fastScroller.attachRecyclerView(playlistView); setupLayoutManager(playlistView, false); - ItemTouchHelper touchHelper = new ItemTouchHelper(new ItemTouchHelper.SimpleCallback(ItemTouchHelper.UP | ItemTouchHelper.DOWN, ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT) { - @Override - public boolean onMove(RecyclerView recyclerView, final RecyclerView.ViewHolder fromHolder, final RecyclerView.ViewHolder toHolder) { - new SilentBackgroundTask<Void>(context) { - private int from; - private int to; - - @Override - protected Void doInBackground() throws Throwable { - from = fromHolder.getAdapterPosition(); - to = toHolder.getAdapterPosition(); - getDownloadService().swap(true, from, to); - return null; - } - - @Override - protected void done(Void result) { - songListAdapter.notifyItemMoved(from, to); - } - }.execute(); - - return true; - } - - @Override - public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) { - SongView songView = (SongView) ((UpdateView.UpdateViewHolder) viewHolder).getUpdateView(); - DownloadFile downloadFile = songView.getDownloadFile(); - - DownloadService downloadService = getDownloadService(); - downloadService.remove(downloadFile); - songListAdapter.removeItem(downloadFile); - } - }); + ItemTouchHelper touchHelper = new ItemTouchHelper(new DownloadFileItemHelperCallback(this, true)); touchHelper.attachToRecyclerView(playlistView); starButton = (ImageButton)rootView.findViewById(R.id.download_star); @@ -860,6 +827,11 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis } } + @Override + public SectionAdapter getCurrentAdapter() { + return songListAdapter; + } + private void scheduleHideControls() { if (hideControlsFuture != null) { hideControlsFuture.cancel(false); diff --git a/app/src/main/java/github/daneren2005/dsub/fragments/SelectDirectoryFragment.java b/app/src/main/java/github/daneren2005/dsub/fragments/SelectDirectoryFragment.java index 93188e2f..abd1c6aa 100644 --- a/app/src/main/java/github/daneren2005/dsub/fragments/SelectDirectoryFragment.java +++ b/app/src/main/java/github/daneren2005/dsub/fragments/SelectDirectoryFragment.java @@ -662,7 +662,7 @@ public class SelectDirectoryFragment extends SubsonicFragment implements Section } @Override - protected SectionAdapter<Entry> getCurrentAdapter() { + public SectionAdapter<Entry> getCurrentAdapter() { return entryGridAdapter; } diff --git a/app/src/main/java/github/daneren2005/dsub/fragments/SelectRecyclerFragment.java b/app/src/main/java/github/daneren2005/dsub/fragments/SelectRecyclerFragment.java index adf22484..787b96e0 100644 --- a/app/src/main/java/github/daneren2005/dsub/fragments/SelectRecyclerFragment.java +++ b/app/src/main/java/github/daneren2005/dsub/fragments/SelectRecyclerFragment.java @@ -142,7 +142,7 @@ public abstract class SelectRecyclerFragment<T> extends SubsonicFragment impleme } } - protected SectionAdapter getCurrentAdapter() { + public SectionAdapter getCurrentAdapter() { return adapter; } diff --git a/app/src/main/java/github/daneren2005/dsub/fragments/SubsonicFragment.java b/app/src/main/java/github/daneren2005/dsub/fragments/SubsonicFragment.java index 6c895edc..6c5b63d1 100644 --- a/app/src/main/java/github/daneren2005/dsub/fragments/SubsonicFragment.java +++ b/app/src/main/java/github/daneren2005/dsub/fragments/SubsonicFragment.java @@ -399,6 +399,9 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR public void replaceFragment(SubsonicFragment fragment, boolean replaceCurrent) { context.replaceFragment(fragment, fragment.getSupportTag(), secondaryFragment && replaceCurrent); } + public void replaceExistingFragment(SubsonicFragment fragment) { + context.replaceExistingFragment(fragment, fragment.getSupportTag()); + } public int getRootId() { return rootView.getId(); @@ -1776,7 +1779,7 @@ public class SubsonicFragment extends Fragment implements SwipeRefreshLayout.OnR }.execute(); } - protected SectionAdapter getCurrentAdapter() { return null; } + public SectionAdapter getCurrentAdapter() { return null; } public void stopActionMode() { SectionAdapter adapter = getCurrentAdapter(); if(adapter != null) { diff --git a/app/src/main/java/github/daneren2005/dsub/service/DownloadService.java b/app/src/main/java/github/daneren2005/dsub/service/DownloadService.java index bac7093a..a828ae4a 100644 --- a/app/src/main/java/github/daneren2005/dsub/service/DownloadService.java +++ b/app/src/main/java/github/daneren2005/dsub/service/DownloadService.java @@ -42,7 +42,6 @@ import github.daneren2005.dsub.domain.RepeatMode; import github.daneren2005.dsub.domain.ServerInfo; import github.daneren2005.dsub.receiver.MediaButtonIntentReceiver; import github.daneren2005.dsub.util.ArtistRadioBuffer; -import github.daneren2005.dsub.util.FileUtil; import github.daneren2005.dsub.util.Notifications; import github.daneren2005.dsub.util.SilentBackgroundTask; import github.daneren2005.dsub.util.Constants; @@ -1319,7 +1318,20 @@ public class DownloadService extends Service { } if(playerState == STARTED && positionCache == null && remoteState == LOCAL) { - positionCache = new PositionCache(); + positionCache = new LocalPositionCache(); + Thread thread = new Thread(positionCache, "PositionCache"); + thread.start(); + } else if(playerState != STARTED && positionCache != null) { + positionCache.stop(); + positionCache = null; + } + + if(playerState == STARTED && positionCache == null) { + if(remoteState == LOCAL) { + positionCache = new LocalPositionCache(); + } else { + positionCache = new PositionCache(); + } Thread thread = new Thread(positionCache, "PositionCache"); thread.start(); } else if(playerState != STARTED && positionCache != null) { @@ -1341,6 +1353,28 @@ public class DownloadService extends Service { // Stop checking position before the song reaches completion while(isRunning) { try { + onSongProgress(); + Thread.sleep(1000L); + } + catch(Exception e) { + isRunning = false; + positionCache = null; + } + } + } + } + private class LocalPositionCache extends PositionCache { + boolean isRunning = true; + + public void stop() { + isRunning = false; + } + + @Override + public void run() { + // Stop checking position before the song reaches completion + while(isRunning) { + try { if(mediaPlayer != null && playerState == STARTED) { int newPosition = mediaPlayer.getCurrentPosition(); @@ -2411,9 +2445,14 @@ public class DownloadService extends Service { } if(run) { - onSongsChanged(); - onSongProgress(); - onStateUpdate(); + mediaPlayerHandler.post(new Runnable() { + @Override + public void run() { + onSongsChanged(); + onSongProgress(); + onStateUpdate(); + } + }); } } public void removeOnSongChangeListener(OnSongChangedListener listener) { @@ -2457,12 +2496,13 @@ public class DownloadService extends Service { final long atRevision = revision; final Integer duration = getPlayerDuration(); final boolean isSeekable = isSeekable(); + final int position = getPlayerPosition(); for(final OnSongChangedListener listener: onSongChangedListeners) { handler.post(new Runnable() { @Override public void run() { if(revision == atRevision) { - listener.onSongProgress(currentPlaying, cachedPosition, duration, isSeekable); + listener.onSongProgress(currentPlaying, position, duration, isSeekable); } } }); diff --git a/app/src/main/java/github/daneren2005/dsub/service/DownloadServiceLifecycleSupport.java b/app/src/main/java/github/daneren2005/dsub/service/DownloadServiceLifecycleSupport.java index 64da9a13..442d3dc1 100644 --- a/app/src/main/java/github/daneren2005/dsub/service/DownloadServiceLifecycleSupport.java +++ b/app/src/main/java/github/daneren2005/dsub/service/DownloadServiceLifecycleSupport.java @@ -316,8 +316,15 @@ public class DownloadServiceLifecycleSupport { @Override protected Void doInBackground() throws Throwable { try { + int index = state.currentPlayingIndex; + int position = state.currentPlayingPosition; + if(index == -1) { + index = 0; + position = 0; + } + MusicService musicService = MusicServiceFactory.getMusicService(downloadService); - musicService.savePlayQueue(state.songs, state.songs.get(state.currentPlayingIndex), state.currentPlayingPosition, downloadService, null); + musicService.savePlayQueue(state.songs, state.songs.get(index), position, downloadService, null); currentSavePlayQueueTask = null; } catch (Exception e) { Log.e(TAG, "Failed to save playing queue to server", e); diff --git a/app/src/main/java/github/daneren2005/dsub/util/DownloadFileItemHelperCallback.java b/app/src/main/java/github/daneren2005/dsub/util/DownloadFileItemHelperCallback.java new file mode 100644 index 00000000..4074fece --- /dev/null +++ b/app/src/main/java/github/daneren2005/dsub/util/DownloadFileItemHelperCallback.java @@ -0,0 +1,112 @@ +package github.daneren2005.dsub.util; + +import android.support.v7.widget.RecyclerView; +import android.support.v7.widget.helper.ItemTouchHelper; + +import org.eclipse.jetty.util.ArrayQueue; + +import java.util.Queue; + +import github.daneren2005.dsub.adapter.SectionAdapter; +import github.daneren2005.dsub.fragments.SubsonicFragment; +import github.daneren2005.dsub.service.DownloadFile; +import github.daneren2005.dsub.service.DownloadService; +import github.daneren2005.dsub.view.SongView; +import github.daneren2005.dsub.view.UpdateView; + +public class DownloadFileItemHelperCallback extends ItemTouchHelper.SimpleCallback { + private SubsonicFragment fragment; + private boolean mainList; + + private BackgroundTask pendingTask = null; + private Queue pendingOperations = new ArrayQueue(); + + public DownloadFileItemHelperCallback(SubsonicFragment fragment, boolean mainList) { + super(ItemTouchHelper.UP | ItemTouchHelper.DOWN, ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT); + this.fragment = fragment; + this.mainList = mainList; + } + + @Override + public boolean onMove(RecyclerView recyclerView, RecyclerView.ViewHolder fromHolder, RecyclerView.ViewHolder toHolder) { + int from = fromHolder.getAdapterPosition(); + int to = toHolder.getAdapterPosition(); + getSectionAdapter().notifyItemMoved(from, to); + + synchronized (pendingOperations) { + pendingOperations.add(new Pair<>(from, to)); + updateDownloadService(); + } + return true; + } + + @Override + public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) { + SongView songView = (SongView) ((UpdateView.UpdateViewHolder) viewHolder).getUpdateView(); + DownloadFile downloadFile = songView.getDownloadFile(); + + getSectionAdapter().removeItem(downloadFile); + synchronized (pendingOperations) { + pendingOperations.add(downloadFile); + updateDownloadService(); + } + } + + public DownloadService getDownloadService() { + return fragment.getDownloadService(); + } + public SectionAdapter getSectionAdapter() { + return fragment.getCurrentAdapter(); + } + + private void updateDownloadService() { + if(pendingTask == null) { + final DownloadService downloadService = getDownloadService(); + if(downloadService == null) { + return; + } + + pendingTask = new SilentBackgroundTask<Void>(downloadService) { + @Override + protected Void doInBackground() throws Throwable { + boolean running = true; + while(running) { + Object nextOperation = null; + synchronized (pendingOperations) { + if(!pendingOperations.isEmpty()) { + nextOperation = pendingOperations.remove(); + } + } + + if(nextOperation != null) { + if(nextOperation instanceof Pair) { + Pair<Integer, Integer> swap = (Pair) nextOperation; + downloadService.swap(mainList, swap.getFirst(), swap.getSecond()); + } else if(nextOperation instanceof DownloadFile) { + DownloadFile downloadFile = (DownloadFile) nextOperation; + if(mainList) { + downloadService.remove(downloadFile); + } else { + downloadService.removeBackground(downloadFile); + } + } + } else { + running = false; + } + } + + synchronized (pendingOperations) { + pendingTask = null; + + // Start a task if this is non-empty. Means someone added while we were running operations + if(!pendingOperations.isEmpty()) { + updateDownloadService(); + } + } + return null; + } + }; + pendingTask.execute(); + } + } +} diff --git a/app/src/main/java/github/daneren2005/dsub/util/FileUtil.java b/app/src/main/java/github/daneren2005/dsub/util/FileUtil.java index 332f775c..31d7e31d 100644 --- a/app/src/main/java/github/daneren2005/dsub/util/FileUtil.java +++ b/app/src/main/java/github/daneren2005/dsub/util/FileUtil.java @@ -70,6 +70,7 @@ public class FileUtil { private static final List<String> MUSIC_FILE_EXTENSIONS = Arrays.asList("mp3", "ogg", "aac", "flac", "m4a", "wav", "wma"); private static final List<String> VIDEO_FILE_EXTENSIONS = Arrays.asList("flv", "mp4", "m4v", "wmv", "avi", "mov", "mpg", "mkv"); private static final List<String> PLAYLIST_FILE_EXTENSIONS = Arrays.asList("m3u"); + private static final int MAX_FILENAME_LENGTH = 254 - ".complete.mp3".length(); private static File DEFAULT_MUSIC_DIR; private static final Kryo kryo = new Kryo(); private static HashMap<String, MusicDirectory.Entry> entryLookup; @@ -123,8 +124,12 @@ public class FileUtil { fileName.append(track).append("-"); } - fileName.append(fileSystemSafe(song.getTitle())).append("."); + fileName.append(fileSystemSafe(song.getTitle())); + if(fileName.length() >= MAX_FILENAME_LENGTH) { + fileName.setLength(MAX_FILENAME_LENGTH); + } + fileName.append("."); if(song.isVideo()) { String videoPlayerType = Util.getVideoPlayerType(context); if("hls".equals(videoPlayerType)) { diff --git a/app/src/main/java/github/daneren2005/dsub/util/Util.java b/app/src/main/java/github/daneren2005/dsub/util/Util.java index 99926716..c2ecdcee 100644 --- a/app/src/main/java/github/daneren2005/dsub/util/Util.java +++ b/app/src/main/java/github/daneren2005/dsub/util/Util.java @@ -417,12 +417,13 @@ public final class Util { builder.append("rest/").append(method).append(".view"); builder.append("?u=").append(username); if(method != null && ServerInfo.canUseToken(context, instance)) { - Pair<String, String> values = tokens.get(instance); + int hash = (username + password).hashCode(); + Pair<String, String> values = tokens.get(hash); if(values == null) { String salt = new BigInteger(130, getRandom()).toString(32); String token = md5Hex(password + salt); values = new Pair<>(salt, token); - tokens.put(instance, values); + tokens.put(hash, values); } builder.append("&s=").append(values.getFirst()); |