From f584cff697de20cda0dc1ec19542f776ddc00b1a Mon Sep 17 00:00:00 2001 From: dkanada Date: Wed, 23 Dec 2020 12:53:43 +0900 Subject: [PATCH 1/8] update exoplayer and implement custom media source factory --- .../gramophone/service/MultiPlayer.java | 79 +++---------------- .../service/UnknownMediaSourceFactory.kt | 73 +++++++++++++++++ 2 files changed, 85 insertions(+), 67 deletions(-) create mode 100644 app/src/main/java/com/dkanada/gramophone/service/UnknownMediaSourceFactory.kt diff --git a/app/src/main/java/com/dkanada/gramophone/service/MultiPlayer.java b/app/src/main/java/com/dkanada/gramophone/service/MultiPlayer.java index b0386073..70d84c20 100644 --- a/app/src/main/java/com/dkanada/gramophone/service/MultiPlayer.java +++ b/app/src/main/java/com/dkanada/gramophone/service/MultiPlayer.java @@ -13,13 +13,9 @@ import com.dkanada.gramophone.util.PreferenceUtil; import com.google.android.exoplayer2.ExoPlaybackException; import com.google.android.exoplayer2.ExoPlayer; import com.google.android.exoplayer2.MediaItem; -import com.google.android.exoplayer2.Player; import com.google.android.exoplayer2.SimpleExoPlayer; import com.google.android.exoplayer2.database.ExoDatabaseProvider; -import com.google.android.exoplayer2.source.ConcatenatingMediaSource; -import com.google.android.exoplayer2.source.MediaSource; -import com.google.android.exoplayer2.source.ProgressiveMediaSource; -import com.google.android.exoplayer2.source.hls.HlsMediaSource; +import com.google.android.exoplayer2.source.MediaSourceFactory; import com.google.android.exoplayer2.upstream.DataSource; import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory; import com.google.android.exoplayer2.upstream.FileDataSource; @@ -29,27 +25,13 @@ import com.google.android.exoplayer2.upstream.cache.LeastRecentlyUsedCacheEvicto import com.google.android.exoplayer2.upstream.cache.SimpleCache; import java.io.File; -import java.io.IOException; - -import okhttp3.Call; -import okhttp3.Callback; -import okhttp3.Dispatcher; -import okhttp3.OkHttpClient; -import okhttp3.Request; -import okhttp3.Response; -import okhttp3.internal.annotations.EverythingIsNonNull; public class MultiPlayer implements Playback { public static final String TAG = MultiPlayer.class.getSimpleName(); private final Context context; - private final OkHttpClient httpClient; - - private SimpleExoPlayer exoPlayer; - private ConcatenatingMediaSource mediaSource; - + private final SimpleExoPlayer exoPlayer; private final SimpleCache simpleCache; - private final DataSource.Factory dataSource; private PlaybackCallbacks callbacks; @@ -83,7 +65,7 @@ public class MultiPlayer implements Playback { int windowIndex = exoPlayer.getCurrentWindowIndex(); if (windowIndex == 1) { - mediaSource.removeMediaSource(0); + exoPlayer.removeMediaItem(0); if (exoPlayer.isPlaying()) { // there are still songs left in the queue callbacks.onTrackWentToNext(); @@ -103,17 +85,11 @@ public class MultiPlayer implements Playback { public MultiPlayer(Context context) { this.context = context; - Dispatcher dispatcher = new Dispatcher(); - dispatcher.setMaxRequests(1); - - httpClient = new OkHttpClient.Builder().dispatcher(dispatcher).build(); - - exoPlayer = new SimpleExoPlayer.Builder(context).build(); - mediaSource = new ConcatenatingMediaSource(); + MediaSourceFactory mediaSourceFactory = new UnknownMediaSourceFactory(buildDataSourceFactory()); + exoPlayer = new SimpleExoPlayer.Builder(context).setMediaSourceFactory(mediaSourceFactory).build(); exoPlayer.addListener(eventListener); - exoPlayer.prepare(mediaSource); - exoPlayer.setRepeatMode(Player.REPEAT_MODE_OFF); + exoPlayer.prepare(); long cacheSize = PreferenceUtil.getInstance(context).getMediaCacheSize(); LeastRecentlyUsedCacheEvictor recentlyUsedCache = new LeastRecentlyUsedCacheEvictor(cacheSize); @@ -121,23 +97,19 @@ public class MultiPlayer implements Playback { File cacheDirectory = new File(context.getCacheDir(), "exoplayer"); simpleCache = new SimpleCache(cacheDirectory, recentlyUsedCache, databaseProvider); - dataSource = buildDataSourceFactory(); } @Override public void setDataSource(Song song) { - mediaSource = new ConcatenatingMediaSource(); - - exoPlayer.addListener(eventListener); - exoPlayer.prepare(mediaSource); - + exoPlayer.clearMediaItems(); appendDataSource(MusicUtil.getSongFileUri(song)); + exoPlayer.seekTo(0, 0); } @Override public void queueDataSource(Song song) { - while (mediaSource.getSize() > 1) { - mediaSource.removeMediaSource(1); + while (exoPlayer.getMediaItemCount() > 1) { + exoPlayer.removeMediaItem(1); } appendDataSource(MusicUtil.getSongFileUri(song)); @@ -145,36 +117,9 @@ public class MultiPlayer implements Playback { private void appendDataSource(String path) { Uri uri = Uri.parse(path); + MediaItem mediaItem = MediaItem.fromUri(uri); - httpClient.newCall(new Request.Builder().url(path).head().build()).enqueue(new Callback() { - @Override - @EverythingIsNonNull - public void onFailure(Call call, IOException e) { - Toast.makeText(context, context.getResources().getString(R.string.unplayable_file), Toast.LENGTH_SHORT).show(); - e.printStackTrace(); - } - - @Override - @EverythingIsNonNull - public void onResponse(Call call, Response response) { - String type = response.header("Content-Type"); - if (type == null) return; - - MediaSource source; - if (type.equals("application/x-mpegURL")) { - source = new HlsMediaSource.Factory(dataSource) - .setTag(path) - .setAllowChunklessPreparation(true) - .createMediaSource(uri); - } else { - source = new ProgressiveMediaSource.Factory(dataSource) - .setTag(path) - .createMediaSource(uri); - } - - mediaSource.addMediaSource(source); - } - }); + exoPlayer.addMediaItem(mediaItem); } private DataSource.Factory buildDataSourceFactory() { diff --git a/app/src/main/java/com/dkanada/gramophone/service/UnknownMediaSourceFactory.kt b/app/src/main/java/com/dkanada/gramophone/service/UnknownMediaSourceFactory.kt new file mode 100644 index 00000000..100a7d03 --- /dev/null +++ b/app/src/main/java/com/dkanada/gramophone/service/UnknownMediaSourceFactory.kt @@ -0,0 +1,73 @@ +package com.dkanada.gramophone.service + +import com.google.android.exoplayer2.MediaItem +import com.google.android.exoplayer2.drm.DrmSessionManager +import com.google.android.exoplayer2.extractor.DefaultExtractorsFactory +import com.google.android.exoplayer2.source.MediaSource +import com.google.android.exoplayer2.source.MediaSourceFactory +import com.google.android.exoplayer2.source.ProgressiveMediaSource +import com.google.android.exoplayer2.source.hls.HlsMediaSource +import com.google.android.exoplayer2.upstream.* + +import kotlinx.coroutines.* + +import java.net.HttpURLConnection +import java.net.URL + +class UnknownMediaSourceFactory(dataSourceFactory: DataSource.Factory) : MediaSourceFactory { + private val hlsMediaSource : HlsMediaSource.Factory + private val progressiveMediaSource : ProgressiveMediaSource.Factory + + private var loadErrorHandlingPolicy: LoadErrorHandlingPolicy + + override fun setDrmSessionManager(drmSessionManager: DrmSessionManager?): MediaSourceFactory { + return this + } + + override fun setDrmHttpDataSourceFactory(drmHttpDataSourceFactory: HttpDataSource.Factory?): MediaSourceFactory { + return this + } + + override fun setDrmUserAgent(drmUserAgent: String?): MediaSourceFactory { + return this + } + + override fun setLoadErrorHandlingPolicy(loadErrorHandlingPolicy: LoadErrorHandlingPolicy?): MediaSourceFactory { + this.loadErrorHandlingPolicy = loadErrorHandlingPolicy!! + return this + } + + override fun getSupportedTypes(): IntArray { + return intArrayOf() + } + + override fun createMediaSource(mediaItem: MediaItem): MediaSource { + val type: String? = runBlocking { + httpGet(mediaItem.playbackProperties!!.uri.toString()) + } + + val sourceFactory: MediaSourceFactory = if (type == "application/x-mpegURL") { + hlsMediaSource + } else { + progressiveMediaSource + } + + return sourceFactory.createMediaSource(mediaItem) + } + + private suspend fun httpGet(url: String?): String? { + return withContext(Dispatchers.IO) { + val request = URL(url) + val conn = request.openConnection() as HttpURLConnection + + return@withContext conn.getHeaderField("Content-Type") + } + } + + init { + hlsMediaSource = HlsMediaSource.Factory(dataSourceFactory) + progressiveMediaSource = ProgressiveMediaSource.Factory(dataSourceFactory, DefaultExtractorsFactory()) + + loadErrorHandlingPolicy = DefaultLoadErrorHandlingPolicy() + } +} From 102a745718adfa2a41f928254fdd21bc47c5be19 Mon Sep 17 00:00:00 2001 From: dkanada Date: Wed, 23 Dec 2020 12:54:31 +0900 Subject: [PATCH 2/8] fix possible crash in progress handler --- .../main/java/com/dkanada/gramophone/service/MusicService.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/com/dkanada/gramophone/service/MusicService.java b/app/src/main/java/com/dkanada/gramophone/service/MusicService.java index b1ec5c71..50d2896b 100644 --- a/app/src/main/java/com/dkanada/gramophone/service/MusicService.java +++ b/app/src/main/java/com/dkanada/gramophone/service/MusicService.java @@ -1286,7 +1286,7 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP info.setItemId(mService.get().getCurrentSong().id); info.setPositionTicks(progress * 10000); - task.cancel(true); + if (task != null) task.cancel(true); executorService.shutdownNow(); } } From ce23df3ef13ee4e968ca8d5b0769177cf0f4159c Mon Sep 17 00:00:00 2001 From: Luuk Nieuwdorp Date: Thu, 7 Jan 2021 17:01:10 +0100 Subject: [PATCH 3/8] Add FavoritesFragment based on SongsFragment --- .../adapter/MusicLibraryPagerAdapter.java | 4 +- .../library/pager/FavoritesFragment.java | 184 ++++++++++++++++++ .../gramophone/model/CategoryInfo.java | 3 +- .../gramophone/util/PreferenceUtil.java | 1 + app/src/main/res/values/strings.xml | 1 + 5 files changed, 191 insertions(+), 2 deletions(-) create mode 100644 app/src/main/java/com/dkanada/gramophone/fragments/mainactivity/library/pager/FavoritesFragment.java diff --git a/app/src/main/java/com/dkanada/gramophone/adapter/MusicLibraryPagerAdapter.java b/app/src/main/java/com/dkanada/gramophone/adapter/MusicLibraryPagerAdapter.java index 1f93edde..0729f818 100644 --- a/app/src/main/java/com/dkanada/gramophone/adapter/MusicLibraryPagerAdapter.java +++ b/app/src/main/java/com/dkanada/gramophone/adapter/MusicLibraryPagerAdapter.java @@ -10,6 +10,7 @@ import androidx.fragment.app.Fragment; import androidx.fragment.app.FragmentManager; import androidx.fragment.app.FragmentPagerAdapter; +import com.dkanada.gramophone.fragments.mainactivity.library.pager.FavoritesFragment; import com.dkanada.gramophone.model.CategoryInfo; import com.dkanada.gramophone.fragments.mainactivity.library.pager.AlbumsFragment; import com.dkanada.gramophone.fragments.mainactivity.library.pager.ArtistsFragment; @@ -154,7 +155,8 @@ public class MusicLibraryPagerAdapter extends FragmentPagerAdapter { ALBUMS(AlbumsFragment.class), ARTISTS(ArtistsFragment.class), GENRES(GenresFragment.class), - PLAYLISTS(PlaylistsFragment.class); + PLAYLISTS(PlaylistsFragment.class), + FAVORITES(FavoritesFragment.class); private final Class mFragmentClass; diff --git a/app/src/main/java/com/dkanada/gramophone/fragments/mainactivity/library/pager/FavoritesFragment.java b/app/src/main/java/com/dkanada/gramophone/fragments/mainactivity/library/pager/FavoritesFragment.java new file mode 100644 index 00000000..79afe827 --- /dev/null +++ b/app/src/main/java/com/dkanada/gramophone/fragments/mainactivity/library/pager/FavoritesFragment.java @@ -0,0 +1,184 @@ +package com.dkanada.gramophone.fragments.mainactivity.library.pager; + +import android.os.Bundle; + +import androidx.annotation.NonNull; +import androidx.recyclerview.widget.GridLayoutManager; + +import com.dkanada.gramophone.App; +import com.dkanada.gramophone.R; +import com.dkanada.gramophone.adapter.song.ShuffleButtonSongAdapter; +import com.dkanada.gramophone.adapter.song.SongAdapter; +import com.dkanada.gramophone.model.Song; +import com.dkanada.gramophone.util.PreferenceUtil; +import com.dkanada.gramophone.util.QueryUtil; + +import org.jellyfin.apiclient.interaction.Response; +import org.jellyfin.apiclient.model.dto.BaseItemDto; +import org.jellyfin.apiclient.model.querying.ItemFields; +import org.jellyfin.apiclient.model.querying.ItemFilter; +import org.jellyfin.apiclient.model.querying.ItemQuery; +import org.jellyfin.apiclient.model.querying.ItemsResult; + +import java.util.ArrayList; +import java.util.List; + +public class FavoritesFragment extends AbsLibraryPagerRecyclerViewCustomGridSizeFragment { + @Override + public void onActivityCreated(Bundle savedInstanceState) { + super.onActivityCreated(savedInstanceState); + } + + @NonNull + @Override + protected GridLayoutManager createLayoutManager() { + return new GridLayoutManager(getActivity(), getGridSize()); + } + + @NonNull + @Override + protected SongAdapter createAdapter() { + int itemLayoutRes = getItemLayoutRes(); + notifyLayoutResChanged(itemLayoutRes); + boolean usePalette = loadUsePalette(); + + List dataSet = getAdapter() == null ? new ArrayList<>() : getAdapter().getDataSet(); + SongAdapter adapter; + + if (getGridSize() <= getMaxGridSizeForList()) { + adapter = new ShuffleButtonSongAdapter( + getLibraryFragment().getMainActivity(), + dataSet, + itemLayoutRes, + usePalette, + getLibraryFragment()); + } else { + adapter = new SongAdapter( + getLibraryFragment().getMainActivity(), + dataSet, + itemLayoutRes, + usePalette, + getLibraryFragment()); + } + + return adapter; + } + + @NonNull + @Override + protected ItemQuery createQuery() { + ItemQuery query = new ItemQuery(); + + query.setIncludeItemTypes(new String[]{"Audio"}); + query.setFields(new ItemFields[]{ItemFields.MediaSources}); + query.setUserId(App.getApiClient().getCurrentUserId()); + query.setRecursive(true); + query.setLimit(PreferenceUtil.getInstance(App.getInstance()).getPageSize()); + query.setStartIndex(getAdapter().getItemCount()); + query.setParentId(QueryUtil.currentLibrary.getId()); + query.setFilters(new ItemFilter[]{ItemFilter.IsFavorite}); + + QueryUtil.applySortMethod(query, PreferenceUtil.getInstance(App.getInstance()).getSongSortMethod()); + QueryUtil.applySortOrder(query, PreferenceUtil.getInstance(App.getInstance()).getSongSortOrder()); + return query; + } + + @Override + protected void loadItems(int index) { + ItemQuery query = getQuery(); + query.setStartIndex(index); + + App.getApiClient().GetItemsAsync(query, new Response() { + @Override + public void onResponse(ItemsResult result) { + if (index == 0) getAdapter().getDataSet().clear(); + for (BaseItemDto itemDto : result.getItems()) { + getAdapter().getDataSet().add(new Song(itemDto)); + } + + size = result.getTotalRecordCount(); + getAdapter().notifyDataSetChanged(); + loading = false; + } + + @Override + public void onError(Exception exception) { + exception.printStackTrace(); + } + }); + } + + @Override + protected int getEmptyMessage() { + return R.string.no_songs; + } + + @Override + protected String loadSortMethod() { + return PreferenceUtil.getInstance(getActivity()).getSongSortMethod(); + } + + @Override + protected void saveSortMethod(String sortMethod) { + PreferenceUtil.getInstance(getActivity()).setSongSortMethod(sortMethod); + } + + @Override + protected void setSortMethod(String sortMethod) { + } + + @Override + protected String loadSortOrder() { + return PreferenceUtil.getInstance(getActivity()).getSongSortOrder(); + } + + @Override + protected void saveSortOrder(String sortOrder) { + PreferenceUtil.getInstance(getActivity()).setSongSortOrder(sortOrder); + } + + @Override + protected void setSortOrder(String sortOrder) { + } + + @Override + protected int loadGridSize() { + return PreferenceUtil.getInstance(getActivity()).getSongGridSize(requireActivity()); + } + + @Override + protected void saveGridSize(int gridSize) { + PreferenceUtil.getInstance(getActivity()).setSongGridSize(gridSize); + } + + @Override + protected int loadGridSizeLand() { + return PreferenceUtil.getInstance(getActivity()).getSongGridSizeLand(requireActivity()); + } + + @Override + protected void saveGridSizeLand(int gridSize) { + PreferenceUtil.getInstance(getActivity()).setSongGridSizeLand(gridSize); + } + + @Override + public void saveUsePalette(boolean usePalette) { + PreferenceUtil.getInstance(getActivity()).setSongColoredFooters(usePalette); + } + + @Override + public boolean loadUsePalette() { + return PreferenceUtil.getInstance(getActivity()).getSongColoredFooters(); + } + + @Override + public void setUsePalette(boolean usePalette) { + getAdapter().usePalette(usePalette); + } + + @Override + protected void setGridSize(int gridSize) { + getLayoutManager().setSpanCount(gridSize); + getAdapter().notifyDataSetChanged(); + } +} diff --git a/app/src/main/java/com/dkanada/gramophone/model/CategoryInfo.java b/app/src/main/java/com/dkanada/gramophone/model/CategoryInfo.java index 214c8221..0b112a6e 100644 --- a/app/src/main/java/com/dkanada/gramophone/model/CategoryInfo.java +++ b/app/src/main/java/com/dkanada/gramophone/model/CategoryInfo.java @@ -44,7 +44,8 @@ public class CategoryInfo implements Parcelable { ALBUMS(R.string.albums), ARTISTS(R.string.artists), GENRES(R.string.genres), - PLAYLISTS(R.string.playlists); + PLAYLISTS(R.string.playlists), + FAVORITES(R.string.favorites); public final int stringRes; diff --git a/app/src/main/java/com/dkanada/gramophone/util/PreferenceUtil.java b/app/src/main/java/com/dkanada/gramophone/util/PreferenceUtil.java index 7217d2f6..da2ff95f 100644 --- a/app/src/main/java/com/dkanada/gramophone/util/PreferenceUtil.java +++ b/app/src/main/java/com/dkanada/gramophone/util/PreferenceUtil.java @@ -429,6 +429,7 @@ public final class PreferenceUtil { defaultCategories.add(new CategoryInfo(CategoryInfo.Category.ARTISTS, true)); defaultCategories.add(new CategoryInfo(CategoryInfo.Category.GENRES, true)); defaultCategories.add(new CategoryInfo(CategoryInfo.Category.PLAYLISTS, true)); + defaultCategories.add(new CategoryInfo(CategoryInfo.Category.FAVORITES, true)); return defaultCategories; } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index e6c53142..b88c2079 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -49,6 +49,7 @@ Genres Songs Playlists + Favorites No playlists No albums No songs From c33809d5a045a7fa9e3ed96f1b7736ec5d553e5e Mon Sep 17 00:00:00 2001 From: Luuk Nieuwdorp Date: Thu, 7 Jan 2021 17:02:22 +0100 Subject: [PATCH 4/8] Add sorting options to FavoritesFragment --- .../fragments/mainactivity/library/LibraryFragment.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/dkanada/gramophone/fragments/mainactivity/library/LibraryFragment.java b/app/src/main/java/com/dkanada/gramophone/fragments/mainactivity/library/LibraryFragment.java index fa8fb365..67a5ad9b 100644 --- a/app/src/main/java/com/dkanada/gramophone/fragments/mainactivity/library/LibraryFragment.java +++ b/app/src/main/java/com/dkanada/gramophone/fragments/mainactivity/library/LibraryFragment.java @@ -19,6 +19,7 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; import com.dkanada.gramophone.databinding.FragmentLibraryBinding; +import com.dkanada.gramophone.fragments.mainactivity.library.pager.FavoritesFragment; import com.google.android.material.appbar.AppBarLayout; import com.afollestad.materialcab.MaterialCab; import com.kabouzeid.appthemehelper.ThemeStore; @@ -354,7 +355,7 @@ public class LibraryFragment extends AbsMainActivityFragment implements CabHolde .setChecked(currentSortMethod.equals(SortMethod.ADDED)); sortMethodMenu.add(0, R.id.action_sort_method_random, 4, R.string.sort_method_random) .setChecked(currentSortMethod.equals(SortMethod.RANDOM)); - } else if (fragment instanceof SongsFragment) { + } else if (fragment instanceof SongsFragment || fragment instanceof FavoritesFragment) { sortMethodMenu.add(0, R.id.action_sort_method_name, 0, R.string.sort_method_name) .setChecked(currentSortMethod.equals(SortMethod.NAME)); sortMethodMenu.add(0, R.id.action_sort_method_album, 1, R.string.sort_method_album) From f58d34344198b6680a50beed84458ffaee83425c Mon Sep 17 00:00:00 2001 From: Luuk Nieuwdorp Date: Thu, 7 Jan 2021 18:51:43 +0100 Subject: [PATCH 5/8] Re-use code from SongsFragment --- .../library/pager/FavoritesFragment.java | 156 +----------------- 1 file changed, 1 insertion(+), 155 deletions(-) diff --git a/app/src/main/java/com/dkanada/gramophone/fragments/mainactivity/library/pager/FavoritesFragment.java b/app/src/main/java/com/dkanada/gramophone/fragments/mainactivity/library/pager/FavoritesFragment.java index 79afe827..0dc9c134 100644 --- a/app/src/main/java/com/dkanada/gramophone/fragments/mainactivity/library/pager/FavoritesFragment.java +++ b/app/src/main/java/com/dkanada/gramophone/fragments/mainactivity/library/pager/FavoritesFragment.java @@ -1,69 +1,14 @@ package com.dkanada.gramophone.fragments.mainactivity.library.pager; -import android.os.Bundle; - import androidx.annotation.NonNull; -import androidx.recyclerview.widget.GridLayoutManager; - import com.dkanada.gramophone.App; -import com.dkanada.gramophone.R; -import com.dkanada.gramophone.adapter.song.ShuffleButtonSongAdapter; -import com.dkanada.gramophone.adapter.song.SongAdapter; -import com.dkanada.gramophone.model.Song; import com.dkanada.gramophone.util.PreferenceUtil; import com.dkanada.gramophone.util.QueryUtil; - -import org.jellyfin.apiclient.interaction.Response; -import org.jellyfin.apiclient.model.dto.BaseItemDto; import org.jellyfin.apiclient.model.querying.ItemFields; import org.jellyfin.apiclient.model.querying.ItemFilter; import org.jellyfin.apiclient.model.querying.ItemQuery; -import org.jellyfin.apiclient.model.querying.ItemsResult; - -import java.util.ArrayList; -import java.util.List; - -public class FavoritesFragment extends AbsLibraryPagerRecyclerViewCustomGridSizeFragment { - @Override - public void onActivityCreated(Bundle savedInstanceState) { - super.onActivityCreated(savedInstanceState); - } - - @NonNull - @Override - protected GridLayoutManager createLayoutManager() { - return new GridLayoutManager(getActivity(), getGridSize()); - } - - @NonNull - @Override - protected SongAdapter createAdapter() { - int itemLayoutRes = getItemLayoutRes(); - notifyLayoutResChanged(itemLayoutRes); - boolean usePalette = loadUsePalette(); - - List dataSet = getAdapter() == null ? new ArrayList<>() : getAdapter().getDataSet(); - SongAdapter adapter; - - if (getGridSize() <= getMaxGridSizeForList()) { - adapter = new ShuffleButtonSongAdapter( - getLibraryFragment().getMainActivity(), - dataSet, - itemLayoutRes, - usePalette, - getLibraryFragment()); - } else { - adapter = new SongAdapter( - getLibraryFragment().getMainActivity(), - dataSet, - itemLayoutRes, - usePalette, - getLibraryFragment()); - } - - return adapter; - } +public class FavoritesFragment extends SongsFragment { @NonNull @Override protected ItemQuery createQuery() { @@ -82,103 +27,4 @@ public class FavoritesFragment extends AbsLibraryPagerRecyclerViewCustomGridSize QueryUtil.applySortOrder(query, PreferenceUtil.getInstance(App.getInstance()).getSongSortOrder()); return query; } - - @Override - protected void loadItems(int index) { - ItemQuery query = getQuery(); - query.setStartIndex(index); - - App.getApiClient().GetItemsAsync(query, new Response() { - @Override - public void onResponse(ItemsResult result) { - if (index == 0) getAdapter().getDataSet().clear(); - for (BaseItemDto itemDto : result.getItems()) { - getAdapter().getDataSet().add(new Song(itemDto)); - } - - size = result.getTotalRecordCount(); - getAdapter().notifyDataSetChanged(); - loading = false; - } - - @Override - public void onError(Exception exception) { - exception.printStackTrace(); - } - }); - } - - @Override - protected int getEmptyMessage() { - return R.string.no_songs; - } - - @Override - protected String loadSortMethod() { - return PreferenceUtil.getInstance(getActivity()).getSongSortMethod(); - } - - @Override - protected void saveSortMethod(String sortMethod) { - PreferenceUtil.getInstance(getActivity()).setSongSortMethod(sortMethod); - } - - @Override - protected void setSortMethod(String sortMethod) { - } - - @Override - protected String loadSortOrder() { - return PreferenceUtil.getInstance(getActivity()).getSongSortOrder(); - } - - @Override - protected void saveSortOrder(String sortOrder) { - PreferenceUtil.getInstance(getActivity()).setSongSortOrder(sortOrder); - } - - @Override - protected void setSortOrder(String sortOrder) { - } - - @Override - protected int loadGridSize() { - return PreferenceUtil.getInstance(getActivity()).getSongGridSize(requireActivity()); - } - - @Override - protected void saveGridSize(int gridSize) { - PreferenceUtil.getInstance(getActivity()).setSongGridSize(gridSize); - } - - @Override - protected int loadGridSizeLand() { - return PreferenceUtil.getInstance(getActivity()).getSongGridSizeLand(requireActivity()); - } - - @Override - protected void saveGridSizeLand(int gridSize) { - PreferenceUtil.getInstance(getActivity()).setSongGridSizeLand(gridSize); - } - - @Override - public void saveUsePalette(boolean usePalette) { - PreferenceUtil.getInstance(getActivity()).setSongColoredFooters(usePalette); - } - - @Override - public boolean loadUsePalette() { - return PreferenceUtil.getInstance(getActivity()).getSongColoredFooters(); - } - - @Override - public void setUsePalette(boolean usePalette) { - getAdapter().usePalette(usePalette); - } - - @Override - protected void setGridSize(int gridSize) { - getLayoutManager().setSpanCount(gridSize); - getAdapter().notifyDataSetChanged(); - } } From e52029d47aa9aee2400fc7e6168ac4408da20640 Mon Sep 17 00:00:00 2001 From: dkanada Date: Sat, 20 Feb 2021 12:26:38 +0900 Subject: [PATCH 6/8] fix issue with queue playback on app start --- .../java/com/dkanada/gramophone/service/MusicService.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/com/dkanada/gramophone/service/MusicService.java b/app/src/main/java/com/dkanada/gramophone/service/MusicService.java index 50d2896b..7d1cf37c 100644 --- a/app/src/main/java/com/dkanada/gramophone/service/MusicService.java +++ b/app/src/main/java/com/dkanada/gramophone/service/MusicService.java @@ -449,8 +449,8 @@ public class MusicService extends Service implements SharedPreferences.OnSharedP if (restoredPositionInTrack > 0) seek(restoredPositionInTrack); notHandledMetaChangedForCurrentTrack = true; - sendChangeInternal(META_CHANGED); - sendChangeInternal(QUEUE_CHANGED); + handleChangeInternal(META_CHANGED); + handleChangeInternal(QUEUE_CHANGED); } } From 50acdf0d97811ea7db83a07689b94c9953be10d4 Mon Sep 17 00:00:00 2001 From: dkanada Date: Sat, 20 Feb 2021 12:34:59 +0900 Subject: [PATCH 7/8] enable crash activity for all builds --- app/src/main/java/com/dkanada/gramophone/App.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/com/dkanada/gramophone/App.java b/app/src/main/java/com/dkanada/gramophone/App.java index 6dd0cdb2..ca36012f 100644 --- a/app/src/main/java/com/dkanada/gramophone/App.java +++ b/app/src/main/java/com/dkanada/gramophone/App.java @@ -33,9 +33,8 @@ public class App extends Application { public void onCreate() { super.onCreate(); - if (BuildConfig.DEBUG) { - RedScreenOfDeath.init(this); - } + // enable for all builds to help with bug reports + RedScreenOfDeath.init(this); app = this; database = createDatabase(this); From 587daca499a287426cc34983111f1ab25994f4e7 Mon Sep 17 00:00:00 2001 From: dkanada Date: Sat, 20 Feb 2021 12:36:42 +0900 Subject: [PATCH 8/8] new release --- app/build.gradle | 4 ++-- metadata/en-US/changelogs/9.txt | 8 ++++++++ 2 files changed, 10 insertions(+), 2 deletions(-) create mode 100644 metadata/en-US/changelogs/9.txt diff --git a/app/build.gradle b/app/build.gradle index a9e44c03..b3d7f366 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -8,8 +8,8 @@ android { minSdkVersion 19 targetSdkVersion 30 - versionCode 8 - versionName '1.2.0' + versionCode 9 + versionName '1.2.1' multiDexEnabled true vectorDrawables { diff --git a/metadata/en-US/changelogs/9.txt b/metadata/en-US/changelogs/9.txt new file mode 100644 index 00000000..82d0692b --- /dev/null +++ b/metadata/en-US/changelogs/9.txt @@ -0,0 +1,8 @@ +- move glide cache to the proper location +- fix issue with lock screen cover display +- change default sort method to random +- replace queue store with room database +- huge improvements for login activity style +- add crash activity to display errors +- refactor ExoPlayer wrapper +- implement favorites tab on home activity