Code refactor
This commit is contained in:
parent
3f27463281
commit
1096cea0b4
26 changed files with 353 additions and 486 deletions
|
@ -16,9 +16,9 @@ android {
|
|||
compileSdkVersion 29
|
||||
defaultConfig {
|
||||
minSdkVersion 21
|
||||
targetSdkVersion 28
|
||||
targetSdkVersion 29
|
||||
|
||||
renderscriptTargetApi 28 //must match target sdk and build tools
|
||||
renderscriptTargetApi 29 //must match target sdk and build tools
|
||||
vectorDrawables.useSupportLibrary = true
|
||||
|
||||
applicationId "code.name.monkey.retromusic"
|
||||
|
@ -70,7 +70,7 @@ android {
|
|||
packagingOptions {
|
||||
exclude 'META-INF/LICENSE'
|
||||
exclude 'META-INF/NOTICE'
|
||||
exclude 'META-INF/rxjava.properties'
|
||||
exclude 'META-INF/java.properties'
|
||||
}
|
||||
lintOptions {
|
||||
disable 'MissingTranslation'
|
||||
|
@ -138,7 +138,6 @@ dependencies {
|
|||
def retrofit_version = "2.6.2"
|
||||
implementation "com.squareup.retrofit2:retrofit:$retrofit_version"
|
||||
implementation "com.squareup.retrofit2:converter-gson:$retrofit_version"
|
||||
implementation "com.squareup.retrofit2:adapter-rxjava2:$retrofit_version"
|
||||
|
||||
implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2'
|
||||
|
||||
|
|
|
@ -9,7 +9,8 @@
|
|||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
|
||||
<uses-permission android:name="android.permission.BROADCAST_STICKY" />
|
||||
<uses-permission android:name="android.permission.WRITE_SETTINGS"
|
||||
<uses-permission
|
||||
android:name="android.permission.WRITE_SETTINGS"
|
||||
tools:ignore="ProtectedPermissions" />
|
||||
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
|
||||
<uses-permission android:name="com.android.vending.BILLING" />
|
||||
|
@ -17,11 +18,11 @@
|
|||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
||||
|
||||
<application
|
||||
android:requestLegacyExternalStorage="true"
|
||||
android:name=".App"
|
||||
android:allowBackup="true"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:requestLegacyExternalStorage="true"
|
||||
android:roundIcon="@mipmap/ic_launcher_round"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/Theme.RetroMusic.FollowSystem"
|
||||
|
@ -30,8 +31,8 @@
|
|||
tools:targetApi="m">
|
||||
<activity
|
||||
android:name=".activities.MainActivity"
|
||||
android:theme="@style/SplashTheme"
|
||||
android:label="@string/app_name" >
|
||||
android:label="@string/app_name"
|
||||
android:theme="@style/SplashTheme">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<action android:name="android.intent.action.MUSIC_PLAYER" />
|
||||
|
|
|
@ -25,7 +25,6 @@ import code.name.monkey.retromusic.loaders.PlaylistSongsLoader
|
|||
import code.name.monkey.retromusic.service.MusicService
|
||||
import code.name.monkey.retromusic.util.AppRater
|
||||
import code.name.monkey.retromusic.util.PreferenceUtil
|
||||
import io.reactivex.disposables.CompositeDisposable
|
||||
import java.util.ArrayList
|
||||
|
||||
class MainActivity : AbsSlidingMusicPanelActivity(), SharedPreferences.OnSharedPreferenceChangeListener {
|
||||
|
@ -33,7 +32,7 @@ class MainActivity : AbsSlidingMusicPanelActivity(), SharedPreferences.OnSharedP
|
|||
private lateinit var currentFragment: MainActivityFragmentCallbacks
|
||||
|
||||
private var blockRequestPermissions: Boolean = false
|
||||
private val disposable = CompositeDisposable()
|
||||
|
||||
private val broadcastReceiver = object : BroadcastReceiver() {
|
||||
override fun onReceive(context: Context, intent: Intent) {
|
||||
val action = intent.action
|
||||
|
@ -107,7 +106,6 @@ class MainActivity : AbsSlidingMusicPanelActivity(), SharedPreferences.OnSharedP
|
|||
|
||||
override fun onDestroy() {
|
||||
super.onDestroy()
|
||||
disposable.clear()
|
||||
unregisterReceiver(broadcastReceiver)
|
||||
PreferenceUtil.getInstance(this).unregisterOnSharedPreferenceChangedListener(this)
|
||||
}
|
||||
|
|
|
@ -28,7 +28,6 @@ import com.bumptech.glide.Glide
|
|||
import com.bumptech.glide.load.engine.DiskCacheStrategy
|
||||
import com.bumptech.glide.request.animation.GlideAnimation
|
||||
import com.bumptech.glide.request.target.SimpleTarget
|
||||
import io.reactivex.disposables.CompositeDisposable
|
||||
import kotlinx.android.synthetic.main.activity_album_tag_editor.albumArtistContainer
|
||||
import kotlinx.android.synthetic.main.activity_album_tag_editor.albumArtistText
|
||||
import kotlinx.android.synthetic.main.activity_album_tag_editor.albumText
|
||||
|
@ -92,7 +91,6 @@ class AlbumTagEditorActivity : AbsTagEditorActivity(), TextWatcher {
|
|||
private var albumArtBitmap: Bitmap? = null
|
||||
private var deleteAlbumArt: Boolean = false
|
||||
private var lastFMRestClient: LastFMRestClient? = null
|
||||
private val disposable = CompositeDisposable()
|
||||
|
||||
private fun setupToolbar() {
|
||||
applyToolbar(toolbar)
|
||||
|
@ -145,7 +143,6 @@ class AlbumTagEditorActivity : AbsTagEditorActivity(), TextWatcher {
|
|||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
disposable.clear()
|
||||
}
|
||||
|
||||
private fun toastLoadingFailed() {
|
||||
|
@ -178,7 +175,8 @@ class AlbumTagEditorActivity : AbsTagEditorActivity(), TextWatcher {
|
|||
fieldKeyValueMap[FieldKey.GENRE] = genreTitle.text.toString()
|
||||
fieldKeyValueMap[FieldKey.YEAR] = yearTitle.text.toString()
|
||||
|
||||
writeValuesToFiles(fieldKeyValueMap,
|
||||
writeValuesToFiles(
|
||||
fieldKeyValueMap,
|
||||
if (deleteAlbumArt) ArtworkInfo(id, null)
|
||||
else if (albumArtBitmap == null) null else ArtworkInfo(id, albumArtBitmap!!)
|
||||
)
|
||||
|
|
|
@ -25,7 +25,6 @@ import code.name.monkey.retromusic.model.lyrics.AbsSynchronizedLyrics
|
|||
import code.name.monkey.retromusic.model.lyrics.Lyrics
|
||||
import code.name.monkey.retromusic.util.NavigationUtil
|
||||
import com.bumptech.glide.Glide
|
||||
import io.reactivex.disposables.CompositeDisposable
|
||||
import kotlinx.android.synthetic.main.fragment_full.artistImage
|
||||
import kotlinx.android.synthetic.main.fragment_full.nextSong
|
||||
import kotlinx.android.synthetic.main.fragment_full.nextSongLabel
|
||||
|
@ -226,11 +225,8 @@ class FullPlayerFragment : AbsPlayerFragment(), MusicProgressViewUpdateHelper.Ca
|
|||
override fun onDestroyView() {
|
||||
super.onDestroyView()
|
||||
progressViewUpdateHelper.stop()
|
||||
compositeDisposable.dispose()
|
||||
}
|
||||
|
||||
private val compositeDisposable = CompositeDisposable()
|
||||
|
||||
private fun updateArtistImage() {
|
||||
CoroutineScope(Dispatchers.IO).launch {
|
||||
val artist = ArtistLoader.getArtist(requireContext(), MusicPlayerRemote.currentSong.artistId)
|
||||
|
|
|
@ -23,9 +23,7 @@ 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 java.util.*
|
||||
|
||||
import java.util.ArrayList
|
||||
|
||||
/**
|
||||
* Created by hemanths on 16/08/17.
|
||||
|
@ -33,37 +31,12 @@ import java.util.*
|
|||
|
||||
object PlaylistSongsLoader {
|
||||
|
||||
fun getPlaylistSongListFlowable(
|
||||
context: Context,
|
||||
playlist: Playlist
|
||||
): Observable<ArrayList<Song>> {
|
||||
return (playlist as? AbsCustomPlaylist)?.getSongsFlowable(context)
|
||||
?: getPlaylistSongListFlowable(context, playlist.id)
|
||||
}
|
||||
|
||||
fun getPlaylistSongList(
|
||||
context: Context,
|
||||
playlist: Playlist
|
||||
context: Context,
|
||||
playlist: Playlist
|
||||
): ArrayList<Song> {
|
||||
return (playlist as? AbsCustomPlaylist)?.getSongs(context)
|
||||
?: getPlaylistSongList(context, playlist.id)
|
||||
}
|
||||
|
||||
|
||||
fun getPlaylistSongListFlowable(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()
|
||||
}
|
||||
?: getPlaylistSongList(context, playlist.id)
|
||||
}
|
||||
|
||||
fun getPlaylistSongList(context: Context, playlistId: Int): ArrayList<Song> {
|
||||
|
@ -79,7 +52,6 @@ object PlaylistSongsLoader {
|
|||
return songs
|
||||
}
|
||||
|
||||
|
||||
private fun getPlaylistSongFromCursorImpl(cursor: Cursor, playlistId: Int): PlaylistSong {
|
||||
val id = cursor.getInt(0)
|
||||
val title = cursor.getString(1)
|
||||
|
@ -95,28 +67,46 @@ object PlaylistSongsLoader {
|
|||
val idInPlaylist = cursor.getInt(11)
|
||||
val composer = cursor.getString(12)
|
||||
|
||||
return PlaylistSong(id, title, trackNumber, year, duration, data, dateModified, albumId, albumName, artistId, artistName, playlistId, idInPlaylist, composer)
|
||||
return PlaylistSong(
|
||||
id,
|
||||
title,
|
||||
trackNumber,
|
||||
year,
|
||||
duration,
|
||||
data,
|
||||
dateModified,
|
||||
albumId,
|
||||
albumName,
|
||||
artistId,
|
||||
artistName,
|
||||
playlistId,
|
||||
idInPlaylist,
|
||||
composer
|
||||
)
|
||||
}
|
||||
|
||||
private fun makePlaylistSongCursor(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
|
||||
AudioColumns.COMPOSER)// 12
|
||||
, BASE_SELECTION, null,
|
||||
MediaStore.Audio.Playlists.Members.DEFAULT_SORT_ORDER)
|
||||
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
|
||||
AudioColumns.COMPOSER
|
||||
)// 12
|
||||
, BASE_SELECTION, null,
|
||||
MediaStore.Audio.Playlists.Members.DEFAULT_SORT_ORDER
|
||||
)
|
||||
} catch (e: SecurityException) {
|
||||
return null
|
||||
}
|
||||
|
|
|
@ -20,52 +20,27 @@ import android.provider.MediaStore
|
|||
import android.provider.MediaStore.Audio.AudioColumns
|
||||
import code.name.monkey.retromusic.Constants.BASE_SELECTION
|
||||
import code.name.monkey.retromusic.Constants.baseProjection
|
||||
import code.name.monkey.retromusic.helper.ShuffleHelper
|
||||
import code.name.monkey.retromusic.model.Song
|
||||
import code.name.monkey.retromusic.providers.BlacklistStore
|
||||
import code.name.monkey.retromusic.util.PreferenceUtil
|
||||
import io.reactivex.Observable
|
||||
import java.util.*
|
||||
|
||||
import java.util.ArrayList
|
||||
|
||||
/**
|
||||
* Created by hemanths on 10/08/17.
|
||||
*/
|
||||
|
||||
object SongLoader {
|
||||
fun getAllSongsFlowable(
|
||||
context: Context
|
||||
): Observable<ArrayList<Song>> {
|
||||
val cursor = makeSongCursor(context, null, null)
|
||||
return getSongsFlowable(cursor)
|
||||
}
|
||||
|
||||
|
||||
fun getAllSongs(
|
||||
context: Context
|
||||
context: Context
|
||||
): ArrayList<Song> {
|
||||
val cursor = makeSongCursor(context, null, null)
|
||||
return getSongs(cursor)
|
||||
}
|
||||
|
||||
fun getSongsFlowable(
|
||||
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()
|
||||
}
|
||||
}
|
||||
|
||||
fun getSongs(
|
||||
cursor: Cursor?
|
||||
cursor: Cursor?
|
||||
): ArrayList<Song> {
|
||||
val songs = arrayListOf<Song>()
|
||||
if (cursor != null && cursor.moveToFirst()) {
|
||||
|
@ -78,40 +53,16 @@ object SongLoader {
|
|||
return songs
|
||||
}
|
||||
|
||||
fun getSongsFlowable(
|
||||
context: Context,
|
||||
query: String
|
||||
): Observable<ArrayList<Song>> {
|
||||
val cursor = makeSongCursor(context, AudioColumns.TITLE + " LIKE ?", arrayOf("%$query%"))
|
||||
return getSongsFlowable(cursor)
|
||||
}
|
||||
|
||||
fun getSongs(
|
||||
context: Context,
|
||||
query: String
|
||||
context: Context,
|
||||
query: String
|
||||
): ArrayList<Song> {
|
||||
val cursor = makeSongCursor(context, AudioColumns.TITLE + " LIKE ?", arrayOf("%$query%"))
|
||||
return getSongs(cursor)
|
||||
}
|
||||
|
||||
|
||||
private fun getSongFlowable(
|
||||
cursor: Cursor?
|
||||
): Observable<Song> {
|
||||
return Observable.create { e ->
|
||||
val song: Song = if (cursor != null && cursor.moveToFirst()) {
|
||||
getSongFromCursorImpl(cursor)
|
||||
} else {
|
||||
Song.emptySong
|
||||
}
|
||||
cursor?.close()
|
||||
e.onNext(song)
|
||||
e.onComplete()
|
||||
}
|
||||
}
|
||||
|
||||
fun getSong(
|
||||
cursor: Cursor?
|
||||
cursor: Cursor?
|
||||
): Song {
|
||||
val song: Song
|
||||
if (cursor != null && cursor.moveToFirst()) {
|
||||
|
@ -123,36 +74,13 @@ object SongLoader {
|
|||
return song
|
||||
}
|
||||
|
||||
fun getSongFlowable(
|
||||
context: Context,
|
||||
queryId: Int
|
||||
): Observable<Song> {
|
||||
val cursor = makeSongCursor(context, AudioColumns._ID + "=?",
|
||||
arrayOf(queryId.toString()))
|
||||
return getSongFlowable(cursor)
|
||||
}
|
||||
|
||||
fun getSong(context: Context, queryId: Int): Song {
|
||||
val cursor = makeSongCursor(context, AudioColumns._ID + "=?", arrayOf(queryId.toString()))
|
||||
return getSong(cursor)
|
||||
}
|
||||
|
||||
fun suggestSongs(
|
||||
context: Context
|
||||
): Observable<ArrayList<Song>> {
|
||||
return SongLoader.getAllSongsFlowable(context)
|
||||
.flatMap {
|
||||
val list = ArrayList<Song>()
|
||||
ShuffleHelper.makeShuffleList(it, -1)
|
||||
if (it.size >= 7) {
|
||||
list.addAll(it.subList(0, 7))
|
||||
}
|
||||
return@flatMap Observable.just(list)
|
||||
}
|
||||
}
|
||||
|
||||
private fun getSongFromCursorImpl(
|
||||
cursor: Cursor
|
||||
cursor: Cursor
|
||||
): Song {
|
||||
val id = cursor.getInt(0)
|
||||
val title = cursor.getString(1)
|
||||
|
@ -167,17 +95,18 @@ object SongLoader {
|
|||
val artistName = cursor.getString(10)
|
||||
val composer = cursor.getString(11)
|
||||
|
||||
return Song(id, title, trackNumber, year, duration, data, dateModified, albumId,
|
||||
albumName ?: "", artistId, artistName, composer ?: "")
|
||||
return Song(
|
||||
id, title, trackNumber, year, duration, data, dateModified, albumId,
|
||||
albumName ?: "", artistId, artistName, composer ?: ""
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@JvmOverloads
|
||||
fun makeSongCursor(
|
||||
context: Context,
|
||||
selection: String?,
|
||||
selectionValues: Array<String>?,
|
||||
sortOrder: String = PreferenceUtil.getInstance(context).songSortOrder
|
||||
context: Context,
|
||||
selection: String?,
|
||||
selectionValues: Array<String>?,
|
||||
sortOrder: String = PreferenceUtil.getInstance(context).songSortOrder
|
||||
): Cursor? {
|
||||
var selectionFinal = selection
|
||||
var selectionValuesFinal = selectionValues
|
||||
|
@ -195,20 +124,26 @@ object SongLoader {
|
|||
}
|
||||
|
||||
try {
|
||||
return context.contentResolver.query(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
|
||||
baseProjection, selectionFinal + " AND " + MediaStore.Audio.Media.DURATION + ">= " + (PreferenceUtil.getInstance(context).filterLength * 1000), selectionValuesFinal, sortOrder)
|
||||
return context.contentResolver.query(
|
||||
MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
|
||||
baseProjection,
|
||||
selectionFinal + " AND " + MediaStore.Audio.Media.DURATION + ">= " + (PreferenceUtil.getInstance(
|
||||
context
|
||||
).filterLength * 1000),
|
||||
selectionValuesFinal,
|
||||
sortOrder
|
||||
)
|
||||
} catch (e: SecurityException) {
|
||||
return null
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private fun generateBlacklistSelection(
|
||||
selection: String?,
|
||||
pathCount: Int
|
||||
selection: String?,
|
||||
pathCount: Int
|
||||
): String {
|
||||
val newSelection = StringBuilder(
|
||||
if (selection != null && selection.trim { it <= ' ' } != "") "$selection AND " else "")
|
||||
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 ?")
|
||||
|
@ -217,8 +152,8 @@ object SongLoader {
|
|||
}
|
||||
|
||||
private fun addBlacklistSelectionValues(
|
||||
selectionValues: Array<String>?,
|
||||
paths: ArrayList<String>
|
||||
selectionValues: Array<String>?,
|
||||
paths: ArrayList<String>
|
||||
): Array<String>? {
|
||||
var selectionValuesFinal = selectionValues
|
||||
if (selectionValuesFinal == null) {
|
||||
|
|
|
@ -23,8 +23,7 @@ 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.*
|
||||
import java.util.ArrayList
|
||||
|
||||
/**
|
||||
* Created by hemanths on 16/08/17.
|
||||
|
@ -32,18 +31,10 @@ import java.util.*
|
|||
|
||||
object TopAndRecentlyPlayedTracksLoader {
|
||||
|
||||
fun getRecentlyPlayedTracksFlowable(context: Context): Observable<ArrayList<Song>> {
|
||||
return SongLoader.getSongsFlowable(makeRecentTracksCursorAndClearUpDatabase(context))
|
||||
}
|
||||
|
||||
fun getRecentlyPlayedTracks(context: Context): ArrayList<Song> {
|
||||
return SongLoader.getSongs(makeRecentTracksCursorAndClearUpDatabase(context))
|
||||
}
|
||||
|
||||
fun getTopTracksFlowable(context: Context): Observable<ArrayList<Song>> {
|
||||
return SongLoader.getSongsFlowable(makeTopTracksCursorAndClearUpDatabase(context))
|
||||
}
|
||||
|
||||
fun getTopTracks(context: Context): ArrayList<Song> {
|
||||
return SongLoader.getSongs(makeTopTracksCursorAndClearUpDatabase(context))
|
||||
}
|
||||
|
@ -83,8 +74,10 @@ object TopAndRecentlyPlayedTracksLoader {
|
|||
val songs = HistoryStore.getInstance(context).queryRecentIds()
|
||||
|
||||
try {
|
||||
return makeSortedCursor(context, songs,
|
||||
songs!!.getColumnIndex(HistoryStore.RecentStoreColumns.ID))
|
||||
return makeSortedCursor(
|
||||
context, songs,
|
||||
songs!!.getColumnIndex(HistoryStore.RecentStoreColumns.ID)
|
||||
)
|
||||
} finally {
|
||||
songs?.close()
|
||||
}
|
||||
|
@ -93,16 +86,20 @@ object TopAndRecentlyPlayedTracksLoader {
|
|||
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)
|
||||
.getTopPlayedResults(NUMBER_OF_TOP_TRACKS)
|
||||
|
||||
songs.use { localSongs ->
|
||||
return makeSortedCursor(context, localSongs,
|
||||
localSongs.getColumnIndex(SongPlayCountStore.SongPlayCountColumns.ID))
|
||||
return makeSortedCursor(
|
||||
context, localSongs,
|
||||
localSongs.getColumnIndex(SongPlayCountStore.SongPlayCountColumns.ID)
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
private fun makeSortedCursor(context: Context,
|
||||
cursor: Cursor?, idColumn: Int): SortedLongCursor? {
|
||||
private fun makeSortedCursor(
|
||||
context: Context,
|
||||
cursor: Cursor?, idColumn: Int
|
||||
): SortedLongCursor? {
|
||||
|
||||
if (cursor != null && cursor.moveToFirst()) {
|
||||
// create the list of ids to select against
|
||||
|
@ -138,37 +135,13 @@ object TopAndRecentlyPlayedTracksLoader {
|
|||
return null
|
||||
}
|
||||
|
||||
fun getTopAlbumsFlowable(
|
||||
context: Context
|
||||
): Observable<ArrayList<Album>> {
|
||||
return Observable.create { e ->
|
||||
getTopTracksFlowable(context).subscribe { songs ->
|
||||
if (songs.size > 0) {
|
||||
e.onNext(AlbumLoader.splitIntoAlbums(songs))
|
||||
}
|
||||
e.onComplete()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun getTopAlbums(
|
||||
context: Context
|
||||
context: Context
|
||||
): ArrayList<Album> {
|
||||
arrayListOf<Album>()
|
||||
return AlbumLoader.splitIntoAlbums(getTopTracks(context))
|
||||
}
|
||||
|
||||
fun getTopArtistsFlowable(context: Context): Observable<ArrayList<Artist>> {
|
||||
return Observable.create { e ->
|
||||
getTopAlbumsFlowable(context).subscribe { albums ->
|
||||
if (albums.size > 0) {
|
||||
e.onNext(ArtistLoader.splitIntoArtists(albums))
|
||||
}
|
||||
e.onComplete()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun getTopArtists(context: Context): ArrayList<Artist> {
|
||||
return ArtistLoader.splitIntoArtists(getTopAlbums(context))
|
||||
}
|
||||
|
|
|
@ -16,18 +16,16 @@ package code.name.monkey.retromusic.model;
|
|||
|
||||
import android.content.Context;
|
||||
import android.os.Parcel;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* @author Karim Abou Zeid (kabouzeid)
|
||||
*/
|
||||
|
||||
public abstract class AbsCustomPlaylist extends Playlist {
|
||||
|
||||
public AbsCustomPlaylist(int id, String name) {
|
||||
super(id, name);
|
||||
}
|
||||
|
|
|
@ -14,8 +14,7 @@
|
|||
|
||||
package code.name.monkey.retromusic.model
|
||||
|
||||
import java.util.*
|
||||
|
||||
import java.util.ArrayList
|
||||
|
||||
class Album {
|
||||
val songs: ArrayList<Song>?
|
||||
|
|
|
@ -15,8 +15,7 @@
|
|||
package code.name.monkey.retromusic.model
|
||||
|
||||
import code.name.monkey.retromusic.util.MusicUtil
|
||||
import java.util.*
|
||||
|
||||
import java.util.ArrayList
|
||||
|
||||
class Artist {
|
||||
val albums: ArrayList<Album>?
|
||||
|
|
|
@ -16,4 +16,8 @@ package code.name.monkey.retromusic.model
|
|||
|
||||
import com.google.gson.annotations.SerializedName
|
||||
|
||||
class Contributor(val name: String, val summary: String, val link: String, @SerializedName("profile_image") val profileImage: String)
|
||||
class Contributor(
|
||||
val name: String,
|
||||
val summary: String,
|
||||
val link: String, @SerializedName("profile_image") val profileImage: String
|
||||
)
|
||||
|
|
|
@ -18,10 +18,12 @@ import androidx.annotation.DrawableRes
|
|||
import androidx.annotation.StringRes
|
||||
import code.name.monkey.retromusic.adapter.HomeAdapter.Companion.HomeSection
|
||||
|
||||
class Home(val priority: Int,
|
||||
@StringRes val title: Int,
|
||||
val arrayList: ArrayList<*>,
|
||||
@HomeSection
|
||||
val homeSection: Int,
|
||||
@DrawableRes
|
||||
val icon: Int)
|
||||
class Home(
|
||||
val priority: Int,
|
||||
@StringRes val title: Int,
|
||||
val arrayList: ArrayList<*>,
|
||||
@HomeSection
|
||||
val homeSection: Int,
|
||||
@DrawableRes
|
||||
val icon: Int
|
||||
)
|
|
@ -17,16 +17,13 @@ package code.name.monkey.retromusic.model;
|
|||
import android.content.Context;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import code.name.monkey.retromusic.loaders.PlaylistSongsLoader;
|
||||
import io.reactivex.Observable;
|
||||
import java.util.ArrayList;
|
||||
|
||||
|
||||
public class Playlist implements Parcelable {
|
||||
|
||||
public static final Creator<Playlist> CREATOR = new Creator<Playlist>() {
|
||||
public Playlist createFromParcel(Parcel source) {
|
||||
return new Playlist(source);
|
||||
|
@ -36,7 +33,9 @@ public class Playlist implements Parcelable {
|
|||
return new Playlist[size];
|
||||
}
|
||||
};
|
||||
|
||||
public final int id;
|
||||
|
||||
public final String name;
|
||||
|
||||
public Playlist(final int id, final String name) {
|
||||
|
@ -54,30 +53,35 @@ public class Playlist implements Parcelable {
|
|||
this.name = in.readString();
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public Observable<ArrayList<Song>> getSongsFlowable(@NonNull Context context) {
|
||||
// this default implementation covers static playlists
|
||||
return PlaylistSongsLoader.INSTANCE.getPlaylistSongListFlowable(context, id);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public ArrayList<Song> getSongs(@NonNull Context context) {
|
||||
// this default implementation covers static playlists
|
||||
return PlaylistSongsLoader.INSTANCE.getPlaylistSongList(context, id);
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) return true;
|
||||
if (o == null || getClass() != o.getClass()) return false;
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
Playlist playlist = (Playlist) o;
|
||||
|
||||
if (id != playlist.id) return false;
|
||||
if (id != playlist.id) {
|
||||
return false;
|
||||
}
|
||||
return name != null ? name.equals(playlist.name) : playlist.name == null;
|
||||
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public ArrayList<Song> getSongs(@NonNull Context context) {
|
||||
// this default implementation covers static playlists
|
||||
return PlaylistSongsLoader.INSTANCE.getPlaylistSongList(context, id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = id;
|
||||
|
@ -93,11 +97,6 @@ public class Playlist implements Parcelable {
|
|||
'}';
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
dest.writeInt(this.id);
|
||||
|
|
|
@ -14,42 +14,44 @@
|
|||
|
||||
package code.name.monkey.retromusic.model;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import kotlinx.android.parcel.Parcelize;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* Created by hemanths on 3/4/19
|
||||
*/
|
||||
@Parcelize
|
||||
public class PlaylistSong extends Song {
|
||||
final int playlistId;
|
||||
|
||||
final int idInPlayList;
|
||||
|
||||
final int playlistId;
|
||||
|
||||
public PlaylistSong(int id,
|
||||
@NotNull String title,
|
||||
int trackNumber,
|
||||
int year,
|
||||
long duration,
|
||||
@NotNull String data,
|
||||
long dateModified,
|
||||
int albumId,
|
||||
@NotNull String albumName,
|
||||
int artistId,
|
||||
@NotNull String artistName,
|
||||
int playlistId,
|
||||
int idInPlayList,
|
||||
@NotNull String composer) {
|
||||
super(id, title, trackNumber, year, duration, data, dateModified, albumId, albumName, artistId, artistName, composer);
|
||||
@NotNull String title,
|
||||
int trackNumber,
|
||||
int year,
|
||||
long duration,
|
||||
@NotNull String data,
|
||||
long dateModified,
|
||||
int albumId,
|
||||
@NotNull String albumName,
|
||||
int artistId,
|
||||
@NotNull String artistName,
|
||||
int playlistId,
|
||||
int idInPlayList,
|
||||
@NotNull String composer) {
|
||||
super(id, title, trackNumber, year, duration, data, dateModified, albumId, albumName, artistId, artistName,
|
||||
composer);
|
||||
this.playlistId = playlistId;
|
||||
this.idInPlayList = idInPlayList;
|
||||
}
|
||||
|
||||
public int getPlaylistId() {
|
||||
return playlistId;
|
||||
}
|
||||
|
||||
public int getIdInPlayList() {
|
||||
return idInPlayList;
|
||||
}
|
||||
|
||||
public int getPlaylistId() {
|
||||
return playlistId;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,36 +18,36 @@ import kotlinx.android.parcel.Parcelize
|
|||
|
||||
@Parcelize
|
||||
open class Song(
|
||||
val id: Int,
|
||||
val title: String,
|
||||
val trackNumber: Int,
|
||||
val year: Int,
|
||||
val duration: Long,
|
||||
val data: String,
|
||||
val dateModified: Long,
|
||||
val albumId: Int,
|
||||
val albumName: String,
|
||||
val artistId: Int,
|
||||
val artistName: String,
|
||||
val composer: String?
|
||||
val id: Int,
|
||||
val title: String,
|
||||
val trackNumber: Int,
|
||||
val year: Int,
|
||||
val duration: Long,
|
||||
val data: String,
|
||||
val dateModified: Long,
|
||||
val albumId: Int,
|
||||
val albumName: String,
|
||||
val artistId: Int,
|
||||
val artistName: String,
|
||||
val composer: String?
|
||||
) : Parcelable {
|
||||
|
||||
|
||||
companion object {
|
||||
@JvmStatic
|
||||
val emptySong = Song(
|
||||
-1,
|
||||
"",
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
"",
|
||||
-1,
|
||||
-1,
|
||||
"",
|
||||
-1,
|
||||
"",
|
||||
""
|
||||
-1,
|
||||
"",
|
||||
-1,
|
||||
-1,
|
||||
-1,
|
||||
"",
|
||||
-1,
|
||||
-1,
|
||||
"",
|
||||
-1,
|
||||
"",
|
||||
""
|
||||
)
|
||||
}
|
||||
}
|
|
@ -17,9 +17,11 @@ package code.name.monkey.retromusic.model.lyrics;
|
|||
import android.util.SparseArray;
|
||||
|
||||
public abstract class AbsSynchronizedLyrics extends Lyrics {
|
||||
|
||||
private static final int TIME_OFFSET_MS = 500; // time adjustment to display line before it actually starts
|
||||
|
||||
protected final SparseArray<String> lines = new SparseArray<>();
|
||||
|
||||
protected int offset = 0;
|
||||
|
||||
public String getLine(int time) {
|
||||
|
@ -40,15 +42,6 @@ public abstract class AbsSynchronizedLyrics extends Lyrics {
|
|||
return lines.get(lastLineTime);
|
||||
}
|
||||
|
||||
public boolean isSynchronized() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean isValid() {
|
||||
parse(true);
|
||||
return valid;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getText() {
|
||||
parse(false);
|
||||
|
@ -66,4 +59,13 @@ public abstract class AbsSynchronizedLyrics extends Lyrics {
|
|||
|
||||
return super.getText();
|
||||
}
|
||||
|
||||
public boolean isSynchronized() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean isValid() {
|
||||
parse(true);
|
||||
return valid;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,39 +15,28 @@
|
|||
package code.name.monkey.retromusic.model.lyrics;
|
||||
|
||||
|
||||
import code.name.monkey.retromusic.model.Song;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import code.name.monkey.retromusic.model.Song;
|
||||
|
||||
public class Lyrics {
|
||||
|
||||
private static final ArrayList<Class<? extends Lyrics>> FORMATS = new ArrayList<>();
|
||||
|
||||
static {
|
||||
Lyrics.FORMATS.add(SynchronizedLyricsLRC.class);
|
||||
}
|
||||
public String data;
|
||||
|
||||
public Song song;
|
||||
public String data;
|
||||
protected boolean parsed = false;
|
||||
protected boolean valid = false;
|
||||
|
||||
public static Lyrics parse(Song song, String data) {
|
||||
for (Class<? extends Lyrics> format : Lyrics.FORMATS) {
|
||||
try {
|
||||
Lyrics lyrics = format.newInstance().setData(song, data);
|
||||
if (lyrics.isValid()) return lyrics.parse(false);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
return new Lyrics().setData(song, data).parse(false);
|
||||
}
|
||||
protected boolean parsed = false;
|
||||
|
||||
protected boolean valid = false;
|
||||
|
||||
public static boolean isSynchronized(String data) {
|
||||
for (Class<? extends Lyrics> format : Lyrics.FORMATS) {
|
||||
try {
|
||||
Lyrics lyrics = format.newInstance().setData(null, data);
|
||||
if (lyrics.isValid()) return true;
|
||||
if (lyrics.isValid()) {
|
||||
return true;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
@ -55,16 +44,22 @@ public class Lyrics {
|
|||
return false;
|
||||
}
|
||||
|
||||
public Lyrics setData(Song song, String data) {
|
||||
this.song = song;
|
||||
this.data = data;
|
||||
return this;
|
||||
public static Lyrics parse(Song song, String data) {
|
||||
for (Class<? extends Lyrics> format : Lyrics.FORMATS) {
|
||||
try {
|
||||
Lyrics lyrics = format.newInstance().setData(song, data);
|
||||
if (lyrics.isValid()) {
|
||||
return lyrics.parse(false);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
return new Lyrics().setData(song, data).parse(false);
|
||||
}
|
||||
|
||||
public Lyrics parse(boolean check) {
|
||||
this.valid = true;
|
||||
this.parsed = true;
|
||||
return this;
|
||||
public String getText() {
|
||||
return this.data.trim().replaceAll("(\r?\n){3,}", "\r\n\r\n");
|
||||
}
|
||||
|
||||
public boolean isSynchronized() {
|
||||
|
@ -76,7 +71,19 @@ public class Lyrics {
|
|||
return this.valid;
|
||||
}
|
||||
|
||||
public String getText() {
|
||||
return this.data.trim().replaceAll("(\r?\n){3,}", "\r\n\r\n");
|
||||
public Lyrics parse(boolean check) {
|
||||
this.valid = true;
|
||||
this.parsed = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Lyrics setData(Song song, String data) {
|
||||
this.song = song;
|
||||
this.data = data;
|
||||
return this;
|
||||
}
|
||||
|
||||
static {
|
||||
Lyrics.FORMATS.add(SynchronizedLyricsLRC.class);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,11 +18,15 @@ import java.util.regex.Matcher;
|
|||
import java.util.regex.Pattern;
|
||||
|
||||
class SynchronizedLyricsLRC extends AbsSynchronizedLyrics {
|
||||
|
||||
private static final Pattern LRC_LINE_PATTERN = Pattern.compile("((?:\\[.*?\\])+)(.*)");
|
||||
|
||||
private static final Pattern LRC_TIME_PATTERN = Pattern.compile("\\[(\\d+):(\\d{2}(?:\\.\\d+)?)\\]");
|
||||
|
||||
private static final Pattern LRC_ATTRIBUTE_PATTERN = Pattern.compile("\\[(\\D+):(.+)\\]");
|
||||
|
||||
private static final float LRC_SECONDS_TO_MS_MULTIPLIER = 1000f;
|
||||
|
||||
private static final int LRC_MINUTES_TO_MS_MULTIPLIER = 60000;
|
||||
|
||||
@Override
|
||||
|
@ -71,7 +75,9 @@ class SynchronizedLyricsLRC extends AbsSynchronizedLyrics {
|
|||
int ms = (int) (s * LRC_SECONDS_TO_MS_MULTIPLIER) + m * LRC_MINUTES_TO_MS_MULTIPLIER;
|
||||
|
||||
this.valid = true;
|
||||
if (check) return this;
|
||||
if (check) {
|
||||
return this;
|
||||
}
|
||||
|
||||
this.lines.append(ms, text);
|
||||
}
|
||||
|
|
|
@ -16,7 +16,6 @@ package code.name.monkey.retromusic.model.smartplaylist;
|
|||
|
||||
import android.content.Context;
|
||||
import android.os.Parcel;
|
||||
|
||||
import androidx.annotation.DrawableRes;
|
||||
import androidx.annotation.Nullable;
|
||||
import code.name.monkey.retromusic.R;
|
||||
|
@ -24,6 +23,7 @@ import code.name.monkey.retromusic.model.AbsCustomPlaylist;
|
|||
|
||||
|
||||
public abstract class AbsSmartPlaylist extends AbsCustomPlaylist {
|
||||
|
||||
@DrawableRes
|
||||
public final int iconRes;
|
||||
|
||||
|
@ -37,18 +37,16 @@ public abstract class AbsSmartPlaylist extends AbsCustomPlaylist {
|
|||
this.iconRes = R.drawable.ic_queue_music_white_24dp;
|
||||
}
|
||||
|
||||
public abstract void clear(Context context);
|
||||
|
||||
public boolean isClearable() {
|
||||
return true;
|
||||
protected AbsSmartPlaylist(Parcel in) {
|
||||
super(in);
|
||||
this.iconRes = in.readInt();
|
||||
}
|
||||
|
||||
public abstract void clear(Context context);
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = super.hashCode();
|
||||
result = prime * result + iconRes;
|
||||
return result;
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -63,10 +61,16 @@ public abstract class AbsSmartPlaylist extends AbsCustomPlaylist {
|
|||
return false;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = super.hashCode();
|
||||
result = prime * result + iconRes;
|
||||
return result;
|
||||
}
|
||||
|
||||
public boolean isClearable() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -74,9 +78,4 @@ public abstract class AbsSmartPlaylist extends AbsCustomPlaylist {
|
|||
super.writeToParcel(dest, flags);
|
||||
dest.writeInt(this.iconRes);
|
||||
}
|
||||
|
||||
protected AbsSmartPlaylist(Parcel in) {
|
||||
super(in);
|
||||
this.iconRes = in.readInt();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,17 +16,13 @@ package code.name.monkey.retromusic.model.smartplaylist;
|
|||
|
||||
import android.content.Context;
|
||||
import android.os.Parcel;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import code.name.monkey.retromusic.R;
|
||||
import code.name.monkey.retromusic.loaders.TopAndRecentlyPlayedTracksLoader;
|
||||
import code.name.monkey.retromusic.model.Song;
|
||||
import code.name.monkey.retromusic.providers.HistoryStore;
|
||||
import java.util.ArrayList;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* @author Karim Abou Zeid (kabouzeid)
|
||||
|
@ -51,12 +47,6 @@ public class HistoryPlaylist extends AbsSmartPlaylist {
|
|||
super(in);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public ArrayList<Song> getSongs(@NotNull @NonNull Context context) {
|
||||
return TopAndRecentlyPlayedTracksLoader.INSTANCE.getRecentlyPlayedTracks(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear(@NonNull Context context) {
|
||||
HistoryStore.getInstance(context).clear();
|
||||
|
@ -66,4 +56,10 @@ public class HistoryPlaylist extends AbsSmartPlaylist {
|
|||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public ArrayList<Song> getSongs(@NotNull @NonNull Context context) {
|
||||
return TopAndRecentlyPlayedTracksLoader.INSTANCE.getRecentlyPlayedTracks(context);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,16 +16,12 @@ package code.name.monkey.retromusic.model.smartplaylist;
|
|||
|
||||
import android.content.Context;
|
||||
import android.os.Parcel;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import code.name.monkey.retromusic.R;
|
||||
import code.name.monkey.retromusic.loaders.LastAddedSongsLoader;
|
||||
import code.name.monkey.retromusic.model.Song;
|
||||
import java.util.ArrayList;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
|
||||
public class LastAddedPlaylist extends AbsSmartPlaylist {
|
||||
|
@ -48,23 +44,23 @@ public class LastAddedPlaylist extends AbsSmartPlaylist {
|
|||
super(in);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear(@NonNull Context context) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public ArrayList<Song> getSongs(@NotNull @NonNull Context context) {
|
||||
return LastAddedSongsLoader.INSTANCE.getLastAddedSongs(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear(@NonNull Context context) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isClearable() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,17 +16,13 @@ package code.name.monkey.retromusic.model.smartplaylist;
|
|||
|
||||
import android.content.Context;
|
||||
import android.os.Parcel;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import code.name.monkey.retromusic.R;
|
||||
import code.name.monkey.retromusic.loaders.TopAndRecentlyPlayedTracksLoader;
|
||||
import code.name.monkey.retromusic.model.Song;
|
||||
import code.name.monkey.retromusic.providers.SongPlayCountStore;
|
||||
import java.util.ArrayList;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
/**
|
||||
* @author Karim Abou Zeid (kabouzeid)
|
||||
|
@ -51,13 +47,6 @@ public class MyTopTracksPlaylist extends AbsSmartPlaylist {
|
|||
super(in);
|
||||
}
|
||||
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public ArrayList<Song> getSongs(@NotNull @NonNull Context context) {
|
||||
return TopAndRecentlyPlayedTracksLoader.INSTANCE.getTopTracks(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear(@NonNull Context context) {
|
||||
SongPlayCountStore.getInstance(context).clear();
|
||||
|
@ -67,4 +56,10 @@ public class MyTopTracksPlaylist extends AbsSmartPlaylist {
|
|||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public ArrayList<Song> getSongs(@NotNull @NonNull Context context) {
|
||||
return TopAndRecentlyPlayedTracksLoader.INSTANCE.getTopTracks(context);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,17 +16,12 @@ package code.name.monkey.retromusic.model.smartplaylist;
|
|||
|
||||
import android.content.Context;
|
||||
import android.os.Parcel;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import code.name.monkey.retromusic.R;
|
||||
import code.name.monkey.retromusic.loaders.SongLoader;
|
||||
import code.name.monkey.retromusic.model.Song;
|
||||
import io.reactivex.Observable;
|
||||
import java.util.ArrayList;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class ShuffleAllPlaylist extends AbsSmartPlaylist {
|
||||
|
||||
|
@ -48,18 +43,6 @@ public class ShuffleAllPlaylist extends AbsSmartPlaylist {
|
|||
super(in);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public Observable<ArrayList<Song>> getSongsFlowable(@NotNull @NonNull Context context) {
|
||||
return SongLoader.INSTANCE.getAllSongsFlowable(context);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public ArrayList<Song> getSongs(@NotNull Context context) {
|
||||
return SongLoader.INSTANCE.getAllSongs(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear(@NonNull Context context) {
|
||||
// Shuffle all is not a real "Smart Playlist"
|
||||
|
@ -69,4 +52,10 @@ public class ShuffleAllPlaylist extends AbsSmartPlaylist {
|
|||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public ArrayList<Song> getSongs(@NotNull Context context) {
|
||||
return SongLoader.INSTANCE.getAllSongs(context);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,16 +20,14 @@ import code.name.monkey.retromusic.mvp.BaseView
|
|||
import code.name.monkey.retromusic.mvp.Presenter
|
||||
import code.name.monkey.retromusic.mvp.PresenterImpl
|
||||
import code.name.monkey.retromusic.providers.interfaces.Repository
|
||||
import io.reactivex.disposables.CompositeDisposable
|
||||
import io.reactivex.disposables.Disposable
|
||||
import kotlinx.coroutines.*
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlinx.coroutines.withContext
|
||||
import javax.inject.Inject
|
||||
import kotlin.coroutines.CoroutineContext
|
||||
|
||||
operator fun CompositeDisposable.plusAssign(disposable: Disposable) {
|
||||
add(disposable)
|
||||
}
|
||||
|
||||
interface HomeView : BaseView {
|
||||
fun sections(sections: ArrayList<Home>)
|
||||
}
|
||||
|
@ -38,8 +36,9 @@ interface HomePresenter : Presenter<HomeView> {
|
|||
fun loadSections()
|
||||
|
||||
class HomePresenterImpl @Inject constructor(
|
||||
private val repository: Repository
|
||||
private val repository: Repository
|
||||
) : PresenterImpl<HomeView>(), HomePresenter, CoroutineScope {
|
||||
|
||||
private val job = Job()
|
||||
|
||||
override val coroutineContext: CoroutineContext
|
||||
|
@ -54,11 +53,11 @@ interface HomePresenter : Presenter<HomeView> {
|
|||
launch {
|
||||
val list = ArrayList<Home>()
|
||||
val recentArtistResult = listOf(
|
||||
repository.topArtists(),
|
||||
repository.topAlbums(),
|
||||
repository.recentArtists(),
|
||||
repository.recentAlbums(),
|
||||
repository.favoritePlaylist()
|
||||
repository.topArtists(),
|
||||
repository.topAlbums(),
|
||||
repository.recentArtists(),
|
||||
repository.recentAlbums(),
|
||||
repository.favoritePlaylist()
|
||||
)
|
||||
for (r in recentArtistResult) {
|
||||
when (r) {
|
||||
|
|
|
@ -20,15 +20,11 @@ import android.database.sqlite.SQLiteDatabase;
|
|||
import android.database.sqlite.SQLiteOpenHelper;
|
||||
import android.provider.BaseColumns;
|
||||
import android.provider.MediaStore.Audio.AudioColumns;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import code.name.monkey.retromusic.loaders.SongLoader;
|
||||
import code.name.monkey.retromusic.model.Song;
|
||||
import io.reactivex.Observable;
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* @author Andrew Neal, modified for Phonograph by Karim Abou Zeid
|
||||
|
@ -36,22 +32,18 @@ import io.reactivex.Observable;
|
|||
* This keeps track of the music playback and history state of the playback service
|
||||
*/
|
||||
public class MusicPlaybackQueueStore extends SQLiteOpenHelper {
|
||||
|
||||
public static final String DATABASE_NAME = "music_playback_state.db";
|
||||
|
||||
public static final String PLAYING_QUEUE_TABLE_NAME = "playing_queue";
|
||||
|
||||
public static final String ORIGINAL_PLAYING_QUEUE_TABLE_NAME = "original_playing_queue";
|
||||
|
||||
private static final int VERSION = 10;
|
||||
|
||||
@Nullable
|
||||
private static MusicPlaybackQueueStore sInstance = null;
|
||||
|
||||
/**
|
||||
* Constructor of <code>MusicPlaybackState</code>
|
||||
*
|
||||
* @param context The {@link Context} to use
|
||||
*/
|
||||
public MusicPlaybackQueueStore(final @NonNull Context context) {
|
||||
super(context, DATABASE_NAME, null, VERSION);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param context The {@link Context} to use
|
||||
* @return A new instance of this class.
|
||||
|
@ -64,12 +56,53 @@ public class MusicPlaybackQueueStore extends SQLiteOpenHelper {
|
|||
return sInstance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor of <code>MusicPlaybackState</code>
|
||||
*
|
||||
* @param context The {@link Context} to use
|
||||
*/
|
||||
public MusicPlaybackQueueStore(final @NonNull Context context) {
|
||||
super(context, DATABASE_NAME, null, VERSION);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(@NonNull final SQLiteDatabase db) {
|
||||
createTable(db, PLAYING_QUEUE_TABLE_NAME);
|
||||
createTable(db, ORIGINAL_PLAYING_QUEUE_TABLE_NAME);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public ArrayList<Song> getSavedOriginalPlayingQueue() {
|
||||
return getQueue(ORIGINAL_PLAYING_QUEUE_TABLE_NAME);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public ArrayList<Song> getSavedPlayingQueue() {
|
||||
return getQueue(PLAYING_QUEUE_TABLE_NAME);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDowngrade(@NonNull SQLiteDatabase db, int oldVersion, int newVersion) {
|
||||
// If we ever have downgrade, drop the table to be safe
|
||||
db.execSQL("DROP TABLE IF EXISTS " + PLAYING_QUEUE_TABLE_NAME);
|
||||
db.execSQL("DROP TABLE IF EXISTS " + ORIGINAL_PLAYING_QUEUE_TABLE_NAME);
|
||||
onCreate(db);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUpgrade(@NonNull final SQLiteDatabase db, final int oldVersion, final int newVersion) {
|
||||
// not necessary yet
|
||||
db.execSQL("DROP TABLE IF EXISTS " + PLAYING_QUEUE_TABLE_NAME);
|
||||
db.execSQL("DROP TABLE IF EXISTS " + ORIGINAL_PLAYING_QUEUE_TABLE_NAME);
|
||||
onCreate(db);
|
||||
}
|
||||
|
||||
public synchronized void saveQueues(@NonNull final ArrayList<Song> playingQueue,
|
||||
@NonNull final ArrayList<Song> originalPlayingQueue) {
|
||||
saveQueue(PLAYING_QUEUE_TABLE_NAME, playingQueue);
|
||||
saveQueue(ORIGINAL_PLAYING_QUEUE_TABLE_NAME, originalPlayingQueue);
|
||||
}
|
||||
|
||||
private void createTable(@NonNull final SQLiteDatabase db, final String tableName) {
|
||||
//noinspection StringBufferReplaceableByString
|
||||
StringBuilder builder = new StringBuilder();
|
||||
|
@ -116,25 +149,11 @@ public class MusicPlaybackQueueStore extends SQLiteOpenHelper {
|
|||
db.execSQL(builder.toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onUpgrade(@NonNull final SQLiteDatabase db, final int oldVersion, final int newVersion) {
|
||||
// not necessary yet
|
||||
db.execSQL("DROP TABLE IF EXISTS " + PLAYING_QUEUE_TABLE_NAME);
|
||||
db.execSQL("DROP TABLE IF EXISTS " + ORIGINAL_PLAYING_QUEUE_TABLE_NAME);
|
||||
onCreate(db);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDowngrade(@NonNull SQLiteDatabase db, int oldVersion, int newVersion) {
|
||||
// If we ever have downgrade, drop the table to be safe
|
||||
db.execSQL("DROP TABLE IF EXISTS " + PLAYING_QUEUE_TABLE_NAME);
|
||||
db.execSQL("DROP TABLE IF EXISTS " + ORIGINAL_PLAYING_QUEUE_TABLE_NAME);
|
||||
onCreate(db);
|
||||
}
|
||||
|
||||
public synchronized void saveQueues(@NonNull final ArrayList<Song> playingQueue, @NonNull final ArrayList<Song> originalPlayingQueue) {
|
||||
saveQueue(PLAYING_QUEUE_TABLE_NAME, playingQueue);
|
||||
saveQueue(ORIGINAL_PLAYING_QUEUE_TABLE_NAME, originalPlayingQueue);
|
||||
@NonNull
|
||||
private ArrayList<Song> getQueue(@NonNull final String tableName) {
|
||||
Cursor cursor = getReadableDatabase().query(tableName, null,
|
||||
null, null, null, null, null);
|
||||
return SongLoader.INSTANCE.getSongs(cursor);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -185,38 +204,4 @@ public class MusicPlaybackQueueStore extends SQLiteOpenHelper {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public Observable<ArrayList<Song>> getSavedPlayingQueueFlowable() {
|
||||
return getQueueFlowable(PLAYING_QUEUE_TABLE_NAME);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public Observable<ArrayList<Song>> getSavedOriginalPlayingQueueFlowable() {
|
||||
return getQueueFlowable(ORIGINAL_PLAYING_QUEUE_TABLE_NAME);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public ArrayList<Song> getSavedPlayingQueue() {
|
||||
return getQueue(PLAYING_QUEUE_TABLE_NAME);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
public ArrayList<Song> getSavedOriginalPlayingQueue() {
|
||||
return getQueue(ORIGINAL_PLAYING_QUEUE_TABLE_NAME);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private Observable<ArrayList<Song>> getQueueFlowable(@NonNull final String tableName) {
|
||||
Cursor cursor = getReadableDatabase().query(tableName, null,
|
||||
null, null, null, null, null);
|
||||
return SongLoader.INSTANCE.getSongsFlowable(cursor);
|
||||
}
|
||||
|
||||
@NonNull
|
||||
private ArrayList<Song> getQueue(@NonNull final String tableName) {
|
||||
Cursor cursor = getReadableDatabase().query(tableName, null,
|
||||
null, null, null, null, null);
|
||||
return SongLoader.INSTANCE.getSongs(cursor);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue