This commit is contained in:
h4h13 2020-02-05 17:14:22 +05:30
parent 016c7f6218
commit b922549dee
37 changed files with 606 additions and 693 deletions

View file

@ -27,14 +27,15 @@ import code.name.monkey.retromusic.dialogs.AddToPlaylistDialog
import code.name.monkey.retromusic.dialogs.DeleteSongsDialog import code.name.monkey.retromusic.dialogs.DeleteSongsDialog
import code.name.monkey.retromusic.extensions.ripAlpha import code.name.monkey.retromusic.extensions.ripAlpha
import code.name.monkey.retromusic.extensions.show import code.name.monkey.retromusic.extensions.show
import code.name.monkey.retromusic.glide.AlbumGlideRequest
import code.name.monkey.retromusic.glide.ArtistGlideRequest import code.name.monkey.retromusic.glide.ArtistGlideRequest
import code.name.monkey.retromusic.glide.RetroMusicColoredTarget import code.name.monkey.retromusic.glide.RetroMusicColoredTarget
import code.name.monkey.retromusic.glide.SongGlideRequest
import code.name.monkey.retromusic.helper.MusicPlayerRemote import code.name.monkey.retromusic.helper.MusicPlayerRemote
import code.name.monkey.retromusic.helper.SortOrder.AlbumSongSortOrder import code.name.monkey.retromusic.helper.SortOrder.AlbumSongSortOrder
import code.name.monkey.retromusic.interfaces.CabHolder import code.name.monkey.retromusic.interfaces.CabHolder
import code.name.monkey.retromusic.model.Album import code.name.monkey.retromusic.model.Album
import code.name.monkey.retromusic.model.Artist import code.name.monkey.retromusic.model.Artist
import code.name.monkey.retromusic.model.Song
import code.name.monkey.retromusic.mvp.presenter.AlbumDetailsPresenter import code.name.monkey.retromusic.mvp.presenter.AlbumDetailsPresenter
import code.name.monkey.retromusic.mvp.presenter.AlbumDetailsView import code.name.monkey.retromusic.mvp.presenter.AlbumDetailsView
import code.name.monkey.retromusic.rest.model.LastFmAlbum import code.name.monkey.retromusic.rest.model.LastFmAlbum
@ -62,7 +63,6 @@ import kotlinx.android.synthetic.main.activity_album_content.scrobbles
import kotlinx.android.synthetic.main.activity_album_content.scrobblesLabel import kotlinx.android.synthetic.main.activity_album_content.scrobblesLabel
import kotlinx.android.synthetic.main.activity_album_content.shuffleAction import kotlinx.android.synthetic.main.activity_album_content.shuffleAction
import kotlinx.android.synthetic.main.activity_album_content.songTitle import kotlinx.android.synthetic.main.activity_album_content.songTitle
import java.util.ArrayList
import javax.inject.Inject import javax.inject.Inject
import android.util.Pair as UtilPair import android.util.Pair as UtilPair
@ -124,7 +124,7 @@ class AlbumDetailsActivity : AbsSlidingMusicPanelActivity(), AlbumDetailsView, C
albumDetailsPresenter.attachView(this) albumDetailsPresenter.attachView(this)
if (intent.extras!!.containsKey(EXTRA_ALBUM_ID)) { if (intent.extras!!.containsKey(EXTRA_ALBUM_ID)) {
intent.extras?.getInt(EXTRA_ALBUM_ID)?.let { intent.extras?.getLong(EXTRA_ALBUM_ID)?.let {
albumDetailsPresenter.loadAlbum(it) albumDetailsPresenter.loadAlbum(it)
albumCoverContainer?.transitionName = "${getString(R.string.transition_album_art)}_$it" albumCoverContainer?.transitionName = "${getString(R.string.transition_album_art)}_$it"
} }
@ -151,10 +151,10 @@ class AlbumDetailsActivity : AbsSlidingMusicPanelActivity(), AlbumDetailsView, C
NavigationUtil.goToArtistOptions(this, album.artistId, artistPairs) NavigationUtil.goToArtistOptions(this, album.artistId, artistPairs)
} }
playAction.apply { playAction.apply {
setOnClickListener { MusicPlayerRemote.openQueue(album.songs!!, 0, true) } //setOnClickListener { MusicPlayerRemote.openQueue(album.songs!!, 0, true) }
} }
shuffleAction.apply { shuffleAction.apply {
setOnClickListener { MusicPlayerRemote.openAndShuffleQueue(album.songs!!, true) } //setOnClickListener { MusicPlayerRemote.openAndShuffleQueue(album.songs!!, true) }
} }
aboutAlbumText.setOnClickListener { aboutAlbumText.setOnClickListener {
@ -187,37 +187,32 @@ class AlbumDetailsActivity : AbsSlidingMusicPanelActivity(), AlbumDetailsView, C
override fun album(album: Album) { override fun album(album: Album) {
complete() complete()
if (album.songs!!.isEmpty()) { /*if (album.songs!!.isEmpty()) {
finish() finish()
return return
} }*/
this.album = album this.album = album
albumTitle.text = album.title albumTitle.text = album.title
if (MusicUtil.getYearString(album.year) == "-") { if (MusicUtil.getYearString(album.year) == "-") {
albumText.text = String.format( albumText.text = String.format("%s", album.artist)
"%s • %s",
album.artistName,
MusicUtil.getReadableDurationString(MusicUtil.getTotalDuration(album.songs))
)
} else { } else {
albumText.text = String.format( albumText.text = String.format("%s • %s", album.artist, MusicUtil.getYearString(album.year))
"%s • %s • %s",
album.artistName,
MusicUtil.getYearString(album.year),
MusicUtil.getReadableDurationString(MusicUtil.getTotalDuration(album.songs))
)
} }
loadAlbumCover() loadAlbumCover()
simpleSongAdapter.swapDataSet(album.songs) albumDetailsPresenter.albumSong(album.id)
albumDetailsPresenter.loadMore(album.artistId) albumDetailsPresenter.loadMore(album.artistId)
albumDetailsPresenter.aboutAlbum(album.artistName!!, album.title!!) albumDetailsPresenter.aboutAlbum(album.artist, album.title)
}
override fun songs(songs: ArrayList<Song>) {
simpleSongAdapter.swapDataSet(songs)
} }
override fun moreAlbums(albums: ArrayList<Album>) { override fun moreAlbums(albums: ArrayList<Album>) {
moreTitle.show() moreTitle.show()
moreRecyclerView.show() moreRecyclerView.show()
moreTitle.text = String.format(getString(R.string.label_more_from), album.artistName) moreTitle.text = String.format(getString(R.string.label_more_from), album.artist)
val albumAdapter = HorizontalAlbumAdapter(this, albums, false, null) val albumAdapter = HorizontalAlbumAdapter(this, albums, false, null)
moreRecyclerView.layoutManager = GridLayoutManager( moreRecyclerView.layoutManager = GridLayoutManager(
@ -250,19 +245,23 @@ class AlbumDetailsActivity : AbsSlidingMusicPanelActivity(), AlbumDetailsView, C
} }
override fun loadArtistImage(artist: Artist) { override fun loadArtistImage(artist: Artist) {
ArtistGlideRequest.Builder.from(Glide.with(this), artist).generatePalette(this).build() ArtistGlideRequest.Builder.from(Glide.with(this), artist)
.dontAnimate().dontTransform().into(object : RetroMusicColoredTarget(artistImage) { .generatePalette(this)
.build()
.dontAnimate()
.dontTransform()
.into(object : RetroMusicColoredTarget(artistImage) {
override fun onColorReady(color: Int) { override fun onColorReady(color: Int) {
} }
}) })
} }
private fun loadAlbumCover() { private fun loadAlbumCover() {
SongGlideRequest.Builder.from(Glide.with(this), album.safeGetFirstSong()) AlbumGlideRequest.Builder(Glide.with(this), album.id)
.checkIgnoreMediaStore(this)
.ignoreMediaStore(PreferenceUtil.getInstance(this).ignoreMediaStoreArtwork())
.generatePalette(this) .generatePalette(this)
.build().dontAnimate().dontTransform() .build()
.dontAnimate()
.dontTransform()
.into(object : RetroMusicColoredTarget(image) { .into(object : RetroMusicColoredTarget(image) {
override fun onColorReady(color: Int) { override fun onColorReady(color: Int) {
setColors(color) setColors(color)
@ -383,7 +382,7 @@ class AlbumDetailsActivity : AbsSlidingMusicPanelActivity(), AlbumDetailsView, C
private fun reload() { private fun reload() {
if (intent.extras!!.containsKey(EXTRA_ALBUM_ID)) { if (intent.extras!!.containsKey(EXTRA_ALBUM_ID)) {
intent.extras?.getInt(EXTRA_ALBUM_ID)?.let { albumDetailsPresenter.loadAlbum(it) } intent.extras?.getLong(EXTRA_ALBUM_ID)?.let { albumDetailsPresenter.loadAlbum(it) }
} else { } else {
finish() finish()
} }

View file

@ -22,14 +22,14 @@ import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.activities.base.AbsSlidingMusicPanelActivity import code.name.monkey.retromusic.activities.base.AbsSlidingMusicPanelActivity
import code.name.monkey.retromusic.adapter.album.HorizontalAlbumAdapter import code.name.monkey.retromusic.adapter.album.HorizontalAlbumAdapter
import code.name.monkey.retromusic.adapter.song.SimpleSongAdapter import code.name.monkey.retromusic.adapter.song.SimpleSongAdapter
import code.name.monkey.retromusic.dialogs.AddToPlaylistDialog
import code.name.monkey.retromusic.extensions.ripAlpha import code.name.monkey.retromusic.extensions.ripAlpha
import code.name.monkey.retromusic.extensions.show import code.name.monkey.retromusic.extensions.show
import code.name.monkey.retromusic.glide.ArtistGlideRequest import code.name.monkey.retromusic.glide.ArtistGlideRequest
import code.name.monkey.retromusic.glide.RetroMusicColoredTarget import code.name.monkey.retromusic.glide.RetroMusicColoredTarget
import code.name.monkey.retromusic.helper.MusicPlayerRemote
import code.name.monkey.retromusic.interfaces.CabHolder import code.name.monkey.retromusic.interfaces.CabHolder
import code.name.monkey.retromusic.model.Album
import code.name.monkey.retromusic.model.Artist import code.name.monkey.retromusic.model.Artist
import code.name.monkey.retromusic.model.Song
import code.name.monkey.retromusic.mvp.presenter.ArtistDetailsPresenter import code.name.monkey.retromusic.mvp.presenter.ArtistDetailsPresenter
import code.name.monkey.retromusic.mvp.presenter.ArtistDetailsView import code.name.monkey.retromusic.mvp.presenter.ArtistDetailsView
import code.name.monkey.retromusic.rest.model.LastFmArtist import code.name.monkey.retromusic.rest.model.LastFmArtist
@ -118,7 +118,7 @@ class ArtistDetailActivity : AbsSlidingMusicPanelActivity(), ArtistDetailsView,
artistDetailsPresenter.attachView(this) artistDetailsPresenter.attachView(this)
if (intent.extras!!.containsKey(EXTRA_ARTIST_ID)) { if (intent.extras!!.containsKey(EXTRA_ARTIST_ID)) {
intent.extras?.getInt(EXTRA_ARTIST_ID)?.let { intent.extras?.getLong(EXTRA_ARTIST_ID)?.let {
artistDetailsPresenter.loadArtist(it) artistDetailsPresenter.loadArtist(it)
val name = "${getString(R.string.transition_artist_image)}_$it" val name = "${getString(R.string.transition_artist_image)}_$it"
artistCoverContainer?.transitionName = name artistCoverContainer?.transitionName = name
@ -133,10 +133,10 @@ class ArtistDetailActivity : AbsSlidingMusicPanelActivity(), ArtistDetailsView,
setupRecyclerView() setupRecyclerView()
playAction.apply { playAction.apply {
setOnClickListener { MusicPlayerRemote.openQueue(artist.songs, 0, true) } //setOnClickListener { MusicPlayerRemote.openQueue(artist.songs, 0, true) }
} }
shuffleAction.apply { shuffleAction.apply {
setOnClickListener { MusicPlayerRemote.openAndShuffleQueue(artist.songs, true) } //setOnClickListener { MusicPlayerRemote.openAndShuffleQueue(artist.songs, true) }
} }
biographyText.setOnClickListener { biographyText.setOnClickListener {
@ -189,6 +189,14 @@ class ArtistDetailActivity : AbsSlidingMusicPanelActivity(), ArtistDetailsView,
ActivityCompat.startPostponedEnterTransition(this) ActivityCompat.startPostponedEnterTransition(this)
} }
override fun songs(songs: ArrayList<Song>) {
songAdapter.swapDataSet(songs)
}
override fun albums(albums: List<Album>) {
albumAdapter.swapDataSet(ArrayList(albums))
}
override fun artist(artist: Artist) { override fun artist(artist: Artist) {
complete() complete()
if (artist.songCount <= 0) { if (artist.songCount <= 0) {
@ -202,13 +210,12 @@ class ArtistDetailActivity : AbsSlidingMusicPanelActivity(), ArtistDetailsView,
} }
artistTitle.text = artist.name artistTitle.text = artist.name
text.text = String.format( text.text = String.format(
"%s • %s", "%s",
MusicUtil.getArtistInfoString(this, artist), MusicUtil.getArtistInfoString(this, artist)
MusicUtil.getReadableDurationString(MusicUtil.getTotalDuration(artist.songs))
) )
artistDetailsPresenter.loadArtistAlbums(artist.id)
songAdapter.swapDataSet(artist.songs) artistDetailsPresenter.loadArtistSongs(artist.id)
albumAdapter.swapDataSet(artist.albums!!) //albumAdapter.swapDataSet(artist.albums!!)
} }
private fun loadBiography( private fun loadBiography(
@ -304,22 +311,22 @@ class ArtistDetailActivity : AbsSlidingMusicPanelActivity(), ArtistDetailsView,
} }
private fun handleSortOrderMenuItem(item: MenuItem): Boolean { private fun handleSortOrderMenuItem(item: MenuItem): Boolean {
val songs = artist.songs //val songs = artist.songs
when (item.itemId) { when (item.itemId) {
android.R.id.home -> { android.R.id.home -> {
super.onBackPressed() super.onBackPressed()
return true return true
} }
R.id.action_play_next -> { R.id.action_play_next -> {
MusicPlayerRemote.playNext(songs) //MusicPlayerRemote.playNext(songs)
return true return true
} }
R.id.action_add_to_current_playing -> { R.id.action_add_to_current_playing -> {
MusicPlayerRemote.enqueue(songs) //MusicPlayerRemote.enqueue(songs)
return true return true
} }
R.id.action_add_to_playlist -> { R.id.action_add_to_playlist -> {
AddToPlaylistDialog.create(songs).show(supportFragmentManager, "ADD_PLAYLIST") //AddToPlaylistDialog.create(songs).show(supportFragmentManager, "ADD_PLAYLIST")
return true return true
} }
R.id.action_set_artist_image -> { R.id.action_set_artist_image -> {
@ -354,7 +361,7 @@ class ArtistDetailActivity : AbsSlidingMusicPanelActivity(), ArtistDetailsView,
private fun reload() { private fun reload() {
if (intent.extras!!.containsKey(EXTRA_ARTIST_ID)) { if (intent.extras!!.containsKey(EXTRA_ARTIST_ID)) {
intent.extras?.getInt(EXTRA_ARTIST_ID)?.let { artistDetailsPresenter.loadArtist(it) } intent.extras?.getLong(EXTRA_ARTIST_ID)?.let { artistDetailsPresenter.loadArtist(it) }
} else { } else {
finish() finish()
} }

View file

@ -19,8 +19,6 @@ import code.name.monkey.retromusic.fragments.mainactivity.home.BannerHomeFragmen
import code.name.monkey.retromusic.helper.MusicPlayerRemote import code.name.monkey.retromusic.helper.MusicPlayerRemote
import code.name.monkey.retromusic.helper.SearchQueryHelper import code.name.monkey.retromusic.helper.SearchQueryHelper
import code.name.monkey.retromusic.interfaces.MainActivityFragmentCallbacks import code.name.monkey.retromusic.interfaces.MainActivityFragmentCallbacks
import code.name.monkey.retromusic.loaders.AlbumLoader
import code.name.monkey.retromusic.loaders.ArtistLoader
import code.name.monkey.retromusic.loaders.PlaylistSongsLoader 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
@ -155,14 +153,14 @@ class MainActivity : AbsSlidingMusicPanelActivity(), SharedPreferences.OnSharedP
val id = parseIdFromIntent(intent, "albumId", "album").toInt() val id = parseIdFromIntent(intent, "albumId", "album").toInt()
if (id >= 0) { if (id >= 0) {
val position = intent.getIntExtra("position", 0) val position = intent.getIntExtra("position", 0)
MusicPlayerRemote.openQueue(AlbumLoader.getAlbum(this, id).songs!!, position, true) //MusicPlayerRemote.openQueue(AlbumLoader.getAlbum(this, id).songs!!, position, true)
handled = true handled = true
} }
} else if (MediaStore.Audio.Artists.CONTENT_TYPE == mimeType) { } else if (MediaStore.Audio.Artists.CONTENT_TYPE == mimeType) {
val id = parseIdFromIntent(intent, "artistId", "artist").toInt() val id = parseIdFromIntent(intent, "artistId", "artist").toInt()
if (id >= 0) { if (id >= 0) {
val position = intent.getIntExtra("position", 0) val position = intent.getIntExtra("position", 0)
MusicPlayerRemote.openQueue(ArtistLoader.getArtist(this, id).songs, position, true) //MusicPlayerRemote.openQueue(ArtistLoader.getArtist(this, id).songs, position, true)
handled = true handled = true
} }
} }

View file

@ -19,7 +19,6 @@ import code.name.monkey.retromusic.extensions.appHandleColor
import code.name.monkey.retromusic.extensions.applyToolbar import code.name.monkey.retromusic.extensions.applyToolbar
import code.name.monkey.retromusic.glide.palette.BitmapPaletteTranscoder import code.name.monkey.retromusic.glide.palette.BitmapPaletteTranscoder
import code.name.monkey.retromusic.glide.palette.BitmapPaletteWrapper import code.name.monkey.retromusic.glide.palette.BitmapPaletteWrapper
import code.name.monkey.retromusic.loaders.AlbumLoader
import code.name.monkey.retromusic.rest.LastFMRestClient import code.name.monkey.retromusic.rest.LastFMRestClient
import code.name.monkey.retromusic.util.ImageUtil import code.name.monkey.retromusic.util.ImageUtil
import code.name.monkey.retromusic.util.RetroColorUtil.generatePalette import code.name.monkey.retromusic.util.RetroColorUtil.generatePalette
@ -39,7 +38,6 @@ import kotlinx.android.synthetic.main.activity_album_tag_editor.toolbar
import kotlinx.android.synthetic.main.activity_album_tag_editor.yearContainer import kotlinx.android.synthetic.main.activity_album_tag_editor.yearContainer
import kotlinx.android.synthetic.main.activity_album_tag_editor.yearTitle import kotlinx.android.synthetic.main.activity_album_tag_editor.yearTitle
import org.jaudiotagger.tag.FieldKey import org.jaudiotagger.tag.FieldKey
import java.util.ArrayList
import java.util.EnumMap import java.util.EnumMap
class AlbumTagEditorActivity : AbsTagEditorActivity(), TextWatcher { class AlbumTagEditorActivity : AbsTagEditorActivity(), TextWatcher {
@ -183,12 +181,13 @@ class AlbumTagEditorActivity : AbsTagEditorActivity(), TextWatcher {
} }
override fun getSongPaths(): List<String> { override fun getSongPaths(): List<String> {
val songs = AlbumLoader.getAlbum(this, id).songs //val songs = AlbumLoader.getAlbum(this, id).songs
val paths = ArrayList<String>(songs!!.size) //val paths = ArrayList<String>(songs!!.size)
for (song in songs) { //for (song in songs) {
paths.add(song.data) // paths.add(song.data)
} //}
return paths //return paths
return emptyList()
} }
override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) { override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {

View file

@ -10,7 +10,6 @@ import code.name.monkey.appthemehelper.ThemeStore
import code.name.monkey.retromusic.R import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.adapter.base.MediaEntryViewHolder import code.name.monkey.retromusic.adapter.base.MediaEntryViewHolder
import code.name.monkey.retromusic.glide.ArtistGlideRequest import code.name.monkey.retromusic.glide.ArtistGlideRequest
import code.name.monkey.retromusic.glide.SongGlideRequest
import code.name.monkey.retromusic.helper.MusicPlayerRemote import code.name.monkey.retromusic.helper.MusicPlayerRemote
import code.name.monkey.retromusic.helper.menu.SongMenuHelper import code.name.monkey.retromusic.helper.menu.SongMenuHelper
import code.name.monkey.retromusic.loaders.PlaylistSongsLoader import code.name.monkey.retromusic.loaders.PlaylistSongsLoader
@ -60,9 +59,9 @@ class SearchAdapter(
ALBUM -> { ALBUM -> {
val album = dataSet?.get(position) as Album val album = dataSet?.get(position) as Album
holder.title?.text = album.title holder.title?.text = album.title
holder.text?.text = album.artistName holder.text?.text = album.artist
SongGlideRequest.Builder.from(Glide.with(activity), album.safeGetFirstSong()) /*SongGlideRequest.Builder.from(Glide.with(activity), album.safeGetFirstSong())
.checkIgnoreMediaStore(activity).build().into(holder.image) .checkIgnoreMediaStore(activity).build().into(holder.image)*/
} }
ARTIST -> { ARTIST -> {
val artist = dataSet?.get(position) as Artist val artist = dataSet?.get(position) as Artist

View file

@ -2,7 +2,6 @@ package code.name.monkey.retromusic.adapter.album
import android.app.ActivityOptions import android.app.ActivityOptions
import android.content.res.ColorStateList import android.content.res.ColorStateList
import android.graphics.drawable.Drawable
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.MenuItem import android.view.MenuItem
import android.view.View import android.view.View
@ -13,9 +12,8 @@ import code.name.monkey.appthemehelper.util.MaterialValueHelper
import code.name.monkey.retromusic.R import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.adapter.base.AbsMultiSelectAdapter import code.name.monkey.retromusic.adapter.base.AbsMultiSelectAdapter
import code.name.monkey.retromusic.adapter.base.MediaEntryViewHolder import code.name.monkey.retromusic.adapter.base.MediaEntryViewHolder
import code.name.monkey.retromusic.glide.AlbumGlideRequest
import code.name.monkey.retromusic.glide.RetroMusicColoredTarget import code.name.monkey.retromusic.glide.RetroMusicColoredTarget
import code.name.monkey.retromusic.glide.SongGlideRequest
import code.name.monkey.retromusic.helper.MusicPlayerRemote
import code.name.monkey.retromusic.helper.SortOrder import code.name.monkey.retromusic.helper.SortOrder
import code.name.monkey.retromusic.helper.menu.SongsMenuHelper import code.name.monkey.retromusic.helper.menu.SongsMenuHelper
import code.name.monkey.retromusic.interfaces.CabHolder import code.name.monkey.retromusic.interfaces.CabHolder
@ -29,7 +27,7 @@ import me.zhanghai.android.fastscroll.PopupTextProvider
open class AlbumAdapter( open class AlbumAdapter(
protected val activity: AppCompatActivity, protected val activity: AppCompatActivity,
dataSet: ArrayList<Album>, dataSet: List<Album>,
protected var itemLayoutRes: Int, protected var itemLayoutRes: Int,
usePalette: Boolean, usePalette: Boolean,
cabHolder: CabHolder? cabHolder: CabHolder?
@ -39,7 +37,7 @@ open class AlbumAdapter(
R.menu.menu_media_selection R.menu.menu_media_selection
), PopupTextProvider { ), PopupTextProvider {
var dataSet: ArrayList<Album> var dataSet: List<Album>
protected set protected set
protected var usePalette = false protected var usePalette = false
@ -60,7 +58,7 @@ open class AlbumAdapter(
notifyDataSetChanged() notifyDataSetChanged()
} }
fun swapDataSet(dataSet: ArrayList<Album>) { fun swapDataSet(dataSet: List<Album>) {
this.dataSet = dataSet this.dataSet = dataSet
notifyDataSetChanged() notifyDataSetChanged()
} }
@ -79,7 +77,7 @@ open class AlbumAdapter(
} }
protected open fun getAlbumText(album: Album): String? { protected open fun getAlbumText(album: Album): String? {
return album.artistName return album.artist
} }
override fun onBindViewHolder(holder: ViewHolder, position: Int) { override fun onBindViewHolder(holder: ViewHolder, position: Int) {
@ -89,13 +87,13 @@ open class AlbumAdapter(
holder.title?.text = getAlbumTitle(album) holder.title?.text = getAlbumTitle(album)
holder.text?.text = getAlbumText(album) holder.text?.text = getAlbumText(album)
holder.playSongs?.setOnClickListener { holder.playSongs?.setOnClickListener {
album.songs?.let { songs -> /*album.songs?.let { songs ->
MusicPlayerRemote.openQueue( MusicPlayerRemote.openQueue(
songs, songs,
0, 0,
true true
) )
} }*/
} }
loadAlbumCover(album, holder) loadAlbumCover(album, holder)
} }
@ -123,15 +121,12 @@ open class AlbumAdapter(
if (holder.image == null) { if (holder.image == null) {
return return
} }
AlbumGlideRequest.Builder(Glide.with(activity), album.id)
SongGlideRequest.Builder.from(Glide.with(activity), album.safeGetFirstSong()) .generatePalette(activity)
.checkIgnoreMediaStore(activity).generatePalette(activity).build() .build()
.dontAnimate()
.dontTransform()
.into(object : RetroMusicColoredTarget(holder.image!!) { .into(object : RetroMusicColoredTarget(holder.image!!) {
override fun onLoadCleared(placeholder: Drawable?) {
super.onLoadCleared(placeholder)
setColors(defaultFooterColor, holder)
}
override fun onColorReady(color: Int) { override fun onColorReady(color: Int) {
setColors(color, holder) setColors(color, holder)
} }
@ -143,7 +138,7 @@ open class AlbumAdapter(
} }
override fun getItemId(position: Int): Long { override fun getItemId(position: Int): Long {
return dataSet[position].id.toLong() return dataSet[position].id
} }
override fun getIdentifier(position: Int): Album? { override fun getIdentifier(position: Int): Album? {
@ -163,7 +158,7 @@ open class AlbumAdapter(
private fun getSongList(albums: List<Album>): ArrayList<Song> { private fun getSongList(albums: List<Album>): ArrayList<Song> {
val songs = ArrayList<Song>() val songs = ArrayList<Song>()
for (album in albums) { for (album in albums) {
songs.addAll(album.songs!!) //songs.addAll(album.songs!!)
} }
return songs return songs
} }
@ -177,7 +172,7 @@ open class AlbumAdapter(
when (PreferenceUtil.getInstance(activity).albumSortOrder) { when (PreferenceUtil.getInstance(activity).albumSortOrder) {
SortOrder.AlbumSortOrder.ALBUM_A_Z, SortOrder.AlbumSortOrder.ALBUM_Z_A -> sectionName = SortOrder.AlbumSortOrder.ALBUM_A_Z, SortOrder.AlbumSortOrder.ALBUM_Z_A -> sectionName =
dataSet[position].title dataSet[position].title
SortOrder.AlbumSortOrder.ALBUM_ARTIST -> sectionName = dataSet[position].artistName SortOrder.AlbumSortOrder.ALBUM_ARTIST -> sectionName = dataSet[position].artist
SortOrder.AlbumSortOrder.ALBUM_YEAR -> return MusicUtil.getYearString( SortOrder.AlbumSortOrder.ALBUM_YEAR -> return MusicUtil.getYearString(
dataSet[position].year dataSet[position].year
) )

View file

@ -22,9 +22,8 @@ import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import code.name.monkey.retromusic.R import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.glide.AlbumGlideRequest
import code.name.monkey.retromusic.glide.RetroMusicColoredTarget import code.name.monkey.retromusic.glide.RetroMusicColoredTarget
import code.name.monkey.retromusic.glide.SongGlideRequest
import code.name.monkey.retromusic.helper.MusicPlayerRemote
import code.name.monkey.retromusic.model.Album import code.name.monkey.retromusic.model.Album
import code.name.monkey.retromusic.util.NavigationUtil import code.name.monkey.retromusic.util.NavigationUtil
import code.name.monkey.retromusic.views.MetalRecyclerViewPager import code.name.monkey.retromusic.views.MetalRecyclerViewPager
@ -47,13 +46,13 @@ class AlbumFullWidthAdapter(
holder.title?.text = getAlbumTitle(album) holder.title?.text = getAlbumTitle(album)
holder.text?.text = getAlbumText(album) holder.text?.text = getAlbumText(album)
holder.playSongs?.setOnClickListener { holder.playSongs?.setOnClickListener {
album.songs?.let { songs -> /*album.songs?.let { songs ->
MusicPlayerRemote.openQueue( MusicPlayerRemote.openQueue(
songs, songs,
0, 0,
true true
) )
} }*/
} }
loadAlbumCover(album, holder) loadAlbumCover(album, holder)
} }
@ -63,21 +62,32 @@ class AlbumFullWidthAdapter(
} }
private fun getAlbumText(album: Album): String? { private fun getAlbumText(album: Album): String? {
return album.artistName return album.artist
} }
private fun loadAlbumCover(album: Album, holder: FullMetalViewHolder) { private fun loadAlbumCover(album: Album, holder: FullMetalViewHolder) {
if (holder.image == null) { if (holder.image == null) {
return return
} }
SongGlideRequest.Builder.from(Glide.with(activity), album.safeGetFirstSong())
AlbumGlideRequest.Builder(Glide.with(activity), album.id)
.generatePalette(activity)
.build()
.dontAnimate()
.dontTransform()
.into(object : RetroMusicColoredTarget(holder.image!!) {
override fun onColorReady(color: Int) {
}
})
/*SongGlideRequest.Builder.from(Glide.with(activity), album.safeGetFirstSong())
.checkIgnoreMediaStore(activity) .checkIgnoreMediaStore(activity)
.generatePalette(activity) .generatePalette(activity)
.build() .build()
.into(object : RetroMusicColoredTarget(holder.image!!) { .into(object : RetroMusicColoredTarget(holder.image!!) {
override fun onColorReady(color: Int) { override fun onColorReady(color: Int) {
} }
}) })*/
} }
override fun getItemCount(): Int { override fun getItemCount(): Int {

View file

@ -1,12 +1,11 @@
package code.name.monkey.retromusic.adapter.album package code.name.monkey.retromusic.adapter.album
import android.graphics.drawable.Drawable
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import code.name.monkey.appthemehelper.util.ATHUtil import code.name.monkey.appthemehelper.util.ATHUtil
import code.name.monkey.retromusic.glide.AlbumGlideRequest
import code.name.monkey.retromusic.glide.RetroMusicColoredTarget import code.name.monkey.retromusic.glide.RetroMusicColoredTarget
import code.name.monkey.retromusic.glide.SongGlideRequest
import code.name.monkey.retromusic.helper.HorizontalAdapterHelper import code.name.monkey.retromusic.helper.HorizontalAdapterHelper
import code.name.monkey.retromusic.interfaces.CabHolder import code.name.monkey.retromusic.interfaces.CabHolder
import code.name.monkey.retromusic.model.Album import code.name.monkey.retromusic.model.Album
@ -36,7 +35,17 @@ class HorizontalAlbumAdapter(
override fun loadAlbumCover(album: Album, holder: ViewHolder) { override fun loadAlbumCover(album: Album, holder: ViewHolder) {
if (holder.image == null) return if (holder.image == null) return
SongGlideRequest.Builder.from(Glide.with(activity), album.safeGetFirstSong()) AlbumGlideRequest.Builder(Glide.with(activity), album.id)
.generatePalette(activity)
.build()
.dontAnimate()
.dontTransform()
.into(object : RetroMusicColoredTarget(holder.image!!) {
override fun onColorReady(color: Int) {
//setColors(color, holder)
}
})
/*SongGlideRequest.Builder.from(Glide.with(activity), album.safeGetFirstSong())
.checkIgnoreMediaStore(activity).generatePalette(activity).build() .checkIgnoreMediaStore(activity).generatePalette(activity).build()
.into(object : RetroMusicColoredTarget(holder.image!!) { .into(object : RetroMusicColoredTarget(holder.image!!) {
override fun onLoadCleared(placeholder: Drawable?) { override fun onLoadCleared(placeholder: Drawable?) {
@ -48,7 +57,7 @@ class HorizontalAlbumAdapter(
if (usePalette) setColors(color, holder) if (usePalette) setColors(color, holder)
else setColors(albumArtistFooterColor, holder) else setColors(albumArtistFooterColor, holder)
} }
}) })*/
} }
override fun getAlbumText(album: Album): String? { override fun getAlbumText(album: Album): String? {

View file

@ -121,7 +121,7 @@ class ArtistAdapter(
private fun getSongList(artists: List<Artist>): ArrayList<Song> { private fun getSongList(artists: List<Artist>): ArrayList<Song> {
val songs = ArrayList<Song>() val songs = ArrayList<Song>()
for (artist in artists) { for (artist in artists) {
songs.addAll(artist.songs) // maybe async in future? //songs.addAll(artist.songs) // maybe async in future?
} }
return songs return songs
} }

View file

@ -63,7 +63,7 @@ open class PlaylistSongAdapter(
imageContainerCard ?: image, imageContainerCard ?: image,
"${activity.getString(R.string.transition_album_art)}_${song.albumId}" "${activity.getString(R.string.transition_album_art)}_${song.albumId}"
) )
NavigationUtil.goToAlbumOptions(activity, song.albumId, activityOptions) NavigationUtil.goToAlbumOptions(activity, song.albumId.toLong(), activityOptions)
return true return true
} }
return super.onSongMenuItemClick(item) return super.onSongMenuItemClick(item)

View file

@ -177,7 +177,7 @@ open class SongAdapter(
imageContainerCard ?: image, imageContainerCard ?: image,
"${activity.getString(R.string.transition_album_art)}_${song.albumId}" "${activity.getString(R.string.transition_album_art)}_${song.albumId}"
) )
NavigationUtil.goToAlbumOptions(activity, song.albumId, activityOptions) NavigationUtil.goToAlbumOptions(activity, song.albumId.toLong(), activityOptions)
return true return true
} }
} }

View file

@ -0,0 +1,47 @@
/*
* Copyright (c) 2020 Hemanth Savarala.
*
* Licensed under the GNU General Public License v3
*
* This is free software: you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by
* the Free Software Foundation either version 3 of the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*/
package code.name.monkey.retromusic.extensions
import android.database.Cursor
/**
* Created by hemanths on 2020-02-05.
*/
fun Cursor?.forEach(
closeAfter: Boolean = false,
each: Cursor.() -> Unit
) {
if (this == null) return
if (moveToFirst()) {
do {
each(this)
} while (moveToNext())
}
if (closeAfter) {
close()
}
}
fun <T> Cursor?.mapList(
closeAfter: Boolean = false,
mapper: Cursor.() -> T
): MutableList<T> {
val result = mutableListOf<T>()
forEach(closeAfter = closeAfter) {
result.add(mapper(this))
}
return result
}

View file

@ -111,7 +111,7 @@ abstract class AbsPlayerFragment : AbsMusicServiceFragment(),
return true return true
} }
R.id.action_go_to_artist -> { R.id.action_go_to_artist -> {
NavigationUtil.goToArtist(requireActivity(), song.artistId) NavigationUtil.goToArtist(requireActivity(), song.artistId.toInt())
return true return true
} }
R.id.now_playing -> { R.id.now_playing -> {

View file

@ -41,7 +41,7 @@ open class AlbumsFragment : AbsLibraryPagerRecyclerViewCustomGridSizeFragment<Al
albumsPresenter.detachView() albumsPresenter.detachView()
} }
override fun albums(albums: java.util.ArrayList<Album>) { override fun albums(albums: List<Album>) {
adapter?.swapDataSet(albums) adapter?.swapDataSet(albums)
} }

View file

@ -0,0 +1,74 @@
/*
* Copyright (c) 2020 Hemanth Savarala.
*
* Licensed under the GNU General Public License v3
*
* This is free software: you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by
* the Free Software Foundation either version 3 of the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*/
package code.name.monkey.retromusic.glide
import android.R.anim
import android.content.Context
import code.name.monkey.retromusic.R.drawable
import code.name.monkey.retromusic.glide.palette.BitmapPaletteTranscoder
import code.name.monkey.retromusic.glide.palette.BitmapPaletteWrapper
import code.name.monkey.retromusic.util.MusicUtil
import com.bumptech.glide.BitmapRequestBuilder
import com.bumptech.glide.DrawableTypeRequest
import com.bumptech.glide.RequestManager
import com.bumptech.glide.load.Key
import com.bumptech.glide.load.engine.DiskCacheStrategy.NONE
import com.bumptech.glide.signature.MediaStoreSignature
/**
* Created by hemanths on 2020-02-05.
*/
class AlbumGlideRequest {
companion object {
private val DEFAULT_DISK_CACHE_STRATEGY = NONE
private const val DEFAULT_ERROR_IMAGE = drawable.default_album_art
private const val DEFAULT_ANIMATION = anim.fade_in
private fun createBaseRequest(
requestManager: RequestManager,
albumId: Long
): DrawableTypeRequest<*> =
requestManager.loadFromMediaStore(MusicUtil.getMediaStoreAlbumCoverUri(albumId))
private fun createSignature(albumId: Long): Key? {
return MediaStoreSignature("", albumId, 0)
}
}
class Builder(val requestManager: RequestManager, val albumId: Long) {
fun from(requestManager: RequestManager, albumId: Long): Builder {
return Builder(requestManager, albumId)
}
fun generatePalette(context: Context): PaletteBuilder {
return PaletteBuilder(this, context)
}
}
class PaletteBuilder(private val builder: Builder, private val context: Context) {
fun build(): BitmapRequestBuilder<out Any, BitmapPaletteWrapper> =
createBaseRequest(builder.requestManager, builder.albumId)
.asBitmap()
.transcode(BitmapPaletteTranscoder(context), BitmapPaletteWrapper::class.java)
.diskCacheStrategy(DEFAULT_DISK_CACHE_STRATEGY)
.error(DEFAULT_ERROR_IMAGE)
.animate(DEFAULT_ANIMATION)
.signature(createSignature(builder.albumId))
}
}

View file

@ -91,7 +91,7 @@ object SongMenuHelper {
return true return true
} }
R.id.action_go_to_artist -> { R.id.action_go_to_artist -> {
NavigationUtil.goToArtist(activity, song.artistId) NavigationUtil.goToArtist(activity, song.artistId.toInt())
return true return true
} }
} }

View file

@ -15,13 +15,16 @@
package code.name.monkey.retromusic.loaders package code.name.monkey.retromusic.loaders
import android.content.Context import android.content.Context
import android.provider.MediaStore.Audio.AudioColumns import android.database.Cursor
import android.provider.BaseColumns
import android.provider.MediaStore
import code.name.monkey.appthemehelper.util.VersionUtils
import code.name.monkey.retromusic.Constants.baseProjection
import code.name.monkey.retromusic.extensions.mapList
import code.name.monkey.retromusic.helper.SortOrder
import code.name.monkey.retromusic.model.Album import code.name.monkey.retromusic.model.Album
import code.name.monkey.retromusic.model.Song import code.name.monkey.retromusic.model.Song
import code.name.monkey.retromusic.util.PreferenceUtil import android.provider.MediaStore.Audio.Media.EXTERNAL_CONTENT_URI as SONGS_URI
import java.util.*
import kotlin.collections.ArrayList
/** /**
* Created by hemanths on 11/08/17. * Created by hemanths on 11/08/17.
@ -29,75 +32,88 @@ import kotlin.collections.ArrayList
object AlbumLoader { object AlbumLoader {
fun getAlbums( fun getAllAlbums(context: Context): List<Album> {
context: Context, return makeAlbumsCursor(context, null, null)
query: String .mapList(true) {
): ArrayList<Album> { Album.fromCursor(this)
val songs = SongLoader.getSongs(SongLoader.makeSongCursor( }
context, }
AudioColumns.ALBUM + " LIKE ?",
arrayOf("%$query%"), fun getSongsForAlbum(context: Context, albumId: Long): ArrayList<Song> {
getSongLoaderSortOrder(context)) return SongLoader.getSongs(makeAlbumSongCursor(context, albumId))
}
fun getAlbum(context: Context, id: Long): Album {
return getAlbum(makeAlbumsCursor(context, "_id=?", arrayOf(id.toString())))
}
fun getAlbumsForArtist(context: Context, artistId: Long): List<Album> {
return makeAlbumForArtistCursor(context, artistId).mapList(true) {
Album.fromCursor(this, artistId)
}
}
private fun makeAlbumForArtistCursor(context: Context, artistId: Long): Cursor? {
if (artistId == -1L) {
return null
}
return context.contentResolver.query(
MediaStore.Audio.Artists.Albums.getContentUri("external", artistId),
arrayOf(
if (VersionUtils.hasQ()) MediaStore.Audio.Artists.Albums.ALBUM_ID else BaseColumns._ID,
MediaStore.Audio.Artists.Albums.ALBUM,
MediaStore.Audio.Artists.Albums.ARTIST,
MediaStore.Audio.Artists.Albums.NUMBER_OF_SONGS,
MediaStore.Audio.Artists.Albums.FIRST_YEAR
),
null,
null,
MediaStore.Audio.Albums.DEFAULT_SORT_ORDER
) )
return splitIntoAlbums(songs)
} }
fun getAlbum( private fun getAlbum(cursor: Cursor?): Album {
context: Context, return cursor?.use {
albumId: Int if (cursor.moveToFirst()) {
): Album { Album.fromCursor(cursor)
val songs = SongLoader.getSongs( } else {
SongLoader.makeSongCursor( null
context, }
AudioColumns.ALBUM_ID + "=?", } ?: Album()
arrayOf(albumId.toString()),
getSongLoaderSortOrder(context)))
val album = Album(songs)
sortSongsByTrackNumber(album)
return album
} }
fun getAllAlbums( private fun getAlbums(cursor: Cursor?): ArrayList<Album> {
context: Context
): ArrayList<Album> {
val songs = SongLoader.getSongs(SongLoader.makeSongCursor(context, null, null, getSongLoaderSortOrder(context)))
return splitIntoAlbums(songs)
}
fun splitIntoAlbums(
songs: ArrayList<Song>?
): ArrayList<Album> {
val albums = ArrayList<Album>() val albums = ArrayList<Album>()
if (songs != null) { if (cursor != null && cursor.moveToFirst()) {
for (song in songs) { do {
getOrCreateAlbum(albums, song.albumId).songs?.add(song) albums.add(getAlbumFromCursorImpl(cursor))
} } while (cursor.moveToNext())
}
for (album in albums) {
sortSongsByTrackNumber(album)
} }
return albums return albums
} }
private fun getOrCreateAlbum( private fun getAlbumFromCursorImpl(cursor: Cursor): Album {
albums: ArrayList<Album>, return Album.fromCursor(cursor)
albumId: Int
): Album {
for (album in albums) {
if (album.songs!!.isNotEmpty() && album.songs[0].albumId == albumId) {
return album
}
}
val album = Album()
albums.add(album)
return album
} }
private fun sortSongsByTrackNumber(album: Album) { private fun makeAlbumsCursor(context: Context, selection: String?, paramArrayOfString: Array<String>?): Cursor? {
album.songs?.sortWith(Comparator { o1, o2 -> o1.trackNumber.compareTo(o2.trackNumber) }) return context.contentResolver.query(
MediaStore.Audio.Albums.EXTERNAL_CONTENT_URI,
arrayOf("_id", "album", "artist", "artist_id", "numsongs", "minyear"),
selection,
paramArrayOfString,
SortOrder.AlbumSortOrder.ALBUM_A_Z
)
} }
private fun getSongLoaderSortOrder(context: Context): String { private fun makeAlbumSongCursor(context: Context, albumID: Long): Cursor? {
return PreferenceUtil.getInstance(context).albumSortOrder + ", " + PreferenceUtil.getInstance(context).albumSongSortOrder val selection = "is_music=1 AND title != '' AND album_id=$albumID"
return context.contentResolver.query(
SONGS_URI,
baseProjection,
selection,
null,
SortOrder.SongSortOrder.SONG_A_Z
)
} }
} }

View file

@ -15,14 +15,16 @@
package code.name.monkey.retromusic.loaders package code.name.monkey.retromusic.loaders
import android.content.Context import android.content.Context
import android.provider.MediaStore.Audio.AudioColumns import android.database.Cursor
import code.name.monkey.retromusic.model.Album import android.provider.MediaStore
import code.name.monkey.retromusic.Constants.baseProjection
import code.name.monkey.retromusic.extensions.mapList
import code.name.monkey.retromusic.helper.SortOrder
import code.name.monkey.retromusic.model.Artist import code.name.monkey.retromusic.model.Artist
import code.name.monkey.retromusic.util.PreferenceUtil import code.name.monkey.retromusic.model.Song
object ArtistLoader { object ArtistLoader {
private fun getSongLoaderSortOrder(context: Context): String { /*private fun getSongLoaderSortOrder(context: Context): String {
return PreferenceUtil.getInstance(context).artistSortOrder + ", " + PreferenceUtil.getInstance(context).artistAlbumSortOrder + ", " + PreferenceUtil.getInstance(context).albumSongSortOrder return PreferenceUtil.getInstance(context).artistSortOrder + ", " + PreferenceUtil.getInstance(context).artistAlbumSortOrder + ", " + PreferenceUtil.getInstance(context).albumSongSortOrder
} }
@ -32,7 +34,7 @@ object ArtistLoader {
null, null, null, null,
getSongLoaderSortOrder(context)) getSongLoaderSortOrder(context))
) )
return splitIntoArtists(AlbumLoader.splitIntoAlbums(songs)) return splitIntoArtists(null)
} }
fun getArtists(context: Context, query: String): ArrayList<Artist> { fun getArtists(context: Context, query: String): ArrayList<Artist> {
@ -42,7 +44,7 @@ object ArtistLoader {
arrayOf("%$query%"), arrayOf("%$query%"),
getSongLoaderSortOrder(context)) getSongLoaderSortOrder(context))
) )
return splitIntoArtists(AlbumLoader.splitIntoAlbums(songs)) return splitIntoArtists(null)
} }
fun splitIntoArtists(albums: ArrayList<Album>?): ArrayList<Artist> { fun splitIntoArtists(albums: ArrayList<Album>?): ArrayList<Artist> {
@ -57,9 +59,9 @@ object ArtistLoader {
private fun getOrCreateArtist(artists: ArrayList<Artist>, artistId: Int): Artist { private fun getOrCreateArtist(artists: ArrayList<Artist>, artistId: Int): Artist {
for (artist in artists) { for (artist in artists) {
if (artist.albums!!.isNotEmpty() && artist.albums[0].songs!!.isNotEmpty() && artist.albums[0].songs!![0].artistId == artistId) { *//*if (artist.albums!!.isNotEmpty() && artist.albums[0].songs!!.isNotEmpty() && artist.albums[0].songs!![0].artistId == artistId) {
return artist return artist
} }*//*
} }
val album = Artist() val album = Artist()
artists.add(album) artists.add(album)
@ -73,6 +75,66 @@ object ArtistLoader {
arrayOf(artistId.toString()), arrayOf(artistId.toString()),
getSongLoaderSortOrder(context)) getSongLoaderSortOrder(context))
) )
return Artist(AlbumLoader.splitIntoAlbums(songs)) return Artist(ArrayList())
}*/
fun getAllArtists(context: Context): ArrayList<Artist> {
return getArtists(makeArtistCursor(context, null, null))
}
fun getArtist(context: Context, artistId: Long): Artist {
return getArtist(makeArtistCursor(context, "_id=?", arrayOf(artistId.toString())))
}
private fun getArtist(cursor: Cursor?): Artist {
return cursor?.use {
if (cursor.moveToFirst()) {
Artist.fromCursor(cursor)
} else {
null
}
} ?: Artist()
}
private fun getArtists(cursor: Cursor?): ArrayList<Artist> {
val artists = ArrayList<Artist>()
if (cursor != null && cursor.moveToFirst()) {
do {
artists.add(getArtistFromCursor(cursor))
} while (cursor.moveToNext())
}
return artists
}
private fun getArtistFromCursor(cursor: Cursor): Artist {
return Artist.fromCursor(cursor)
}
private fun makeArtistCursor(context: Context, selection: String?, paramArrayOfString: Array<String>?): Cursor? {
return context.contentResolver.query(
MediaStore.Audio.Artists.EXTERNAL_CONTENT_URI,
arrayOf("_id", "artist", "number_of_albums", "number_of_tracks"),
selection,
paramArrayOfString,
SortOrder.ArtistSortOrder.ARTIST_A_Z
)
}
fun getSongsForArtist(context: Context, artistId: Long): List<Any> {
return makeArtistSongCursor(context, artistId)
.mapList(true) { Song.fromCursor(this, artistId = artistId) }
}
private fun makeArtistSongCursor(context: Context, artistId: Long): Cursor? {
val artistSongSortOrder = MediaStore.Audio.Media.DEFAULT_SORT_ORDER
val uri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI
val selection = "is_music=1 AND title != '' AND artist_id=$artistId"
return context.contentResolver.query(
uri,
baseProjection,
selection,
null,
artistSongSortOrder
)
} }
} }

View file

@ -43,10 +43,10 @@ object LastAddedSongsLoader {
} }
fun getLastAddedAlbums(context: Context): ArrayList<Album> { fun getLastAddedAlbums(context: Context): ArrayList<Album> {
return AlbumLoader.splitIntoAlbums(getLastAddedSongs(context)) return ArrayList()
} }
fun getLastAddedArtists(context: Context): ArrayList<Artist> { fun getLastAddedArtists(context: Context): ArrayList<Artist> {
return ArtistLoader.splitIntoArtists(getLastAddedAlbums(context)) return ArrayList()
} }
} }

View file

@ -16,6 +16,8 @@ package code.name.monkey.retromusic.loaders
import android.content.Context import android.content.Context
import code.name.monkey.retromusic.R import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.model.Album
import code.name.monkey.retromusic.model.Artist
import code.name.monkey.retromusic.model.Genre import code.name.monkey.retromusic.model.Genre
import java.util.Locale import java.util.Locale
@ -29,13 +31,13 @@ object SearchLoader {
results.addAll(songs) results.addAll(songs)
} }
val artists = ArtistLoader.getArtists(context, searchString) val artists = emptyArray<Artist>()//ArtistLoader.getArtists(context, searchString)
if (artists.isNotEmpty()) { if (artists.isNotEmpty()) {
results.add(context.resources.getString(R.string.artists)) results.add(context.resources.getString(R.string.artists))
results.addAll(artists) results.addAll(artists)
} }
val albums = AlbumLoader.getAlbums(context, searchString) val albums = emptyArray<Album>()//AlbumLoader.getAlbums(context, searchString)
if (albums.isNotEmpty()) { if (albums.isNotEmpty()) {
results.add(context.resources.getString(R.string.albums)) results.add(context.resources.getString(R.string.albums))
results.addAll(albums) results.addAll(albums)

View file

@ -83,7 +83,7 @@ object SongLoader {
private fun getSongFromCursorImpl( private fun getSongFromCursorImpl(
cursor: Cursor cursor: Cursor
): Song { ): Song {
val id = cursor.getInt(0) val id = cursor.getLong(0)
val title = cursor.getString(1) val title = cursor.getString(1)
val trackNumber = cursor.getInt(2) val trackNumber = cursor.getInt(2)
val year = cursor.getInt(3) val year = cursor.getInt(3)
@ -92,7 +92,7 @@ object SongLoader {
val dateModified = cursor.getLong(6) val dateModified = cursor.getLong(6)
val albumId = cursor.getInt(7) val albumId = cursor.getInt(7)
val albumName = cursor.getString(8) val albumName = cursor.getString(8)
val artistId = cursor.getInt(9) val artistId = cursor.getLong(9)
val artistName = cursor.getString(10) val artistName = cursor.getString(10)
val composer = cursor.getString(11) val composer = cursor.getString(11)

View file

@ -139,10 +139,10 @@ object TopAndRecentlyPlayedTracksLoader {
context: Context context: Context
): ArrayList<Album> { ): ArrayList<Album> {
arrayListOf<Album>() arrayListOf<Album>()
return AlbumLoader.splitIntoAlbums(getTopTracks(context)) return ArrayList()//AlbumLoader.splitIntoAlbums(getTopTracks(context))
} }
fun getTopArtists(context: Context): ArrayList<Artist> { fun getTopArtists(context: Context): ArrayList<Artist> {
return ArtistLoader.splitIntoArtists(getTopAlbums(context)) return ArrayList()//ArtistLoader.splitIntoArtists(getTopAlbums(context))
} }
} }

View file

@ -1,50 +0,0 @@
/*
* Copyright (c) 2019 Hemanth Savarala.
*
* Licensed under the GNU General Public License v3
*
* This is free software: you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by
* the Free Software Foundation either version 3 of the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*/
package code.name.monkey.retromusic.misc
import android.content.Context
import android.text.TextUtils
import code.name.monkey.retromusic.R
import code.name.monkey.retromusic.loaders.AlbumLoader
import code.name.monkey.retromusic.loaders.ArtistLoader
import code.name.monkey.retromusic.loaders.SongLoader
import java.util.*
internal class AsyncSearchResultLoader(context: Context, private val query: String) : WrappedAsyncTaskLoader<List<Any>>(context) {
override fun loadInBackground(): List<Any>? {
val results = ArrayList<Any>()
if (!TextUtils.isEmpty(query)) {
val songs = SongLoader.getSongs(context, query.trim { it <= ' ' })
if (!songs.isEmpty()) {
results.add(context.resources.getString(R.string.songs))
results.addAll(songs)
}
val artists = ArtistLoader.getArtists(context, query.trim { it <= ' ' })
if (!artists.isEmpty()) {
results.add(context.resources.getString(R.string.artists))
results.addAll(artists)
}
val albums = AlbumLoader.getAlbums(context, query.trim { it <= ' ' })
if (!albums.isEmpty()) {
results.add(context.resources.getString(R.string.albums))
results.addAll(albums)
}
}
return results
}
}

View file

@ -14,41 +14,69 @@
package code.name.monkey.retromusic.model package code.name.monkey.retromusic.model
import java.util.ArrayList import android.database.Cursor
import android.provider.MediaStore.Audio.Albums.ALBUM
import android.provider.MediaStore.Audio.Albums.ARTIST
import android.provider.MediaStore.Audio.Albums.FIRST_YEAR
import android.provider.MediaStore.Audio.Albums.NUMBER_OF_SONGS
import android.provider.MediaStore.Audio.Albums._ID
import android.provider.MediaStore.Audio.Artists.Albums.ALBUM_ID
import code.name.monkey.appthemehelper.util.VersionUtils
class Album { data class Album(
val songs: ArrayList<Song>? var id: Long = 0,
var title: String = "",
var artist: String = "",
var artistId: Long = 0,
var songCount: Int = 0,
var year: Int = 0
) {
val id: Int companion object {
get() = safeGetFirstSong().albumId fun fromCursor(cursor: Cursor, artistId: Long = -1): Album {
return Album(
val title: String? id = cursor.value(if (VersionUtils.hasQ()) ALBUM_ID else _ID),
get() = safeGetFirstSong().albumName title = cursor.valueOrEmpty(ALBUM),
artist = cursor.valueOrEmpty(ARTIST),
val artistId: Int artistId = artistId,
get() = safeGetFirstSong().artistId songCount = cursor.value(NUMBER_OF_SONGS),
year = cursor.value(FIRST_YEAR)
val artistName: String? )
get() = safeGetFirstSong().artistName
val year: Int
get() = safeGetFirstSong().year
val dateModified: Long
get() = safeGetFirstSong().dateModified
val songCount: Int
get() = songs!!.size
constructor(songs: ArrayList<Song>) {
this.songs = songs
} }
}
constructor() { }
this.songs = ArrayList()
} fun Cursor.valueOrEmpty(name: String): String = valueOrDefault(name, "")
fun safeGetFirstSong(): Song { inline fun <reified T> Cursor.value(name: String): T {
return if (songs!!.isEmpty()) Song.emptySong else songs[0] val index = getColumnIndexOrThrow(name)
return when (T::class) {
Short::class -> getShort(index) as T
Int::class -> getInt(index) as T
Long::class -> getLong(index) as T
Boolean::class -> (getInt(index) == 1) as T
String::class -> getString(index) as T
Float::class -> getFloat(index) as T
Double::class -> getDouble(index) as T
ByteArray::class -> getBlob(index) as T
else -> throw IllegalStateException("What do I do with ${T::class.java.simpleName}?")
}
}
inline fun <reified T> Cursor.valueOrDefault(name: String, defaultValue: T): T {
val index = getColumnIndex(name)
if (index == -1) {
return defaultValue
}
return when (T::class) {
Short::class -> getShort(index) as? T ?: defaultValue
Int::class -> getInt(index) as? T ?: defaultValue
Long::class -> getLong(index) as? T ?: defaultValue
Boolean::class -> (getInt(index) == 1) as T
String::class -> getString(index) as? T ?: defaultValue
Float::class -> getFloat(index) as? T ?: defaultValue
Double::class -> getDouble(index) as? T ?: defaultValue
ByteArray::class -> getBlob(index) as? T ?: defaultValue
else -> throw IllegalStateException("What do I do with ${T::class.java.simpleName}?")
} }
} }

View file

@ -14,18 +14,27 @@
package code.name.monkey.retromusic.model package code.name.monkey.retromusic.model
import code.name.monkey.retromusic.util.MusicUtil import android.database.Cursor
import java.util.ArrayList import android.provider.MediaStore.Audio.Artists.ARTIST
import android.provider.MediaStore.Audio.Artists.NUMBER_OF_ALBUMS
import android.provider.MediaStore.Audio.Artists.NUMBER_OF_TRACKS
import android.provider.MediaStore.Audio.Artists._ID
class Artist { class Artist(
val albums: ArrayList<Album>? var id: Long = 0,
var name: String = "",
var songCount: Int = 0,
var albumCount: Int = 0
) {
/*val albums: ArrayList<Album>?
val id: Int val id: Int
get() = safeGetFirstAlbum().artistId get() = safeGetFirstAlbum().artistId
val name: String val name: String
get() { get() {
val name = safeGetFirstAlbum().artistName val name = safeGetFirstAlbum().artist
return if (MusicUtil.isArtistNameUnknown(name)) { return if (MusicUtil.isArtistNameUnknown(name)) {
UNKNOWN_ARTIST_DISPLAY_NAME UNKNOWN_ARTIST_DISPLAY_NAME
} else name!! } else name!!
@ -47,7 +56,7 @@ class Artist {
get() { get() {
val songs = ArrayList<Song>() val songs = ArrayList<Song>()
for (album in albums!!) { for (album in albums!!) {
songs.addAll(album.songs!!) //songs.addAll(album.songs!!)
} }
return songs return songs
} }
@ -63,8 +72,18 @@ class Artist {
fun safeGetFirstAlbum(): Album { fun safeGetFirstAlbum(): Album {
return if (albums!!.isEmpty()) Album() else albums[0] return if (albums!!.isEmpty()) Album() else albums[0]
} }
*/
companion object { companion object {
fun fromCursor(cursor: Cursor): Artist {
return Artist(
id = cursor.value(_ID),
name = cursor.value(ARTIST),
songCount = cursor.value(NUMBER_OF_TRACKS),
albumCount = cursor.value(NUMBER_OF_ALBUMS)
)
}
const val UNKNOWN_ARTIST_DISPLAY_NAME = "Unknown Artist" const val UNKNOWN_ARTIST_DISPLAY_NAME = "Unknown Artist"
} }
} }

View file

@ -13,12 +13,14 @@
*/ */
package code.name.monkey.retromusic.model package code.name.monkey.retromusic.model
import android.database.Cursor
import android.os.Parcelable import android.os.Parcelable
import android.provider.MediaStore.Audio.Media
import kotlinx.android.parcel.Parcelize import kotlinx.android.parcel.Parcelize
@Parcelize @Parcelize
open class Song( open class Song(
val id: Int, val id: Long,
val title: String, val title: String,
val trackNumber: Int, val trackNumber: Int,
val year: Int, val year: Int,
@ -27,7 +29,7 @@ open class Song(
val dateModified: Long, val dateModified: Long,
val albumId: Int, val albumId: Int,
val albumName: String, val albumName: String,
val artistId: Int, val artistId: Long,
val artistName: String, val artistName: String,
val composer: String? val composer: String?
) : Parcelable { ) : Parcelable {
@ -49,5 +51,22 @@ open class Song(
"", "",
"" ""
) )
fun fromCursor(cursor: Cursor, artistId: Long): Any {
return Song(
id = cursor.value(Media._ID),
albumId = cursor.value(Media.ALBUM_ID),
artistId = cursor.value(Media.ARTIST_ID),
albumName = cursor.valueOrEmpty(Media.ALBUM),
artistName = cursor.valueOrEmpty(Media.ARTIST),
composer = cursor.valueOrEmpty(Media.COMPOSER),
data = cursor.valueOrEmpty(Media.DATA),
dateModified = cursor.value(Media.DATE_ADDED),
duration = cursor.value(Media.DURATION),
title = cursor.valueOrEmpty(Media.TITLE),
trackNumber = cursor.value(Media.TRACK),
year = cursor.value(Media.YEAR)
)
}
} }
} }

View file

@ -14,9 +14,12 @@
package code.name.monkey.retromusic.mvp.presenter package code.name.monkey.retromusic.mvp.presenter
import code.name.monkey.retromusic.App
import code.name.monkey.retromusic.Result.Success import code.name.monkey.retromusic.Result.Success
import code.name.monkey.retromusic.loaders.AlbumLoader
import code.name.monkey.retromusic.model.Album import code.name.monkey.retromusic.model.Album
import code.name.monkey.retromusic.model.Artist import code.name.monkey.retromusic.model.Artist
import code.name.monkey.retromusic.model.Song
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
@ -36,6 +39,8 @@ interface AlbumDetailsView {
fun album(album: Album) fun album(album: Album)
fun songs(songs: ArrayList<Song>)
fun complete() fun complete()
fun loadArtistImage(artist: Artist) fun loadArtistImage(artist: Artist)
@ -48,9 +53,12 @@ interface AlbumDetailsView {
} }
interface AlbumDetailsPresenter : Presenter<AlbumDetailsView> { interface AlbumDetailsPresenter : Presenter<AlbumDetailsView> {
fun loadAlbum(albumId: Int) fun loadAlbum(albumId: Long)
fun albumSong(albumId: Long)
fun loadMore(artistId: Long)
fun loadMore(artistId: Int)
fun aboutAlbum(artist: String, album: String) fun aboutAlbum(artist: String, album: String)
class AlbumDetailsPresenterImpl @Inject constructor( class AlbumDetailsPresenterImpl @Inject constructor(
@ -60,7 +68,7 @@ interface AlbumDetailsPresenter : Presenter<AlbumDetailsView> {
private val job = Job() private val job = Job()
private lateinit var album: Album private lateinit var album: Album
override fun loadMore(artistId: Int) { override fun loadMore(artistId: Long) {
launch { launch {
when (val result = repository.artistById(artistId)) { when (val result = repository.artistById(artistId)) {
is Success -> withContext(Dispatchers.Main) { showArtistImage(result.data) } is Success -> withContext(Dispatchers.Main) { showArtistImage(result.data) }
@ -81,12 +89,12 @@ interface AlbumDetailsPresenter : Presenter<AlbumDetailsView> {
private fun showArtistImage(artist: Artist) { private fun showArtistImage(artist: Artist) {
view?.loadArtistImage(artist) view?.loadArtistImage(artist)
artist.albums?.filter { it.id != album.id }?.let { /* artist.albums?.filter { it.id != album.id }?.let {
if (it.isNotEmpty()) view?.moreAlbums(ArrayList(it)) if (it.isNotEmpty()) view?.moreAlbums(ArrayList(it))
} }*/
} }
override fun loadAlbum(albumId: Int) { override fun loadAlbum(albumId: Long) {
launch { launch {
when (val result = repository.albumById(albumId)) { when (val result = repository.albumById(albumId)) {
is Success -> withContext(Dispatchers.Main) { is Success -> withContext(Dispatchers.Main) {
@ -98,6 +106,15 @@ interface AlbumDetailsPresenter : Presenter<AlbumDetailsView> {
} }
} }
override fun albumSong(albumId: Long) {
launch {
val songs = AlbumLoader.getSongsForAlbum(App.getContext(), albumId)
withContext(Dispatchers.Main) {
view.songs(songs)
}
}
}
override fun detachView() { override fun detachView() {
super.detachView() super.detachView()
job.cancel() job.cancel()

View file

@ -25,7 +25,6 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job import kotlinx.coroutines.Job
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext import kotlinx.coroutines.withContext
import java.util.ArrayList
import javax.inject.Inject import javax.inject.Inject
import kotlin.coroutines.CoroutineContext import kotlin.coroutines.CoroutineContext
@ -33,7 +32,8 @@ import kotlin.coroutines.CoroutineContext
* Created by hemanths on 12/08/17. * Created by hemanths on 12/08/17.
*/ */
interface AlbumsView : BaseView { interface AlbumsView : BaseView {
fun albums(albums: ArrayList<Album>)
fun albums(albums: List<Album>)
} }
interface AlbumsPresenter : Presenter<AlbumsView> { interface AlbumsPresenter : Presenter<AlbumsView> {
@ -43,6 +43,7 @@ interface AlbumsPresenter : Presenter<AlbumsView> {
class AlbumsPresenterImpl @Inject constructor( class AlbumsPresenterImpl @Inject constructor(
private val repository: Repository private val repository: Repository
) : PresenterImpl<AlbumsView>(), AlbumsPresenter, CoroutineScope { ) : PresenterImpl<AlbumsView>(), AlbumsPresenter, CoroutineScope {
private val job = Job() private val job = Job()
override val coroutineContext: CoroutineContext override val coroutineContext: CoroutineContext

View file

@ -14,8 +14,12 @@
package code.name.monkey.retromusic.mvp.presenter package code.name.monkey.retromusic.mvp.presenter
import code.name.monkey.retromusic.App
import code.name.monkey.retromusic.Result import code.name.monkey.retromusic.Result
import code.name.monkey.retromusic.loaders.AlbumLoader
import code.name.monkey.retromusic.model.Album
import code.name.monkey.retromusic.model.Artist import code.name.monkey.retromusic.model.Artist
import code.name.monkey.retromusic.model.Song
import code.name.monkey.retromusic.mvp.BaseView 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
@ -35,14 +39,24 @@ import kotlin.coroutines.CoroutineContext
*/ */
interface ArtistDetailsView : BaseView { interface ArtistDetailsView : BaseView {
fun songs(songs: ArrayList<Song>)
fun albums(albums: List<Album>)
fun artist(artist: Artist) fun artist(artist: Artist)
fun artistInfo(lastFmArtist: LastFmArtist?) fun artistInfo(lastFmArtist: LastFmArtist?)
fun complete() fun complete()
} }
interface ArtistDetailsPresenter : Presenter<ArtistDetailsView> { interface ArtistDetailsPresenter : Presenter<ArtistDetailsView> {
fun loadArtist(artistId: Int) fun loadArtist(artistId: Long)
fun loadArtistSongs(artistId: Long)
fun loadArtistAlbums(artistId: Long)
fun loadBiography( fun loadBiography(
name: String, name: String,
@ -72,7 +86,7 @@ interface ArtistDetailsPresenter : Presenter<ArtistDetailsView> {
} }
} }
override fun loadArtist(artistId: Int) { override fun loadArtist(artistId: Long) {
launch { launch {
when (val result = repository.artistById(artistId)) { when (val result = repository.artistById(artistId)) {
is Result.Success -> withContext(Dispatchers.Main) { is Result.Success -> withContext(Dispatchers.Main) {
@ -86,6 +100,24 @@ interface ArtistDetailsPresenter : Presenter<ArtistDetailsView> {
} }
} }
override fun loadArtistSongs(artistId: Long) {
launch {
val songs = AlbumLoader.getSongsForAlbum(App.getContext(), artistId)
withContext(Dispatchers.Main) {
view.songs(songs)
}
}
}
override fun loadArtistAlbums(artistId: Long) {
launch {
val albums = AlbumLoader.getAlbumsForArtist(App.getContext(), artistId)
withContext(Dispatchers.Main) {
view.albums(albums)
}
}
}
override fun detachView() { override fun detachView() {
super.detachView() super.detachView()
job.cancel() job.cancel()

View file

@ -45,7 +45,7 @@ import javax.inject.Inject
class RepositoryImpl @Inject constructor(private val context: Context) : Repository { class RepositoryImpl @Inject constructor(private val context: Context) : Repository {
override suspend fun allAlbums(): Result<ArrayList<Album>> { override suspend fun allAlbums(): Result<List<Album>> {
return try { return try {
val albums = AlbumLoader.getAllAlbums(context) val albums = AlbumLoader.getAllAlbums(context)
if (albums.isNotEmpty()) { if (albums.isNotEmpty()) {
@ -58,14 +58,10 @@ class RepositoryImpl @Inject constructor(private val context: Context) : Reposit
} }
} }
override suspend fun albumById(albumId: Int): Result<Album> { override suspend fun albumById(albumId: Long): Result<Album> {
return try { return try {
val album = AlbumLoader.getAlbum(context, albumId) val album = AlbumLoader.getAlbum(context, albumId)
if (album != null) {
Success(album) Success(album)
} else {
Error(Throwable("No album"))
}
} catch (e: Exception) { } catch (e: Exception) {
Error(e) Error(e)
} }
@ -289,7 +285,7 @@ class RepositoryImpl @Inject constructor(private val context: Context) : Reposit
errorMessage = "Error" errorMessage = "Error"
) )
override suspend fun artistById(artistId: Int): Result<Artist> { override suspend fun artistById(artistId: Long): Result<Artist> {
return try { return try {
val artist = ArtistLoader.getArtist(context, artistId) val artist = ArtistLoader.getArtist(context, artistId)
return Success(artist) return Success(artist)

View file

@ -30,9 +30,9 @@ import code.name.monkey.retromusic.rest.model.LastFmArtist
interface Repository { interface Repository {
suspend fun allAlbums(): Result<ArrayList<Album>> suspend fun allAlbums(): Result<List<Album>>
suspend fun albumById(albumId: Int): Result<Album> suspend fun albumById(albumId: Long): Result<Album>
suspend fun allSongs(): Result<ArrayList<Song>> suspend fun allSongs(): Result<ArrayList<Song>>
@ -62,5 +62,5 @@ interface Repository {
suspend fun albumInfo(artist: String, album: String): Result<LastFmAlbum> suspend fun albumInfo(artist: String, album: String): Result<LastFmAlbum>
suspend fun artistById(artistId: Int): Result<Artist> suspend fun artistById(artistId: Long): Result<Artist>
} }

View file

@ -642,7 +642,7 @@ public class MusicService extends Service implements
break; break;
case SHUFFLE_MODE_NONE: case SHUFFLE_MODE_NONE:
this.shuffleMode = shuffleMode; this.shuffleMode = shuffleMode;
int currentSongId = Objects.requireNonNull(getCurrentSong()).getId(); long currentSongId = Objects.requireNonNull(getCurrentSong()).getId();
playingQueue = new ArrayList<>(originalPlayingQueue); playingQueue = new ArrayList<>(originalPlayingQueue);
int newPosition = 0; int newPosition = 0;
if (getPlayingQueue() != null) { if (getPlayingQueue() != null) {

View file

@ -1,370 +0,0 @@
/*
* Copyright (c) 2019 Hemanth Savarala.
*
* Licensed under the GNU General Public License v3
*
* This is free software: you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by
* the Free Software Foundation either version 3 of the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
* See the GNU General Public License for more details.
*/
package code.name.monkey.retromusic.service;
import android.annotation.TargetApi;
import android.content.Context;
import android.content.Intent;
import android.media.MediaDescription;
import android.media.browse.MediaBrowser;
import android.media.session.MediaSession;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.service.media.MediaBrowserService;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.content.ContextCompat;
import java.util.ArrayList;
import java.util.List;
import code.name.monkey.retromusic.R;
import code.name.monkey.retromusic.helper.MusicPlayerRemote;
import code.name.monkey.retromusic.loaders.AlbumLoader;
import code.name.monkey.retromusic.loaders.ArtistLoader;
import code.name.monkey.retromusic.loaders.PlaylistLoader;
import code.name.monkey.retromusic.loaders.PlaylistSongsLoader;
import code.name.monkey.retromusic.loaders.SongLoader;
import code.name.monkey.retromusic.model.Album;
import code.name.monkey.retromusic.model.Artist;
import code.name.monkey.retromusic.model.Playlist;
import code.name.monkey.retromusic.model.Song;
import code.name.monkey.retromusic.util.MusicUtil;
import code.name.monkey.retromusic.util.RetroUtil;
/**
* @author Hemanth S (h4h13).
*/
@TargetApi(21)
public class WearBrowserService extends MediaBrowserService {
public static final String MEDIA_ID_ROOT = "__ROOT__";
public static final int TYPE_ARTIST = 0;
public static final int TYPE_ALBUM = 1;
public static final int TYPE_SONG = 2;
public static final int TYPE_PLAYLIST = 3;
public static final int TYPE_ARTIST_SONG_ALBUMS = 4;
public static final int TYPE_ALBUM_SONGS = 5;
public static final int TYPE_ARTIST_ALL_SONGS = 6;
public static final int TYPE_PLAYLIST_ALL_SONGS = 7;
public static WearBrowserService sInstance;
private MediaSession mSession;
private Context mContext;
private boolean mServiceStarted;
public static WearBrowserService getInstance() {
return sInstance;
}
@Override
public void onCreate() {
super.onCreate();
sInstance = this;
mContext = this;
mSession = new MediaSession(this, "WearBrowserService");
setSessionToken(mSession.getSessionToken());
mSession.setCallback(new MediaSessionCallback());
mSession.setFlags(MediaSession.FLAG_HANDLES_MEDIA_BUTTONS | MediaSession.FLAG_HANDLES_TRANSPORT_CONTROLS);
}
@Override
public int onStartCommand(Intent startIntent, int flags, int startId) {
return START_STICKY;
}
@Override
public void onDestroy() {
mServiceStarted = false;
mSession.release();
}
@Nullable
@Override
public BrowserRoot onGetRoot(@NonNull String s, int i, @Nullable Bundle bundle) {
return new BrowserRoot(MEDIA_ID_ROOT, null);
}
@Override
public void onLoadChildren(@NonNull String parentId, @NonNull Result<List<MediaBrowser.MediaItem>> result) {
result.detach();
loadChildren(parentId, result);
}
private void setSessionActive() {
if (!mServiceStarted) {
startService(new Intent(getApplicationContext(), WearBrowserService.class));
mServiceStarted = true;
}
if (!mSession.isActive()) {
mSession.setActive(true);
}
}
private void setSessionInactive() {
if (mServiceStarted) {
stopSelf();
mServiceStarted = false;
}
if (mSession.isActive()) {
mSession.setActive(false);
}
}
private void fillMediaItems(List<MediaBrowser.MediaItem> mediaItems,
String mediaId,
String title,
String subTitle,
Uri icon,
int playableOrBrowsable) {
mediaItems.add(new MediaBrowser.MediaItem(
new MediaDescription.Builder()
.setMediaId(mediaId)
.setTitle(title)
.setIconUri(icon)
.setSubtitle(subTitle)
.build(), playableOrBrowsable
));
}
private void addMediaRoots(List<MediaBrowser.MediaItem> mMediaRoot) {
mMediaRoot.add(new MediaBrowser.MediaItem(
new MediaDescription.Builder()
.setMediaId(Integer.toString(TYPE_ARTIST))
.setTitle(getString(R.string.artists))
.setIconBitmap(RetroUtil.createBitmap(ContextCompat.getDrawable(getApplicationContext(), R.drawable.default_artist_art), 1f))
.setSubtitle(getString(R.string.artists))
.build(), MediaBrowser.MediaItem.FLAG_BROWSABLE
));
mMediaRoot.add(new MediaBrowser.MediaItem(
new MediaDescription.Builder()
.setMediaId(Integer.toString(TYPE_ALBUM))
.setTitle(getString(R.string.albums))
.setIconBitmap(RetroUtil.createBitmap(ContextCompat.getDrawable(getApplicationContext(), R.drawable.default_album_art), 1f))
.setSubtitle(getString(R.string.albums))
.build(), MediaBrowser.MediaItem.FLAG_BROWSABLE
));
mMediaRoot.add(new MediaBrowser.MediaItem(
new MediaDescription.Builder()
.setMediaId(Integer.toString(TYPE_SONG))
.setTitle(getString(R.string.songs))
.setIconBitmap(RetroUtil.createBitmap(ContextCompat.getDrawable(getApplicationContext(), R.drawable.default_album_art), 1f))
.setSubtitle(getString(R.string.songs))
.build(), MediaBrowser.MediaItem.FLAG_BROWSABLE
));
mMediaRoot.add(new MediaBrowser.MediaItem(
new MediaDescription.Builder()
.setMediaId(Integer.toString(TYPE_PLAYLIST))
.setTitle(getString(R.string.playlists))
.setIconUri(Uri.parse("android.resource://code.name.monkey.retromusic/drawable/ic_queue_music_white_24dp"))
.setSubtitle(getString(R.string.playlists))
.build(), MediaBrowser.MediaItem.FLAG_BROWSABLE
));
}
private void loadChildren(final String parentId, final Result<List<MediaBrowser.MediaItem>> result) {
final List<MediaBrowser.MediaItem> mediaItems = new ArrayList<>();
new AsyncTask<Void, Void, Void>() {
@Override
protected Void doInBackground(final Void... unused) {
if (parentId.equals(MEDIA_ID_ROOT)) {
addMediaRoots(mediaItems);
} else {
switch (Integer.parseInt(Character.toString(parentId.charAt(0)))) {
case TYPE_ARTIST:
List<Artist> artistList = ArtistLoader.INSTANCE.getAllArtists(mContext) ;
for (Artist artist : artistList) {
String albumNmber = String.format("%d %s", artist.getAlbums().size(), artist.getAlbums().size() > 1 ? "Albums" : "Album");
String songCount = String.format("%d %s", artist.getSongs().size(), artist.getSongs().size() > 1 ? "Songs" : "Song");
fillMediaItems(mediaItems,
Integer.toString(TYPE_ARTIST_SONG_ALBUMS) + Long.toString(artist.getId()),
artist.getName(),
albumNmber + "" + songCount,
Uri.parse("android.resource://code.name.monkey.retromusic/drawable/default_artist_art"),
MediaBrowser.MediaItem.FLAG_BROWSABLE);
}
break;
case TYPE_ARTIST_SONG_ALBUMS:
fillMediaItems(mediaItems,
Integer.toString(TYPE_ARTIST_ALL_SONGS) + Long.parseLong(parentId.substring(1)),
"All songs",
"All songs by artist",
Uri.parse("android.resource://code.name.monkey.retromusic/drawable/default_artist_art"),
MediaBrowser.MediaItem.FLAG_BROWSABLE);
List<Album> artistAlbums = ArtistLoader.INSTANCE.getArtist(mContext, Integer.parseInt(parentId.substring(1))).getAlbums(); //ArtistAlbumLoader.getAlbumsForArtist(mContext, Long.parseLong(parentId.substring(1)));
for (Album album : artistAlbums) {
String songCount = String.format("%d %s", album.getSongs().size(), album.getSongs().size() > 1 ? "Songs" : "Song");
fillMediaItems(mediaItems,
Integer.toString(TYPE_ALBUM_SONGS) + Long.toString(album.getId()),
album.getTitle(),
songCount,
Uri.parse("android.resource://code.name.monkey.retromusic/drawable/default_artist_art"),
MediaBrowser.MediaItem.FLAG_BROWSABLE);
}
break;
case TYPE_ALBUM:
List<Album> albumList = AlbumLoader.INSTANCE.getAllAlbums(mContext);
for (Album album : albumList) {
fillMediaItems(mediaItems,
Integer.toString(TYPE_ALBUM_SONGS) + Long.toString(album.getId()),
album.getTitle(),
album.getArtistName(),
MusicUtil.getMediaStoreAlbumCoverUri(album.getId()),
MediaBrowser.MediaItem.FLAG_BROWSABLE);
}
break;
case TYPE_SONG:
List<Song> songList = SongLoader.INSTANCE.getAllSongs(mContext);
for (Song song : songList) {
fillMediaItems(mediaItems,
String.valueOf(song.getId()),
song.getTitle(),
song.getAlbumName(),
Uri.parse("android.resource://code.name.monkey.retromusic/drawable/default_album_art"),
MediaBrowser.MediaItem.FLAG_PLAYABLE);
}
break;
case TYPE_ALBUM_SONGS:
List<Song> albumSongList = AlbumLoader.INSTANCE.getAlbum(mContext, Integer.parseInt(parentId.substring(1))).getSongs();
for (Song song : albumSongList) {
fillMediaItems(mediaItems,
String.valueOf(song.getId()),
song.getTitle(),
song.getAlbumName(),
Uri.parse("android.resource://code.name.monkey.retromusic/drawable/default_album_art"),
MediaBrowser.MediaItem.FLAG_PLAYABLE);
}
break;
case TYPE_ARTIST_ALL_SONGS:
List<Song> artistSongs = ArtistLoader.INSTANCE.getArtist(mContext, Integer.parseInt(parentId.substring(1))).getSongs();
for (Song song : artistSongs) {
fillMediaItems(mediaItems,
String.valueOf(song.getId()),
song.getTitle(),
song.getAlbumName(),
Uri.parse("android.resource://code.name.monkey.retromusic/drawable/default_album_art"),
MediaBrowser.MediaItem.FLAG_PLAYABLE);
}
break;
case TYPE_PLAYLIST:
List<Playlist> playlistList = PlaylistLoader.INSTANCE.getAllPlaylists(mContext);
for (Playlist playlist : playlistList) {
int size = PlaylistSongsLoader.INSTANCE.getPlaylistSongList(mContext, playlist).size();
String songCount = String.format("%d %s", size, size > 1 ? "Songs" : "Song");
fillMediaItems(mediaItems,
Integer.toString(TYPE_PLAYLIST_ALL_SONGS) + Long.toString(playlist.id),
playlist.name,
songCount,
Uri.parse("android.resource://code.name.monkey.retromusic/drawable/ic_queue_music_white_24dp"),
MediaBrowser.MediaItem.FLAG_BROWSABLE);
}
break;
case TYPE_PLAYLIST_ALL_SONGS:
List<Song> playlistSongs = PlaylistSongsLoader.INSTANCE.getPlaylistSongList(mContext, Integer.parseInt(parentId.substring(1)));
for (Song song : playlistSongs) {
fillMediaItems(mediaItems,
String.valueOf(song.getId()),
song.getTitle(),
song.getAlbumName(),
Uri.parse("android.resource://code.name.monkey.retromusic/drawable/default_album_art"),
MediaBrowser.MediaItem.FLAG_PLAYABLE);
}
break;
}
}
return null;
}
@Override
protected void onPostExecute(Void aVoid) {
result.sendResult(mediaItems);
}
}.execute();
}
private final class MediaSessionCallback extends MediaSession.Callback {
@Override
public void onPlay() {
setSessionActive();
}
@Override
public void onSeekTo(long position) {
}
@Override
public void onPlayFromMediaId(final String mediaId, Bundle extras) {
long songId = Long.parseLong(mediaId);
setSessionActive();
ArrayList<Song> songs = new ArrayList<>();
songs.add(SongLoader.INSTANCE.getSong(mContext, Integer.parseInt(mediaId)));
MusicPlayerRemote.INSTANCE.openQueue(songs, 0, true);
}
@Override
public void onPause() {
}
@Override
public void onStop() {
setSessionInactive();
}
@Override
public void onSkipToNext() {
}
@Override
public void onSkipToPrevious() {
}
@Override
public void onFastForward() {
}
@Override
public void onRewind() {
}
@Override
public void onCustomAction(@NonNull String action, Bundle extras) {
}
}
}

View file

@ -262,7 +262,7 @@ public class MusicUtil {
} }
@NonNull @NonNull
public static Uri getMediaStoreAlbumCoverUri(int albumId) { public static Uri getMediaStoreAlbumCoverUri(long albumId) {
final Uri sArtworkUri = Uri.parse("content://media/external/audio/albumart"); final Uri sArtworkUri = Uri.parse("content://media/external/audio/albumart");
return ContentUris.withAppendedId(sArtworkUri, albumId); return ContentUris.withAppendedId(sArtworkUri, albumId);
} }
@ -322,7 +322,7 @@ public class MusicUtil {
return songCount + " " + songString; return songCount + " " + songString;
} }
public static Uri getSongFileUri(int songId) { public static Uri getSongFileUri(long songId) {
return ContentUris.withAppendedId(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, songId); return ContentUris.withAppendedId(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, songId);
} }

View file

@ -66,7 +66,7 @@ public class NavigationUtil {
} }
public static void goToAlbumOptions(@NonNull Activity activity, public static void goToAlbumOptions(@NonNull Activity activity,
int albumId, long albumId,
@NonNull ActivityOptions options) { @NonNull ActivityOptions options) {
Intent intent = new Intent(activity, AlbumDetailsActivity.class); Intent intent = new Intent(activity, AlbumDetailsActivity.class);
intent.putExtra(AlbumDetailsActivity.EXTRA_ALBUM_ID, albumId); intent.putExtra(AlbumDetailsActivity.EXTRA_ALBUM_ID, albumId);
@ -80,7 +80,7 @@ public class NavigationUtil {
} }
public static void goToArtistOptions(@NotNull Activity activity, public static void goToArtistOptions(@NotNull Activity activity,
int artistId, long artistId,
@NonNull ActivityOptions options) { @NonNull ActivityOptions options) {
Intent intent = new Intent(activity, ArtistDetailActivity.class); Intent intent = new Intent(activity, ArtistDetailActivity.class);

View file

@ -130,7 +130,7 @@ public class PlaylistsUtil {
} }
static boolean doPlaylistContains(@NonNull final Context context, final long playlistId, static boolean doPlaylistContains(@NonNull final Context context, final long playlistId,
final int songId) { final long songId) {
if (playlistId != -1) { if (playlistId != -1) {
try { try {
Cursor c = context.getContentResolver().query( Cursor c = context.getContentResolver().query(

View file

@ -42,4 +42,8 @@ object VersionUtils {
fun hasOreo(): Boolean { fun hasOreo(): Boolean {
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.O return Build.VERSION.SDK_INT >= Build.VERSION_CODES.O
} }
fun hasQ(): Boolean {
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q
}
} }