diff --git a/application/television/src/main/java/org/videolan/television/viewmodel/MainTvModel.kt b/application/television/src/main/java/org/videolan/television/viewmodel/MainTvModel.kt index f805b91e7..a92bc32f0 100644 --- a/application/television/src/main/java/org/videolan/television/viewmodel/MainTvModel.kt +++ b/application/television/src/main/java/org/videolan/television/viewmodel/MainTvModel.kt @@ -33,6 +33,7 @@ import kotlinx.coroutines.channels.actor import kotlinx.coroutines.flow.launchIn import kotlinx.coroutines.flow.onEach import org.videolan.medialibrary.interfaces.Medialibrary +import org.videolan.medialibrary.interfaces.media.Playlist import org.videolan.medialibrary.interfaces.media.MediaWrapper import org.videolan.medialibrary.media.DummyItem import org.videolan.medialibrary.media.MediaLibraryItem @@ -202,7 +203,7 @@ class MainTvModel(app: Application) : AndroidViewModel(app), Medialibrary.OnMedi private fun updatePlaylists() = viewModelScope.launch { context.getFromMl { - getPagedPlaylists(Medialibrary.SORT_INSERTIONDATE, true, true, NUM_ITEMS_PREVIEW, 0) + getPagedPlaylists(Playlist.Type.All, Medialibrary.SORT_INSERTIONDATE, true, true, NUM_ITEMS_PREVIEW, 0) }.let { (playlist as MutableLiveData).value = mutableListOf().apply { add(DummyItem(HEADER_PLAYLISTS, context.getString(R.string.playlists), "")) diff --git a/application/television/src/main/java/org/videolan/television/viewmodel/MediaBrowserViewModel.kt b/application/television/src/main/java/org/videolan/television/viewmodel/MediaBrowserViewModel.kt index 0f489cfe0..d163ce9bf 100644 --- a/application/television/src/main/java/org/videolan/television/viewmodel/MediaBrowserViewModel.kt +++ b/application/television/src/main/java/org/videolan/television/viewmodel/MediaBrowserViewModel.kt @@ -4,6 +4,7 @@ import android.content.Context import androidx.fragment.app.Fragment import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModelProvider +import org.videolan.medialibrary.interfaces.media.Playlist import org.videolan.medialibrary.media.MediaLibraryItem import org.videolan.resources.* import org.videolan.vlc.providers.medialibrary.* @@ -22,7 +23,7 @@ class MediaBrowserViewModel(context: Context, val category: Long, val parent : M CATEGORY_ARTISTS -> ArtistsProvider(context, this, false) CATEGORY_GENRES -> GenresProvider(context, this) CATEGORY_VIDEOS -> VideosProvider(null, null, context, this) - CATEGORY_PLAYLISTS -> PlaylistsProvider(context, this) + CATEGORY_PLAYLISTS -> PlaylistsProvider(context, this, Playlist.Type.All) else -> TracksProvider(null, context, this) } override val providers = arrayOf(provider) diff --git a/application/vlc-android/src/org/videolan/vlc/gui/PlaylistFragment.kt b/application/vlc-android/src/org/videolan/vlc/gui/PlaylistFragment.kt index f5c0dadf6..567c14294 100644 --- a/application/vlc-android/src/org/videolan/vlc/gui/PlaylistFragment.kt +++ b/application/vlc-android/src/org/videolan/vlc/gui/PlaylistFragment.kt @@ -35,6 +35,7 @@ import com.google.android.material.appbar.AppBarLayout import com.google.android.material.floatingactionbutton.FloatingActionButton import org.videolan.medialibrary.interfaces.Medialibrary import org.videolan.medialibrary.interfaces.media.MediaWrapper +import org.videolan.medialibrary.interfaces.media.Playlist import org.videolan.medialibrary.media.MediaLibraryItem import org.videolan.resources.CTX_PLAY_ALL import org.videolan.tools.Settings @@ -68,7 +69,7 @@ class PlaylistFragment : BaseAudioBrowser(), SwipeRefreshLay override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) - viewModel = getViewModel() + viewModel = getViewModel(Playlist.Type.All) } override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { diff --git a/application/vlc-android/src/org/videolan/vlc/gui/dialogs/SavePlaylistDialog.kt b/application/vlc-android/src/org/videolan/vlc/gui/dialogs/SavePlaylistDialog.kt index cb5605949..6c79ce843 100644 --- a/application/vlc-android/src/org/videolan/vlc/gui/dialogs/SavePlaylistDialog.kt +++ b/application/vlc-android/src/org/videolan/vlc/gui/dialogs/SavePlaylistDialog.kt @@ -153,7 +153,7 @@ class SavePlaylistDialog : VLCBottomSheetDialogFragment(), View.OnClickListener, } binding.list.layoutManager = LinearLayoutManager(view.context) binding.list.adapter = adapter - adapter.submitList(listOf(*medialibrary.playlists.apply { forEach { it.description = resources.getQuantityString(R.plurals.media_quantity, it.tracksCount, it.tracksCount) } })) + adapter.submitList(listOf(*medialibrary.getPlaylists(Playlist.Type.All).apply { forEach { it.description = resources.getQuantityString(R.plurals.media_quantity, it.tracksCount, it.tracksCount) } })) if (!Tools.isArrayEmpty(newTracks)) binding.dialogPlaylistSave.setText(R.string.save) updateEmptyView() parentFragmentManager.setFragmentResultListener( @@ -261,4 +261,4 @@ class SavePlaylistDialog : VLCBottomSheetDialogFragment(), View.OnClickListener, } } -fun Medialibrary.getPlaylistByName(name: String) = playlists.firstOrNull { it.title == name } +fun Medialibrary.getPlaylistByName(name: String) = getPlaylists(Playlist.Type.All).firstOrNull { it.title == name } diff --git a/application/vlc-android/src/org/videolan/vlc/media/MediaSessionBrowser.kt b/application/vlc-android/src/org/videolan/vlc/media/MediaSessionBrowser.kt index eb12f14ce..2512d90af 100644 --- a/application/vlc-android/src/org/videolan/vlc/media/MediaSessionBrowser.kt +++ b/application/vlc-android/src/org/videolan/vlc/media/MediaSessionBrowser.kt @@ -37,6 +37,7 @@ import androidx.core.net.toUri import org.videolan.medialibrary.interfaces.Medialibrary import org.videolan.medialibrary.interfaces.media.Album import org.videolan.medialibrary.interfaces.media.MediaWrapper +import org.videolan.medialibrary.interfaces.media.Playlist import org.videolan.medialibrary.media.MediaLibraryItem import org.videolan.resources.* import org.videolan.tools.* @@ -293,7 +294,7 @@ class MediaSessionBrowser { list = genres.copyOfRange(pageOffset.coerceAtMost(genres.size), (pageOffset + MAX_RESULT_SIZE).coerceAtMost(genres.size)) } ID_PLAYLIST -> { - list = ml.playlists + list = ml.getPlaylists(Playlist.Type.AudioOnly) list.sortWith(MediaComparators.ANDROID_AUTO) } ID_STREAM -> { diff --git a/application/vlc-android/src/org/videolan/vlc/providers/medialibrary/PlaylistsProvider.kt b/application/vlc-android/src/org/videolan/vlc/providers/medialibrary/PlaylistsProvider.kt index 591fe1913..862b53614 100644 --- a/application/vlc-android/src/org/videolan/vlc/providers/medialibrary/PlaylistsProvider.kt +++ b/application/vlc-android/src/org/videolan/vlc/providers/medialibrary/PlaylistsProvider.kt @@ -27,12 +27,12 @@ import org.videolan.medialibrary.interfaces.media.Playlist import org.videolan.tools.Settings import org.videolan.vlc.viewmodels.SortableModel -class PlaylistsProvider(context: Context, model: SortableModel) : MedialibraryProvider(context, model) { +class PlaylistsProvider(context: Context, model: SortableModel, val type: Playlist.Type) : MedialibraryProvider(context, model) { - override fun getAll() : Array = medialibrary.getPlaylists(sort, desc, Settings.includeMissing) + override fun getAll() : Array = medialibrary.getPlaylists(type, sort, desc, Settings.includeMissing) override fun getPage(loadSize: Int, startposition: Int) : Array { - val list = if (model.filterQuery == null) medialibrary.getPagedPlaylists(sort, desc, Settings.includeMissing, loadSize, startposition) + val list = if (model.filterQuery == null) medialibrary.getPagedPlaylists(type, sort, desc, Settings.includeMissing, loadSize, startposition) else medialibrary.searchPlaylist(model.filterQuery, Playlist.Type.All, sort, desc, Settings.includeMissing, loadSize, startposition) model.viewModelScope.launch { completeHeaders(list, startposition) } return list diff --git a/application/vlc-android/src/org/videolan/vlc/viewmodels/mobile/PlaylistsViewModel.kt b/application/vlc-android/src/org/videolan/vlc/viewmodels/mobile/PlaylistsViewModel.kt index b33cd57fc..cb84aa347 100644 --- a/application/vlc-android/src/org/videolan/vlc/viewmodels/mobile/PlaylistsViewModel.kt +++ b/application/vlc-android/src/org/videolan/vlc/viewmodels/mobile/PlaylistsViewModel.kt @@ -23,15 +23,16 @@ package org.videolan.vlc.viewmodels.mobile import android.content.Context import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModelProvider +import org.videolan.medialibrary.interfaces.media.Playlist import org.videolan.medialibrary.media.MediaLibraryItem import org.videolan.vlc.gui.PlaylistFragment import org.videolan.vlc.providers.medialibrary.MedialibraryProvider import org.videolan.vlc.providers.medialibrary.PlaylistsProvider import org.videolan.vlc.viewmodels.MedialibraryViewModel -class PlaylistsViewModel(context: Context) : MedialibraryViewModel(context) { +class PlaylistsViewModel(context: Context, type: Playlist.Type) : MedialibraryViewModel(context) { val displayModeKey: String = "display_mode_playlists" - val provider = PlaylistsProvider(context, this) + val provider = PlaylistsProvider(context, this, type) var providerInCard = true override val providers : Array> = arrayOf(provider) @@ -40,12 +41,12 @@ class PlaylistsViewModel(context: Context) : MedialibraryViewModel(context) { providerInCard = settings.getBoolean(displayModeKey, providerInCard) } - class Factory(val context: Context): ViewModelProvider.NewInstanceFactory() { + class Factory(val context: Context, val type: Playlist.Type): ViewModelProvider.NewInstanceFactory() { override fun create(modelClass: Class): T { @Suppress("UNCHECKED_CAST") - return PlaylistsViewModel(context.applicationContext) as T + return PlaylistsViewModel(context.applicationContext, type) as T } } } -internal fun PlaylistFragment.getViewModel() = ViewModelProvider(requireActivity(), PlaylistsViewModel.Factory(requireContext())).get(PlaylistsViewModel::class.java) \ No newline at end of file +internal fun PlaylistFragment.getViewModel(type: Playlist.Type) = ViewModelProvider(requireActivity(), PlaylistsViewModel.Factory(requireContext(), type)).get(PlaylistsViewModel::class.java) \ No newline at end of file diff --git a/medialibrary/jni/AndroidMediaLibrary.cpp b/medialibrary/jni/AndroidMediaLibrary.cpp index fbcac616f..5989aaff0 100644 --- a/medialibrary/jni/AndroidMediaLibrary.cpp +++ b/medialibrary/jni/AndroidMediaLibrary.cpp @@ -437,9 +437,9 @@ AndroidMediaLibrary::genre(int64_t genreId) } medialibrary::Query -AndroidMediaLibrary::playlists(const medialibrary::QueryParameters* params) +AndroidMediaLibrary::playlists(medialibrary::PlaylistType type, medialibrary::QueryParameters* params) { - return p_ml->playlists(medialibrary::PlaylistType::All, params); + return p_ml->playlists(type, params); } medialibrary::PlaylistPtr diff --git a/medialibrary/jni/AndroidMediaLibrary.h b/medialibrary/jni/AndroidMediaLibrary.h index 181c45ca7..a9882dc1a 100644 --- a/medialibrary/jni/AndroidMediaLibrary.h +++ b/medialibrary/jni/AndroidMediaLibrary.h @@ -96,7 +96,7 @@ public: medialibrary::ArtistPtr artist(int64_t artistId); medialibrary::Query genres(const medialibrary::QueryParameters* params); medialibrary::GenrePtr genre(int64_t genreId); - medialibrary::Query playlists(const medialibrary::QueryParameters* params); + medialibrary::Query playlists(medialibrary::PlaylistType type, medialibrary::QueryParameters* params); medialibrary::PlaylistPtr playlist( int64_t playlistId ); medialibrary::PlaylistPtr PlaylistCreate( const std::string &name ); medialibrary::Query tracksFromAlbum( int64_t albumId, const medialibrary::QueryParameters* params = nullptr ); diff --git a/medialibrary/jni/medialibrary.cpp b/medialibrary/jni/medialibrary.cpp index 8a11a26bb..a86295a9f 100644 --- a/medialibrary/jni/medialibrary.cpp +++ b/medialibrary/jni/medialibrary.cpp @@ -915,11 +915,11 @@ getGenre(JNIEnv* env, jobject thiz, jlong id) } jobjectArray -getPlaylists(JNIEnv* env, jobject thiz, jint sortingCriteria, jboolean desc, jboolean includeMissing) +getPlaylists(JNIEnv* env, jobject thiz, medialibrary::PlaylistType type, jint sortingCriteria, jboolean desc, jboolean includeMissing) { AndroidMediaLibrary *aml = MediaLibrary_getInstance(env, thiz); medialibrary::QueryParameters params = generateParams(sortingCriteria, desc, includeMissing); - std::vector playlists = aml->playlists(¶ms)->all(); + std::vector playlists = aml->playlists(type, ¶ms)->all(); jobjectArray playlistRefs = (jobjectArray) env->NewObjectArray(playlists.size(), ml_fields.Playlist.clazz, NULL); int index = -1; for(medialibrary::PlaylistPtr const& playlist : playlists) { @@ -931,11 +931,11 @@ getPlaylists(JNIEnv* env, jobject thiz, jint sortingCriteria, jboolean desc, jbo jobjectArray -getPagedPlaylists(JNIEnv* env, jobject thiz, jint sortingCriteria, jboolean desc, jboolean includeMissing, jint nbItems, jint offset) +getPagedPlaylists(JNIEnv* env, jobject thiz, medialibrary::PlaylistType type, jint sortingCriteria, jboolean desc, jboolean includeMissing, jint nbItems, jint offset) { AndroidMediaLibrary *aml = MediaLibrary_getInstance(env, thiz); medialibrary::QueryParameters params = generateParams(sortingCriteria, desc, includeMissing); - const auto query = aml->playlists(¶ms); + const auto query = aml->playlists(type, ¶ms); std::vector playlists = nbItems != 0 ? query->items(nbItems, offset) : query->all(); jobjectArray playlistRefs = (jobjectArray) env->NewObjectArray(playlists.size(), ml_fields.Playlist.clazz, NULL); int index = -1; @@ -947,8 +947,8 @@ getPagedPlaylists(JNIEnv* env, jobject thiz, jint sortingCriteria, jboolean desc } jint -getPlaylistsCount(JNIEnv* env, jobject thiz) { - return (jint) MediaLibrary_getInstance(env, thiz)->playlists(nullptr)->count(); +getPlaylistsCount(JNIEnv* env, medialibrary::PlaylistType type, jobject thiz) { + return (jint) MediaLibrary_getInstance(env, thiz)->playlists(type, nullptr)->count(); } jobject @@ -2444,8 +2444,8 @@ static JNINativeMethod methods[] = { {"nativeGetPagedGenres", "(IZZII)[Lorg/videolan/medialibrary/interfaces/media/Genre;", (void*)getPagedGenres }, {"nativeGetGenresCount", "()I", (void*)getGenresCount }, {"nativeGetGenre", "(J)Lorg/videolan/medialibrary/interfaces/media/Genre;", (void*)getGenre }, - {"nativeGetPlaylists", "(IZZ)[Lorg/videolan/medialibrary/interfaces/media/Playlist;", (void*)getPlaylists }, - {"nativeGetPagedPlaylists", "(IZZII)[Lorg/videolan/medialibrary/interfaces/media/Playlist;", (void*)getPagedPlaylists }, + {"nativeGetPlaylists", "(IIZZ)[Lorg/videolan/medialibrary/interfaces/media/Playlist;", (void*)getPlaylists }, + {"nativeGetPagedPlaylists", "(IIZZII)[Lorg/videolan/medialibrary/interfaces/media/Playlist;", (void*)getPagedPlaylists }, {"nativeGetPlaylistsCount", "()I", (void*)getPlaylistsCount }, {"nativeGetPlaylist", "(JZ)Lorg/videolan/medialibrary/interfaces/media/Playlist;", (void*)getPlaylist }, {"nativeGetFolders", "(IIZZII)[Lorg/videolan/medialibrary/interfaces/media/Folder;", (void*)folders }, diff --git a/medialibrary/src/org/videolan/medialibrary/MedialibraryImpl.java b/medialibrary/src/org/videolan/medialibrary/MedialibraryImpl.java index 0af7cfde7..17239c493 100644 --- a/medialibrary/src/org/videolan/medialibrary/MedialibraryImpl.java +++ b/medialibrary/src/org/videolan/medialibrary/MedialibraryImpl.java @@ -361,18 +361,18 @@ public class MedialibraryImpl extends Medialibrary { } @WorkerThread - public Playlist[] getPlaylists() { - return getPlaylists(Medialibrary.SORT_DEFAULT, false, true); + public Playlist[] getPlaylists(Playlist.Type type) { + return getPlaylists(type, Medialibrary.SORT_DEFAULT, false, true); } @WorkerThread - public Playlist[] getPlaylists(int sort, boolean desc, boolean includeMissing) { - return mIsInitiated ? nativeGetPlaylists(sort, desc, includeMissing) : new Playlist[0]; + public Playlist[] getPlaylists(Playlist.Type type, int sort, boolean desc, boolean includeMissing) { + return mIsInitiated ? nativeGetPlaylists(type.ordinal(), sort, desc, includeMissing) : new Playlist[0]; } @WorkerThread - public Playlist[] getPagedPlaylists(int sort, boolean desc, boolean includeMissing, int nbItems, int offset) { - return mIsInitiated ? nativeGetPagedPlaylists(sort, desc, includeMissing, nbItems, offset) : new Playlist[0]; + public Playlist[] getPagedPlaylists(Playlist.Type type, int sort, boolean desc, boolean includeMissing, int nbItems, int offset) { + return mIsInitiated ? nativeGetPagedPlaylists(type.ordinal(), sort, desc, includeMissing, nbItems, offset) : new Playlist[0]; } public int getPlaylistsCount() { @@ -706,8 +706,8 @@ public class MedialibraryImpl extends Medialibrary { private native Genre[] nativeGetPagedGenres(int sort, boolean desc, boolean includeMissing, int nbItems, int offset); private native int nativeGetGenresCount(); private native Genre nativeGetGenre(long genreId); - private native Playlist[] nativeGetPlaylists(int sort, boolean desc, boolean includeMissing); - private native Playlist[] nativeGetPagedPlaylists(int sort, boolean desc, boolean includeMissing, int nbItems, int offset); + private native Playlist[] nativeGetPlaylists(int type, int sort, boolean desc, boolean includeMissing); + private native Playlist[] nativeGetPagedPlaylists(int type, int sort, boolean desc, boolean includeMissing, int nbItems, int offset); private native int nativeGetPlaylistsCount(); private native Playlist nativeGetPlaylist(long playlistId, boolean includeMissing); private native Playlist nativePlaylistCreate(String name, boolean includeMissing); diff --git a/medialibrary/src/org/videolan/medialibrary/interfaces/Medialibrary.java b/medialibrary/src/org/videolan/medialibrary/interfaces/Medialibrary.java index e9a54b661..8fa2f3f92 100644 --- a/medialibrary/src/org/videolan/medialibrary/interfaces/Medialibrary.java +++ b/medialibrary/src/org/videolan/medialibrary/interfaces/Medialibrary.java @@ -753,9 +753,9 @@ abstract public class Medialibrary { abstract public int getGenresCount(); abstract public int getGenresCount(String query); abstract public Genre getGenre(long genreId); - abstract public Playlist[] getPlaylists(int sort, boolean desc, boolean includeMissing); - abstract public Playlist[] getPlaylists(); - abstract public Playlist[] getPagedPlaylists(int sort, boolean desc, boolean includeMissing, int nbItems, int offset); + abstract public Playlist[] getPlaylists(Playlist.Type type, int sort, boolean desc, boolean includeMissing); + abstract public Playlist[] getPlaylists(Playlist.Type type); + abstract public Playlist[] getPagedPlaylists(Playlist.Type type, int sort, boolean desc, boolean includeMissing, int nbItems, int offset); abstract public int getPlaylistsCount(); abstract public int getPlaylistsCount(String query); abstract public Playlist getPlaylist(long playlistId, boolean includeMissing); diff --git a/medialibrary/src/org/videolan/medialibrary/stubs/StubMedialibrary.java b/medialibrary/src/org/videolan/medialibrary/stubs/StubMedialibrary.java index fe7bf3067..354dbc208 100644 --- a/medialibrary/src/org/videolan/medialibrary/stubs/StubMedialibrary.java +++ b/medialibrary/src/org/videolan/medialibrary/stubs/StubMedialibrary.java @@ -319,15 +319,15 @@ public class StubMedialibrary extends Medialibrary { return null; } - public Playlist[] getPlaylists() { + public Playlist[] getPlaylists(Playlist.Type type) { return dt.mPlaylists.toArray(new Playlist[0]); } - public Playlist[] getPlaylists(int sort, boolean desc, boolean includeMissing) { + public Playlist[] getPlaylists(Playlist.Type type, int sort, boolean desc, boolean includeMissing) { return dt.sortPlaylist(dt.mPlaylists, sort, desc); } - public Playlist[] getPagedPlaylists(int sort, boolean desc, boolean includeMissing, int nbItems, int offset) { + public Playlist[] getPagedPlaylists(Playlist.Type type, int sort, boolean desc, boolean includeMissing, int nbItems, int offset) { return dt.sortPlaylist(dt.secureSublist(dt.mPlaylists, offset, offset + nbItems), sort, desc); }