kotlin conversion
This commit is contained in:
parent
8e6ab40d93
commit
b2c15ef186
316 changed files with 13055 additions and 22983 deletions
|
@ -1,104 +0,0 @@
|
|||
package code.name.monkey.retromusic.loaders;
|
||||
|
||||
import android.content.Context;
|
||||
import android.provider.MediaStore.Audio.AudioColumns;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import code.name.monkey.retromusic.model.Album;
|
||||
import code.name.monkey.retromusic.model.Song;
|
||||
import code.name.monkey.retromusic.util.PreferenceUtil;
|
||||
import io.reactivex.Observable;
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* Created by hemanths on 11/08/17.
|
||||
*/
|
||||
|
||||
public class AlbumLoader {
|
||||
|
||||
public static Observable<ArrayList<Album>> getAllAlbums(@NonNull Context context) {
|
||||
Observable<ArrayList<Song>> songs = SongLoader.Companion.getSongs(SongLoader.Companion.makeSongCursor(
|
||||
context,
|
||||
null,
|
||||
null,
|
||||
getSongLoaderSortOrder(context))
|
||||
);
|
||||
|
||||
return splitIntoAlbums(songs);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public static Observable<ArrayList<Album>> getAlbums(@NonNull final Context context,
|
||||
String query) {
|
||||
Observable<ArrayList<Song>> songs = SongLoader.Companion.getSongs(SongLoader.Companion.makeSongCursor(
|
||||
context,
|
||||
AudioColumns.ALBUM + " LIKE ?",
|
||||
new String[]{"%" + query + "%"},
|
||||
getSongLoaderSortOrder(context))
|
||||
);
|
||||
return splitIntoAlbums(songs);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public static Observable<Album> getAlbum(@NonNull final Context context, int albumId) {
|
||||
return Observable.create(e -> {
|
||||
Observable<ArrayList<Song>> songs = SongLoader.Companion.getSongs(SongLoader.Companion
|
||||
.makeSongCursor(context, AudioColumns.ALBUM_ID + "=?",
|
||||
new String[]{String.valueOf(albumId)}, getSongLoaderSortOrder(context)));
|
||||
songs.subscribe(songs1 -> {
|
||||
e.onNext(new Album(songs1));
|
||||
e.onComplete();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public static Observable<ArrayList<Album>> splitIntoAlbums(
|
||||
@Nullable final Observable<ArrayList<Song>> songs) {
|
||||
return Observable.create(e -> {
|
||||
ArrayList<Album> albums = new ArrayList<>();
|
||||
if (songs != null) {
|
||||
songs.subscribe(songs1 -> {
|
||||
for (Song song : songs1) {
|
||||
getOrCreateAlbum(albums, song.albumId).subscribe(album -> album.songs.add(song));
|
||||
}
|
||||
});
|
||||
}
|
||||
e.onNext(albums);
|
||||
e.onComplete();
|
||||
});
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public static ArrayList<Album> splitIntoAlbums(@Nullable final ArrayList<Song> songs) {
|
||||
ArrayList<Album> albums = new ArrayList<>();
|
||||
if (songs != null) {
|
||||
for (Song song : songs) {
|
||||
getOrCreateAlbum(albums, song.albumId).subscribe(album -> album.songs.add(song));
|
||||
}
|
||||
}
|
||||
return albums;
|
||||
}
|
||||
|
||||
private static Observable<Album> getOrCreateAlbum(ArrayList<Album> albums, int albumId) {
|
||||
return Observable.create(e -> {
|
||||
for (Album album : albums) {
|
||||
if (!album.songs.isEmpty() && album.songs.get(0).albumId == albumId) {
|
||||
e.onNext(album);
|
||||
e.onComplete();
|
||||
return;
|
||||
}
|
||||
}
|
||||
Album album = new Album();
|
||||
albums.add(album);
|
||||
e.onNext(album);
|
||||
e.onComplete();
|
||||
});
|
||||
}
|
||||
|
||||
public static String getSongLoaderSortOrder(Context context) {
|
||||
return PreferenceUtil.getInstance().getAlbumSortOrder() + ", " +
|
||||
//PreferenceUtil.getInstance().getAlbumSongSortOrder() + "," +
|
||||
PreferenceUtil.getInstance().getAlbumDetailSongSortOrder();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,95 @@
|
|||
package code.name.monkey.retromusic.loaders
|
||||
|
||||
import android.content.Context
|
||||
import android.provider.MediaStore.Audio.AudioColumns
|
||||
import code.name.monkey.retromusic.model.Album
|
||||
import code.name.monkey.retromusic.model.Song
|
||||
import code.name.monkey.retromusic.util.PreferenceUtil
|
||||
import io.reactivex.Observable
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
* Created by hemanths on 11/08/17.
|
||||
*/
|
||||
|
||||
open class AlbumLoader {
|
||||
companion object {
|
||||
fun getAllAlbums(context: Context): Observable<ArrayList<Album>> {
|
||||
val songs = SongLoader.getSongs(SongLoader.makeSongCursor(
|
||||
context, null, null,
|
||||
getSongLoaderSortOrder())
|
||||
)
|
||||
|
||||
return splitIntoAlbums(songs)
|
||||
}
|
||||
|
||||
fun getAlbums(context: Context,
|
||||
query: String): Observable<ArrayList<Album>> {
|
||||
val songs = SongLoader.getSongs(SongLoader.makeSongCursor(
|
||||
context,
|
||||
AudioColumns.ALBUM + " LIKE ?",
|
||||
arrayOf("%$query%"),
|
||||
getSongLoaderSortOrder())
|
||||
)
|
||||
return splitIntoAlbums(songs)
|
||||
}
|
||||
|
||||
fun getAlbum(context: Context, albumId: Int): Observable<Album> {
|
||||
return Observable.create { e ->
|
||||
val songs = SongLoader.getSongs(SongLoader
|
||||
.makeSongCursor(context, AudioColumns.ALBUM_ID + "=?",
|
||||
arrayOf(albumId.toString()), getSongLoaderSortOrder()))
|
||||
songs.subscribe { songs1 ->
|
||||
e.onNext(Album(songs1))
|
||||
e.onComplete()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun splitIntoAlbums(
|
||||
songs: Observable<ArrayList<Song>>?): Observable<ArrayList<Album>> {
|
||||
return Observable.create { e ->
|
||||
val albums = ArrayList<Album>()
|
||||
songs?.subscribe { songs1 ->
|
||||
for (song in songs1) {
|
||||
getOrCreateAlbum(albums, song.albumId).subscribe { album -> album.songs!!.add(song) }
|
||||
}
|
||||
}
|
||||
e.onNext(albums)
|
||||
e.onComplete()
|
||||
}
|
||||
}
|
||||
|
||||
fun splitIntoAlbums(songs: ArrayList<Song>?): ArrayList<Album> {
|
||||
val albums = ArrayList<Album>()
|
||||
if (songs != null) {
|
||||
for (song in songs) {
|
||||
getOrCreateAlbum(albums, song.albumId).subscribe { album -> album.songs!!.add(song) }
|
||||
}
|
||||
}
|
||||
return albums
|
||||
}
|
||||
|
||||
private fun getOrCreateAlbum(albums: ArrayList<Album>, albumId: Int): Observable<Album> {
|
||||
return Observable.create { e ->
|
||||
for (album in albums) {
|
||||
if (!album.songs!!.isEmpty() && album.songs[0].albumId == albumId) {
|
||||
e.onNext(album)
|
||||
e.onComplete()
|
||||
return@create
|
||||
}
|
||||
}
|
||||
val album = Album()
|
||||
albums.add(album)
|
||||
e.onNext(album)
|
||||
e.onComplete()
|
||||
}
|
||||
}
|
||||
|
||||
fun getSongLoaderSortOrder(): String {
|
||||
return PreferenceUtil.getInstance().albumSortOrder + ", " +
|
||||
//PreferenceUtil.getInstance().getAlbumSongSortOrder() + "," +
|
||||
PreferenceUtil.getInstance().albumDetailSongSortOrder
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,101 +0,0 @@
|
|||
package code.name.monkey.retromusic.loaders;
|
||||
|
||||
import android.content.Context;
|
||||
import android.provider.MediaStore.Audio.AudioColumns;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import code.name.monkey.retromusic.model.Album;
|
||||
import code.name.monkey.retromusic.model.Artist;
|
||||
import code.name.monkey.retromusic.util.PreferenceUtil;
|
||||
import io.reactivex.Observable;
|
||||
|
||||
public class ArtistLoader {
|
||||
private static String getSongLoaderSortOrder(Context context) {
|
||||
return PreferenceUtil.getInstance().getArtistSortOrder() + ", " +
|
||||
PreferenceUtil.getInstance().getArtistAlbumSortOrder() + ", " +
|
||||
PreferenceUtil.getInstance().getAlbumDetailSongSortOrder() + ", " +
|
||||
PreferenceUtil.getInstance().getArtistDetailSongSortOrder();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public static Observable<Artist> getArtist(@NonNull final Context context, int artistId) {
|
||||
return Observable.create(e -> SongLoader.Companion.getSongs(SongLoader.Companion.makeSongCursor(
|
||||
context,
|
||||
AudioColumns.ARTIST_ID + "=?",
|
||||
new String[]{String.valueOf(artistId)},
|
||||
getSongLoaderSortOrder(context)))
|
||||
.subscribe(songs -> {
|
||||
Artist artist = new Artist(AlbumLoader.splitIntoAlbums(songs));
|
||||
e.onNext(artist);
|
||||
e.onComplete();
|
||||
}));
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public static Observable<ArrayList<Artist>> getAllArtists(@NonNull final Context context) {
|
||||
return Observable.create(e -> SongLoader.Companion
|
||||
.getSongs(SongLoader.Companion.makeSongCursor(
|
||||
context,
|
||||
null,
|
||||
null,
|
||||
getSongLoaderSortOrder(context))
|
||||
).subscribe(songs -> {
|
||||
e.onNext(splitIntoArtists(AlbumLoader.splitIntoAlbums(songs)));
|
||||
e.onComplete();
|
||||
}));
|
||||
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public static Observable<ArrayList<Artist>> getArtists(@NonNull final Context context, String query) {
|
||||
return Observable.create(e -> SongLoader.Companion.getSongs(SongLoader.Companion.makeSongCursor(
|
||||
context,
|
||||
AudioColumns.ARTIST + " LIKE ?",
|
||||
new String[]{"%" + query + "%"},
|
||||
getSongLoaderSortOrder(context))
|
||||
).subscribe(songs -> {
|
||||
e.onNext(splitIntoArtists(AlbumLoader.splitIntoAlbums(songs)));
|
||||
e.onComplete();
|
||||
}));
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public static ArrayList<Artist> splitIntoArtists(@Nullable final ArrayList<Album> albums) {
|
||||
ArrayList<Artist> artists = new ArrayList<>();
|
||||
if (albums != null) {
|
||||
for (Album album : albums) {
|
||||
getOrCreateArtist(artists, album.getArtistId()).albums.add(album);
|
||||
}
|
||||
}
|
||||
return artists;
|
||||
}
|
||||
|
||||
private static Artist getOrCreateArtist(ArrayList<Artist> artists, int artistId) {
|
||||
for (Artist artist : artists) {
|
||||
if (!artist.albums.isEmpty() && !artist.albums.get(0).songs.isEmpty() && artist.albums.get(0).songs.get(0).artistId == artistId) {
|
||||
return artist;
|
||||
}
|
||||
}
|
||||
Artist album = new Artist();
|
||||
artists.add(album);
|
||||
return album;
|
||||
}
|
||||
|
||||
public static Observable<ArrayList<Artist>> splitIntoArtists(Observable<ArrayList<Album>> albums) {
|
||||
return Observable.create(e -> {
|
||||
ArrayList<Artist> artists = new ArrayList<>();
|
||||
albums.subscribe(localAlbums -> {
|
||||
if (localAlbums != null) {
|
||||
for (Album album : localAlbums) {
|
||||
getOrCreateArtist(artists, album.getArtistId()).albums.add(album);
|
||||
}
|
||||
}
|
||||
e.onNext(artists);
|
||||
e.onComplete();
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,99 @@
|
|||
package code.name.monkey.retromusic.loaders
|
||||
|
||||
import android.content.Context
|
||||
import android.provider.MediaStore.Audio.AudioColumns
|
||||
|
||||
import java.util.ArrayList
|
||||
|
||||
import code.name.monkey.retromusic.model.Album
|
||||
import code.name.monkey.retromusic.model.Artist
|
||||
import code.name.monkey.retromusic.util.PreferenceUtil
|
||||
import io.reactivex.Observable
|
||||
|
||||
object ArtistLoader {
|
||||
private fun getSongLoaderSortOrder(): String {
|
||||
return PreferenceUtil.getInstance().artistSortOrder + ", " +
|
||||
PreferenceUtil.getInstance().artistAlbumSortOrder + ", " +
|
||||
PreferenceUtil.getInstance().albumDetailSongSortOrder + ", " +
|
||||
PreferenceUtil.getInstance().artistDetailSongSortOrder
|
||||
}
|
||||
|
||||
fun getArtist(context: Context, artistId: Int): Observable<Artist> {
|
||||
return Observable.create { e ->
|
||||
SongLoader.getSongs(SongLoader.makeSongCursor(
|
||||
context,
|
||||
AudioColumns.ARTIST_ID + "=?",
|
||||
arrayOf(artistId.toString()),
|
||||
getSongLoaderSortOrder()))
|
||||
.subscribe { songs ->
|
||||
val artist = Artist(AlbumLoader.splitIntoAlbums(songs))
|
||||
e.onNext(artist)
|
||||
e.onComplete()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun getAllArtists(context: Context): Observable<ArrayList<Artist>> {
|
||||
return Observable.create { e ->
|
||||
SongLoader
|
||||
.getSongs(SongLoader.makeSongCursor(
|
||||
context, null, null,
|
||||
getSongLoaderSortOrder())
|
||||
).subscribe { songs ->
|
||||
e.onNext(splitIntoArtists(AlbumLoader.splitIntoAlbums(songs)))
|
||||
e.onComplete()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fun getArtists(context: Context, query: String): Observable<ArrayList<Artist>> {
|
||||
return Observable.create { e ->
|
||||
SongLoader.getSongs(SongLoader.makeSongCursor(
|
||||
context,
|
||||
AudioColumns.ARTIST + " LIKE ?",
|
||||
arrayOf("%$query%"),
|
||||
getSongLoaderSortOrder())
|
||||
).subscribe { songs ->
|
||||
e.onNext(splitIntoArtists(AlbumLoader.splitIntoAlbums(songs)))
|
||||
e.onComplete()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun splitIntoArtists(albums: ArrayList<Album>?): ArrayList<Artist> {
|
||||
val artists = ArrayList<Artist>()
|
||||
if (albums != null) {
|
||||
for (album in albums) {
|
||||
getOrCreateArtist(artists, album.artistId).albums!!.add(album)
|
||||
}
|
||||
}
|
||||
return artists
|
||||
}
|
||||
|
||||
private fun getOrCreateArtist(artists: ArrayList<Artist>, artistId: Int): Artist {
|
||||
for (artist in artists) {
|
||||
if (!artist.albums!!.isEmpty() && !artist.albums[0].songs!!.isEmpty() && artist.albums[0].songs!![0].artistId == artistId) {
|
||||
return artist
|
||||
}
|
||||
}
|
||||
val album = Artist()
|
||||
artists.add(album)
|
||||
return album
|
||||
}
|
||||
|
||||
fun splitIntoArtists(albums: Observable<ArrayList<Album>>): Observable<ArrayList<Artist>> {
|
||||
return Observable.create { e ->
|
||||
val artists = ArrayList<Artist>()
|
||||
albums.subscribe { localAlbums ->
|
||||
if (localAlbums != null) {
|
||||
for (album in localAlbums) {
|
||||
getOrCreateArtist(artists, album.artistId).albums!!.add(album)
|
||||
}
|
||||
}
|
||||
e.onNext(artists)
|
||||
e.onComplete()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,37 +0,0 @@
|
|||
package code.name.monkey.retromusic.loaders;
|
||||
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.provider.MediaStore;
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import code.name.monkey.retromusic.model.Song;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import code.name.monkey.retromusic.util.PreferenceUtil;
|
||||
import io.reactivex.Observable;
|
||||
|
||||
|
||||
public class ArtistSongLoader extends SongLoader {
|
||||
|
||||
@NonNull
|
||||
public static Observable<ArrayList<Song>> getArtistSongList(@NonNull final Context context, final int artistId) {
|
||||
return Companion.getSongs(makeArtistSongCursor(context, artistId));
|
||||
}
|
||||
|
||||
public static Cursor makeArtistSongCursor(@NonNull final Context context, final int artistId) {
|
||||
try {
|
||||
return Companion.makeSongCursor(
|
||||
context,
|
||||
MediaStore.Audio.AudioColumns.ARTIST_ID + "=?",
|
||||
new String[]{
|
||||
String.valueOf(artistId)
|
||||
},
|
||||
PreferenceUtil.getInstance().getArtistSongSortOrder()
|
||||
);
|
||||
} catch (SecurityException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,133 +0,0 @@
|
|||
package code.name.monkey.retromusic.loaders;
|
||||
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.net.Uri;
|
||||
import android.provider.BaseColumns;
|
||||
import android.provider.MediaStore.Audio.Genres;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import code.name.monkey.retromusic.model.Genre;
|
||||
import code.name.monkey.retromusic.model.Song;
|
||||
import code.name.monkey.retromusic.util.PreferenceUtil;
|
||||
import io.reactivex.Observable;
|
||||
|
||||
public class GenreLoader {
|
||||
|
||||
@NonNull
|
||||
public static Observable<ArrayList<Genre>> getAllGenres(@NonNull final Context context) {
|
||||
return getGenresFromCursor(context, makeGenreCursor(context));
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public static Observable<ArrayList<Song>> getSongs(@NonNull final Context context, final int genreId) {
|
||||
// The genres table only stores songs that have a genre specified,
|
||||
// so we need to get songs without a genre a different way.
|
||||
if (genreId == -1) {
|
||||
return getSongsWithNoGenre(context);
|
||||
}
|
||||
|
||||
return SongLoader.Companion.getSongs(makeGenreSongCursor(context, genreId));
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private static Genre getGenreFromCursor(@NonNull Context context, @NonNull final Cursor cursor) {
|
||||
final int id = cursor.getInt(0);
|
||||
final String name = cursor.getString(1);
|
||||
final int songCount = getSongs(context, id).blockingFirst().size();
|
||||
return new Genre(id, name, songCount);
|
||||
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private static Observable<ArrayList<Song>> getSongsWithNoGenre(@NonNull final Context context) {
|
||||
String selection = BaseColumns._ID + " NOT IN " +
|
||||
"(SELECT " + Genres.Members.AUDIO_ID + " FROM audio_genres_map)";
|
||||
return SongLoader.Companion.getSongs(SongLoader.Companion.makeSongCursor(context, selection, null));
|
||||
}
|
||||
|
||||
private static boolean hasSongsWithNoGenre(@NonNull final Context context) {
|
||||
final Cursor allSongsCursor = SongLoader.Companion.makeSongCursor(context, null, null);
|
||||
final Cursor allSongsWithGenreCursor = makeAllSongsWithGenreCursor(context);
|
||||
|
||||
if (allSongsCursor == null || allSongsWithGenreCursor == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
final boolean hasSongsWithNoGenre = allSongsCursor.getCount() > allSongsWithGenreCursor.getCount();
|
||||
allSongsCursor.close();
|
||||
allSongsWithGenreCursor.close();
|
||||
return hasSongsWithNoGenre;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static Cursor makeAllSongsWithGenreCursor(@NonNull final Context context) {
|
||||
try {
|
||||
return context.getContentResolver().query(
|
||||
Uri.parse("content://media/external/audio/genres/all/members"),
|
||||
new String[]{Genres.Members.AUDIO_ID}, null, null, null);
|
||||
} catch (SecurityException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static Cursor makeGenreSongCursor(@NonNull final Context context, int genreId) {
|
||||
try {
|
||||
return context.getContentResolver().query(
|
||||
Genres.Members.getContentUri("external", genreId),
|
||||
SongLoader.Companion.getBASE_PROJECTION(), SongLoader.BASE_SELECTION, null, PreferenceUtil.getInstance().getSongSortOrder());
|
||||
} catch (SecurityException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private static Observable<ArrayList<Genre>> getGenresFromCursor(@NonNull final Context context, @Nullable final Cursor cursor) {
|
||||
return Observable.create(e -> {
|
||||
final ArrayList<Genre> genres = new ArrayList<>();
|
||||
if (cursor != null) {
|
||||
if (cursor.moveToFirst()) {
|
||||
do {
|
||||
Genre genre = getGenreFromCursor(context, cursor);
|
||||
if (genre.songCount > 0) {
|
||||
genres.add(genre);
|
||||
} else {
|
||||
// try to remove the empty genre from the media store
|
||||
try {
|
||||
context.getContentResolver().delete(Genres.EXTERNAL_CONTENT_URI, Genres._ID + " == " + genre.id, null);
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
// nothing we can do then
|
||||
}
|
||||
}
|
||||
} while (cursor.moveToNext());
|
||||
}
|
||||
cursor.close();
|
||||
}
|
||||
e.onNext(genres);
|
||||
e.onComplete();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@Nullable
|
||||
private static Cursor makeGenreCursor(@NonNull final Context context) {
|
||||
final String[] projection = new String[]{
|
||||
Genres._ID,
|
||||
Genres.NAME
|
||||
};
|
||||
|
||||
try {
|
||||
return context.getContentResolver().query(
|
||||
Genres.EXTERNAL_CONTENT_URI,
|
||||
projection, null, null, PreferenceUtil.getInstance().getGenreSortOrder());
|
||||
} catch (SecurityException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,123 @@
|
|||
package code.name.monkey.retromusic.loaders
|
||||
|
||||
import android.content.Context
|
||||
import android.database.Cursor
|
||||
import android.net.Uri
|
||||
import android.provider.BaseColumns
|
||||
import android.provider.MediaStore.Audio.Genres
|
||||
import code.name.monkey.retromusic.Constants.BASE_PROJECTION
|
||||
import code.name.monkey.retromusic.Constants.BASE_SELECTION
|
||||
import code.name.monkey.retromusic.model.Genre
|
||||
import code.name.monkey.retromusic.model.Song
|
||||
import code.name.monkey.retromusic.util.PreferenceUtil
|
||||
import io.reactivex.Observable
|
||||
import java.util.*
|
||||
|
||||
object GenreLoader {
|
||||
|
||||
fun getAllGenres(context: Context): Observable<ArrayList<Genre>> {
|
||||
return getGenresFromCursor(context, makeGenreCursor(context))
|
||||
}
|
||||
|
||||
fun getSongs(context: Context, genreId: Int): Observable<ArrayList<Song>> {
|
||||
// The genres table only stores songs that have a genre specified,
|
||||
// so we need to get songs without a genre a different way.
|
||||
return if (genreId == -1) {
|
||||
getSongsWithNoGenre(context)
|
||||
} else SongLoader.getSongs(makeGenreSongCursor(context, genreId))
|
||||
|
||||
}
|
||||
|
||||
private fun getGenreFromCursor(context: Context, cursor: Cursor): Genre {
|
||||
val id = cursor.getInt(0)
|
||||
val name = cursor.getString(1)
|
||||
val songCount = getSongs(context, id).blockingFirst().size
|
||||
return Genre(id, name, songCount)
|
||||
|
||||
}
|
||||
|
||||
private fun getSongsWithNoGenre(context: Context): Observable<ArrayList<Song>> {
|
||||
val selection = BaseColumns._ID + " NOT IN " +
|
||||
"(SELECT " + Genres.Members.AUDIO_ID + " FROM audio_genres_map)"
|
||||
return SongLoader.getSongs(SongLoader.makeSongCursor(context, selection, null))
|
||||
}
|
||||
|
||||
private fun hasSongsWithNoGenre(context: Context): Boolean {
|
||||
val allSongsCursor = SongLoader.makeSongCursor(context, null, null)
|
||||
val allSongsWithGenreCursor = makeAllSongsWithGenreCursor(context)
|
||||
|
||||
if (allSongsCursor == null || allSongsWithGenreCursor == null) {
|
||||
return false
|
||||
}
|
||||
|
||||
val hasSongsWithNoGenre = allSongsCursor.count > allSongsWithGenreCursor.count
|
||||
allSongsCursor.close()
|
||||
allSongsWithGenreCursor.close()
|
||||
return hasSongsWithNoGenre
|
||||
}
|
||||
|
||||
private fun makeAllSongsWithGenreCursor(context: Context): Cursor? {
|
||||
try {
|
||||
return context.contentResolver.query(
|
||||
Uri.parse("content://media/external/audio/genres/all/members"),
|
||||
arrayOf(Genres.Members.AUDIO_ID), null, null, null)
|
||||
} catch (e: SecurityException) {
|
||||
return null
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private fun makeGenreSongCursor(context: Context, genreId: Int): Cursor? {
|
||||
try {
|
||||
return context.contentResolver.query(
|
||||
Genres.Members.getContentUri("external", genreId.toLong()),
|
||||
BASE_PROJECTION, BASE_SELECTION, null, PreferenceUtil.getInstance().songSortOrder)
|
||||
} catch (e: SecurityException) {
|
||||
return null
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private fun getGenresFromCursor(context: Context, cursor: Cursor?): Observable<ArrayList<Genre>> {
|
||||
return Observable.create { e ->
|
||||
val genres = ArrayList<Genre>()
|
||||
if (cursor != null) {
|
||||
if (cursor.moveToFirst()) {
|
||||
do {
|
||||
val genre = getGenreFromCursor(context, cursor)
|
||||
if (genre.songCount > 0) {
|
||||
genres.add(genre)
|
||||
} else {
|
||||
// try to remove the empty genre from the media store
|
||||
try {
|
||||
context.contentResolver.delete(Genres.EXTERNAL_CONTENT_URI, Genres._ID + " == " + genre.id, null)
|
||||
} catch (ex: Exception) {
|
||||
ex.printStackTrace()
|
||||
// nothing we can do then
|
||||
}
|
||||
|
||||
}
|
||||
} while (cursor.moveToNext())
|
||||
}
|
||||
cursor.close()
|
||||
}
|
||||
e.onNext(genres)
|
||||
e.onComplete()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private fun makeGenreCursor(context: Context): Cursor? {
|
||||
val projection = arrayOf(Genres._ID, Genres.NAME)
|
||||
|
||||
try {
|
||||
return context.contentResolver.query(
|
||||
Genres.EXTERNAL_CONTENT_URI,
|
||||
projection, null, null, PreferenceUtil.getInstance().genreSortOrder)
|
||||
} catch (e: SecurityException) {
|
||||
return null
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -1,76 +0,0 @@
|
|||
package code.name.monkey.retromusic.loaders;
|
||||
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.provider.MediaStore;
|
||||
import android.provider.MediaStore.Audio.AudioColumns;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import code.name.monkey.retromusic.model.Song;
|
||||
import io.reactivex.Observable;
|
||||
|
||||
/**
|
||||
* @author Hemanth S (h4h13).
|
||||
*/
|
||||
|
||||
public class GenreSongsLoader {
|
||||
|
||||
public static Observable<ArrayList<Song>> getGenreSongsList(@NonNull Context context, int genreId) {
|
||||
return Observable.create(e -> {
|
||||
ArrayList<Song> list = new ArrayList<>();
|
||||
Cursor cursor = makeGenreSongCursor(context, genreId);
|
||||
if (cursor != null && cursor.moveToFirst()) {
|
||||
do {
|
||||
list.add(getGenreSongFromCursorImpl(cursor));
|
||||
} while (cursor.moveToNext());
|
||||
}
|
||||
if (cursor != null) {
|
||||
cursor.close();
|
||||
}
|
||||
e.onNext((ArrayList<Song>) (List) list);
|
||||
e.onComplete();
|
||||
});
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private static Song getGenreSongFromCursorImpl(@NonNull Cursor cursor) {
|
||||
final int id = cursor.getInt(0);
|
||||
final String title = cursor.getString(1);
|
||||
final int trackNumber = cursor.getInt(2);
|
||||
final int year = cursor.getInt(3);
|
||||
final long duration = cursor.getLong(4);
|
||||
final String data = cursor.getString(5);
|
||||
final int dateModified = cursor.getInt(6);
|
||||
final int albumId = cursor.getInt(7);
|
||||
final String albumName = cursor.getString(8);
|
||||
final int artistId = cursor.getInt(9);
|
||||
final String artistName = cursor.getString(10);
|
||||
return new Song(id, title, trackNumber, year, duration, data, dateModified, albumId, albumName, artistId, artistName);
|
||||
}
|
||||
|
||||
private static Cursor makeGenreSongCursor(Context context, long genreId) {
|
||||
try {
|
||||
return context.getContentResolver().query(
|
||||
MediaStore.Audio.Genres.Members.getContentUri("external", genreId),
|
||||
new String[]{
|
||||
MediaStore.Audio.Playlists.Members.AUDIO_ID,// 0
|
||||
AudioColumns.TITLE,// 1
|
||||
AudioColumns.TRACK,// 2
|
||||
AudioColumns.YEAR,// 3
|
||||
AudioColumns.DURATION,// 4
|
||||
AudioColumns.DATA,// 5
|
||||
AudioColumns.DATE_MODIFIED,// 6
|
||||
AudioColumns.ALBUM_ID,// 7
|
||||
AudioColumns.ALBUM,// 8
|
||||
AudioColumns.ARTIST_ID,// 9
|
||||
AudioColumns.ARTIST,// 10
|
||||
}, SongLoader.BASE_SELECTION, null,
|
||||
MediaStore.Audio.Genres.Members.DEFAULT_SORT_ORDER);
|
||||
} catch (SecurityException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,63 +0,0 @@
|
|||
package code.name.monkey.retromusic.loaders;
|
||||
|
||||
|
||||
import android.content.Context;
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import code.name.monkey.retromusic.model.Playlist;
|
||||
import code.name.monkey.retromusic.model.smartplaylist.AbsSmartPlaylist;
|
||||
import code.name.monkey.retromusic.model.smartplaylist.HistoryPlaylist;
|
||||
import code.name.monkey.retromusic.model.smartplaylist.LastAddedPlaylist;
|
||||
import code.name.monkey.retromusic.model.smartplaylist.MyTopTracksPlaylist;
|
||||
import io.reactivex.Observable;
|
||||
|
||||
public class HomeLoader {
|
||||
|
||||
public static Observable<ArrayList<AbsSmartPlaylist>> getRecentAndTopThings(
|
||||
@NonNull Context context) {
|
||||
ArrayList<AbsSmartPlaylist> objects = new ArrayList<>();
|
||||
return Observable.create(e -> {
|
||||
|
||||
new HistoryPlaylist(context).getSongs(context).subscribe(songs -> {
|
||||
if (!songs.isEmpty()) {
|
||||
objects.add(new HistoryPlaylist(context));
|
||||
}
|
||||
});
|
||||
new LastAddedPlaylist(context).getSongs(context).subscribe(songs -> {
|
||||
if (!songs.isEmpty()) {
|
||||
objects.add(new LastAddedPlaylist(context));
|
||||
}
|
||||
});
|
||||
new MyTopTracksPlaylist(context).getSongs(context).subscribe(songs -> {
|
||||
if (!songs.isEmpty()) {
|
||||
objects.add(new MyTopTracksPlaylist(context));
|
||||
}
|
||||
});
|
||||
|
||||
e.onNext(objects);
|
||||
e.onComplete();
|
||||
});
|
||||
}
|
||||
|
||||
public static Observable<ArrayList<Playlist>> getHomeLoader(@NonNull Context context) {
|
||||
ArrayList<Playlist> playlists = new ArrayList<>();
|
||||
PlaylistLoader.getAllPlaylists(context)
|
||||
.subscribe(playlists1 -> {
|
||||
if (playlists1.size() > 0) {
|
||||
for (Playlist playlist : playlists1) {
|
||||
PlaylistSongsLoader.getPlaylistSongList(context, playlist)
|
||||
.subscribe(songs -> {
|
||||
if (songs.size() > 0) {
|
||||
playlists.add(playlist);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
return Observable.just(playlists);
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
package code.name.monkey.retromusic.loaders
|
||||
|
||||
|
||||
import android.content.Context
|
||||
|
||||
import java.util.ArrayList
|
||||
import code.name.monkey.retromusic.model.Playlist
|
||||
import code.name.monkey.retromusic.model.smartplaylist.AbsSmartPlaylist
|
||||
import code.name.monkey.retromusic.model.smartplaylist.HistoryPlaylist
|
||||
import code.name.monkey.retromusic.model.smartplaylist.LastAddedPlaylist
|
||||
import code.name.monkey.retromusic.model.smartplaylist.MyTopTracksPlaylist
|
||||
import io.reactivex.Observable
|
||||
|
||||
object HomeLoader {
|
||||
|
||||
fun getRecentAndTopThings(
|
||||
context: Context): Observable<ArrayList<AbsSmartPlaylist>> {
|
||||
val objects = ArrayList<AbsSmartPlaylist>()
|
||||
return Observable.create { e ->
|
||||
|
||||
HistoryPlaylist(context).getSongs(context).subscribe { songs ->
|
||||
if (!songs.isEmpty()) {
|
||||
objects.add(HistoryPlaylist(context))
|
||||
}
|
||||
}
|
||||
LastAddedPlaylist(context).getSongs(context).subscribe { songs ->
|
||||
if (!songs.isEmpty()) {
|
||||
objects.add(LastAddedPlaylist(context))
|
||||
}
|
||||
}
|
||||
MyTopTracksPlaylist(context).getSongs(context).subscribe { songs ->
|
||||
if (!songs.isEmpty()) {
|
||||
objects.add(MyTopTracksPlaylist(context))
|
||||
}
|
||||
}
|
||||
|
||||
e.onNext(objects)
|
||||
e.onComplete()
|
||||
}
|
||||
}
|
||||
|
||||
fun getHomeLoader(context: Context): Observable<ArrayList<Playlist>> {
|
||||
val playlists = ArrayList<Playlist>()
|
||||
PlaylistLoader.getAllPlaylists(context)
|
||||
.subscribe { playlists1 ->
|
||||
if (playlists1.size > 0) {
|
||||
for (playlist in playlists1) {
|
||||
PlaylistSongsLoader.getPlaylistSongList(context, playlist)
|
||||
.subscribe { songs ->
|
||||
if (songs.size > 0) {
|
||||
playlists.add(playlist)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return Observable.just(playlists)
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -1,46 +0,0 @@
|
|||
package code.name.monkey.retromusic.loaders;
|
||||
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.provider.MediaStore;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import code.name.monkey.retromusic.model.Album;
|
||||
import code.name.monkey.retromusic.model.Artist;
|
||||
import code.name.monkey.retromusic.model.Song;
|
||||
import code.name.monkey.retromusic.util.PreferenceUtil;
|
||||
import io.reactivex.Observable;
|
||||
import io.reactivex.annotations.NonNull;
|
||||
|
||||
/**
|
||||
* Created by hemanths on 16/08/17.
|
||||
*/
|
||||
|
||||
public class LastAddedSongsLoader {
|
||||
|
||||
@NonNull
|
||||
public static Observable<ArrayList<Song>> getLastAddedSongs(@NonNull Context context) {
|
||||
return SongLoader.Companion.getSongs(makeLastAddedCursor(context));
|
||||
}
|
||||
|
||||
public static Cursor makeLastAddedCursor(@NonNull final Context context) {
|
||||
long cutoff = PreferenceUtil.getInstance().getLastAddedCutoff();
|
||||
|
||||
return SongLoader.Companion.makeSongCursor(
|
||||
context,
|
||||
MediaStore.Audio.Media.DATE_ADDED + ">?",
|
||||
new String[]{String.valueOf(cutoff)},
|
||||
MediaStore.Audio.Media.DATE_ADDED + " DESC");
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public static Observable<ArrayList<Album>> getLastAddedAlbums(@NonNull Context context) {
|
||||
return AlbumLoader.splitIntoAlbums(getLastAddedSongs(context));
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public static Observable<ArrayList<Artist>> getLastAddedArtists(@NonNull Context context) {
|
||||
return ArtistLoader.splitIntoArtists(getLastAddedAlbums(context));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
package code.name.monkey.retromusic.loaders
|
||||
|
||||
import android.content.Context
|
||||
import android.database.Cursor
|
||||
import android.provider.MediaStore
|
||||
|
||||
import java.util.ArrayList
|
||||
|
||||
import code.name.monkey.retromusic.model.Album
|
||||
import code.name.monkey.retromusic.model.Artist
|
||||
import code.name.monkey.retromusic.model.Song
|
||||
import code.name.monkey.retromusic.util.PreferenceUtil
|
||||
import io.reactivex.Observable
|
||||
import io.reactivex.annotations.NonNull
|
||||
|
||||
/**
|
||||
* Created by hemanths on 16/08/17.
|
||||
*/
|
||||
|
||||
object LastAddedSongsLoader {
|
||||
|
||||
@NonNull
|
||||
fun getLastAddedSongs(@NonNull context: Context): Observable<ArrayList<Song>> {
|
||||
return SongLoader.getSongs(makeLastAddedCursor(context))
|
||||
}
|
||||
|
||||
fun makeLastAddedCursor(@NonNull context: Context): Cursor? {
|
||||
val cutoff = PreferenceUtil.getInstance().lastAddedCutoff
|
||||
|
||||
return SongLoader.makeSongCursor(
|
||||
context,
|
||||
MediaStore.Audio.Media.DATE_ADDED + ">?",
|
||||
arrayOf(cutoff.toString()),
|
||||
MediaStore.Audio.Media.DATE_ADDED + " DESC")
|
||||
}
|
||||
|
||||
@NonNull
|
||||
fun getLastAddedAlbums(@NonNull context: Context): Observable<ArrayList<Album>> {
|
||||
return AlbumLoader.splitIntoAlbums(getLastAddedSongs(context))
|
||||
}
|
||||
|
||||
@NonNull
|
||||
fun getLastAddedArtists(@NonNull context: Context): Observable<ArrayList<Artist>> {
|
||||
return ArtistLoader.splitIntoArtists(getLastAddedAlbums(context))
|
||||
}
|
||||
}
|
|
@ -1,118 +0,0 @@
|
|||
package code.name.monkey.retromusic.loaders;
|
||||
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.net.Uri;
|
||||
import android.provider.BaseColumns;
|
||||
import android.provider.MediaStore;
|
||||
import android.provider.MediaStore.Audio.PlaylistsColumns;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import code.name.monkey.retromusic.model.Playlist;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import io.reactivex.Observable;
|
||||
|
||||
/**
|
||||
* Created by hemanths on 16/08/17.
|
||||
*/
|
||||
|
||||
public class PlaylistLoader {
|
||||
@Nullable
|
||||
public static Cursor makePlaylistCursor(@NonNull final Context context, final String selection, final String[] values) {
|
||||
try {
|
||||
return context.getContentResolver().query(MediaStore.Audio.Playlists.EXTERNAL_CONTENT_URI,
|
||||
new String[]{
|
||||
/* 0 */
|
||||
BaseColumns._ID,
|
||||
/* 1 */
|
||||
PlaylistsColumns.NAME
|
||||
}, selection, values, MediaStore.Audio.Playlists.DEFAULT_SORT_ORDER);
|
||||
} catch (SecurityException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public static Observable<Playlist> getPlaylist(@Nullable final Cursor cursor) {
|
||||
return Observable.create(e -> {
|
||||
Playlist playlist = new Playlist();
|
||||
|
||||
if (cursor != null && cursor.moveToFirst()) {
|
||||
playlist = getPlaylistFromCursorImpl(cursor);
|
||||
}
|
||||
if (cursor != null)
|
||||
cursor.close();
|
||||
|
||||
e.onNext(playlist);
|
||||
e.onComplete();
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public static Observable<Playlist> getPlaylist(@NonNull final Context context, final String playlistName) {
|
||||
return getPlaylist(makePlaylistCursor(
|
||||
context,
|
||||
PlaylistsColumns.NAME + "=?",
|
||||
new String[]{
|
||||
playlistName
|
||||
}
|
||||
));
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public static Observable<Playlist> getPlaylist(@NonNull final Context context, final int playlistId) {
|
||||
return getPlaylist(makePlaylistCursor(
|
||||
context,
|
||||
BaseColumns._ID + "=?",
|
||||
new String[]{
|
||||
String.valueOf(playlistId)
|
||||
}
|
||||
));
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private static Playlist getPlaylistFromCursorImpl(@NonNull final Cursor cursor) {
|
||||
|
||||
final int id = cursor.getInt(0);
|
||||
final String name = cursor.getString(1);
|
||||
return new Playlist(id, name);
|
||||
}
|
||||
|
||||
|
||||
@NonNull
|
||||
public static Observable<ArrayList<Playlist>> getAllPlaylists(@Nullable final Cursor cursor) {
|
||||
return Observable.create(e -> {
|
||||
ArrayList<Playlist> playlists = new ArrayList<>();
|
||||
|
||||
if (cursor != null && cursor.moveToFirst()) {
|
||||
do {
|
||||
playlists.add(getPlaylistFromCursorImpl(cursor));
|
||||
} while (cursor.moveToNext());
|
||||
}
|
||||
if (cursor != null)
|
||||
cursor.close();
|
||||
|
||||
e.onNext(playlists);
|
||||
e.onComplete();
|
||||
});
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public static Observable<ArrayList<Playlist>> getAllPlaylists(@NonNull final Context context) {
|
||||
return getAllPlaylists(makePlaylistCursor(context, null, null));
|
||||
}
|
||||
|
||||
public static void deletePlaylists(Context context, long playlistId) {
|
||||
Uri localUri = MediaStore.Audio.Playlists.EXTERNAL_CONTENT_URI;
|
||||
StringBuilder localStringBuilder = new StringBuilder();
|
||||
localStringBuilder.append("_id IN (");
|
||||
localStringBuilder.append((playlistId));
|
||||
localStringBuilder.append(")");
|
||||
context.getContentResolver().delete(localUri, localStringBuilder.toString(), null);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,103 @@
|
|||
package code.name.monkey.retromusic.loaders
|
||||
|
||||
import android.content.Context
|
||||
import android.database.Cursor
|
||||
import android.net.Uri
|
||||
import android.provider.BaseColumns
|
||||
import android.provider.MediaStore
|
||||
import android.provider.MediaStore.Audio.PlaylistsColumns
|
||||
|
||||
import code.name.monkey.retromusic.model.Playlist
|
||||
|
||||
import java.util.ArrayList
|
||||
|
||||
import io.reactivex.Observable
|
||||
|
||||
/**
|
||||
* Created by hemanths on 16/08/17.
|
||||
*/
|
||||
|
||||
object PlaylistLoader {
|
||||
fun makePlaylistCursor(context: Context, selection: String?, values: Array<String>?): Cursor? {
|
||||
try {
|
||||
return context.contentResolver.query(MediaStore.Audio.Playlists.EXTERNAL_CONTENT_URI,
|
||||
arrayOf(
|
||||
/* 0 */
|
||||
BaseColumns._ID,
|
||||
/* 1 */
|
||||
PlaylistsColumns.NAME), selection, values, MediaStore.Audio.Playlists.DEFAULT_SORT_ORDER)
|
||||
} catch (e: SecurityException) {
|
||||
return null
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fun getPlaylist(cursor: Cursor?): Observable<Playlist> {
|
||||
return Observable.create { e ->
|
||||
var playlist = Playlist()
|
||||
|
||||
if (cursor != null && cursor.moveToFirst()) {
|
||||
playlist = getPlaylistFromCursorImpl(cursor)
|
||||
}
|
||||
cursor?.close()
|
||||
|
||||
e.onNext(playlist)
|
||||
e.onComplete()
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
fun getPlaylist(context: Context, playlistName: String): Observable<Playlist> {
|
||||
return getPlaylist(makePlaylistCursor(
|
||||
context,
|
||||
PlaylistsColumns.NAME + "=?",
|
||||
arrayOf(playlistName)
|
||||
))
|
||||
}
|
||||
|
||||
fun getPlaylist(context: Context, playlistId: Int): Observable<Playlist> {
|
||||
return getPlaylist(makePlaylistCursor(
|
||||
context,
|
||||
BaseColumns._ID + "=?",
|
||||
arrayOf(playlistId.toString())
|
||||
))
|
||||
}
|
||||
|
||||
private fun getPlaylistFromCursorImpl(cursor: Cursor): Playlist {
|
||||
|
||||
val id = cursor.getInt(0)
|
||||
val name = cursor.getString(1)
|
||||
return Playlist(id, name)
|
||||
}
|
||||
|
||||
|
||||
fun getAllPlaylists(cursor: Cursor?): Observable<ArrayList<Playlist>> {
|
||||
return Observable.create { e ->
|
||||
val playlists = ArrayList<Playlist>()
|
||||
|
||||
if (cursor != null && cursor.moveToFirst()) {
|
||||
do {
|
||||
playlists.add(getPlaylistFromCursorImpl(cursor))
|
||||
} while (cursor.moveToNext())
|
||||
}
|
||||
cursor?.close()
|
||||
|
||||
e.onNext(playlists)
|
||||
e.onComplete()
|
||||
}
|
||||
}
|
||||
|
||||
fun getAllPlaylists(context: Context): Observable<ArrayList<Playlist>> {
|
||||
return getAllPlaylists(makePlaylistCursor(context, null, null))
|
||||
}
|
||||
|
||||
fun deletePlaylists(context: Context, playlistId: Long) {
|
||||
val localUri = MediaStore.Audio.Playlists.EXTERNAL_CONTENT_URI
|
||||
val localStringBuilder = StringBuilder()
|
||||
localStringBuilder.append("_id IN (")
|
||||
localStringBuilder.append(playlistId)
|
||||
localStringBuilder.append(")")
|
||||
context.contentResolver.delete(localUri, localStringBuilder.toString(), null)
|
||||
}
|
||||
}
|
|
@ -1,94 +0,0 @@
|
|||
package code.name.monkey.retromusic.loaders;
|
||||
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.provider.MediaStore;
|
||||
import android.provider.MediaStore.Audio.AudioColumns;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import code.name.monkey.retromusic.model.AbsCustomPlaylist;
|
||||
import code.name.monkey.retromusic.model.Playlist;
|
||||
import code.name.monkey.retromusic.model.PlaylistSong;
|
||||
import code.name.monkey.retromusic.model.Song;
|
||||
import io.reactivex.Observable;
|
||||
import io.reactivex.annotations.NonNull;
|
||||
|
||||
/**
|
||||
* Created by hemanths on 16/08/17.
|
||||
*/
|
||||
|
||||
public class PlaylistSongsLoader {
|
||||
|
||||
@NonNull
|
||||
public static Observable<ArrayList<Song>> getPlaylistSongList(@NonNull Context context, Playlist playlist) {
|
||||
if (playlist instanceof AbsCustomPlaylist) {
|
||||
return ((AbsCustomPlaylist) playlist).getSongs(context);
|
||||
} else {
|
||||
//noinspection unchecked
|
||||
return getPlaylistSongList(context, playlist.id);
|
||||
}
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public static Observable<ArrayList<Song>> getPlaylistSongList(@NonNull Context context, final int playlistId) {
|
||||
return Observable.create(e -> {
|
||||
ArrayList<PlaylistSong> songs = new ArrayList<>();
|
||||
Cursor cursor = makePlaylistSongCursor(context, playlistId);
|
||||
|
||||
if (cursor != null && cursor.moveToFirst()) {
|
||||
do {
|
||||
songs.add(getPlaylistSongFromCursorImpl(cursor, playlistId));
|
||||
} while (cursor.moveToNext());
|
||||
}
|
||||
if (cursor != null) {
|
||||
cursor.close();
|
||||
}
|
||||
e.onNext((ArrayList<Song>) (List) songs);
|
||||
e.onComplete();
|
||||
});
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private static PlaylistSong getPlaylistSongFromCursorImpl(@NonNull Cursor cursor, int playlistId) {
|
||||
final int id = cursor.getInt(0);
|
||||
final String title = cursor.getString(1);
|
||||
final int trackNumber = cursor.getInt(2);
|
||||
final int year = cursor.getInt(3);
|
||||
final long duration = cursor.getLong(4);
|
||||
final String data = cursor.getString(5);
|
||||
final int dateModified = cursor.getInt(6);
|
||||
final int albumId = cursor.getInt(7);
|
||||
final String albumName = cursor.getString(8);
|
||||
final int artistId = cursor.getInt(9);
|
||||
final String artistName = cursor.getString(10);
|
||||
final int idInPlaylist = cursor.getInt(11);
|
||||
|
||||
return new PlaylistSong(id, title, trackNumber, year, duration, data, dateModified, albumId, albumName, artistId, artistName, playlistId, idInPlaylist);
|
||||
}
|
||||
|
||||
private static Cursor makePlaylistSongCursor(@NonNull final Context context, final int playlistId) {
|
||||
try {
|
||||
return context.getContentResolver().query(
|
||||
MediaStore.Audio.Playlists.Members.getContentUri("external", playlistId),
|
||||
new String[]{
|
||||
MediaStore.Audio.Playlists.Members.AUDIO_ID,// 0
|
||||
AudioColumns.TITLE,// 1
|
||||
AudioColumns.TRACK,// 2
|
||||
AudioColumns.YEAR,// 3
|
||||
AudioColumns.DURATION,// 4
|
||||
AudioColumns.DATA,// 5
|
||||
AudioColumns.DATE_MODIFIED,// 6
|
||||
AudioColumns.ALBUM_ID,// 7
|
||||
AudioColumns.ALBUM,// 8
|
||||
AudioColumns.ARTIST_ID,// 9
|
||||
AudioColumns.ARTIST,// 10
|
||||
MediaStore.Audio.Playlists.Members._ID, // 11
|
||||
}, SongLoader.BASE_SELECTION, null,
|
||||
MediaStore.Audio.Playlists.Members.DEFAULT_SORT_ORDER);
|
||||
} catch (SecurityException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,86 @@
|
|||
package code.name.monkey.retromusic.loaders
|
||||
|
||||
import android.content.Context
|
||||
import android.database.Cursor
|
||||
import android.provider.MediaStore
|
||||
import android.provider.MediaStore.Audio.AudioColumns
|
||||
import code.name.monkey.retromusic.Constants.BASE_SELECTION
|
||||
import code.name.monkey.retromusic.model.AbsCustomPlaylist
|
||||
import code.name.monkey.retromusic.model.Playlist
|
||||
import code.name.monkey.retromusic.model.PlaylistSong
|
||||
import code.name.monkey.retromusic.model.Song
|
||||
import io.reactivex.Observable
|
||||
import io.reactivex.annotations.NonNull
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
* Created by hemanths on 16/08/17.
|
||||
*/
|
||||
|
||||
object PlaylistSongsLoader {
|
||||
|
||||
@NonNull
|
||||
fun getPlaylistSongList(@NonNull context: Context, playlist: Playlist): Observable<ArrayList<Song>> {
|
||||
return (playlist as? AbsCustomPlaylist)?.getSongs(context)
|
||||
?: getPlaylistSongList(context, playlist.id)
|
||||
}
|
||||
|
||||
@NonNull
|
||||
fun getPlaylistSongList(@NonNull context: Context, playlistId: Int): Observable<ArrayList<Song>> {
|
||||
return Observable.create { e ->
|
||||
val songs = ArrayList<Song>()
|
||||
val cursor = makePlaylistSongCursor(context, playlistId)
|
||||
|
||||
if (cursor != null && cursor.moveToFirst()) {
|
||||
do {
|
||||
songs.add(getPlaylistSongFromCursorImpl(cursor, playlistId))
|
||||
} while (cursor.moveToNext())
|
||||
}
|
||||
cursor?.close()
|
||||
e.onNext(songs)
|
||||
e.onComplete()
|
||||
}
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private fun getPlaylistSongFromCursorImpl(@NonNull cursor: Cursor, playlistId: Int): PlaylistSong {
|
||||
val id = cursor.getInt(0)
|
||||
val title = cursor.getString(1)
|
||||
val trackNumber = cursor.getInt(2)
|
||||
val year = cursor.getInt(3)
|
||||
val duration = cursor.getLong(4)
|
||||
val data = cursor.getString(5)
|
||||
val dateModified = cursor.getInt(6)
|
||||
val albumId = cursor.getInt(7)
|
||||
val albumName = cursor.getString(8)
|
||||
val artistId = cursor.getInt(9)
|
||||
val artistName = cursor.getString(10)
|
||||
val idInPlaylist = cursor.getInt(11)
|
||||
|
||||
return PlaylistSong(id, title, trackNumber, year, duration, data, dateModified, albumId, albumName, artistId, artistName, playlistId, idInPlaylist)
|
||||
}
|
||||
|
||||
private fun makePlaylistSongCursor(@NonNull context: Context, playlistId: Int): Cursor? {
|
||||
try {
|
||||
return context.contentResolver.query(
|
||||
MediaStore.Audio.Playlists.Members.getContentUri("external", playlistId.toLong()),
|
||||
arrayOf(MediaStore.Audio.Playlists.Members.AUDIO_ID, // 0
|
||||
AudioColumns.TITLE, // 1
|
||||
AudioColumns.TRACK, // 2
|
||||
AudioColumns.YEAR, // 3
|
||||
AudioColumns.DURATION, // 4
|
||||
AudioColumns.DATA, // 5
|
||||
AudioColumns.DATE_MODIFIED, // 6
|
||||
AudioColumns.ALBUM_ID, // 7
|
||||
AudioColumns.ALBUM, // 8
|
||||
AudioColumns.ARTIST_ID, // 9
|
||||
AudioColumns.ARTIST, // 10
|
||||
MediaStore.Audio.Playlists.Members._ID)// 11
|
||||
, BASE_SELECTION, null,
|
||||
MediaStore.Audio.Playlists.Members.DEFAULT_SORT_ORDER)
|
||||
} catch (e: SecurityException) {
|
||||
return null
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -1,44 +0,0 @@
|
|||
package code.name.monkey.retromusic.loaders;
|
||||
|
||||
import android.content.Context;
|
||||
import androidx.annotation.NonNull;
|
||||
import android.text.TextUtils;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import code.name.monkey.retromusic.R;
|
||||
import io.reactivex.Observable;
|
||||
|
||||
public class SearchLoader {
|
||||
|
||||
public static Observable<ArrayList<Object>> searchAll(@NonNull Context context, @NonNull String query) {
|
||||
ArrayList<Object> results = new ArrayList<>();
|
||||
return Observable.create(e -> {
|
||||
if (!TextUtils.isEmpty(query)) {
|
||||
SongLoader.Companion.getSongs(context, query)
|
||||
.subscribe(songs -> {
|
||||
if (!songs.isEmpty()) {
|
||||
results.add(context.getResources().getString(R.string.songs));
|
||||
results.addAll(songs);
|
||||
}
|
||||
});
|
||||
|
||||
ArtistLoader.getArtists(context, query)
|
||||
.subscribe(artists -> {
|
||||
if (!artists.isEmpty()) {
|
||||
results.add(context.getResources().getString(R.string.artists));
|
||||
results.addAll(artists);
|
||||
}
|
||||
});
|
||||
AlbumLoader.getAlbums(context, query)
|
||||
.subscribe(albums -> {
|
||||
if (!albums.isEmpty()) {
|
||||
results.add(context.getResources().getString(R.string.albums));
|
||||
results.addAll(albums);
|
||||
}
|
||||
});
|
||||
}
|
||||
e.onNext(results);
|
||||
e.onComplete();
|
||||
});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
package code.name.monkey.retromusic.loaders
|
||||
|
||||
import android.content.Context
|
||||
import android.text.TextUtils
|
||||
import java.util.ArrayList
|
||||
|
||||
import code.name.monkey.retromusic.R
|
||||
import io.reactivex.Observable
|
||||
|
||||
object SearchLoader {
|
||||
|
||||
fun searchAll(context: Context, query: String): Observable<ArrayList<Any>> {
|
||||
val results = ArrayList<Any>()
|
||||
return Observable.create { e ->
|
||||
if (!TextUtils.isEmpty(query)) {
|
||||
SongLoader.getSongs(context, query)
|
||||
.subscribe { songs ->
|
||||
if (!songs.isEmpty()) {
|
||||
results.add(context.resources.getString(R.string.songs))
|
||||
results.addAll(songs)
|
||||
}
|
||||
}
|
||||
|
||||
ArtistLoader.getArtists(context, query)
|
||||
.subscribe { artists ->
|
||||
if (!artists.isEmpty()) {
|
||||
results.add(context.resources.getString(R.string.artists))
|
||||
results.addAll(artists)
|
||||
}
|
||||
}
|
||||
AlbumLoader.getAlbums(context, query)
|
||||
.subscribe { albums ->
|
||||
if (!albums.isEmpty()) {
|
||||
results.add(context.resources.getString(R.string.albums))
|
||||
results.addAll(albums)
|
||||
}
|
||||
}
|
||||
}
|
||||
e.onNext(results)
|
||||
e.onComplete()
|
||||
}
|
||||
}
|
||||
}
|
|
@ -2,9 +2,10 @@ package code.name.monkey.retromusic.loaders
|
|||
|
||||
import android.content.Context
|
||||
import android.database.Cursor
|
||||
import android.provider.BaseColumns
|
||||
import android.provider.MediaStore
|
||||
import android.provider.MediaStore.Audio.AudioColumns
|
||||
import code.name.monkey.retromusic.Constants.BASE_PROJECTION
|
||||
import code.name.monkey.retromusic.Constants.BASE_SELECTION
|
||||
import code.name.monkey.retromusic.helper.ShuffleHelper
|
||||
import code.name.monkey.retromusic.model.Song
|
||||
import code.name.monkey.retromusic.providers.BlacklistStore
|
||||
|
@ -16,167 +17,152 @@ import java.util.*
|
|||
* Created by hemanths on 10/08/17.
|
||||
*/
|
||||
|
||||
open class SongLoader {
|
||||
companion object {
|
||||
|
||||
const val BASE_SELECTION = AudioColumns.IS_MUSIC + "=1" + " AND " + AudioColumns.TITLE + " != ''"
|
||||
val BASE_PROJECTION = arrayOf(BaseColumns._ID, // 0
|
||||
AudioColumns.TITLE, // 1
|
||||
AudioColumns.TRACK, // 2
|
||||
AudioColumns.YEAR, // 3
|
||||
AudioColumns.DURATION, // 4
|
||||
AudioColumns.DATA, // 5
|
||||
AudioColumns.DATE_MODIFIED, // 6
|
||||
AudioColumns.ALBUM_ID, // 7
|
||||
AudioColumns.ALBUM, // 8
|
||||
AudioColumns.ARTIST_ID, // 9
|
||||
AudioColumns.ARTIST)// 10
|
||||
object SongLoader {
|
||||
|
||||
fun getAllSongs(context: Context): Observable<ArrayList<Song>> {
|
||||
val cursor = makeSongCursor(context, null, null)
|
||||
return getSongs(cursor)
|
||||
}
|
||||
fun getAllSongs(context: Context): Observable<ArrayList<Song>> {
|
||||
val cursor = makeSongCursor(context, null, null)
|
||||
return getSongs(cursor)
|
||||
}
|
||||
|
||||
fun getSongs(context: Context, query: String): Observable<ArrayList<Song>> {
|
||||
val cursor = makeSongCursor(context, AudioColumns.TITLE + " LIKE ?", arrayOf("%$query%"))
|
||||
return getSongs(cursor)
|
||||
}
|
||||
fun getSongs(context: Context, query: String): Observable<ArrayList<Song>> {
|
||||
val cursor = makeSongCursor(context, AudioColumns.TITLE + " LIKE ?", arrayOf("%$query%"))
|
||||
return getSongs(cursor)
|
||||
}
|
||||
|
||||
fun getSongs(cursor: Cursor?): Observable<ArrayList<Song>> {
|
||||
return Observable.create { e ->
|
||||
val songs = ArrayList<Song>()
|
||||
if (cursor != null && cursor.moveToFirst()) {
|
||||
do {
|
||||
songs.add(getSongFromCursorImpl(cursor))
|
||||
} while (cursor.moveToNext())
|
||||
}
|
||||
|
||||
cursor?.close()
|
||||
e.onNext(songs)
|
||||
e.onComplete()
|
||||
}
|
||||
}
|
||||
|
||||
private fun getSongFromCursorImpl(cursor: Cursor): Song {
|
||||
val id = cursor.getInt(0)
|
||||
val title = cursor.getString(1)
|
||||
val trackNumber = cursor.getInt(2)
|
||||
val year = cursor.getInt(3)
|
||||
val duration = cursor.getLong(4)
|
||||
val data = cursor.getString(5)
|
||||
val dateModified = cursor.getLong(6)
|
||||
val albumId = cursor.getInt(7)
|
||||
val albumName = cursor.getString(8)
|
||||
val artistId = cursor.getInt(9)
|
||||
val artistName = cursor.getString(10)
|
||||
|
||||
return Song(id, title, trackNumber, year, duration, data, dateModified, albumId, albumName,
|
||||
artistId, artistName)
|
||||
}
|
||||
|
||||
@JvmOverloads
|
||||
fun makeSongCursor(context: Context, selection: String?, selectionValues: Array<String>?, sortOrder: String = PreferenceUtil.getInstance().songSortOrder): Cursor? {
|
||||
var selectionFinal = selection
|
||||
var selectionValuesFinal = selectionValues
|
||||
selectionFinal = if (selection != null && selection.trim { it <= ' ' } != "") {
|
||||
"$BASE_SELECTION AND $selectionFinal"
|
||||
} else {
|
||||
BASE_SELECTION
|
||||
fun getSongs(cursor: Cursor?): Observable<ArrayList<Song>> {
|
||||
return Observable.create { e ->
|
||||
val songs = ArrayList<Song>()
|
||||
if (cursor != null && cursor.moveToFirst()) {
|
||||
do {
|
||||
songs.add(getSongFromCursorImpl(cursor))
|
||||
} while (cursor.moveToNext())
|
||||
}
|
||||
|
||||
// Blacklist
|
||||
val paths = BlacklistStore.getInstance(context).paths
|
||||
if (!paths.isEmpty()) {
|
||||
selectionFinal = generateBlacklistSelection(selectionFinal, paths.size)
|
||||
selectionValuesFinal = addBlacklistSelectionValues(selectionValuesFinal, paths)
|
||||
}
|
||||
|
||||
try {
|
||||
return context.contentResolver.query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
|
||||
BASE_PROJECTION, selectionFinal, selectionValuesFinal, sortOrder)
|
||||
} catch (e: SecurityException) {
|
||||
return null
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private fun generateBlacklistSelection(selection: String?, pathCount: Int): String {
|
||||
val newSelection = StringBuilder(
|
||||
if (selection != null && selection.trim { it <= ' ' } != "") "$selection AND " else "")
|
||||
newSelection.append(AudioColumns.DATA + " NOT LIKE ?")
|
||||
for (i in 0 until pathCount - 1) {
|
||||
newSelection.append(" AND " + AudioColumns.DATA + " NOT LIKE ?")
|
||||
}
|
||||
return newSelection.toString()
|
||||
}
|
||||
|
||||
private fun addBlacklistSelectionValues(selectionValues: Array<String>?,
|
||||
paths: ArrayList<String>): Array<String>? {
|
||||
var selectionValuesFinal = selectionValues
|
||||
if (selectionValuesFinal == null) {
|
||||
selectionValuesFinal = emptyArray()
|
||||
}
|
||||
val newSelectionValues = Array(selectionValuesFinal.size + paths.size) {
|
||||
"n = $it"
|
||||
}
|
||||
System.arraycopy(selectionValuesFinal, 0, newSelectionValues, 0, selectionValuesFinal.size)
|
||||
for (i in selectionValuesFinal.size until newSelectionValues.size) {
|
||||
newSelectionValues[i] = paths[i - selectionValuesFinal.size] + "%"
|
||||
}
|
||||
return newSelectionValues
|
||||
}
|
||||
|
||||
fun getSong(cursor: Cursor?): Observable<Song> {
|
||||
return Observable.create { e ->
|
||||
val song: Song
|
||||
if (cursor != null && cursor.moveToFirst()) {
|
||||
song = getSongFromCursorImpl(cursor)
|
||||
} else {
|
||||
song = Song.EMPTY_SONG
|
||||
}
|
||||
cursor?.close()
|
||||
e.onNext(song)
|
||||
e.onComplete()
|
||||
}
|
||||
}
|
||||
|
||||
fun getSong(context: Context, queryId: Int): Observable<Song> {
|
||||
val cursor = makeSongCursor(context, AudioColumns._ID + "=?",
|
||||
arrayOf(queryId.toString()))
|
||||
return getSong(cursor)
|
||||
}
|
||||
|
||||
fun suggestSongs(context: Context): Observable<ArrayList<Song>> {
|
||||
return SongLoader.getAllSongs(context)
|
||||
.flatMap {
|
||||
val list = ArrayList<Song>()
|
||||
ShuffleHelper.makeShuffleList(it, -1)
|
||||
if (it.size > 9) {
|
||||
list.addAll(it.subList(0, 9))
|
||||
}
|
||||
return@flatMap Observable.just(list)
|
||||
}
|
||||
/*.flatMap({ songs ->
|
||||
val list = ArrayList<Song>()
|
||||
ShuffleHelper.makeShuffleList(songs, -1)
|
||||
if (songs.size > 9) {
|
||||
list.addAll(songs.subList(0, 9))
|
||||
}
|
||||
Observable.just(list)
|
||||
} as Function<ArrayList<Song>, ObservableSource<ArrayList<Song>>>)*/
|
||||
/*.subscribe(songs -> {
|
||||
ArrayList<Song> list = new ArrayList<>();
|
||||
if (songs.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
ShuffleHelper.makeShuffleList(songs, -1);
|
||||
if (songs.size() > 10) {
|
||||
list.addAll(songs.subList(0, 10));
|
||||
} else {
|
||||
list.addAll(songs);
|
||||
}
|
||||
return;
|
||||
});*/
|
||||
cursor?.close()
|
||||
e.onNext(songs)
|
||||
e.onComplete()
|
||||
}
|
||||
}
|
||||
|
||||
private fun getSongFromCursorImpl(cursor: Cursor): Song {
|
||||
val id = cursor.getInt(0)
|
||||
val title = cursor.getString(1)
|
||||
val trackNumber = cursor.getInt(2)
|
||||
val year = cursor.getInt(3)
|
||||
val duration = cursor.getLong(4)
|
||||
val data = cursor.getString(5)
|
||||
val dateModified = cursor.getLong(6)
|
||||
val albumId = cursor.getInt(7)
|
||||
val albumName = cursor.getString(8)
|
||||
val artistId = cursor.getInt(9)
|
||||
val artistName = cursor.getString(10)
|
||||
|
||||
return Song(id, title, trackNumber, year, duration, data, dateModified, albumId, albumName,
|
||||
artistId, artistName)
|
||||
}
|
||||
|
||||
@JvmOverloads
|
||||
fun makeSongCursor(context: Context, selection: String?, selectionValues: Array<String>?, sortOrder: String = PreferenceUtil.getInstance().songSortOrder): Cursor? {
|
||||
var selectionFinal = selection
|
||||
var selectionValuesFinal = selectionValues
|
||||
selectionFinal = if (selection != null && selection.trim { it <= ' ' } != "") {
|
||||
"$BASE_SELECTION AND $selectionFinal"
|
||||
} else {
|
||||
BASE_SELECTION
|
||||
}
|
||||
|
||||
// Blacklist
|
||||
val paths = BlacklistStore.getInstance(context).paths
|
||||
if (!paths.isEmpty()) {
|
||||
selectionFinal = generateBlacklistSelection(selectionFinal, paths.size)
|
||||
selectionValuesFinal = addBlacklistSelectionValues(selectionValuesFinal, paths)
|
||||
}
|
||||
|
||||
try {
|
||||
return context.contentResolver.query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
|
||||
BASE_PROJECTION, selectionFinal, selectionValuesFinal, sortOrder)
|
||||
} catch (e: SecurityException) {
|
||||
return null
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private fun generateBlacklistSelection(selection: String?, pathCount: Int): String {
|
||||
val newSelection = StringBuilder(
|
||||
if (selection != null && selection.trim { it <= ' ' } != "") "$selection AND " else "")
|
||||
newSelection.append(AudioColumns.DATA + " NOT LIKE ?")
|
||||
for (i in 0 until pathCount - 1) {
|
||||
newSelection.append(" AND " + AudioColumns.DATA + " NOT LIKE ?")
|
||||
}
|
||||
return newSelection.toString()
|
||||
}
|
||||
|
||||
private fun addBlacklistSelectionValues(selectionValues: Array<String>?,
|
||||
paths: ArrayList<String>): Array<String>? {
|
||||
var selectionValuesFinal = selectionValues
|
||||
if (selectionValuesFinal == null) {
|
||||
selectionValuesFinal = emptyArray()
|
||||
}
|
||||
val newSelectionValues = Array(selectionValuesFinal.size + paths.size) {
|
||||
"n = $it"
|
||||
}
|
||||
System.arraycopy(selectionValuesFinal, 0, newSelectionValues, 0, selectionValuesFinal.size)
|
||||
for (i in selectionValuesFinal.size until newSelectionValues.size) {
|
||||
newSelectionValues[i] = paths[i - selectionValuesFinal.size] + "%"
|
||||
}
|
||||
return newSelectionValues
|
||||
}
|
||||
|
||||
fun getSong(cursor: Cursor?): Observable<Song> {
|
||||
return Observable.create { e ->
|
||||
val song: Song = if (cursor != null && cursor.moveToFirst()) {
|
||||
getSongFromCursorImpl(cursor)
|
||||
} else {
|
||||
Song.EMPTY_SONG
|
||||
}
|
||||
cursor?.close()
|
||||
e.onNext(song)
|
||||
e.onComplete()
|
||||
}
|
||||
}
|
||||
|
||||
fun getSong(context: Context, queryId: Int): Observable<Song> {
|
||||
val cursor = makeSongCursor(context, AudioColumns._ID + "=?",
|
||||
arrayOf(queryId.toString()))
|
||||
return getSong(cursor)
|
||||
}
|
||||
|
||||
fun suggestSongs(context: Context): Observable<ArrayList<Song>> {
|
||||
return SongLoader.getAllSongs(context)
|
||||
.flatMap {
|
||||
val list = ArrayList<Song>()
|
||||
ShuffleHelper.makeShuffleList(it, -1)
|
||||
if (it.size > 9) {
|
||||
list.addAll(it.subList(0, 9))
|
||||
}
|
||||
return@flatMap Observable.just(list)
|
||||
}
|
||||
/*.flatMap({ songs ->
|
||||
val list = ArrayList<Song>()
|
||||
ShuffleHelper.makeShuffleList(songs, -1)
|
||||
if (songs.size > 9) {
|
||||
list.addAll(songs.subList(0, 9))
|
||||
}
|
||||
Observable.just(list)
|
||||
} as Function<ArrayList<Song>, ObservableSource<ArrayList<Song>>>)*/
|
||||
/*.subscribe(songs -> {
|
||||
ArrayList<Song> list = new ArrayList<>();
|
||||
if (songs.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
ShuffleHelper.makeShuffleList(songs, -1);
|
||||
if (songs.size() > 10) {
|
||||
list.addAll(songs.subList(0, 10));
|
||||
} else {
|
||||
list.addAll(songs);
|
||||
}
|
||||
return;
|
||||
});*/
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,158 +0,0 @@
|
|||
package code.name.monkey.retromusic.loaders;
|
||||
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.provider.BaseColumns;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import code.name.monkey.retromusic.model.Album;
|
||||
import code.name.monkey.retromusic.model.Artist;
|
||||
import code.name.monkey.retromusic.model.Song;
|
||||
import code.name.monkey.retromusic.providers.HistoryStore;
|
||||
import code.name.monkey.retromusic.providers.SongPlayCountStore;
|
||||
import io.reactivex.Observable;
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* Created by hemanths on 16/08/17.
|
||||
*/
|
||||
|
||||
public class TopAndRecentlyPlayedTracksLoader {
|
||||
|
||||
private static final int NUMBER_OF_TOP_TRACKS = 99;
|
||||
|
||||
@NonNull
|
||||
public static Observable<ArrayList<Song>> getRecentlyPlayedTracks(@NonNull Context context) {
|
||||
return SongLoader.Companion.getSongs(makeRecentTracksCursorAndClearUpDatabase(context));
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public static Observable<ArrayList<Song>> getTopTracks(@NonNull Context context) {
|
||||
return SongLoader.Companion.getSongs(makeTopTracksCursorAndClearUpDatabase(context));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static Cursor makeRecentTracksCursorAndClearUpDatabase(@NonNull final Context context) {
|
||||
SortedLongCursor retCursor = makeRecentTracksCursorImpl(context);
|
||||
|
||||
// clean up the databases with any ids not found
|
||||
if (retCursor != null) {
|
||||
ArrayList<Long> missingIds = retCursor.getMissingIds();
|
||||
if (missingIds != null && missingIds.size() > 0) {
|
||||
for (long id : missingIds) {
|
||||
HistoryStore.getInstance(context).removeSongId(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
return retCursor;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static Cursor makeTopTracksCursorAndClearUpDatabase(@NonNull final Context context) {
|
||||
SortedLongCursor retCursor = makeTopTracksCursorImpl(context);
|
||||
|
||||
// clean up the databases with any ids not found
|
||||
if (retCursor != null) {
|
||||
ArrayList<Long> missingIds = retCursor.getMissingIds();
|
||||
if (missingIds != null && missingIds.size() > 0) {
|
||||
for (long id : missingIds) {
|
||||
SongPlayCountStore.getInstance(context).removeItem(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
return retCursor;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static SortedLongCursor makeRecentTracksCursorImpl(@NonNull final Context context) {
|
||||
// first get the top results ids from the internal database
|
||||
Cursor songs = HistoryStore.getInstance(context).queryRecentIds();
|
||||
|
||||
try {
|
||||
return makeSortedCursor(context, songs,
|
||||
songs.getColumnIndex(HistoryStore.RecentStoreColumns.ID));
|
||||
} finally {
|
||||
if (songs != null) {
|
||||
songs.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static SortedLongCursor makeTopTracksCursorImpl(@NonNull final Context context) {
|
||||
// first get the top results ids from the internal database
|
||||
Cursor songs = SongPlayCountStore.getInstance(context)
|
||||
.getTopPlayedResults(NUMBER_OF_TOP_TRACKS);
|
||||
|
||||
try {
|
||||
return makeSortedCursor(context, songs,
|
||||
songs.getColumnIndex(SongPlayCountStore.SongPlayCountColumns.ID));
|
||||
} finally {
|
||||
if (songs != null) {
|
||||
songs.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static SortedLongCursor makeSortedCursor(@NonNull final Context context,
|
||||
@Nullable final Cursor cursor, final int idColumn) {
|
||||
|
||||
if (cursor != null && cursor.moveToFirst()) {
|
||||
// create the list of ids to select against
|
||||
StringBuilder selection = new StringBuilder();
|
||||
selection.append(BaseColumns._ID);
|
||||
selection.append(" IN (");
|
||||
|
||||
// this tracks the order of the ids
|
||||
long[] order = new long[cursor.getCount()];
|
||||
|
||||
long id = cursor.getLong(idColumn);
|
||||
selection.append(id);
|
||||
order[cursor.getPosition()] = id;
|
||||
|
||||
while (cursor.moveToNext()) {
|
||||
selection.append(",");
|
||||
|
||||
id = cursor.getLong(idColumn);
|
||||
order[cursor.getPosition()] = id;
|
||||
selection.append(String.valueOf(id));
|
||||
}
|
||||
|
||||
selection.append(")");
|
||||
|
||||
// get a list of songs with the data given the selection statement
|
||||
Cursor songCursor = SongLoader.Companion.makeSongCursor(context, selection.toString(), null);
|
||||
if (songCursor != null) {
|
||||
// now return the wrapped TopTracksCursor to handle sorting given order
|
||||
return new SortedLongCursor(songCursor, order, BaseColumns._ID);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public static Observable<ArrayList<Album>> getTopAlbums(@NonNull Context context) {
|
||||
return Observable.create(e -> {
|
||||
getTopTracks(context).subscribe(songs -> {
|
||||
if (songs.size() > 0) {
|
||||
e.onNext(AlbumLoader.splitIntoAlbums(songs));
|
||||
}
|
||||
e.onComplete();
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public static Observable<ArrayList<Artist>> getTopArtists(@NonNull Context context) {
|
||||
return Observable.create(e -> {
|
||||
getTopAlbums(context).subscribe(albums -> {
|
||||
if (albums.size() > 0) {
|
||||
e.onNext(ArtistLoader.splitIntoArtists(albums));
|
||||
}
|
||||
e.onComplete();
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,142 @@
|
|||
package code.name.monkey.retromusic.loaders
|
||||
|
||||
import android.content.Context
|
||||
import android.database.Cursor
|
||||
import android.provider.BaseColumns
|
||||
import code.name.monkey.retromusic.Constants.NUMBER_OF_TOP_TRACKS
|
||||
import code.name.monkey.retromusic.model.Album
|
||||
import code.name.monkey.retromusic.model.Artist
|
||||
import code.name.monkey.retromusic.model.Song
|
||||
import code.name.monkey.retromusic.providers.HistoryStore
|
||||
import code.name.monkey.retromusic.providers.SongPlayCountStore
|
||||
import io.reactivex.Observable
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
* Created by hemanths on 16/08/17.
|
||||
*/
|
||||
|
||||
object TopAndRecentlyPlayedTracksLoader {
|
||||
|
||||
fun getRecentlyPlayedTracks(context: Context): Observable<ArrayList<Song>> {
|
||||
return SongLoader.getSongs(makeRecentTracksCursorAndClearUpDatabase(context))
|
||||
}
|
||||
|
||||
fun getTopTracks(context: Context): Observable<ArrayList<Song>> {
|
||||
return SongLoader.getSongs(makeTopTracksCursorAndClearUpDatabase(context))
|
||||
}
|
||||
|
||||
private fun makeRecentTracksCursorAndClearUpDatabase(context: Context): Cursor? {
|
||||
val retCursor = makeRecentTracksCursorImpl(context)
|
||||
|
||||
// clean up the databases with any ids not found
|
||||
if (retCursor != null) {
|
||||
val missingIds = retCursor.missingIds
|
||||
if (missingIds != null && missingIds.size > 0) {
|
||||
for (id in missingIds) {
|
||||
HistoryStore.getInstance(context).removeSongId(id)
|
||||
}
|
||||
}
|
||||
}
|
||||
return retCursor
|
||||
}
|
||||
|
||||
private fun makeTopTracksCursorAndClearUpDatabase(context: Context): Cursor? {
|
||||
val retCursor = makeTopTracksCursorImpl(context)
|
||||
|
||||
// clean up the databases with any ids not found
|
||||
if (retCursor != null) {
|
||||
val missingIds = retCursor.missingIds
|
||||
if (missingIds != null && missingIds.size > 0) {
|
||||
for (id in missingIds) {
|
||||
SongPlayCountStore.getInstance(context).removeItem(id)
|
||||
}
|
||||
}
|
||||
}
|
||||
return retCursor
|
||||
}
|
||||
|
||||
private fun makeRecentTracksCursorImpl(context: Context): SortedLongCursor? {
|
||||
// first get the top results ids from the internal database
|
||||
val songs = HistoryStore.getInstance(context).queryRecentIds()
|
||||
|
||||
try {
|
||||
return makeSortedCursor(context, songs,
|
||||
songs!!.getColumnIndex(HistoryStore.RecentStoreColumns.ID))
|
||||
} finally {
|
||||
songs?.close()
|
||||
}
|
||||
}
|
||||
|
||||
private fun makeTopTracksCursorImpl(context: Context): SortedLongCursor? {
|
||||
// first get the top results ids from the internal database
|
||||
val songs = SongPlayCountStore.getInstance(context)
|
||||
.getTopPlayedResults(NUMBER_OF_TOP_TRACKS)
|
||||
|
||||
try {
|
||||
return makeSortedCursor(context, songs,
|
||||
songs!!.getColumnIndex(SongPlayCountStore.SongPlayCountColumns.ID))
|
||||
} finally {
|
||||
songs?.close()
|
||||
}
|
||||
}
|
||||
|
||||
private fun makeSortedCursor(context: Context,
|
||||
cursor: Cursor?, idColumn: Int): SortedLongCursor? {
|
||||
|
||||
if (cursor != null && cursor.moveToFirst()) {
|
||||
// create the list of ids to select against
|
||||
val selection = StringBuilder()
|
||||
selection.append(BaseColumns._ID)
|
||||
selection.append(" IN (")
|
||||
|
||||
// this tracks the order of the ids
|
||||
val order = LongArray(cursor.count)
|
||||
|
||||
var id = cursor.getLong(idColumn)
|
||||
selection.append(id)
|
||||
order[cursor.position] = id
|
||||
|
||||
while (cursor.moveToNext()) {
|
||||
selection.append(",")
|
||||
|
||||
id = cursor.getLong(idColumn)
|
||||
order[cursor.position] = id
|
||||
selection.append(id.toString())
|
||||
}
|
||||
|
||||
selection.append(")")
|
||||
|
||||
// get a list of songs with the data given the selection statement
|
||||
val songCursor = SongLoader.makeSongCursor(context, selection.toString(), null)
|
||||
if (songCursor != null) {
|
||||
// now return the wrapped TopTracksCursor to handle sorting given order
|
||||
return SortedLongCursor(songCursor, order, BaseColumns._ID)
|
||||
}
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
fun getTopAlbums(context: Context): Observable<ArrayList<Album>> {
|
||||
return Observable.create { e ->
|
||||
getTopTracks(context).subscribe { songs ->
|
||||
if (songs.size > 0) {
|
||||
e.onNext(AlbumLoader.splitIntoAlbums(songs))
|
||||
}
|
||||
e.onComplete()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun getTopArtists(context: Context): Observable<ArrayList<Artist>> {
|
||||
return Observable.create { e ->
|
||||
getTopAlbums(context).subscribe { albums ->
|
||||
if (albums.size > 0) {
|
||||
e.onNext(ArtistLoader.splitIntoArtists(albums))
|
||||
}
|
||||
e.onComplete()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue