diff --git a/compile.sh b/compile.sh index b7cdf8b81..c9c59db53 100755 --- a/compile.sh +++ b/compile.sh @@ -66,6 +66,9 @@ while [ $# -gt 0 ]; do run) RUN=1 ;; + test) + TEST=1 + ;; --no-ml) NO_ML=1 ;; @@ -370,10 +373,14 @@ fi ####### if [ "$RUN" = 1 ]; then export PATH="${ANDROID_SDK}/platform-tools/:$PATH" + EXTRA="" + if [ "$TEST" = 1 ]; then + EXTRA="--ez 'extra_test_stubs' true" + fi adb wait-for-device if [ "$RELEASE" = 1 ]; then - adb shell am start -n org.videolan.vlc/org.videolan.vlc.StartActivity + adb shell am start -n org.videolan.vlc/org.videolan.vlc.StartActivity $EXTRA else - adb shell am start -n org.videolan.vlc.debug/org.videolan.vlc.StartActivity + adb shell am start -n org.videolan.vlc.debug/org.videolan.vlc.StartActivity $EXTRA fi fi diff --git a/medialibrary/src/org/videolan/medialibrary/Medialibrary.java b/medialibrary/src/org/videolan/medialibrary/Medialibrary.java index 1bb349eff..8e5986a47 100644 --- a/medialibrary/src/org/videolan/medialibrary/Medialibrary.java +++ b/medialibrary/src/org/videolan/medialibrary/Medialibrary.java @@ -1,4 +1,5 @@ -/***************************************************************************** +/* + ***************************************************************************** * Medialibrary.java ***************************************************************************** * Copyright © 2017-2018 VLC authors and VideoLAN @@ -423,308 +424,6 @@ public class Medialibrary extends AMedialibrary { return mw; } - @SuppressWarnings("unused") - public void onMediaAdded(AMediaWrapper[] mediaList) { - synchronized (mMediaCbs) { - for (MediaCb cb : mMediaCbs) cb.onMediaAdded(); - } - } - - @SuppressWarnings("unused") - public void onMediaUpdated(AMediaWrapper[] mediaList) { - synchronized (mMediaCbs) { - for (MediaCb cb : mMediaCbs) cb.onMediaModified(); - } - } - - @SuppressWarnings("unused") - public void onMediaDeleted() { - synchronized (mMediaCbs) { - for (MediaCb cb : mMediaCbs) cb.onMediaDeleted(); - } - } - - @SuppressWarnings("unused") - public void onArtistsAdded() { - synchronized (mArtistsCbs) { - for (ArtistsCb cb : mArtistsCbs) cb.onArtistsAdded(); - } - } - - @SuppressWarnings("unused") - public void onArtistsModified() { - synchronized (mArtistsCbs) { - for (ArtistsCb cb : mArtistsCbs) cb.onArtistsModified(); - } - } - - @SuppressWarnings("unused") - public void onArtistsDeleted() { - synchronized (mArtistsCbs) { - for (ArtistsCb cb : mArtistsCbs) cb.onArtistsDeleted(); - } - } - - @SuppressWarnings("unused") - public void onAlbumsAdded() { - synchronized (mAlbumsCbs) { - for (AlbumsCb cb : mAlbumsCbs) cb.onAlbumsAdded(); - } - } - - @SuppressWarnings("unused") - public void onAlbumsModified() { - synchronized (mAlbumsCbs) { - for (AlbumsCb cb : mAlbumsCbs) cb.onAlbumsModified(); - } - } - - @SuppressWarnings("unused") - public void onAlbumsDeleted() { - synchronized (mAlbumsCbs) { - for (AlbumsCb cb : mAlbumsCbs) cb.onAlbumsDeleted(); - } - } - - @SuppressWarnings("unused") - public void onGenresAdded() { - synchronized (mGenreCbs) { - for (GenresCb cb : mGenreCbs) cb.onGenresAdded(); - } - } - - @SuppressWarnings("unused") - public void onGenresModified() { - synchronized (mGenreCbs) { - for (GenresCb cb : mGenreCbs) cb.onGenresModified(); - } - } - - @SuppressWarnings("unused") - public void onGenresDeleted() { - synchronized (mGenreCbs) { - for (GenresCb cb : mGenreCbs) cb.onGenresDeleted(); - } - } - - @SuppressWarnings("unused") - public void onPlaylistsAdded() { - synchronized (mPlaylistCbs) { - for (PlaylistsCb cb : mPlaylistCbs) cb.onPlaylistsAdded(); - } - } - - @SuppressWarnings("unused") - public void onPlaylistsModified() { - synchronized (mPlaylistCbs) { - for (PlaylistsCb cb : mPlaylistCbs) cb.onPlaylistsModified(); - } - } - - @SuppressWarnings("unused") - public void onPlaylistsDeleted() { - synchronized (mPlaylistCbs) { - for (PlaylistsCb cb : mPlaylistCbs) cb.onPlaylistsDeleted(); - } - } - - public void onDiscoveryStarted(String entryPoint) { - synchronized (devicesDiscoveryCbList) { - if (!devicesDiscoveryCbList.isEmpty()) - for (DevicesDiscoveryCb cb : devicesDiscoveryCbList) - cb.onDiscoveryStarted(entryPoint); - } - synchronized (entryPointsEventsCbList) { - if (!entryPointsEventsCbList.isEmpty()) - for (EntryPointsEventsCb cb : entryPointsEventsCbList) - cb.onDiscoveryStarted(entryPoint); - } - } - - public void onDiscoveryProgress(String entryPoint) { - synchronized (devicesDiscoveryCbList) { - if (!devicesDiscoveryCbList.isEmpty()) - for (DevicesDiscoveryCb cb : devicesDiscoveryCbList) - cb.onDiscoveryProgress(entryPoint); - } - synchronized (entryPointsEventsCbList) { - if (!entryPointsEventsCbList.isEmpty()) - for (EntryPointsEventsCb cb : entryPointsEventsCbList) - cb.onDiscoveryProgress(entryPoint); - } - } - - public void onDiscoveryCompleted(String entryPoint) { - synchronized (devicesDiscoveryCbList) { - if (!devicesDiscoveryCbList.isEmpty()) - for (DevicesDiscoveryCb cb : devicesDiscoveryCbList) - cb.onDiscoveryCompleted(entryPoint); - } - synchronized (entryPointsEventsCbList) { - if (!entryPointsEventsCbList.isEmpty()) - for (EntryPointsEventsCb cb : entryPointsEventsCbList) - cb.onDiscoveryCompleted(entryPoint); - } - } - - public void onParsingStatsUpdated(int percent) { - synchronized (devicesDiscoveryCbList) { - if (!devicesDiscoveryCbList.isEmpty()) - for (DevicesDiscoveryCb cb : devicesDiscoveryCbList) - cb.onParsingStatsUpdated(percent); - } - } - - @SuppressWarnings("unused") - public void onBackgroundTasksIdleChanged(boolean isIdle) { - mIsWorking = !isIdle; - sRunning.postValue(mIsWorking); - LocalBroadcastManager.getInstance(sContext).sendBroadcast(new Intent(ACTION_IDLE).putExtra(STATE_IDLE, isIdle)); - if (isIdle) { - synchronized (onMedialibraryReadyListeners) { - for (OnMedialibraryReadyListener listener : onMedialibraryReadyListeners) listener.onMedialibraryIdle(); - } - } - } - - @SuppressWarnings("unused") - public void onReloadStarted(String entryPoint) { - synchronized (devicesDiscoveryCbList) { - if (!devicesDiscoveryCbList.isEmpty()) - for (DevicesDiscoveryCb cb : devicesDiscoveryCbList) - cb.onReloadStarted(entryPoint); - } - } - - @SuppressWarnings("unused") - public void onReloadCompleted(String entryPoint) { - synchronized (devicesDiscoveryCbList) { - if (!devicesDiscoveryCbList.isEmpty()) - for (DevicesDiscoveryCb cb : devicesDiscoveryCbList) - cb.onReloadCompleted(entryPoint); - } - } - - @SuppressWarnings("unused") - public void onEntryPointBanned(String entryPoint, boolean success) { - synchronized (entryPointsEventsCbList) { - if (!entryPointsEventsCbList.isEmpty()) - for (EntryPointsEventsCb cb : entryPointsEventsCbList) - cb.onEntryPointBanned(entryPoint, success); - } - } - - @SuppressWarnings("unused") - public void onEntryPointUnbanned(String entryPoint, boolean success) { - synchronized (entryPointsEventsCbList) { - if (!entryPointsEventsCbList.isEmpty()) - for (EntryPointsEventsCb cb : entryPointsEventsCbList) - cb.onEntryPointUnbanned(entryPoint, success); - } - } - - @SuppressWarnings("unused") - void onEntryPointAdded(String entryPoint, boolean success) { - synchronized (entryPointsEventsCbList) { - if (!entryPointsEventsCbList.isEmpty()) - for (EntryPointsEventsCb cb : entryPointsEventsCbList) - cb.onEntryPointAdded(entryPoint, success); - } - } - - @SuppressWarnings("unused") - public void onEntryPointRemoved(String entryPoint, boolean success) { - synchronized (entryPointsEventsCbList) { - if (!entryPointsEventsCbList.isEmpty()) - for (EntryPointsEventsCb cb : entryPointsEventsCbList) - cb.onEntryPointRemoved(entryPoint, success); - } - } - -// public static LiveData lastThumb = new SingleEvent<>(); - @SuppressWarnings({"unused", "unchecked"}) - public void onMediaThumbnailReady(AMediaWrapper media, boolean success) { - if (success) ((MutableLiveData)lastThumb).postValue(media); - } - - public void addMediaCb(MediaCb mediaUpdatedCb) { - if (!mIsInitiated) return; - synchronized (mMediaCbs) { -// if (mMediaCbs.isEmpty()) { -// nativeSetMediaAddedCbFlag(FLAG_MEDIA_ADDED_AUDIO|FLAG_MEDIA_ADDED_VIDEO); -// nativeSetMediaUpdatedCbFlag(FLAG_MEDIA_UPDATED_AUDIO|FLAG_MEDIA_UPDATED_VIDEO); -// } - mMediaCbs.add(mediaUpdatedCb); - } - } - - public void removeMediaCb(MediaCb mediaUpdatedCb) { - if (!mIsInitiated) return; - synchronized (mMediaCbs) { - mMediaCbs.remove(mediaUpdatedCb); -// if (mMediaCbs.isEmpty()) { -// nativeSetMediaAddedCbFlag(0); -// nativeSetMediaUpdatedCbFlag(0); -// } - } - } - - public void addArtistsCb(ArtistsCb artistsAddedCb) { - if (!mIsInitiated) return; - synchronized (mArtistsCbs) { - mArtistsCbs.add(artistsAddedCb); - } - } - - public void removeArtistsCb(ArtistsCb artistsAddedCb) { - if (!mIsInitiated) return; - synchronized (mArtistsCbs) { - mArtistsCbs.remove(artistsAddedCb); - } - } - - public void addAlbumsCb(AlbumsCb AlbumsAddedCb) { - if (!mIsInitiated) return; - synchronized (mAlbumsCbs) { - mAlbumsCbs.add(AlbumsAddedCb); - } - } - - public void removeAlbumsCb(AlbumsCb AlbumsAddedCb) { - if (!mIsInitiated) return; - synchronized (mAlbumsCbs) { - mAlbumsCbs.remove(AlbumsAddedCb); - } - } - - public void addGenreCb(GenresCb GenreCb) { - if (!mIsInitiated) return; - synchronized (mGenreCbs) { - this.mGenreCbs.add(GenreCb); - } - } - - public void removeGenreCb(GenresCb GenreCb) { - if (!mIsInitiated) return; - synchronized (mGenreCbs) { - this.mGenreCbs.remove(GenreCb); - } - } - - public void addPlaylistCb(PlaylistsCb playlistCb) { - if (!mIsInitiated) return; - synchronized (mPlaylistCbs) { - this.mPlaylistCbs.add(playlistCb); - } - } - - public void removePlaylistCb(PlaylistsCb playlistCb) { - if (!mIsInitiated) return; - synchronized (mPlaylistCbs) { - this.mPlaylistCbs.remove(playlistCb); - } - } - public SearchAggregate search(String query) { return mIsInitiated && !TextUtils.isEmpty(query) ? nativeSearch(query) : null; } @@ -789,58 +488,6 @@ public class Medialibrary extends AMedialibrary { return mIsInitiated && !TextUtils.isEmpty(query) ? nativeSearchPagedPlaylist(query, sort, desc, nbItems, offset) : null; } - public void addDeviceDiscoveryCb(DevicesDiscoveryCb cb) { - synchronized (devicesDiscoveryCbList) { - if (!devicesDiscoveryCbList.contains(cb)) - devicesDiscoveryCbList.add(cb); - } - } - - public void removeDeviceDiscoveryCb(DevicesDiscoveryCb cb) { - synchronized (devicesDiscoveryCbList) { - devicesDiscoveryCbList.remove(cb); - } - } - - public void addOnMedialibraryReadyListener(OnMedialibraryReadyListener cb) { - synchronized (onMedialibraryReadyListeners) { - if (!onMedialibraryReadyListeners.contains(cb)) - onMedialibraryReadyListeners.add(cb); - } - } - - public void removeOnMedialibraryReadyListener(OnMedialibraryReadyListener cb) { - synchronized (onMedialibraryReadyListeners) { - onMedialibraryReadyListeners.remove(cb); - } - } - - public void addEntryPointsEventsCb(EntryPointsEventsCb cb) { - synchronized (entryPointsEventsCbList) { - if (!entryPointsEventsCbList.contains(cb)) - entryPointsEventsCbList.add(cb); - } - } - - public void removeEntryPointsEventsCb(EntryPointsEventsCb cb) { - synchronized (entryPointsEventsCbList) { - entryPointsEventsCbList.remove(cb); - } - } - - public void addOnDeviceChangeListener(OnDeviceChangeListener listener) { - synchronized (onDeviceChangeListeners) { - if (!onDeviceChangeListeners.contains(listener)) - onDeviceChangeListeners.add(listener); - } - } - - public void removeOnDeviceChangeListener(OnDeviceChangeListener listener) { - synchronized (onDeviceChangeListeners) { - onDeviceChangeListeners.remove(listener); - } - } - // Native methods private native int nativeInit(String dbPath, String thumbsPath); private native void nativeStart(); diff --git a/medialibrary/src/org/videolan/medialibrary/ServiceLocator.java b/medialibrary/src/org/videolan/medialibrary/ServiceLocator.java index f2c01f5ac..54bcb8a42 100644 --- a/medialibrary/src/org/videolan/medialibrary/ServiceLocator.java +++ b/medialibrary/src/org/videolan/medialibrary/ServiceLocator.java @@ -28,22 +28,18 @@ import org.videolan.medialibrary.stubs.StubPlaylist; public class ServiceLocator { - private static ServiceLocator mServiceLocator; private static LocatorMode mMode = LocatorMode.VLC_ANDROID; public static void setLocatorMode(LocatorMode mode) { ServiceLocator.mMode = mode; } - enum LocatorMode { + public static String EXTRA_TEST_STUBS = "extra_test_stubs"; + public enum LocatorMode { VLC_ANDROID, TESTS, } - public static ServiceLocator getInstance() { - return mServiceLocator; - } - public static AMedialibrary getAMedialibrary() { if (mMode == LocatorMode.VLC_ANDROID) { return new Medialibrary(); diff --git a/medialibrary/src/org/videolan/medialibrary/interfaces/AMedialibrary.java b/medialibrary/src/org/videolan/medialibrary/interfaces/AMedialibrary.java index a988a4f22..fd1b9a286 100644 --- a/medialibrary/src/org/videolan/medialibrary/interfaces/AMedialibrary.java +++ b/medialibrary/src/org/videolan/medialibrary/interfaces/AMedialibrary.java @@ -2,18 +2,22 @@ package org.videolan.medialibrary.interfaces; import android.Manifest; import android.content.Context; +import android.content.Intent; import android.content.pm.PackageManager; import android.net.Uri; import android.os.Build; import android.os.Environment; +import android.text.TextUtils; import androidx.annotation.NonNull; import androidx.core.content.ContextCompat; import androidx.lifecycle.LiveData; import androidx.lifecycle.MutableLiveData; +import androidx.localbroadcastmanager.content.LocalBroadcastManager; import org.videolan.medialibrary.ServiceLocator; import org.videolan.medialibrary.SingleEvent; +import org.videolan.medialibrary.Tools; import org.videolan.medialibrary.interfaces.media.AAlbum; import org.videolan.medialibrary.interfaces.media.AArtist; import org.videolan.medialibrary.interfaces.media.AFolder; @@ -101,7 +105,6 @@ abstract public class AMedialibrary { @NonNull public static AMedialibrary getInstance() { - System.out.println("This is the real medialibrary"); return instance; } @@ -197,6 +200,382 @@ abstract public class AMedialibrary { void onDeviceChange(); } + // If media is not in ML, find it with its path + public AMediaWrapper findMedia(AMediaWrapper mw) { + if (mIsInitiated && mw != null && mw.getId() == 0L) { + final Uri uri = mw.getUri(); + final AMediaWrapper libraryMedia = getMedia(uri); + if (libraryMedia != null) { + libraryMedia.addFlags(mw.getFlags()); + return libraryMedia; + } + if (TextUtils.equals("file", uri.getScheme()) && + uri.getPath() != null && uri.getPath().startsWith("/sdcard")) { + final AMediaWrapper alternateMedia = getMedia(Tools.convertLocalUri(uri)); + if (alternateMedia != null) { + alternateMedia.addFlags(mw.getFlags()); + return alternateMedia; + } + } + } + return mw; + } + + @SuppressWarnings("unused") + public void onMediaAdded(AMediaWrapper[] mediaList) { + synchronized (mMediaCbs) { + for (MediaCb cb : mMediaCbs) cb.onMediaAdded(); + } + } + + @SuppressWarnings("unused") + public void onMediaUpdated(AMediaWrapper[] mediaList) { + synchronized (mMediaCbs) { + for (MediaCb cb : mMediaCbs) cb.onMediaModified(); + } + } + + @SuppressWarnings("unused") + public void onMediaDeleted() { + synchronized (mMediaCbs) { + for (MediaCb cb : mMediaCbs) cb.onMediaDeleted(); + } + } + + @SuppressWarnings("unused") + public void onArtistsAdded() { + synchronized (mArtistsCbs) { + for (ArtistsCb cb : mArtistsCbs) cb.onArtistsAdded(); + } + } + + @SuppressWarnings("unused") + public void onArtistsModified() { + synchronized (mArtistsCbs) { + for (ArtistsCb cb : mArtistsCbs) cb.onArtistsModified(); + } + } + + @SuppressWarnings("unused") + public void onArtistsDeleted() { + synchronized (mArtistsCbs) { + for (ArtistsCb cb : mArtistsCbs) cb.onArtistsDeleted(); + } + } + + @SuppressWarnings("unused") + public void onAlbumsAdded() { + synchronized (mAlbumsCbs) { + for (AlbumsCb cb : mAlbumsCbs) cb.onAlbumsAdded(); + } + } + + @SuppressWarnings("unused") + public void onAlbumsModified() { + synchronized (mAlbumsCbs) { + for (AlbumsCb cb : mAlbumsCbs) cb.onAlbumsModified(); + } + } + + @SuppressWarnings("unused") + public void onAlbumsDeleted() { + synchronized (mAlbumsCbs) { + for (AlbumsCb cb : mAlbumsCbs) cb.onAlbumsDeleted(); + } + } + + @SuppressWarnings("unused") + public void onGenresAdded() { + synchronized (mGenreCbs) { + for (GenresCb cb : mGenreCbs) cb.onGenresAdded(); + } + } + + @SuppressWarnings("unused") + public void onGenresModified() { + synchronized (mGenreCbs) { + for (GenresCb cb : mGenreCbs) cb.onGenresModified(); + } + } + + @SuppressWarnings("unused") + public void onGenresDeleted() { + synchronized (mGenreCbs) { + for (GenresCb cb : mGenreCbs) cb.onGenresDeleted(); + } + } + + @SuppressWarnings("unused") + public void onPlaylistsAdded() { + synchronized (mPlaylistCbs) { + for (PlaylistsCb cb : mPlaylistCbs) cb.onPlaylistsAdded(); + } + } + + @SuppressWarnings("unused") + public void onPlaylistsModified() { + synchronized (mPlaylistCbs) { + for (PlaylistsCb cb : mPlaylistCbs) cb.onPlaylistsModified(); + } + } + + @SuppressWarnings("unused") + public void onPlaylistsDeleted() { + synchronized (mPlaylistCbs) { + for (PlaylistsCb cb : mPlaylistCbs) cb.onPlaylistsDeleted(); + } + } + + public void onDiscoveryStarted(String entryPoint) { + synchronized (devicesDiscoveryCbList) { + if (!devicesDiscoveryCbList.isEmpty()) + for (DevicesDiscoveryCb cb : devicesDiscoveryCbList) + cb.onDiscoveryStarted(entryPoint); + } + synchronized (entryPointsEventsCbList) { + if (!entryPointsEventsCbList.isEmpty()) + for (EntryPointsEventsCb cb : entryPointsEventsCbList) + cb.onDiscoveryStarted(entryPoint); + } + } + + public void onDiscoveryProgress(String entryPoint) { + synchronized (devicesDiscoveryCbList) { + if (!devicesDiscoveryCbList.isEmpty()) + for (DevicesDiscoveryCb cb : devicesDiscoveryCbList) + cb.onDiscoveryProgress(entryPoint); + } + synchronized (entryPointsEventsCbList) { + if (!entryPointsEventsCbList.isEmpty()) + for (EntryPointsEventsCb cb : entryPointsEventsCbList) + cb.onDiscoveryProgress(entryPoint); + } + } + + public void onDiscoveryCompleted(String entryPoint) { + synchronized (devicesDiscoveryCbList) { + if (!devicesDiscoveryCbList.isEmpty()) + for (DevicesDiscoveryCb cb : devicesDiscoveryCbList) + cb.onDiscoveryCompleted(entryPoint); + } + synchronized (entryPointsEventsCbList) { + if (!entryPointsEventsCbList.isEmpty()) + for (EntryPointsEventsCb cb : entryPointsEventsCbList) + cb.onDiscoveryCompleted(entryPoint); + } + } + + public void onParsingStatsUpdated(int percent) { + synchronized (devicesDiscoveryCbList) { + if (!devicesDiscoveryCbList.isEmpty()) + for (DevicesDiscoveryCb cb : devicesDiscoveryCbList) + cb.onParsingStatsUpdated(percent); + } + } + + @SuppressWarnings("unused") + public void onBackgroundTasksIdleChanged(boolean isIdle) { + mIsWorking = !isIdle; + sRunning.postValue(mIsWorking); + LocalBroadcastManager.getInstance(sContext).sendBroadcast(new Intent(ACTION_IDLE).putExtra(STATE_IDLE, isIdle)); + if (isIdle) { + synchronized (onMedialibraryReadyListeners) { + for (OnMedialibraryReadyListener listener : onMedialibraryReadyListeners) listener.onMedialibraryIdle(); + } + } + } + + @SuppressWarnings("unused") + public void onReloadStarted(String entryPoint) { + synchronized (devicesDiscoveryCbList) { + if (!devicesDiscoveryCbList.isEmpty()) + for (DevicesDiscoveryCb cb : devicesDiscoveryCbList) + cb.onReloadStarted(entryPoint); + } + } + + @SuppressWarnings("unused") + public void onReloadCompleted(String entryPoint) { + synchronized (devicesDiscoveryCbList) { + if (!devicesDiscoveryCbList.isEmpty()) + for (DevicesDiscoveryCb cb : devicesDiscoveryCbList) + cb.onReloadCompleted(entryPoint); + } + } + + @SuppressWarnings("unused") + public void onEntryPointBanned(String entryPoint, boolean success) { + synchronized (entryPointsEventsCbList) { + if (!entryPointsEventsCbList.isEmpty()) + for (EntryPointsEventsCb cb : entryPointsEventsCbList) + cb.onEntryPointBanned(entryPoint, success); + } + } + + @SuppressWarnings("unused") + public void onEntryPointUnbanned(String entryPoint, boolean success) { + synchronized (entryPointsEventsCbList) { + if (!entryPointsEventsCbList.isEmpty()) + for (EntryPointsEventsCb cb : entryPointsEventsCbList) + cb.onEntryPointUnbanned(entryPoint, success); + } + } + + + @SuppressWarnings("unused") + void onEntryPointAdded(String entryPoint, boolean success) { + synchronized (entryPointsEventsCbList) { + if (!entryPointsEventsCbList.isEmpty()) + for (EntryPointsEventsCb cb : entryPointsEventsCbList) + cb.onEntryPointAdded(entryPoint, success); + } + } + + @SuppressWarnings("unused") + public void onEntryPointRemoved(String entryPoint, boolean success) { + synchronized (entryPointsEventsCbList) { + if (!entryPointsEventsCbList.isEmpty()) + for (EntryPointsEventsCb cb : entryPointsEventsCbList) + cb.onEntryPointRemoved(entryPoint, success); + } + } + + // public static LiveData lastThumb = new SingleEvent<>(); + @SuppressWarnings({"unused", "unchecked"}) + public void onMediaThumbnailReady(AMediaWrapper media, boolean success) { + if (success) ((MutableLiveData)lastThumb).postValue(media); + } + + public void addMediaCb(MediaCb mediaUpdatedCb) { + if (!mIsInitiated) return; + synchronized (mMediaCbs) { +// if (mMediaCbs.isEmpty()) { +// nativeSetMediaAddedCbFlag(FLAG_MEDIA_ADDED_AUDIO|FLAG_MEDIA_ADDED_VIDEO); +// nativeSetMediaUpdatedCbFlag(FLAG_MEDIA_UPDATED_AUDIO|FLAG_MEDIA_UPDATED_VIDEO); +// } + mMediaCbs.add(mediaUpdatedCb); + } + } + + public void removeMediaCb(MediaCb mediaUpdatedCb) { + if (!mIsInitiated) return; + synchronized (mMediaCbs) { + mMediaCbs.remove(mediaUpdatedCb); +// if (mMediaCbs.isEmpty()) { +// nativeSetMediaAddedCbFlag(0); +// nativeSetMediaUpdatedCbFlag(0); +// } + } + } + + public void addArtistsCb(ArtistsCb artistsAddedCb) { + if (!mIsInitiated) return; + synchronized (mArtistsCbs) { + mArtistsCbs.add(artistsAddedCb); + } + } + + public void removeArtistsCb(ArtistsCb artistsAddedCb) { + if (!mIsInitiated) return; + synchronized (mArtistsCbs) { + mArtistsCbs.remove(artistsAddedCb); + } + } + + public void addAlbumsCb(AlbumsCb AlbumsAddedCb) { + if (!mIsInitiated) return; + synchronized (mAlbumsCbs) { + mAlbumsCbs.add(AlbumsAddedCb); + } + } + + public void removeAlbumsCb(AlbumsCb AlbumsAddedCb) { + if (!mIsInitiated) return; + synchronized (mAlbumsCbs) { + mAlbumsCbs.remove(AlbumsAddedCb); + } + } + + public void addGenreCb(GenresCb GenreCb) { + if (!mIsInitiated) return; + synchronized (mGenreCbs) { + this.mGenreCbs.add(GenreCb); + } + } + + public void removeGenreCb(GenresCb GenreCb) { + if (!mIsInitiated) return; + synchronized (mGenreCbs) { + this.mGenreCbs.remove(GenreCb); + } + } + + public void addPlaylistCb(PlaylistsCb playlistCb) { + if (!mIsInitiated) return; + synchronized (mPlaylistCbs) { + this.mPlaylistCbs.add(playlistCb); + } + } + + public void removePlaylistCb(PlaylistsCb playlistCb) { + if (!mIsInitiated) return; + synchronized (mPlaylistCbs) { + this.mPlaylistCbs.remove(playlistCb); + } + } + + public void addDeviceDiscoveryCb(DevicesDiscoveryCb cb) { + synchronized (devicesDiscoveryCbList) { + if (!devicesDiscoveryCbList.contains(cb)) + devicesDiscoveryCbList.add(cb); + } + } + + public void removeDeviceDiscoveryCb(DevicesDiscoveryCb cb) { + synchronized (devicesDiscoveryCbList) { + devicesDiscoveryCbList.remove(cb); + } + } + + public void addOnMedialibraryReadyListener(OnMedialibraryReadyListener cb) { + synchronized (onMedialibraryReadyListeners) { + if (!onMedialibraryReadyListeners.contains(cb)) + onMedialibraryReadyListeners.add(cb); + } + } + + public void removeOnMedialibraryReadyListener(OnMedialibraryReadyListener cb) { + synchronized (onMedialibraryReadyListeners) { + onMedialibraryReadyListeners.remove(cb); + } + } + + public void addEntryPointsEventsCb(EntryPointsEventsCb cb) { + synchronized (entryPointsEventsCbList) { + if (!entryPointsEventsCbList.contains(cb)) + entryPointsEventsCbList.add(cb); + } + } + + public void removeEntryPointsEventsCb(EntryPointsEventsCb cb) { + synchronized (entryPointsEventsCbList) { + entryPointsEventsCbList.remove(cb); + } + } + + public void addOnDeviceChangeListener(OnDeviceChangeListener listener) { + synchronized (onDeviceChangeListeners) { + if (!onDeviceChangeListeners.contains(listener)) + onDeviceChangeListeners.add(listener); + } + } + + public void removeOnDeviceChangeListener(OnDeviceChangeListener listener) { + synchronized (onDeviceChangeListeners) { + onDeviceChangeListeners.remove(listener); + } + } + abstract public int init(Context context); abstract public void start(); abstract public void banFolder(@NonNull String path); @@ -262,43 +641,6 @@ abstract public class AMedialibrary { abstract public int getFoldersCount(int type); abstract public void requestThumbnail(long id); abstract public boolean increasePlayCount(long mediaId); - abstract public AMediaWrapper findMedia(AMediaWrapper mw); - abstract public void onMediaAdded(AMediaWrapper[] mediaList); - abstract public void onMediaUpdated(AMediaWrapper[] mediaList); - abstract public void onMediaDeleted(); - abstract public void onArtistsAdded(); - abstract public void onArtistsModified(); - abstract public void onArtistsDeleted(); - abstract public void onAlbumsAdded(); - abstract public void onAlbumsModified(); - abstract public void onAlbumsDeleted(); - abstract public void onGenresAdded(); - abstract public void onGenresModified(); - abstract public void onGenresDeleted(); - abstract public void onPlaylistsAdded(); - abstract public void onPlaylistsModified(); - abstract public void onPlaylistsDeleted(); - abstract public void onDiscoveryStarted(String entryPoint); - abstract public void onDiscoveryProgress(String entryPoint); - abstract public void onDiscoveryCompleted(String entryPoint); - abstract public void onParsingStatsUpdated(int percent); - abstract public void onBackgroundTasksIdleChanged(boolean isIdle); - abstract public void onReloadStarted(String entryPoint); - abstract public void onReloadCompleted(String entryPoint); - abstract public void onEntryPointBanned(String entryPoint, boolean success); - abstract public void onEntryPointUnbanned(String entryPoint, boolean success); - abstract public void onEntryPointRemoved(String entryPoint, boolean success); - abstract public void onMediaThumbnailReady(AMediaWrapper Amedia, boolean success); - abstract public void addMediaCb(MediaCb mediaUpdated); - abstract public void removeMediaCb(MediaCb mediaUpdatedCb); - abstract public void addArtistsCb(ArtistsCb artictAddedCb); - abstract public void removeArtistsCb(ArtistsCb artistCb); - abstract public void addAlbumsCb(AlbumsCb albumsAddedCb); - abstract public void removeAlbumsCb(AlbumsCb albumsAddedCb); - abstract public void addGenreCb(GenresCb genresAddedCb); - abstract public void removeGenreCb(GenresCb genresAddedCb); - abstract public void addPlaylistCb(PlaylistsCb playlistsAddedCb); - abstract public void removePlaylistCb(PlaylistsCb playlistsAddedCb); abstract public SearchAggregate search(String query); abstract public AMediaWrapper[] searchMedia(String query); abstract public AMediaWrapper[] searchMedia(String query, int sort, boolean desc, int nbItems, int offset); @@ -315,12 +657,4 @@ abstract public class AMedialibrary { abstract public AGenre[] searchGenre(String query, int sort, boolean desc, int nbItems, int offset); abstract public APlaylist[] searchPlaylist(String query); abstract public APlaylist[] searchPlaylist(String query, int sort, boolean desc, int nbItems, int offset); - abstract public void addDeviceDiscoveryCb(DevicesDiscoveryCb cb); - abstract public void removeDeviceDiscoveryCb(DevicesDiscoveryCb cb); - abstract public void addOnMedialibraryReadyListener(OnMedialibraryReadyListener cb); - abstract public void removeOnMedialibraryReadyListener(OnMedialibraryReadyListener cb); - abstract public void addEntryPointsEventsCb(EntryPointsEventsCb cb); - abstract public void removeEntryPointsEventsCb(EntryPointsEventsCb cb); - abstract public void addOnDeviceChangeListener(OnDeviceChangeListener cb); - abstract public void removeOnDeviceChangeListener(OnDeviceChangeListener cb); } diff --git a/medialibrary/src/org/videolan/medialibrary/interfaces/media/AAlbum.java b/medialibrary/src/org/videolan/medialibrary/interfaces/media/AAlbum.java index 845a32d3d..9e61de137 100644 --- a/medialibrary/src/org/videolan/medialibrary/interfaces/media/AAlbum.java +++ b/medialibrary/src/org/videolan/medialibrary/interfaces/media/AAlbum.java @@ -53,6 +53,7 @@ public abstract class AAlbum extends MediaLibraryItem { abstract public AMediaWrapper[] getPagedTracks(int sort, boolean desc, int nbItems, int offset); abstract public AMediaWrapper[] searchTracks(String query, int sort, boolean desc, int nbItems, int offset); abstract public int searchTracksCount(String query); + abstract public AArtist getAlbumArtist(); @Override public long getId() { @@ -73,11 +74,6 @@ public abstract class AAlbum extends MediaLibraryItem { return artworkMrl; } - public AArtist getAlbumArtist() { - //TODO - return null; - } - @Override public int getTracksCount() { return mTracksCount; diff --git a/medialibrary/src/org/videolan/medialibrary/interfaces/media/AFolder.java b/medialibrary/src/org/videolan/medialibrary/interfaces/media/AFolder.java index ae986151f..90522a2da 100644 --- a/medialibrary/src/org/videolan/medialibrary/interfaces/media/AFolder.java +++ b/medialibrary/src/org/videolan/medialibrary/interfaces/media/AFolder.java @@ -13,7 +13,7 @@ public abstract class AFolder extends MediaLibraryItem { public static int TYPE_FOLDER_EXTERNAL = 3; public static int TYPE_FOLDER_STREAM = 4; - private String mMrl; + public String mMrl; public AFolder(long id, String name, String mrl) { super(id, name); diff --git a/medialibrary/src/org/videolan/medialibrary/interfaces/media/AMediaWrapper.java b/medialibrary/src/org/videolan/medialibrary/interfaces/media/AMediaWrapper.java index c3a995430..7e0314ac0 100644 --- a/medialibrary/src/org/videolan/medialibrary/interfaces/media/AMediaWrapper.java +++ b/medialibrary/src/org/videolan/medialibrary/interfaces/media/AMediaWrapper.java @@ -62,45 +62,45 @@ public abstract class AMediaWrapper extends MediaLibraryItem implements Parcelab public final static int META_APPLICATION_SPECIFIC = 250; // threshold lentgh between song and podcast ep, set to 15 minutes - private static final long PODCAST_THRESHOLD = 900000L; - private static final long PODCAST_ABSOLUTE = 3600000L; - - private String mDisplayTitle; - private String mArtist; - private String mGenre; - private String mCopyright; - private String mAlbum; - private int mTrackNumber; - private int mDiscNumber; - private String mAlbumArtist; - private String mRating; - private String mDate; - private String mSettings; - private String mNowPlaying; - private String mPublisher; - private String mEncodedBy; - private String mTrackID; + protected static final long PODCAST_THRESHOLD = 900000L; + protected static final long PODCAST_ABSOLUTE = 3600000L; + + protected String mDisplayTitle; + protected String mArtist; + protected String mGenre; + protected String mCopyright; + protected String mAlbum; + protected int mTrackNumber; + protected int mDiscNumber; + protected String mAlbumArtist; + protected String mRating; + protected String mDate; + protected String mSettings; + protected String mNowPlaying; + protected String mPublisher; + protected String mEncodedBy; + protected String mTrackID; protected String mArtworkURL; - private boolean mThumbnailGenerated; + protected boolean mThumbnailGenerated; - private final Uri mUri; - private String mFilename; + protected final Uri mUri; + protected String mFilename; protected long mTime = 0; - private long mDisplayTime = 0; + protected long mDisplayTime = 0; /* -1 is a valid track (Disabled) */ - private int mAudioTrack = -2; - private int mSpuTrack = -2; - private long mLength = 0; + protected int mAudioTrack = -2; + protected int mSpuTrack = -2; + protected long mLength = 0; protected int mType; - private int mWidth = 0; - private int mHeight = 0; - private Bitmap mPicture; - private boolean mIsPictureParsed; + protected int mWidth = 0; + protected int mHeight = 0; + protected Bitmap mPicture; + protected boolean mIsPictureParsed; protected int mFlags = 0; - private long mLastModified = 0L; - private Media.Slave[] mSlaves = null; + protected long mLastModified = 0L; + protected Media.Slave[] mSlaves = null; - private long mSeen = 0L; + protected long mSeen = 0L; public abstract void rename(String name); public abstract long getMetaLong(int metaDataType); diff --git a/medialibrary/src/org/videolan/medialibrary/media/Album.java b/medialibrary/src/org/videolan/medialibrary/media/Album.java index 2bb502150..f5f344639 100644 --- a/medialibrary/src/org/videolan/medialibrary/media/Album.java +++ b/medialibrary/src/org/videolan/medialibrary/media/Album.java @@ -4,6 +4,7 @@ import android.os.Parcel; import org.videolan.medialibrary.interfaces.AMedialibrary; import org.videolan.medialibrary.interfaces.media.AAlbum; +import org.videolan.medialibrary.interfaces.media.AArtist; import org.videolan.medialibrary.interfaces.media.AMediaWrapper; @SuppressWarnings("JniMissingFunction") @@ -43,6 +44,11 @@ public class Album extends AAlbum { return ml.isInitiated() ? nativeGetSearchCount(ml, mId, query) : 0; } + public AArtist getAlbumArtist() { + //TODO + return null; + } + private native AMediaWrapper[] nativeGetTracks(AMedialibrary ml, long mId, int sort, boolean desc); private native AMediaWrapper[] nativeGetPagedTracks(AMedialibrary ml, long mId, int sort, boolean desc, int nbItems, int offset); private native AMediaWrapper[] nativeSearch(AMedialibrary ml, long mId, String query, int sort, boolean desc, int nbItems, int offset); diff --git a/medialibrary/src/org/videolan/medialibrary/media/MediaWrapper.java b/medialibrary/src/org/videolan/medialibrary/media/MediaWrapper.java index c26a1d187..8e514fbc2 100644 --- a/medialibrary/src/org/videolan/medialibrary/media/MediaWrapper.java +++ b/medialibrary/src/org/videolan/medialibrary/media/MediaWrapper.java @@ -25,6 +25,7 @@ package org.videolan.medialibrary.media; import android.graphics.Bitmap; import android.net.Uri; import android.os.Parcel; +import android.text.TextUtils; import androidx.annotation.Nullable; @@ -68,7 +69,7 @@ public class MediaWrapper extends AMediaWrapper { public void removeFromHistory() { if (mId != 0L) { - final Medialibrary ml = Medialibrary.getInstance(); + final AMedialibrary ml = AMedialibrary.getInstance(); if (ml.isInitiated()) nativeRemoveFromHistory(ml, mId); } } @@ -248,11 +249,11 @@ public class MediaWrapper extends AMediaWrapper { if (mId != 0 && ml.isInitiated()) nativeSetMediaThumbnail(ml, mId, Tools.encodeVLCMrl(mrl)); } - private native long nativeGetMediaLongMetadata(Medialibrary ml, long id, int metaDataType); - private native String nativeGetMediaStringMetadata(Medialibrary ml, long id, int metaDataType); - private native void nativeSetMediaStringMetadata(Medialibrary ml, long id, int metaDataType, String metadataValue); - private native void nativeSetMediaLongMetadata(Medialibrary ml, long id, int metaDataType, long metadataValue); - private native void nativeSetMediaThumbnail(Medialibrary ml, long id, String mrl); - private native void nativeSetMediaTitle(Medialibrary ml, long id, String name); - private native void nativeRemoveFromHistory(Medialibrary ml, long id); + private native long nativeGetMediaLongMetadata(AMedialibrary ml, long id, int metaDataType); + private native String nativeGetMediaStringMetadata(AMedialibrary ml, long id, int metaDataType); + private native void nativeSetMediaStringMetadata(AMedialibrary ml, long id, int metaDataType, String metadataValue); + private native void nativeSetMediaLongMetadata(AMedialibrary ml, long id, int metaDataType, long metadataValue); + private native void nativeSetMediaThumbnail(AMedialibrary ml, long id, String mrl); + private native void nativeSetMediaTitle(AMedialibrary ml, long id, String name); + private native void nativeRemoveFromHistory(AMedialibrary ml, long id); } diff --git a/medialibrary/src/org/videolan/medialibrary/stubs/StubAlbum.java b/medialibrary/src/org/videolan/medialibrary/stubs/StubAlbum.java index 2d320838e..7f753d4d4 100644 --- a/medialibrary/src/org/videolan/medialibrary/stubs/StubAlbum.java +++ b/medialibrary/src/org/videolan/medialibrary/stubs/StubAlbum.java @@ -2,11 +2,17 @@ package org.videolan.medialibrary.stubs; import android.os.Parcel; +import org.videolan.medialibrary.interfaces.AMedialibrary; import org.videolan.medialibrary.interfaces.media.AAlbum; +import org.videolan.medialibrary.interfaces.media.AArtist; import org.videolan.medialibrary.interfaces.media.AMediaWrapper; +import java.util.ArrayList; + public class StubAlbum extends AAlbum { + private StubDataSource dt = StubDataSource.getInstance(); + public StubAlbum(long id, String title, int releaseYear, String artworkMrl, String albumArtist, long albumArtistId, int nbTracks, int duration) { super(id, title, releaseYear, artworkMrl, albumArtist, albumArtistId, nbTracks, duration); } @@ -16,22 +22,53 @@ public class StubAlbum extends AAlbum { } public int getRealTracksCount() { - return 0; + int count = 0; + for (AMediaWrapper media : dt.mAudioMediaWrappers) { + if (media.getAlbum().equals(this.getTitle())) count++; + } + return count; + } + + public AArtist getAlbumArtist() { + AMedialibrary ml = AMedialibrary.getInstance(); + return ml.getArtist(this.albumArtistId); + } + + private ArrayList getAlbumTracks() { + ArrayList results = new ArrayList<>(); + for (AMediaWrapper media : dt.mAudioMediaWrappers) { + if (media.getAlbum().equals(this.getTitle())) results.add(media); + } + return results; } public AMediaWrapper[] getTracks(int sort, boolean desc) { - return null; + return dt.sortMedia(getAlbumTracks(), sort, desc); } public AMediaWrapper[] getPagedTracks(int sort, boolean desc, int nbItems, int offset) { - return null; + return dt.sortMedia(dt.secureSublist(getAlbumTracks(), offset, offset + nbItems), sort, desc); } public AMediaWrapper[] searchTracks(String query, int sort, boolean desc, int nbItems, int offset) { - return null; + ArrayList results = new ArrayList<>(); + for (AMediaWrapper media : dt.mAudioMediaWrappers) { + if (media.getAlbum().equals(this.getTitle()) || + media.getTitle().contains(query)) { + results.add(media); + } + } + return dt.sortMedia(dt.secureSublist(results, offset, offset + nbItems), sort, desc); } public int searchTracksCount(String query) { - return 0; + int count = 0; + for (AMediaWrapper media : dt.mAudioMediaWrappers) { + if (media.getAlbum().equals(this.getTitle()) || + media.getTitle().contains(query)) { + count++; + } + } + return count; } } diff --git a/medialibrary/src/org/videolan/medialibrary/stubs/StubArtist.java b/medialibrary/src/org/videolan/medialibrary/stubs/StubArtist.java index bf214ac65..834fe452e 100644 --- a/medialibrary/src/org/videolan/medialibrary/stubs/StubArtist.java +++ b/medialibrary/src/org/videolan/medialibrary/stubs/StubArtist.java @@ -6,8 +6,13 @@ import org.videolan.medialibrary.interfaces.media.AAlbum; import org.videolan.medialibrary.interfaces.media.AArtist; import org.videolan.medialibrary.interfaces.media.AMediaWrapper; +import java.util.ArrayList; +import java.util.Arrays; + public class StubArtist extends AArtist { + private StubDataSource dt = StubDataSource.getInstance(); + public StubArtist(long id, String name, String shortBio, String artworkMrl, String musicBrainzId) { super(id, name, shortBio, artworkMrl, musicBrainzId); } @@ -17,42 +22,104 @@ public class StubArtist extends AArtist { } public AAlbum[] getAlbums(int sort, boolean desc) { - return null; + ArrayList results = new ArrayList<>(); + for (AAlbum album : dt.mAlbums) { + if (album.getDescription().equals(this.getTitle())) results.add(album); + } + return dt.sortAlbum(results, sort, desc); + } + + public int getAlbumsCount() { + int count = 0; + for (AAlbum album : dt.mAlbums) { + if (album.getDescription().equals(this.getTitle())) count++; + } + return count; } public AAlbum[] getPagedAlbums(int sort, boolean desc, int nbItems, int offset) { - return null; + ArrayList results = new ArrayList<>(Arrays.asList(getAlbums(sort, desc))); + return results.toArray(new AAlbum[0]); } public AAlbum[] searchAlbums(String query, int sort, boolean desc, int nbItems, int offset) { - return null; + ArrayList results = new ArrayList<>(); + for (AAlbum album : dt.mAlbums) { + if (album.getDescription().equals(this.getTitle()) || + album.getTitle().equals(query)) { + results.add(album); + } + } + return dt.sortAlbum(dt.secureSublist(results, offset, offset + nbItems), sort, desc); } public int searchAlbumsCount(String query) { - return 0; - } - - public AMediaWrapper[] searchTracks(String query, int sort, boolean desc, int nbItems, int offset) { - return null; + int count = 0; + for (AAlbum album : dt.mAlbums) { + if (album.getDescription().equals(this.getTitle()) || + album.getTitle().equals(query)) { + count++; + } + } + return count; } + //TODO checkout if query is on artist or albumArtist or both public int searchTracksCount(String query) { - return 0; + int count = 0; + for (AMediaWrapper media : dt.mAudioMediaWrappers) { + if (media.getArtist().equals(this.getTitle()) || + media.getAlbumArtist().equals(this.getTitle()) || + media.getTitle().contains(query)) { + count++; + } + } + return count; } - public int getAlbumsCount() { - return 0; + //TODO checkout if query is on artist or albumArtist or both (same as above) + public AMediaWrapper[] searchTracks(String query, int sort, boolean desc, int nbItems, int offset) { + ArrayList results = new ArrayList<>(); + for (AMediaWrapper media : dt.mAudioMediaWrappers) { + if (media.getArtist().equals(this.getTitle()) || + media.getAlbumArtist().equals(this.getTitle()) || + media.getTitle().contains(query)) { + results.add(media); + } + } + return dt.sortMedia(dt.secureSublist(results, offset, offset + nbItems), sort, desc); } public AMediaWrapper[] getTracks(int sort, boolean desc) { - return null; + ArrayList results = new ArrayList<>(); + for (AMediaWrapper media : dt.mAudioMediaWrappers) { + if (media.getArtist().equals(this.getTitle()) || + media.getAlbumArtist().equals(this.getTitle())) { + results.add(media); + } + } + return dt.sortMedia(results, sort, desc); } public AMediaWrapper[] getPagedTracks(int sort, boolean desc, int nbItems, int offset) { - return null; + ArrayList results = new ArrayList<>(); + for (AMediaWrapper media : dt.mAudioMediaWrappers) { + if (media.getArtist().equals(this.getTitle()) || + media.getAlbumArtist().equals(this.getTitle())) { + results.add(media); + } + } + return dt.sortMedia(dt.secureSublist(results, offset, offset + nbItems), sort, desc); } public int getTracksCount() { - return 0; + int count = 0; + for (AMediaWrapper media : dt.mAudioMediaWrappers) { + if (media.getArtist().equals(this.getTitle()) || + media.getAlbumArtist().equals(this.getTitle())) { + count++; + } + } + return count; } } diff --git a/medialibrary/src/org/videolan/medialibrary/stubs/StubDataSource.java b/medialibrary/src/org/videolan/medialibrary/stubs/StubDataSource.java new file mode 100644 index 000000000..20974da6f --- /dev/null +++ b/medialibrary/src/org/videolan/medialibrary/stubs/StubDataSource.java @@ -0,0 +1,357 @@ +package org.videolan.medialibrary.stubs; + +import android.os.Handler; +import android.text.TextUtils; + +import org.videolan.medialibrary.ServiceLocator; +import org.videolan.medialibrary.interfaces.media.AAlbum; +import org.videolan.medialibrary.interfaces.media.AArtist; +import org.videolan.medialibrary.interfaces.media.AFolder; +import org.videolan.medialibrary.interfaces.media.AGenre; +import org.videolan.medialibrary.interfaces.media.AMediaWrapper; +import org.videolan.medialibrary.interfaces.media.APlaylist; +import org.videolan.medialibrary.media.MediaLibraryItem; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; + +import static org.videolan.medialibrary.interfaces.AMedialibrary.SORT_ALBUM; +import static org.videolan.medialibrary.interfaces.AMedialibrary.SORT_ALPHA; +import static org.videolan.medialibrary.interfaces.AMedialibrary.SORT_ARTIST; +import static org.videolan.medialibrary.interfaces.AMedialibrary.SORT_DEFAULT; +import static org.videolan.medialibrary.interfaces.AMedialibrary.SORT_DURATION; +import static org.videolan.medialibrary.interfaces.AMedialibrary.SORT_FILENAME; +import static org.videolan.medialibrary.interfaces.AMedialibrary.SORT_INSERTIONDATE; +import static org.videolan.medialibrary.interfaces.AMedialibrary.SORT_LASTMODIFICATIONDATE; +import static org.videolan.medialibrary.interfaces.AMedialibrary.SORT_RELEASEDATE; + +public class StubDataSource { + + ArrayList mVideoMediaWrappers = new ArrayList<>(); + ArrayList mAudioMediaWrappers = new ArrayList<>(); + ArrayList mStreamMediaWrappers = new ArrayList<>(); + ArrayList mHistory = new ArrayList<>(); + ArrayList mAlbums = new ArrayList<>(); + ArrayList mArtists = new ArrayList<>(); + ArrayList mGenres = new ArrayList<>(); + ArrayList mPlaylists = new ArrayList<>(); + ArrayList mBannedFolders = new ArrayList<>(); + ArrayList mFolders = new ArrayList<>(); + ArrayList mDevices = new ArrayList<>(); + + private static long uuid = 2; + + private static StubDataSource mInstance = null; + + public static StubDataSource getInstance() { + if (mInstance == null) { + mInstance = new StubDataSource(); + } + return mInstance; + } + + private StubDataSource() { } + + public void init() { + String baseMrl = "/storage/emulated/0/Movies/"; + AMediaWrapper media; + + // Video + String fileName = "058_foar_everywun_frum_boxxy.flv"; + media = ServiceLocator.getAMediaWrapper(getUUID(), baseMrl + fileName, 0L, 18820L, 0, + fileName, fileName, "", "", + "", "", 416, 304, "", 0, -2, + 0, 0, 1509466228L, 0L, true); + addVideo(media); + + fileName = "FMA - MultiChapter.mkv"; + media = ServiceLocator.getAMediaWrapper(getUUID(), baseMrl + fileName, 0L, 1467383L, 0, + "Encoded with MiniCoder", fileName, "", "", + "", "", 1280, 720, "", 0, + -2, 0, 0, 1512396147L, 0L, true); + addVideo(media); + + fileName = "114_My_Heart_Will_Go_On.avi"; + media = ServiceLocator.getAMediaWrapper(getUUID(), baseMrl + fileName, 0L, 20000L, 0, + "My Heart Will Go On - Celine Dion", fileName, "", "", + "", "", 352, 220, "", 0, + -2, 0, 0, 1509465852L, 0L, true); + addVideo(media); + + // Audio + + fileName = "01-Show Me The Way.mp3"; + baseMrl = "/storage/emulated/0/Music/Peter Frampton/Shine On - CD2/"; + media = ServiceLocator.getAMediaWrapper(getUUID(), baseMrl + fileName, 0L, 280244L, 1, + "01-Show Me The Way", fileName, "Peter Frampton", "Rock", + "Shine On CD2", "Peter Frampton", + 0, 0, "/storage/emulated/0/Music/Peter Frampton/Shine On - CD2/Folder.jpg", + 0, -2, 1, 0, + 1547452796L, 0L, true); + addAudio(media, "", 1965, 400); + + fileName = "01-Wind Of Change.mp3"; + baseMrl = "/storage/emulated/0/Music/Peter Frampton/Shine On - CD1/"; + media = ServiceLocator.getAMediaWrapper(getUUID(), baseMrl + fileName, 0L, 184271L, 1, + "01-Wind Of Change", fileName, "Peter Frampton", "Rock", + "Shine On CD1", "Peter Frampton", + 0, 0, "/storage/emulated/0/Music/Peter Frampton/Shine On - CD1/Folder.jpg", + 0, -2, 1, 0, + 1547452786L, 0L, true); + addAudio(media, "", 1960, 250); + + fileName = "03 Bloody Well Right.wma"; + baseMrl = "/storage/emulated/0/Music/Supertramp/Best of/"; + media = ServiceLocator.getAMediaWrapper(getUUID(), baseMrl + fileName, 0L, 257199L, 1, + "Bloody Well Right", fileName, "Supertramp", "Rock", + "The Autobiography of Supertramp", "Supertramp", + 0, 0, "/storage/emulated/0/Music/Supertramp/Best of/Folder.jpg", 0, + -2, 3, 0, + 1547452814L, 0L, true); + addAudio(media, "", 1970, 360); + } + + List secureSublist(List list, int offset, int nbItems) { + int min = list.size() - 1 < 0 ? 0 : list.size(); + int secureOffset = (offset >= list.size()) && (offset > 0) ? min : offset; + int end = offset + nbItems; + int secureEnd = (end >= list.size()) && end > 0 ? min : end; + return list.subList(secureOffset, secureEnd); + } + + class MediaComparator implements Comparator { + private int sort; + MediaComparator(int sort) { this.sort = sort; } + + @Override //TODO checkout if types of sort are verified before being used in native + public int compare(AMediaWrapper o1, AMediaWrapper o2) { + switch(sort) { + case SORT_DEFAULT: + case SORT_ALPHA: return o1.getTitle().compareTo(o2.getTitle()); + case SORT_FILENAME :return o1.getFileName().compareTo(o2.getFileName()); + case SORT_DURATION: return (int)(o1.getLength() - o2.getLength()); + case SORT_INSERTIONDATE: return (int)(o1.getTime() - o2.getTime()); // TODO checkout if insertiton <=> time + case SORT_LASTMODIFICATIONDATE: return (int)(o1.getLastModified() - o2.getLastModified()); + case SORT_ARTIST: return o1.getArtist().compareTo(o2.getArtist()); + default: return 0; + } + } + } + + class ArtistComparator implements Comparator { + private int sort; + ArtistComparator(int sort) { this.sort = sort; } + + @Override + public int compare(AArtist o1, AArtist o2) { + switch(sort) { + case SORT_DEFAULT: + case SORT_ARTIST: return o1.getTitle().compareTo(o2.getTitle()); + default: return 0; + } + } + } + + class AlbumComparator implements Comparator { + private int sort; + AlbumComparator(int sort) { this.sort = sort; } + + @Override + public int compare(AAlbum o1, AAlbum o2) { + switch (sort) { + case SORT_DEFAULT: + case SORT_ALBUM: return o1.getTitle().compareTo(o2.getTitle()); + case SORT_RELEASEDATE: return o1.getReleaseYear() - o2.getReleaseYear(); + case SORT_DURATION: return o1.getDuration() - o2.getDuration(); + default: return 0; + } + } + } + + class GenreComparator implements Comparator { + private int sort; + GenreComparator(int sort) { this.sort = sort; } + + @Override + public int compare(AGenre o1, AGenre o2) { + switch(sort) { + case SORT_DEFAULT: + case SORT_ALPHA: return o1.getTitle().compareTo(o2.getTitle()); + default: return 0; + } + } + } + + class PlaylistComparator implements Comparator { + private int sort; + PlaylistComparator(int sort) { this.sort = sort; } + + @Override + public int compare(APlaylist o1, APlaylist o2) { + switch (sort) { + case SORT_DEFAULT: + case SORT_ALPHA: return o1.getTitle().compareTo(o2.getTitle()); + case SORT_DURATION: return 0; //TODO WTF is there a duration attribute + default: return 0; + } + } + } + + class FolderComparator implements Comparator { + private int sort; + FolderComparator(int sort) { this.sort = sort; } + + @Override + public int compare(AFolder o1, AFolder o2) { + switch (sort) { + case SORT_DEFAULT: + case SORT_ALPHA: return o1.getTitle().compareTo(o2.getTitle()); + default: return 0; + } + } + } + + AMediaWrapper[] sortMedia(List arrayList, int sort, boolean desc) { + List array = new ArrayList<>(arrayList); + Collections.sort(array, new MediaComparator(sort)); + if (desc) + Collections.reverse(array); + return array.toArray(new AMediaWrapper[0]); + } + + AAlbum[] sortAlbum(List arrayList, int sort, boolean desc) { + List array = new ArrayList<>(arrayList); + Collections.sort(array, new AlbumComparator(sort)); + if (desc) + Collections.reverse(array); + return array.toArray(new AAlbum[0]); + } + + AArtist[] sortArtist(List arrayList, int sort, boolean desc) { + List array = new ArrayList<>(arrayList); + Collections.sort(array, new ArtistComparator(sort)); + if (desc) + Collections.reverse(array); + return array.toArray(new AArtist[0]); + } + + AGenre[] sortGenre(List arrayList, int sort, boolean desc) { + List array = new ArrayList<>(arrayList); + Collections.sort(array, new GenreComparator(sort)); + if (desc) + Collections.reverse(array); + return array.toArray(new AGenre[0]); + } + + APlaylist[] sortPlaylist(List arrayList, int sort, boolean desc) { + List array = new ArrayList<>(arrayList); + Collections.sort(array, new PlaylistComparator(sort)); + if (desc) + Collections.reverse(array); + return array.toArray(new APlaylist[0]); + } + + AFolder[] sortFolder(List arrayList, int sort, boolean desc) { + List array = new ArrayList<>(arrayList); + Collections.sort(array, new FolderComparator(sort)); + if (desc) + Collections.reverse(array); + return array.toArray(new AFolder[0]); + } + + private boolean checkUuidForMatches(long id) { + if (id == 1L || id == 2L) + return true; + for (MediaLibraryItem item : mVideoMediaWrappers) { + if (item.getId() == id) + return true; + } + for (MediaLibraryItem item : mAudioMediaWrappers) { + if (item.getId() == id) + return true; + } + for (MediaLibraryItem item : mAlbums) { + if (item.getId() == id) + return true; + } + for (MediaLibraryItem item : mArtists) { + if (item.getId() == id) + return true; + } + for (MediaLibraryItem item : mGenres) { + if (item.getId() == id) + return true; + } + for (MediaLibraryItem item : mFolders) { + if (item.getId() == id) + return true; + } + return false; + } + + long getUUID() { + uuid++; + return uuid; + } + + private void addAudio(AMediaWrapper media, String shortBio, int releaseYear, int albumDuration) { + addFolders(media); + mAudioMediaWrappers.add(media); + AArtist artist = ServiceLocator.getAArtist(getUUID(), media.getArtist(), shortBio, media.getArtworkMrl(), ""); + mArtists.add(artist); + AArtist albumArtist = null; + if (!media.getArtist().equals(media.getAlbumArtist())) { + albumArtist = ServiceLocator.getAArtist(getUUID(), media.getAlbumArtist(), "", media.getArtworkMrl(), ""); + mArtists.add(albumArtist); + } + AAlbum album; + if (albumArtist == null) + album = ServiceLocator.getAAlbum(getUUID(), media.getAlbum(), releaseYear, + media.getArtworkMrl(), artist.getTitle(), + artist.getId(), media.getTracks().length, albumDuration); + else + album = ServiceLocator.getAAlbum(getUUID(), media.getAlbum(), releaseYear, + media.getArtworkMrl(), albumArtist.getTitle(), + albumArtist.getId(), media.getTracks().length, albumDuration); + mAlbums.add(album); + ArrayList genreStrings = new ArrayList<>(); +// if (!getGenresString()) + mGenres.add(ServiceLocator.getAGenre(getUUID(), media.getGenre())); + } + + private void addVideo(AMediaWrapper media) { + addFolders(media); + mVideoMediaWrappers.add(media); + } + + private String[] getGenresString() { + ArrayList results = new ArrayList<>(); + for (AGenre genre : mGenres) { results.add(genre.getTitle()); } + return results.toArray(new String[0]); + } + + private String[] getFoldersString() { + ArrayList results = new ArrayList<>(); + for (AFolder folder : mFolders) { results.add(folder.getTitle()); } + return results.toArray(new String[0]); + } + + private void addFolders(AMediaWrapper media) { + String path = media.getUri().getPath(); + if (path == null) + return; + String[] folderArray = path.split("/"); + ArrayList newFolders = new ArrayList<>(Arrays.asList(folderArray)); + for (int i = 0; i < newFolders.size(); i++) { + final String mrl = TextUtils.join("/", secureSublist(newFolders, 0, i)); + ArrayList mlFolders = new ArrayList<>(Arrays.asList(getFoldersString())); + if (!mlFolders.contains(mrl)) { + final String name = folderArray[folderArray.length - 1]; + mFolders.add(ServiceLocator.getAFolder(getUUID(), name, mrl)); + } + } + } +} diff --git a/medialibrary/src/org/videolan/medialibrary/stubs/StubFolder.java b/medialibrary/src/org/videolan/medialibrary/stubs/StubFolder.java index 7ce1c38b0..004512a72 100644 --- a/medialibrary/src/org/videolan/medialibrary/stubs/StubFolder.java +++ b/medialibrary/src/org/videolan/medialibrary/stubs/StubFolder.java @@ -5,8 +5,14 @@ import android.os.Parcel; import org.videolan.medialibrary.interfaces.media.AFolder; import org.videolan.medialibrary.interfaces.media.AMediaWrapper; +import java.io.File; +import java.util.ArrayList; +import java.util.Arrays; + public class StubFolder extends AFolder { + private StubDataSource dt = StubDataSource.getInstance(); + public StubFolder(long id, String name, String mrl) { super(id, name, mrl); } @@ -14,27 +20,83 @@ public class StubFolder extends AFolder { super(in); } + //TODO checkout results not sure att all ... + private boolean isParentFolder(String parentMrl, String childMrl) { + if (!childMrl.contains(parentMrl)) return false; + File mediaFile = new File(childMrl); + String parentPath = mediaFile.getParent(); + return parentPath.equals(parentMrl); + } + + //TODO WTF would media be null ?? public AMediaWrapper[] media(int type, int sort, boolean desc, int nbItems, int offset) { - return null; + ArrayList results = new ArrayList<>(); + ArrayList source; + if (type == TYPE_FOLDER_VIDEO) source = dt.mVideoMediaWrappers; + else if (type == TYPE_FOLDER_AUDIO) source = dt.mAudioMediaWrappers; + else return null; + for (AMediaWrapper media : source) { + if (isParentFolder(this.mMrl, media.getUri().getPath())) results.add(media); + } + results = new ArrayList<>(Arrays.asList(dt.sortMedia(results, sort, desc))); + return dt.secureSublist(results, offset, offset + nbItems).toArray(new AMediaWrapper[0]); } public int mediaCount(int type) { - return 0; + int count = 0; + ArrayList source; + if (type == TYPE_FOLDER_VIDEO) source = dt.mVideoMediaWrappers; + else if (type == TYPE_FOLDER_AUDIO) source = dt.mAudioMediaWrappers; + else return 0; + for (AMediaWrapper media : source) { + if (isParentFolder(this.mMrl, media.getUri().getPath())) count++; + } + return count; } public AFolder[] subfolders(int sort, boolean desc, int nbItems, int offset) { - return null; + ArrayList results = new ArrayList<>(); + for (AFolder folder : dt.mFolders) { + if (isParentFolder(this.mMrl, folder.mMrl)) results.add(folder); + } + results = new ArrayList<>(Arrays.asList(dt.sortFolder(results, sort, desc))); + return dt.secureSublist(results, offset, offset + nbItems).toArray(new AFolder[0]); } public int subfoldersCount(int type) { - return 0; + int count = 0; + for (AFolder folder : dt.mFolders) { + if (isParentFolder(this.mMrl, folder.mMrl)) count++; + } + return count; } public AMediaWrapper[] searchTracks(String query, int mediaType, int sort, boolean desc, int nbItems, int offset) { - return null; + ArrayList results = new ArrayList<>(); + ArrayList source; + if (mediaType == TYPE_FOLDER_VIDEO) source = dt.mVideoMediaWrappers; + else if (mediaType == TYPE_FOLDER_AUDIO) source = dt.mAudioMediaWrappers; + else return null; + for (AMediaWrapper media : source) { + if (media.getTitle().contains(query) && + isParentFolder(this.mMrl, media.getUri().getPath())) { + results.add(media); + } + } + results = new ArrayList<>(Arrays.asList(dt.sortMedia(results, sort, desc))); + return dt.secureSublist(results, offset, offset + nbItems).toArray(new AMediaWrapper[0]); } public int searchTracksCount(String query, int mediaType) { - return 0; + int count = 0; + ArrayList source; + if (mediaType == TYPE_FOLDER_VIDEO) source = dt.mVideoMediaWrappers; + else if (mediaType == TYPE_FOLDER_AUDIO) source = dt.mAudioMediaWrappers; + else return 0; + for (AMediaWrapper media : source) { + if (media.getTitle().contains(query) && + isParentFolder(this.mMrl, media.getUri().getPath())) count++; + } + return count; } } diff --git a/medialibrary/src/org/videolan/medialibrary/stubs/StubGenre.java b/medialibrary/src/org/videolan/medialibrary/stubs/StubGenre.java index 6c1c4f2ec..3bd862e5a 100644 --- a/medialibrary/src/org/videolan/medialibrary/stubs/StubGenre.java +++ b/medialibrary/src/org/videolan/medialibrary/stubs/StubGenre.java @@ -7,52 +7,135 @@ import org.videolan.medialibrary.interfaces.media.AArtist; import org.videolan.medialibrary.interfaces.media.AGenre; import org.videolan.medialibrary.interfaces.media.AMediaWrapper; +import java.util.ArrayList; +import java.util.Arrays; + public class StubGenre extends AGenre { + private StubDataSource dt = StubDataSource.getInstance(); + public StubGenre(long id, String title) { super(id, title); } public StubGenre(Parcel in) { super(in); } public AAlbum[] getAlbums(int sort, boolean desc) { - return null; + ArrayList results = new ArrayList<>(); + for (AMediaWrapper media : dt.mAudioMediaWrappers) { + if (media.getGenre().equals(this.getTitle())) { + for (AAlbum album : dt.mAlbums) { + if (album.getTitle().equals(media.getAlbum()) && + !results.contains(album)) { + results.add(album); + } + } + } + } + return dt.sortAlbum(results, sort, desc); } public AAlbum[] getPagedAlbums(int sort, boolean desc, int nbItems, int offset) { - return null; + ArrayList results = new ArrayList<>(Arrays.asList(getAlbums(sort, desc))); + return dt.secureSublist(results, offset, offset + nbItems).toArray(new AAlbum[0]); } - public AArtist[] getArtists(int sort, boolean desc) { - return null; + @Override + public int getAlbumsCount() { + return getAlbums().length; } - public AMediaWrapper[] getTracks(int sort, boolean desc) { - return null; + public AAlbum[] searchAlbums(String query, int sort, boolean desc, int nbItems, int offset) { + ArrayList results = new ArrayList<>(); + for (AMediaWrapper media : dt.mAudioMediaWrappers) { + if (media.getGenre().equals(this.getTitle()) && + media.getTitle().contains(query)) { + for (AAlbum album : dt.mAlbums) { + if (album.getTitle().equals(media.getAlbum()) && + !results.contains(album)) { + results.add(album); + } + } + } + } + results = new ArrayList<>(Arrays.asList(dt.sortAlbum(results, sort, desc))); + return dt.secureSublist(results, offset, offset + nbItems).toArray(new AAlbum[0]); } - public AMediaWrapper[] getPagedTracks(int sort, boolean desc, int nbItems, int offset) { - return null; + public int searchAlbumsCount(String query) { + ArrayList results = new ArrayList<>(); + for (AMediaWrapper media : dt.mAudioMediaWrappers) { + if (media.getGenre().equals(this.getTitle()) && + media.getTitle().contains(query)) { + for (AAlbum album : dt.mAlbums) { + if (album.getTitle().equals(media.getAlbum()) && + !results.contains(album)) { + results.add(album); + } + } + } + } + return results.size(); } - public int getTracksCount() { - return 0; + public AArtist[] getArtists(int sort, boolean desc) { + ArrayList results = new ArrayList<>(); + for (AMediaWrapper media : dt.mAudioMediaWrappers) { + if (media.getGenre().equals(this.getTitle())) { + for (AArtist artist : dt.mArtists) { + if ((artist.getTitle().equals(media.getArtist()) || + artist.getTitle().equals(media.getAlbumArtist())) && + !results.contains(artist)) { + results.add(artist); + break; + } + } + } + } + return dt.sortArtist(results, sort, desc); } - public int getAlbumsCount() { - return 0; + public AMediaWrapper[] getTracks(int sort, boolean desc) { + ArrayList results = new ArrayList<>(); + for (AMediaWrapper media : dt.mAudioMediaWrappers) { + if (media.getGenre().equals(this.getTitle())) results.add(media); + } + return dt.sortMedia(results, sort, desc); } - public AAlbum[] searchAlbums(String query, int sort, boolean desc, int nbItems, int offset) { - return null; + public AMediaWrapper[] getPagedTracks(int sort, boolean desc, int nbItems, int offset) { + ArrayList results = new ArrayList<>(); + for (AMediaWrapper media : dt.mAudioMediaWrappers) { + if (media.getGenre().equals(this.getTitle())) results.add(media); + } + return dt.sortMedia(dt.secureSublist(results, offset, offset + nbItems), sort, desc); } - public int searchAlbumsCount(String query) { - return 0; + public int getTracksCount() { + int count = 0; + for (AMediaWrapper media : dt.mAudioMediaWrappers) { + if (media.getGenre().equals(this.getTitle())) count++; + } + return count; } + public AMediaWrapper[] searchTracks(String query, int sort, boolean desc, int nbItems, int offset) { - return null; + ArrayList results = new ArrayList<>(); + for (AMediaWrapper media : dt.mAudioMediaWrappers) { + if (media.getGenre().equals(this.getTitle()) && + media.getTitle().contains(query)) { + results.add(media); + } + } + return dt.sortMedia(dt.secureSublist(results, offset, offset + nbItems), sort, desc); } public int searchTracksCount(String query) { - return 0; + int count = 0; + for (AMediaWrapper media : dt.mAudioMediaWrappers) { + if (media.getGenre().equals(this.getTitle()) && + media.getTitle().contains(query)) { + count++; + } + } + return count; } } diff --git a/medialibrary/src/org/videolan/medialibrary/stubs/StubMediaWrapper.java b/medialibrary/src/org/videolan/medialibrary/stubs/StubMediaWrapper.java index 6f49e1827..347813671 100644 --- a/medialibrary/src/org/videolan/medialibrary/stubs/StubMediaWrapper.java +++ b/medialibrary/src/org/videolan/medialibrary/stubs/StubMediaWrapper.java @@ -3,6 +3,7 @@ package org.videolan.medialibrary.stubs; import android.graphics.Bitmap; import android.net.Uri; import android.os.Parcel; +import android.util.SparseArray; import org.videolan.libvlc.Media; import org.videolan.medialibrary.interfaces.media.AMediaWrapper; @@ -30,26 +31,33 @@ public class StubMediaWrapper extends AMediaWrapper { public StubMediaWrapper(Media media) { super(media); } public StubMediaWrapper(Parcel in) { super(in); } + private SparseArray mMetaLong = new SparseArray<>(); + private SparseArray mMetaString = new SparseArray<>(); + public void rename(String name) { + mTitle = name; } public long getMetaLong(int metaDataType) { - return 0L; + return mMetaLong.get(metaDataType); } public String getMetaString(int metaDataType) { - return ""; + return mMetaString.get(metaDataType); } public boolean setLongMeta(int metaDataType, long metadataValue) { + mMetaLong.setValueAt(metaDataType, metadataValue); return true; } public boolean setStringMeta(int metaDataType, String metadataValue) { + mMetaString.setValueAt(metaDataType, metadataValue); return true; } public void setThumbnail(String mrl) { + //TODO } } diff --git a/medialibrary/src/org/videolan/medialibrary/stubs/StubMedialibrary.java b/medialibrary/src/org/videolan/medialibrary/stubs/StubMedialibrary.java index 78eb509b8..101cb71b4 100644 --- a/medialibrary/src/org/videolan/medialibrary/stubs/StubMedialibrary.java +++ b/medialibrary/src/org/videolan/medialibrary/stubs/StubMedialibrary.java @@ -2,12 +2,12 @@ package org.videolan.medialibrary.stubs; import android.content.Context; import android.net.Uri; +import android.util.Log; import androidx.annotation.NonNull; +import org.videolan.medialibrary.ServiceLocator; import org.videolan.medialibrary.interfaces.AMedialibrary; -import org.videolan.medialibrary.interfaces.DevicesDiscoveryCb; -import org.videolan.medialibrary.interfaces.EntryPointsEventsCb; import org.videolan.medialibrary.interfaces.media.AAlbum; import org.videolan.medialibrary.interfaces.media.AArtist; import org.videolan.medialibrary.interfaces.media.AFolder; @@ -16,211 +16,355 @@ import org.videolan.medialibrary.interfaces.media.AMediaWrapper; import org.videolan.medialibrary.interfaces.media.APlaylist; import org.videolan.medialibrary.media.SearchAggregate; +import java.util.ArrayList; +import java.util.Arrays; + public class StubMedialibrary extends AMedialibrary { + private StubDataSource dt = StubDataSource.getInstance(); + private String TAG = this.getClass().getName(); + public int init(Context context) { + if (context == null) return ML_INIT_FAILED; + sContext = context; + dt.init(); return ML_INIT_SUCCESS; } public void start() { - + isMedialibraryStarted = true; + synchronized (onMedialibraryReadyListeners) { + for (OnMedialibraryReadyListener listener : onMedialibraryReadyListeners) listener.onMedialibraryReady(); + } } public void banFolder(@NonNull String path) { - + if (!dt.mBannedFolders.contains(path)) + dt.mBannedFolders.add(path); } - public void unbanFolder(@NonNull String path) { + // TODO checkout error handling for ban / unban folder + // TODO checkout probably useless as there is no folder parsing + // TODO also unban folder might trigger an action + public void unbanFolder(@NonNull String path) { + dt.mBannedFolders.remove(path); } public String[] getDevices() { - return null; + return new String[0]; } public boolean addDevice(@NonNull String uuid, @NonNull String path, boolean removable) { return false; } - public void discover(@NonNull String path) {} - public void removeFolder(@NonNull String mrl) {} - - public String[] getFoldersList() { - return null; + public void discover(@NonNull String path) { + onDiscoveryStarted(path); + onDiscoveryCompleted(path); } + public void removeFolder(@NonNull String mrl) {} public boolean removeDevice(String uuid, String path) { return true; } + + public String[] getFoldersList() { + ArrayList results = new ArrayList<>(); + for (AFolder folder : dt.mFolders) { + results.add(folder.getTitle()); + } + return results.toArray(new String[0]); + } public AMediaWrapper[] getVideos() { - return null; + return getVideos(SORT_DEFAULT, false); } + //TODO sublist of sorted result ... public AMediaWrapper[] getPagedVideos(int sort, boolean desc, int nbItems, int offset) { - return null; + return dt.sortMedia(dt.secureSublist(dt.mVideoMediaWrappers, offset, offset + nbItems), sort, desc); } public AMediaWrapper[] getVideos(int sort, boolean desc) { - return null; + return dt.sortMedia(dt.mVideoMediaWrappers, sort, desc); } public AMediaWrapper[] getRecentVideos() { - return null; + ArrayList results = new ArrayList<>(); + for (AMediaWrapper media : dt.mVideoMediaWrappers) { + if (media.getItemType() == AMediaWrapper.TYPE_VIDEO) results.add(media); + } + return results.toArray(new AMediaWrapper[0]); } public AMediaWrapper[] getAudio() { - return null; + return getAudio(SORT_DEFAULT, false); } public AMediaWrapper[] getAudio(int sort, boolean desc) { - return null; + return dt.sortMedia(dt.mAudioMediaWrappers, sort, desc); } public AMediaWrapper[] getPagedAudio(int sort, boolean desc, int nbitems, int offset) { - return null; + return dt.sortMedia(dt.secureSublist(dt.mAudioMediaWrappers, offset, offset + nbitems), sort, desc); } public AMediaWrapper[] getRecentAudio() { - return null; + ArrayList results = new ArrayList<>(); + for (AMediaWrapper media : dt.mVideoMediaWrappers) { + if (media.getItemType() == AMediaWrapper.TYPE_AUDIO) results.add(media); + } + return results.toArray(new AMediaWrapper[0]); } public int getVideoCount() { - return 0; + return dt.mVideoMediaWrappers.size(); } public int getAudioCount() { - return 0; + return dt.mAudioMediaWrappers.size(); } public AAlbum[] getAlbums() { - return null; + return getAlbums(SORT_DEFAULT, false); } public AAlbum[] getAlbums(int sort, boolean desc) { - return null; + return dt.sortAlbum(dt.mAlbums, sort, desc); } public AAlbum[] getPagedAlbums(int sort, boolean desc, int nbItems, int offset) { - return null; + return dt.sortAlbum(dt.secureSublist(dt.mAlbums, offset, offset + nbItems), sort, desc); } public int getAlbumsCount() { - return 0; + return dt.mAlbums.size(); } public int getAlbumsCount(String query) { - return 0; + int count = 0; + for (AAlbum album : dt.mAlbums) { + if (album.getTitle().contains(query)) count++; + } + return count; } public AAlbum getAlbum(long albumId) { + for (AAlbum album : dt.mAlbums) { + if (album.getId() == albumId) return album; + } return null; } public AArtist[] getArtists(boolean all) { - return null; + return getArtists(all, SORT_DEFAULT, false); + } + + private AArtist[] getAlbumArtists() { + ArrayList results = new ArrayList<>(); + for (AAlbum album : dt.mAlbums) { + results.add(album.getAlbumArtist()); + } + return results.toArray(new AArtist[0]); } public AArtist[] getArtists(boolean all, int sort, boolean desc) { - return null; + ArrayList results; + if (all) results = dt.mArtists; + else results = new ArrayList<>(Arrays.asList(getAlbumArtists())); + return dt.sortArtist(results, sort, desc); } public AArtist[] getPagedArtists(boolean all, int sort, boolean desc, int nbItems, int offset) { - return null; + ArrayList results; + if (all) results = dt.mArtists; + else results = new ArrayList<>(Arrays.asList(getAlbumArtists())); + return dt.sortArtist(dt.secureSublist(results, offset, offset + nbItems), sort, desc); } public int getArtistsCount(boolean all) { - return 0; + int count; + if (all) count = dt.mArtists.size(); + else count = getAlbumArtists().length; + return count; } public int getArtistsCount(String query) { - return 0; + int count = 0; + for (AArtist artist : dt.mArtists) { + if (artist.getTitle().contains(query)) count++; + } + return count; } public AArtist getArtist(long artistId) { + for (AArtist artist : dt.mArtists) { + if (artist.getId() == artistId) return artist; + } return null; } public AGenre[] getGenres() { - return null; + return dt.mGenres.toArray(new AGenre[0]); } public AGenre[] getGenres(int sort, boolean desc) { - return null; + return dt.sortGenre(dt.mGenres, sort, desc); } public AGenre[] getPagedGenres(int sort, boolean desc, int nbItems, int offset) { - return null; + return dt.sortGenre(dt.secureSublist(dt.mGenres, offset, offset + nbItems), sort, desc); } public int getGenresCount() { - return 0; + return dt.mGenres.size(); } public int getGenresCount(String query) { - return 0; + int count = 0; + for (AGenre genre : dt.mGenres) { + if (genre.getTitle().contains(query)) count++; + } + return count; } public AGenre getGenre(long genreId) { + for (AGenre genre : dt.mGenres) { + if (genre.getId() == genreId) return genre; + } return null; } - public APlaylist[] getPlaylists(int sort, boolean desc) { - return null; + public APlaylist[] getPlaylists() { + return dt.mPlaylists.toArray(new APlaylist[0]); } - public APlaylist[] getPlaylists() { - return null; + public APlaylist[] getPlaylists(int sort, boolean desc) { + return dt.sortPlaylist(dt.mPlaylists, sort, desc); } public APlaylist[] getPagedPlaylists(int sort, boolean desc, int nbItems, int offset) { - return null; + return dt.sortPlaylist(dt.secureSublist(dt.mPlaylists, offset, offset + nbItems), sort, desc); } public int getPlaylistsCount() { - return 0; + return dt.mPlaylists.size(); } public int getPlaylistsCount(String query) { - return 0; + int count = 0; + for (APlaylist playlist : dt.mPlaylists) { + if (playlist.getTitle().contains(query)) count ++; + } + return count; } public APlaylist getPlaylist(long playlistId) { + for (APlaylist playlist : dt.mPlaylists) { + if (playlist.getId() == playlistId) return playlist; + } return null; } public APlaylist createPlaylist(String name) { - return null; + APlaylist playlist = ServiceLocator.getAPlaylist(dt.getUUID(), name, 0); + dt.mPlaylists.add(playlist); + onPlaylistsAdded(); + return playlist; } public void pauseBackgroundOperations() {} public void resumeBackgroundOperations() {} - public void reload() {} - public void reload(String entrypoint) {} + public void reload() { + Log.e(TAG, "reload: no entrypoint"); + reload(""); + } + public void reload(String entrypoint) { + Log.e(TAG, "reload(string entrypoint): "); + onReloadStarted(entrypoint); + onReloadCompleted(entrypoint); + onBackgroundTasksIdleChanged(true); + } public void forceParserRetry() {} public void forceRescan() {} public AMediaWrapper[] lastMediaPlayed() { - return null; + ArrayList results = new ArrayList<>(); + for (AMediaWrapper media : dt.mHistory) { + if (media.getItemType() == AMediaWrapper.TYPE_VIDEO || + media.getItemType() == AMediaWrapper.TYPE_AUDIO) results.add(media); + // the native method specifies an nbItems of 100, offset 0 + if (results.size() >= 100) break; + } + return results.toArray(new AMediaWrapper[0]); } public AMediaWrapper[] lastStreamsPlayed() { - return null; + ArrayList results = new ArrayList<>(); + for (AMediaWrapper media : dt.mHistory) { + if (media.getItemType() == AMediaWrapper.TYPE_STREAM) results.add(media); + // the native method specifies an nbItems of 100, offset 0 + if (results.size() >= 100) break; + } + return results.toArray(new AMediaWrapper[0]); } + //TODO see when it would return false public boolean clearHistory() { + dt.mHistory.clear(); return true; } + //TODO what if two files have the same name ?? + // TODO what happens in case of false return public boolean addToHistory(String mrl, String title) { + AMediaWrapper media = getMedia(mrl, title); + if (media == null) { + media = addStream(mrl, title); + } + dt.mHistory.add(media); + increasePlayCount(media.getId()); return true; } + // TODO Handle uri to mrl + private AMediaWrapper getMedia(String mrl, String title) { + for (AMediaWrapper media : dt.mVideoMediaWrappers) { + if (media.getTitle().equals(title)) return media; + } + for (AMediaWrapper media : dt.mAudioMediaWrappers) { + if (media.getTitle().equals(title)) return media; + } + for (AMediaWrapper media : dt.mStreamMediaWrappers) { + if (media.getTitle().equals(title)) return media; + } + return null; + } + public AMediaWrapper getMedia(long id) { + for (AMediaWrapper media : dt.mVideoMediaWrappers) { + if (media.getId() == id) return media; + } + for (AMediaWrapper media : dt.mAudioMediaWrappers) { + if (media.getId() == id) return media; + } + for (AMediaWrapper media : dt.mStreamMediaWrappers) { + if (media.getId() == id) return media; + } return null; } public AMediaWrapper getMedia(Uri uri) { + for (AMediaWrapper media : dt.mVideoMediaWrappers) { + if (media.getUri().equals(uri)) return media; + } + for (AMediaWrapper media : dt.mAudioMediaWrappers) { + if (media.getUri().equals(uri)) return media; + } + for (AMediaWrapper media : dt.mStreamMediaWrappers) { + if (media.getUri().equals(uri)) return media; + } return null; } @@ -228,6 +372,8 @@ public class StubMedialibrary extends AMedialibrary { return null; } + /* TODO maybe add a list of medias not in the medialibrary which can be retrieved with mrl to + * simulate adding a media from system */ public AMediaWrapper addMedia(String mrl) { return null; } @@ -251,120 +397,155 @@ public class StubMedialibrary extends AMedialibrary { public void requestThumbnail(long id) {} public boolean increasePlayCount(long mediaId) { + for (int i = 0 ; i < dt.mVideoMediaWrappers.size() ; i++) { + AMediaWrapper media = dt.mVideoMediaWrappers.get(i); + if (media.getId() == mediaId) { + media.setSeen(media.getSeen() + 1); + dt.mVideoMediaWrappers.set(i, media); + } + } return true; } - public AMediaWrapper findMedia(AMediaWrapper mw) { - return null; - } - - public void onMediaAdded(AMediaWrapper[] mediaList) {} - public void onMediaUpdated(AMediaWrapper[] mediaList) {} - public void onMediaDeleted() {} - public void onArtistsAdded() {} - public void onArtistsModified() {} - public void onArtistsDeleted() {} - public void onAlbumsAdded() {} - public void onAlbumsModified() {} - public void onAlbumsDeleted() {} - public void onGenresAdded() {} - public void onGenresModified() {} - public void onGenresDeleted() {} - public void onPlaylistsAdded() {} - public void onPlaylistsModified() {} - public void onPlaylistsDeleted() {} - public void onDiscoveryStarted(String entryPoint) {} - public void onDiscoveryProgress(String entryPoint) {} - public void onDiscoveryCompleted(String entryPoint) {} - public void onParsingStatsUpdated(int percent) {} - public void onBackgroundTasksIdleChanged(boolean isIdle) {} - public void onReloadStarted(String entryPoint) {} - public void onReloadCompleted(String entryPoint) {} - public void onEntryPointBanned(String entryPoint, boolean success) {} - public void onEntryPointUnbanned(String entryPoint, boolean success) {} - public void onEntryPointRemoved(String entryPoint, boolean success) {} - public void onMediaThumbnailReady(AMediaWrapper Amedia, boolean success) {} - public void addMediaCb(MediaCb mediaUpdated) {} - public void removeMediaCb(MediaCb mediaUpdatedCb) {} - public void addArtistsCb(ArtistsCb artictAddedCb) {} - public void removeArtistsCb(ArtistsCb artistCb) {} - public void addAlbumsCb(AlbumsCb albumsAddedCb) {} - public void removeAlbumsCb(AlbumsCb albumsAddedCb) {} - public void addGenreCb(GenresCb genresAddedCb) {} - public void removeGenreCb(GenresCb genresAddedCb) {} - public void addPlaylistCb(PlaylistsCb playlistsAddedCb) {} - public void removePlaylistCb(PlaylistsCb playlistsAddedCb) {} - public SearchAggregate search(String query) { - return null; + AMediaWrapper[] videos = searchVideo(query); + AMediaWrapper[] tracks = searchAudio(query); + AAlbum[] albums = searchAlbum(query); + AArtist[] artists = searchArtist(query); + AGenre[] genres = searchGenre(query); + APlaylist[] playlists = searchPlaylist(query); + return new SearchAggregate(albums, artists, genres, videos, tracks, playlists); } public AMediaWrapper[] searchMedia(String query) { - return null; + ArrayList results = new ArrayList<>(); + for (AMediaWrapper media : dt.mVideoMediaWrappers) { + if (media.getTitle().contains(query)) results.add(media); + } + for (AMediaWrapper media : dt.mAudioMediaWrappers) { + if (media.getTitle().contains(query)) results.add(media); + } + for (AMediaWrapper media : dt.mStreamMediaWrappers) { + if (media.getTitle().contains(query)) results.add(media); + } + return results.toArray(new AMediaWrapper[0]); } public AMediaWrapper[] searchMedia(String query, int sort, boolean desc, int nbItems, int offset) { - return null; + ArrayList results = new ArrayList<>(Arrays.asList(searchMedia(query))); + return dt.sortMedia(dt.secureSublist(results, offset, offset + nbItems), sort, desc); } public int getMediaCount(String query) { - return 0; + int count = 0; + for (AMediaWrapper media : dt.mVideoMediaWrappers) { + if (media.getTitle().contains(query)) count++; + } + for (AMediaWrapper media : dt.mAudioMediaWrappers) { + if (media.getTitle().contains(query)) count++; + } + for (AMediaWrapper media : dt.mStreamMediaWrappers) { + if (media.getTitle().contains(query)) count++; + } + return count; + } + + private AMediaWrapper[] searchAudio(String query) { + ArrayList results = new ArrayList<>(); + for (AMediaWrapper media : dt.mAudioMediaWrappers) { + if (media.getTitle().contains(query)) results.add(media); + } + return dt.sortMedia(results, SORT_DEFAULT, false); } public AMediaWrapper[] searchAudio(String query, int sort, boolean desc, int nbItems, int offset) { - return null; + ArrayList results = new ArrayList<>(); + for (AMediaWrapper media : dt.mAudioMediaWrappers) { + if (media.getTitle().contains(query)) results.add(media); + } + return dt.sortMedia(dt.secureSublist(results, offset, offset + nbItems), sort, desc); } public int getAudioCount(String query) { - return 0; + int count = 0; + for (AMediaWrapper media : dt.mAudioMediaWrappers) { + if (media.getTitle().contains(query)) count++; + } + return count; + } + + private AMediaWrapper[] searchVideo(String query) { + ArrayList results = new ArrayList<>(); + for (AMediaWrapper media : dt.mVideoMediaWrappers) { + if (media.getTitle().contains(query)) results.add(media); + } + return dt.sortMedia(results, SORT_DEFAULT, false); } public AMediaWrapper[] searchVideo(String query, int sort, boolean desc, int nbItems, int offset) { - return null; + ArrayList results = new ArrayList<>(); + for (AMediaWrapper media : dt.mVideoMediaWrappers) { + if (media.getTitle().contains(query)) results.add(media); + } + return dt.sortMedia(dt.secureSublist(results, offset, offset + nbItems), sort, desc); } public int getVideoCount(String query) { - return 0; + int count = 0; + for (AMediaWrapper media : dt.mVideoMediaWrappers) { + if (media.getTitle().contains(query)) count++; + } + return count; } public AArtist[] searchArtist(String query) { - return null; + ArrayList results = new ArrayList<>(); + for (AArtist artist: dt.mArtists) { + if (artist.getTitle().contains(query)) results.add(artist); + } + return results.toArray(new AArtist[0]); } public AArtist[] searchArtist(String query, int sort, boolean desc, int nbItems, int offset) { - return null; + ArrayList results = new ArrayList<>(Arrays.asList(searchArtist(query))); + return dt.sortArtist(dt.secureSublist(results, offset, offset + nbItems), sort, desc); } public AAlbum[] searchAlbum(String query) { - return null; - + ArrayList results = new ArrayList<>(); + for (AAlbum album: dt.mAlbums) { + if (album.getTitle().contains(query)) results.add(album); + } + return results.toArray(new AAlbum[0]); } public AAlbum[] searchAlbum(String query, int sort, boolean desc, int nbItems, int offset) { - return null; + ArrayList results = new ArrayList<>(Arrays.asList(searchAlbum(query))); + return dt.sortAlbum(dt.secureSublist(results, offset, offset + nbItems), sort, desc); } public AGenre[] searchGenre(String query) { - return null; + ArrayList results = new ArrayList<>(); + for (AGenre genre: dt.mGenres) { + if (genre.getTitle().contains(query)) results.add(genre); + } + return results.toArray(new AGenre[0]); } public AGenre[] searchGenre(String query, int sort, boolean desc, int nbItems, int offset) { - return null; + ArrayList results = new ArrayList<>(Arrays.asList(searchGenre(query))); + return dt.sortGenre(dt.secureSublist(results, offset, offset + nbItems), sort, desc); } public APlaylist[] searchPlaylist(String query) { - return null; + ArrayList results = new ArrayList<>(); + for (APlaylist playlist: dt.mPlaylists) { + if (playlist.getTitle().contains(query)) results.add(playlist); + } + return results.toArray(new APlaylist[0]); } public APlaylist[] searchPlaylist(String query, int sort, boolean desc, int nbItems, int offset) { - return null; + ArrayList results = new ArrayList<>(Arrays.asList(searchPlaylist(query))); + return dt.sortPlaylist(dt.secureSublist(results, offset, offset + nbItems), sort, desc); } - - public void addDeviceDiscoveryCb(DevicesDiscoveryCb cb) {} - public void removeDeviceDiscoveryCb(DevicesDiscoveryCb cb) {} - public void addOnMedialibraryReadyListener(OnMedialibraryReadyListener cb) {} - public void removeOnMedialibraryReadyListener(OnMedialibraryReadyListener cb) {} - public void addEntryPointsEventsCb(EntryPointsEventsCb cb) {} - public void removeEntryPointsEventsCb(EntryPointsEventsCb cb) {} - public void addOnDeviceChangeListener(OnDeviceChangeListener cb) {} - public void removeOnDeviceChangeListener(OnDeviceChangeListener cb){} } diff --git a/medialibrary/src/org/videolan/medialibrary/stubs/StubPlaylist.java b/medialibrary/src/org/videolan/medialibrary/stubs/StubPlaylist.java index 9e1eecc85..3863c5b12 100644 --- a/medialibrary/src/org/videolan/medialibrary/stubs/StubPlaylist.java +++ b/medialibrary/src/org/videolan/medialibrary/stubs/StubPlaylist.java @@ -5,10 +5,15 @@ import android.os.Parcel; import org.videolan.medialibrary.interfaces.media.AMediaWrapper; import org.videolan.medialibrary.interfaces.media.APlaylist; +import java.util.ArrayList; +import java.util.Arrays; import java.util.List; public class StubPlaylist extends APlaylist { + private ArrayList mTracksId = new ArrayList<>(); + private StubDataSource dt = StubDataSource.getInstance(); + public StubPlaylist(long id, String name, int trackCount) { super(id, name, trackCount); } @@ -18,50 +23,91 @@ public class StubPlaylist extends APlaylist { } public AMediaWrapper[] getTracks() { - return null; + ArrayList results = new ArrayList<>(); + for (AMediaWrapper media : dt.mAudioMediaWrappers) { + if (mTracksId.contains(media.getId())) results.add(media); + } + return results.toArray(new AMediaWrapper[0]); } public AMediaWrapper[] getPagedTracks(int nbItems, int offset) { - return null; + ArrayList results = new ArrayList<>(Arrays.asList(getTracks())); + return dt.secureSublist(results, offset, offset + nbItems).toArray(new AMediaWrapper[0]); } public int getRealTracksCount() { - return 0; + int count = 0; + for (AMediaWrapper media : dt.mAudioMediaWrappers) { + if (mTracksId.contains(media.getId())) count++; + } + return count; } public boolean append(long mediaId) { + mTracksId.add(mediaId); + mTracksCount++; return true; } public boolean append(long[] mediaIds) { + for (long id : mediaIds) { + append(id); + } return true; } public boolean append(List mediaIds) { + for (long id : mediaIds) { + append(id); + } return true; } public boolean add(long mediaId, int position) { + mTracksId.add(position, mediaId); return true; } public boolean move(int oldPosition, int newPosition) { + long id = mTracksId.get(oldPosition); + mTracksId.remove(oldPosition); + mTracksId.add(newPosition, id); return true; } public boolean remove(int position) { + mTracksId.remove(position); + mTracksCount--; return true; } public boolean delete() { - return true; + for (int i = 0 ; i < dt.mPlaylists.size() ; i++) { + if (dt.mPlaylists.get(i).getId() == this.getId()) { + dt.mPlaylists.remove(i); + return true; + } + } + return false; } public AMediaWrapper[] searchTracks(String query, int sort, boolean desc, int nbItems, int offset) { - return null; + ArrayList results = new ArrayList<>(); + for (AMediaWrapper media : dt.mAudioMediaWrappers) { + if (mTracksId.contains(media.getId()) && + media.getTitle().contains(query)) results.add(media); + } + results = new ArrayList<>(Arrays.asList(dt.sortMedia(results, sort, desc))); + return dt.secureSublist(results, offset, offset + nbItems).toArray(new AMediaWrapper[0]); + } public int searchTracksCount(String query) { - return 0; + int count = 0; + for (AMediaWrapper media : dt.mAudioMediaWrappers) { + if (mTracksId.contains(media.getId()) && + media.getTitle().contains(query)) count++; + } + return count; } } diff --git a/vlc-android/res/layout/activity_media_list_tv_item.xml b/vlc-android/res/layout/activity_media_list_tv_item.xml index b28b38983..cfd868bec 100644 --- a/vlc-android/res/layout/activity_media_list_tv_item.xml +++ b/vlc-android/res/layout/activity_media_list_tv_item.xml @@ -12,12 +12,12 @@ - + + type="AbstractMediaWrapper" /> MediaUtils.openList(this, tracks, 0) R.id.action_mode_audio_append -> MediaUtils.appendMedia(this, tracks) R.id.action_mode_audio_add_playlist -> UiTools.addToPlaylist(this, tracks) -<<<<<<< HEAD - R.id.action_mode_audio_info -> showInfoDialog(list[0] as MediaWrapper) - R.id.action_mode_audio_set_song -> AudioUtil.setRingtone(list[0] as MediaWrapper, this) - R.id.action_mode_audio_delete -> if (isPlaylist) removeFromPlaylist(tracks, indexes) else removeItems(tracks) -======= R.id.action_mode_audio_info -> showInfoDialog(list[0] as AMediaWrapper) R.id.action_mode_audio_set_song -> AudioUtil.setRingtone(list[0] as AMediaWrapper, this) - R.id.action_mode_audio_delete -> removeFromPlaylist(tracks, indexes) ->>>>>>> Medialibrary: move MediaWrapper to AMediaWrapper + R.id.action_mode_audio_delete -> if (isPlaylist) removeFromPlaylist(tracks, indexes) else removeItems(tracks) else -> return false } return true @@ -329,18 +323,14 @@ open class PlaylistActivity : AudioPlayerContainerActivity(), IEventsHandler, IL private fun removeItem(position: Int, media: AMediaWrapper) { val resId = if (isPlaylist) R.string.confirm_remove_from_playlist else R.string.confirm_delete if (isPlaylist) { -<<<<<<< HEAD - snackerConfirm(binding.root, getString(resId, media.title), Runnable { (viewModel.playlist as Playlist).remove(position) }) -======= - UiTools.snackerConfirm(binding.root, getString(resId, media.title), Runnable { (viewModel.playlist as APlaylist).remove(position) }) ->>>>>>> Medialibrary: move Playlist to APlaylist + snackerConfirm(binding.root, getString(resId, media.title), Runnable { (viewModel.playlist as APlaylist).remove(position) }) } else { val deleteAction = Runnable { deleteMedia(media) } snackerConfirm(binding.root, getString(resId, media.title), Runnable { if (Util.checkWritePermission(this@PlaylistActivity, media, deleteAction)) deleteAction.run() }) } } - private fun removeItems(items: List) { + private fun removeItems(items: List) { snackerConfirm(binding.root,getString(R.string.confirm_delete_several_media, items.size)) { for (item in items) { if (!isStarted()) break diff --git a/vlc-android/src/org/videolan/vlc/gui/audio/AudioBrowserFragment.kt b/vlc-android/src/org/videolan/vlc/gui/audio/AudioBrowserFragment.kt index 813cf965c..fb7469e54 100644 --- a/vlc-android/src/org/videolan/vlc/gui/audio/AudioBrowserFragment.kt +++ b/vlc-android/src/org/videolan/vlc/gui/audio/AudioBrowserFragment.kt @@ -44,11 +44,7 @@ import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.ObsoleteCoroutinesApi import org.videolan.medialibrary.interfaces.media.AMediaWrapper import org.videolan.medialibrary.media.MediaLibraryItem -<<<<<<< HEAD -import org.videolan.medialibrary.media.MediaWrapper import org.videolan.vlc.BuildConfig -======= ->>>>>>> Medialibrary: move MediaWrapper to AMediaWrapper import org.videolan.vlc.R import org.videolan.vlc.gui.* import org.videolan.vlc.gui.view.FastScroller diff --git a/vlc-android/src/org/videolan/vlc/gui/audio/BaseAudioBrowser.kt b/vlc-android/src/org/videolan/vlc/gui/audio/BaseAudioBrowser.kt index 46a54b854..f42a6d8ab 100644 --- a/vlc-android/src/org/videolan/vlc/gui/audio/BaseAudioBrowser.kt +++ b/vlc-android/src/org/videolan/vlc/gui/audio/BaseAudioBrowser.kt @@ -32,18 +32,10 @@ import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView import androidx.viewpager.widget.ViewPager import com.google.android.material.tabs.TabLayout -<<<<<<< HEAD import kotlinx.coroutines.* -import org.videolan.medialibrary.media.MediaLibraryItem -import org.videolan.medialibrary.media.MediaWrapper -import org.videolan.tools.isStarted -======= -import kotlinx.coroutines.ExperimentalCoroutinesApi -import kotlinx.coroutines.ObsoleteCoroutinesApi -import kotlinx.coroutines.launch import org.videolan.medialibrary.interfaces.media.AMediaWrapper import org.videolan.medialibrary.media.MediaLibraryItem ->>>>>>> Medialibrary: move MediaWrapper to AMediaWrapper +import org.videolan.tools.isStarted import org.videolan.vlc.R import org.videolan.vlc.gui.ContentActivity import org.videolan.vlc.gui.browser.MediaBrowserFragment @@ -186,39 +178,21 @@ abstract class BaseAudioBrowser : MediaBrowserFragment(), override fun onActionItemClicked(mode: ActionMode, item: MenuItem): Boolean { val list = getCurrentAdapter()?.multiSelectHelper?.getSelection() stopActionMode() -<<<<<<< HEAD if (!list.isNullOrEmpty()) launch { if (isStarted()) when (item.itemId) { R.id.action_mode_audio_play -> MediaUtils.openList(activity, list.getTracks(), 0) R.id.action_mode_audio_append -> MediaUtils.appendMedia(activity, list.getTracks()) R.id.action_mode_audio_add_playlist -> UiTools.addToPlaylist(requireActivity(), list.getTracks()) R.id.action_mode_audio_info -> showInfoDialog(list[0]) - R.id.action_mode_audio_set_song -> AudioUtil.setRingtone(list[0] as MediaWrapper, requireActivity()) + R.id.action_mode_audio_set_song -> AudioUtil.setRingtone(list[0] as AMediaWrapper, requireActivity()) R.id.action_mode_audio_delete -> removeItems(list) } } -======= - if (list != null && list.isNotEmpty()) - runIO(Runnable { - val tracks = ArrayList() - for (mediaItem in list) - tracks.addAll(Arrays.asList(*mediaItem.tracks)) - launch { - when (item.itemId) { - R.id.action_mode_audio_play -> MediaUtils.openList(activity, tracks, 0) - R.id.action_mode_audio_append -> MediaUtils.appendMedia(activity, tracks) - R.id.action_mode_audio_add_playlist -> UiTools.addToPlaylist(requireActivity(), tracks) - R.id.action_mode_audio_info -> showInfoDialog(list[0]) - R.id.action_mode_audio_set_song -> AudioUtil.setRingtone(list[0] as AMediaWrapper, requireActivity()) - } - } - }) ->>>>>>> Medialibrary: move MediaWrapper to AMediaWrapper return true } private suspend fun List.getTracks() = withContext(Dispatchers.Default) { - ArrayList().apply { + ArrayList().apply { for (mediaItem in this@getTracks) addAll(Arrays.asList(*mediaItem.tracks)) } } diff --git a/vlc-android/src/org/videolan/vlc/gui/browser/MediaBrowserFragment.kt b/vlc-android/src/org/videolan/vlc/gui/browser/MediaBrowserFragment.kt index 7216332d7..c171c5e33 100644 --- a/vlc-android/src/org/videolan/vlc/gui/browser/MediaBrowserFragment.kt +++ b/vlc-android/src/org/videolan/vlc/gui/browser/MediaBrowserFragment.kt @@ -162,8 +162,8 @@ abstract class MediaBrowserFragment : Fragment(), ActionMode. for (item in items) { if (!isStarted()) break when(item) { - is MediaWrapper -> if (getWritePermission(item.uri)) deleteMedia(item) - is Playlist -> withContext(Dispatchers.IO) { item.delete() } + is AMediaWrapper -> if (getWritePermission(item.uri)) deleteMedia(item) + is APlaylist -> withContext(Dispatchers.IO) { item.delete() } } } if (isStarted()) viewModel.refresh() @@ -175,15 +175,10 @@ abstract class MediaBrowserFragment : Fragment(), ActionMode. when { item.itemType == MediaLibraryItem.TYPE_PLAYLIST -> UiTools.snackerConfirm(view!!, getString(R.string.confirm_delete_playlist, item.title), Runnable { MediaUtils.deletePlaylist(item as APlaylist) }) item.itemType == MediaLibraryItem.TYPE_MEDIA -> { -<<<<<<< HEAD val deleteAction = Runnable { if (isStarted()) launch { deleteMedia(item, false, null) } } - val resid = if ((item as MediaWrapper).type == MediaWrapper.TYPE_DIR) R.string.confirm_delete_folder else R.string.confirm_delete -======= - val deleteAction = Runnable { deleteMedia(item, false, null) } val resid = if ((item as AMediaWrapper).type == AMediaWrapper.TYPE_DIR) R.string.confirm_delete_folder else R.string.confirm_delete ->>>>>>> Medialibrary: move MediaWrapper to AMediaWrapper UiTools.snackerConfirm(view!!, getString(resid, item.getTitle()), Runnable { if (Util.checkWritePermission(requireActivity(), item, deleteAction)) deleteAction.run() }) } else -> return false diff --git a/vlc-android/src/org/videolan/vlc/gui/helpers/UiTools.kt b/vlc-android/src/org/videolan/vlc/gui/helpers/UiTools.kt index 48d6e4d44..140802714 100644 --- a/vlc-android/src/org/videolan/vlc/gui/helpers/UiTools.kt +++ b/vlc-android/src/org/videolan/vlc/gui/helpers/UiTools.kt @@ -261,12 +261,8 @@ object UiTools { addToPlaylist(activity, list.toTypedArray(), SavePlaylistDialog.KEY_NEW_TRACKS) } -<<<<<<< HEAD - fun addToPlaylist(activity: FragmentActivity, tracks: Array, key: String) { - if (!activity.isStarted()) return -======= fun addToPlaylist(activity: FragmentActivity, tracks: Array, key: String) { ->>>>>>> Medialibrary: move MediaWrapper to AMediaWrapper + if (!activity.isStarted()) return val savePlaylistDialog = SavePlaylistDialog() val args = Bundle() args.putParcelableArray(key, tracks) diff --git a/vlc-android/src/org/videolan/vlc/gui/tv/MediaHeaderAdapter.kt b/vlc-android/src/org/videolan/vlc/gui/tv/MediaHeaderAdapter.kt index 0472d2b67..bc39d1ed3 100644 --- a/vlc-android/src/org/videolan/vlc/gui/tv/MediaHeaderAdapter.kt +++ b/vlc-android/src/org/videolan/vlc/gui/tv/MediaHeaderAdapter.kt @@ -30,11 +30,7 @@ class MediaHeaderAdapter(private val onHeaderSelected: OnHeaderSelected) : Recyc override fun onBindViewHolder(holder: ViewHolder, position: Int) { -<<<<<<< HEAD - if (sortType == Medialibrary.SORT_ALPHA || sortType == Medialibrary.SORT_DEFAULT) { -======= - if (sortType == AMedialibrary.SORT_ALPHA) { ->>>>>>> Medialibrary: move Medialibrary to AMedialibrary + if (sortType == AMedialibrary.SORT_ALPHA || sortType == AMedialibrary.SORT_DEFAULT) { holder.binding.headerText = alphaItems[position] holder.binding.hasContent = items.contains(alphaItems[position]) } else { @@ -44,11 +40,7 @@ class MediaHeaderAdapter(private val onHeaderSelected: OnHeaderSelected) : Recyc } fun getItem(position: Int): String { -<<<<<<< HEAD - return if (sortType == Medialibrary.SORT_ALPHA || sortType == Medialibrary.SORT_DEFAULT) { -======= - return if (sortType == AMedialibrary.SORT_ALPHA) { ->>>>>>> Medialibrary: move Medialibrary to AMedialibrary + return if (sortType == AMedialibrary.SORT_ALPHA || sortType == AMedialibrary.SORT_DEFAULT) { alphaItems[position] } else { items[position] diff --git a/vlc-android/src/org/videolan/vlc/gui/tv/TvUtil.kt b/vlc-android/src/org/videolan/vlc/gui/tv/TvUtil.kt index 10d2a9518..be88c842f 100644 --- a/vlc-android/src/org/videolan/vlc/gui/tv/TvUtil.kt +++ b/vlc-android/src/org/videolan/vlc/gui/tv/TvUtil.kt @@ -118,7 +118,7 @@ object TvUtil { MediaUtils.openMedia(activity, media) } - fun playMedia(activity: Activity, media: List) { + fun playMedia(activity: Activity, media: List) { val intent = Intent(activity, AudioPlayerActivity::class.java) intent.putExtra(AudioPlayerActivity.MEDIA_LIST, ArrayList(media)) activity.startActivity(intent) diff --git a/vlc-android/src/org/videolan/vlc/gui/tv/browser/BaseBrowserTvFragment.kt b/vlc-android/src/org/videolan/vlc/gui/tv/browser/BaseBrowserTvFragment.kt index 2f3a74ece..582bdc0d9 100644 --- a/vlc-android/src/org/videolan/vlc/gui/tv/browser/BaseBrowserTvFragment.kt +++ b/vlc-android/src/org/videolan/vlc/gui/tv/browser/BaseBrowserTvFragment.kt @@ -45,10 +45,7 @@ import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView import kotlinx.android.synthetic.main.song_browser.* -import kotlinx.coroutines.CoroutineScope -import kotlinx.coroutines.ExperimentalCoroutinesApi -import kotlinx.coroutines.MainScope -import kotlinx.coroutines.ObsoleteCoroutinesApi +import kotlinx.coroutines.* import org.videolan.medialibrary.interfaces.AMedialibrary import org.videolan.medialibrary.interfaces.media.AMediaWrapper import org.videolan.medialibrary.media.MediaLibraryItem diff --git a/vlc-android/src/org/videolan/vlc/gui/tv/browser/FileBrowserTvFragment.kt b/vlc-android/src/org/videolan/vlc/gui/tv/browser/FileBrowserTvFragment.kt index fef86e3e3..14801978c 100644 --- a/vlc-android/src/org/videolan/vlc/gui/tv/browser/FileBrowserTvFragment.kt +++ b/vlc-android/src/org/videolan/vlc/gui/tv/browser/FileBrowserTvFragment.kt @@ -69,7 +69,7 @@ class FileBrowserTvFragment : BaseBrowserTvFragment() { if (BuildConfig.DEBUG) Log.d("FileBrowserTvFragment", "Submit lis of ${items.size} items") //headers - val nbColumns = if ((viewModel as BrowserModel).sort == Medialibrary.SORT_ALPHA || (viewModel as BrowserModel).sort == Medialibrary.SORT_DEFAULT) 9 else 1 + val nbColumns = if ((viewModel as BrowserModel).sort == AMedialibrary.SORT_ALPHA || (viewModel as BrowserModel).sort == AMedialibrary.SORT_DEFAULT) 9 else 1 headerList.layoutManager = GridLayoutManager(requireActivity(), nbColumns) headerAdapter.sortType = (viewModel as BrowserModel).sort diff --git a/vlc-android/src/org/videolan/vlc/gui/tv/browser/MediaBrowserTvFragment.kt b/vlc-android/src/org/videolan/vlc/gui/tv/browser/MediaBrowserTvFragment.kt index b89e6365b..d35b93a26 100644 --- a/vlc-android/src/org/videolan/vlc/gui/tv/browser/MediaBrowserTvFragment.kt +++ b/vlc-android/src/org/videolan/vlc/gui/tv/browser/MediaBrowserTvFragment.kt @@ -67,7 +67,7 @@ class MediaBrowserTvFragment : BaseBrowserTvFragment() { submitList(items) //headers - val nbColumns = if ((viewModel as MediaBrowserViewModel).sort == Medialibrary.SORT_ALPHA || (viewModel as MediaBrowserViewModel).sort == Medialibrary.SORT_DEFAULT) 9 else 1 + val nbColumns = if ((viewModel as MediaBrowserViewModel).sort == AMedialibrary.SORT_ALPHA || (viewModel as MediaBrowserViewModel).sort == AMedialibrary.SORT_DEFAULT) 9 else 1 headerList.layoutManager = GridLayoutManager(requireActivity(), nbColumns) headerAdapter.sortType = (viewModel as MediaBrowserViewModel).sort diff --git a/vlc-android/src/org/videolan/vlc/gui/tv/details/MediaListAdapter.kt b/vlc-android/src/org/videolan/vlc/gui/tv/details/MediaListAdapter.kt index d10473f47..9c793e454 100644 --- a/vlc-android/src/org/videolan/vlc/gui/tv/details/MediaListAdapter.kt +++ b/vlc-android/src/org/videolan/vlc/gui/tv/details/MediaListAdapter.kt @@ -10,8 +10,8 @@ import android.view.ViewGroup import androidx.constraintlayout.widget.ConstraintLayout import kotlinx.coroutines.ExperimentalCoroutinesApi import kotlinx.coroutines.ObsoleteCoroutinesApi +import org.videolan.medialibrary.interfaces.media.AbstractMediaWrapper import org.videolan.medialibrary.media.MediaLibraryItem -import org.videolan.medialibrary.media.MediaWrapper import org.videolan.vlc.BuildConfig import org.videolan.vlc.databinding.ActivityMediaListTvItemBinding import org.videolan.vlc.gui.DiffUtilAdapter @@ -22,7 +22,7 @@ import org.videolan.vlc.interfaces.ITVEventsHandler @ExperimentalCoroutinesApi @ObsoleteCoroutinesApi -class MediaListAdapter(private val type: Int, private val listener: ITVEventsHandler) : DiffUtilAdapter(), TvFocusableAdapter { +class MediaListAdapter(private val type: Int, private val listener: ITVEventsHandler) : DiffUtilAdapter(), TvFocusableAdapter { private var focusListener: FocusableRecyclerView.FocusListener? = null @@ -56,8 +56,8 @@ class MediaListAdapter(private val type: Int, private val listener: ITVEventsHan override fun detectMoves() = true - override fun createCB(): DiffCallback { - return object : DiffCallback() { + override fun createCB(): DiffCallback { + return object : DiffCallback() { override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean { if (newItemPosition == lastMovedItemFrom) { lastMovedItemFrom = -1 diff --git a/vlc-android/src/org/videolan/vlc/providers/BrowserProvider.kt b/vlc-android/src/org/videolan/vlc/providers/BrowserProvider.kt index 744ffa6cf..c1f777f91 100644 --- a/vlc-android/src/org/videolan/vlc/providers/BrowserProvider.kt +++ b/vlc-android/src/org/videolan/vlc/providers/BrowserProvider.kt @@ -25,6 +25,7 @@ import android.net.Uri import android.os.Handler import android.os.HandlerThread import android.os.Process +import android.util.Log import androidx.collection.SimpleArrayMap import androidx.lifecycle.MutableLiveData import kotlinx.coroutines.* diff --git a/vlc-android/src/org/videolan/vlc/viewmodels/tv/MainTvModel.kt b/vlc-android/src/org/videolan/vlc/viewmodels/tv/MainTvModel.kt index 4d3c769a6..a8db09959 100644 --- a/vlc-android/src/org/videolan/vlc/viewmodels/tv/MainTvModel.kt +++ b/vlc-android/src/org/videolan/vlc/viewmodels/tv/MainTvModel.kt @@ -73,7 +73,7 @@ class MainTvModel(app: Application) : AndroidViewModel(app), AMedialibrary.OnMed val videos: LiveData> = MutableLiveData() val audioCategories: LiveData> = MutableLiveData() val browsers: LiveData> = MutableLiveData() - val history: LiveData> = MutableLiveData() + val history: LiveData> = MutableLiveData() val playlist: LiveData> = MutableLiveData() private val nowPlayingDelegate = NowPlayingDelegate(this) @@ -150,7 +150,7 @@ class MainTvModel(app: Application) : AndroidViewModel(app), AMedialibrary.OnMed private fun updatePlaylists() = launch { context.getFromMl { - getPagedPlaylists(Medialibrary.SORT_INSERTIONDATE, true, NUM_ITEMS_PREVIEW, 0) + getPagedPlaylists(AMedialibrary.SORT_INSERTIONDATE, true, NUM_ITEMS_PREVIEW, 0) }.let { (playlist as MutableLiveData).value = mutableListOf().apply { // add(DummyItem(HEADER_PLAYLISTS, context.getString(R.string.playlists), ""))