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