diff --git a/app/src/main/java/code/name/monkey/retromusic/activities/base/AbsCastActivity.kt b/app/src/main/java/code/name/monkey/retromusic/activities/base/AbsCastActivity.kt index 0a88ef350..e4939c49b 100644 --- a/app/src/main/java/code/name/monkey/retromusic/activities/base/AbsCastActivity.kt +++ b/app/src/main/java/code/name/monkey/retromusic/activities/base/AbsCastActivity.kt @@ -1,7 +1,6 @@ package code.name.monkey.retromusic.activities.base import android.os.Bundle -import code.name.monkey.retromusic.cast.CastHelper import code.name.monkey.retromusic.cast.RetroSessionManagerListener import code.name.monkey.retromusic.cast.RetroWebServer import code.name.monkey.retromusic.helper.MusicPlayerRemote @@ -30,20 +29,7 @@ abstract class AbsCastActivity : AbsSlidingMusicPanelActivity() { override fun onSessionStarted(castSession: CastSession, p1: String) { invalidateOptionsMenu() mCastSession = castSession - loadCastQueue() - MusicPlayerRemote.isCasting = true - setAllowDragging(false) - collapsePanel() - } - - override fun onSessionEnding(castSession: CastSession) { - MusicPlayerRemote.isCasting = false - castSession.remoteMediaClient?.let { - val position = it.mediaQueue.indexOfItemWithId(it.currentItem?.itemId ?: 0) - val progress = it.approximateStreamPosition - MusicPlayerRemote.position = position - MusicPlayerRemote.seekTo(progress.toInt()) - } + MusicPlayerRemote.switchToRemotePlayback(castSession) } override fun onSessionEnded(castSession: CastSession, p1: Int) { @@ -51,7 +37,7 @@ abstract class AbsCastActivity : AbsSlidingMusicPanelActivity() { if (mCastSession == castSession) { mCastSession = null } - setAllowDragging(true) + MusicPlayerRemote.switchToLocalPlayback() webServer.stop() } @@ -59,14 +45,7 @@ abstract class AbsCastActivity : AbsSlidingMusicPanelActivity() { invalidateOptionsMenu() mCastSession = castSession webServer.start() - mCastSession?.remoteMediaClient?.let { - loadCastQueue(it.mediaQueue.indexOfItemWithId(it.currentItem?.itemId ?: 0), - it.approximateStreamPosition) - } - - MusicPlayerRemote.isCasting = true - setAllowDragging(false) - collapsePanel() + MusicPlayerRemote.switchToRemotePlayback(castSession) } override fun onSessionSuspended(castSession: CastSession, p1: Int) { @@ -74,8 +53,7 @@ abstract class AbsCastActivity : AbsSlidingMusicPanelActivity() { if (mCastSession == castSession) { mCastSession = null } - MusicPlayerRemote.isCasting = false - setAllowDragging(true) + MusicPlayerRemote.switchToLocalPlayback() webServer.stop() } } @@ -121,27 +99,4 @@ abstract class AbsCastActivity : AbsSlidingMusicPanelActivity() { mCastSession = null } } - - fun loadCastQueue( - position: Int = MusicPlayerRemote.position, - progress: Long = MusicPlayerRemote.songProgressMillis.toLong(), - ) { - mCastSession?.let { - if (MusicPlayerRemote.playingQueue.isNotEmpty()) { - CastHelper.castQueue( - it, - MusicPlayerRemote.playingQueue, - position, - progress - ) - } - } - } - - override fun onQueueChanged() { - super.onQueueChanged() - if (playServicesAvailable) { - loadCastQueue() - } - } } \ No newline at end of file diff --git a/app/src/main/java/code/name/monkey/retromusic/activities/base/AbsSlidingMusicPanelActivity.kt b/app/src/main/java/code/name/monkey/retromusic/activities/base/AbsSlidingMusicPanelActivity.kt index ae8bab0fc..7130f3901 100644 --- a/app/src/main/java/code/name/monkey/retromusic/activities/base/AbsSlidingMusicPanelActivity.kt +++ b/app/src/main/java/code/name/monkey/retromusic/activities/base/AbsSlidingMusicPanelActivity.kt @@ -393,9 +393,7 @@ abstract class AbsSlidingMusicPanelActivity : AbsMusicServiceActivity() { animate: Boolean = false, isBottomNavVisible: Boolean = bottomNavigationView.isVisible, ) { - val heightOfBar = - windowInsets.safeGetBottomInsets() + - if (MusicPlayerRemote.isCasting) dip(R.dimen.cast_mini_player_height) else dip(R.dimen.mini_player_height) + val heightOfBar = windowInsets.safeGetBottomInsets() + dip(R.dimen.mini_player_height) val heightOfBarWithTabs = heightOfBar + dip(R.dimen.bottom_nav_height) if (hide) { bottomSheetBehavior.peekHeight = -windowInsets.safeGetBottomInsets() diff --git a/app/src/main/java/code/name/monkey/retromusic/cast/CastHelper.kt b/app/src/main/java/code/name/monkey/retromusic/cast/CastHelper.kt index 33ac06250..982d1fe18 100644 --- a/app/src/main/java/code/name/monkey/retromusic/cast/CastHelper.kt +++ b/app/src/main/java/code/name/monkey/retromusic/cast/CastHelper.kt @@ -6,12 +6,11 @@ import code.name.monkey.retromusic.cast.RetroWebServer.Companion.PART_COVER_ART import code.name.monkey.retromusic.cast.RetroWebServer.Companion.PART_SONG import code.name.monkey.retromusic.model.Song import code.name.monkey.retromusic.util.RetroUtil -import com.google.android.gms.cast.* +import com.google.android.gms.cast.MediaInfo import com.google.android.gms.cast.MediaInfo.STREAM_TYPE_BUFFERED +import com.google.android.gms.cast.MediaMetadata import com.google.android.gms.cast.MediaMetadata.* -import com.google.android.gms.cast.framework.CastSession import com.google.android.gms.common.images.WebImage -import org.json.JSONObject import java.net.MalformedURLException import java.net.URL @@ -21,39 +20,7 @@ object CastHelper { private const val CAST_MUSIC_METADATA_ALBUM_ID = "metadata_album_id" private const val CAST_URL_PROTOCOL = "http" - fun castSong(castSession: CastSession, song: Song) { - try { - val remoteMediaClient = castSession.remoteMediaClient - val mediaLoadOptions = MediaLoadOptions.Builder().apply { - setPlayPosition(0) - setAutoplay(true) - }.build() - remoteMediaClient?.load(song.toMediaInfo()!!, mediaLoadOptions) - } catch (e: Exception) { - e.printStackTrace() - } - } - - fun castQueue(castSession: CastSession, songs: List, position: Int, progress: Long) { - try { - val remoteMediaClient = castSession.remoteMediaClient - remoteMediaClient?.queueLoad( - songs.toMediaInfoList(), - if (position != -1) position else 0, - MediaStatus.REPEAT_MODE_REPEAT_OFF, - progress, - JSONObject() - ) - } catch (e: Exception) { - e.printStackTrace() - } - } - - private fun List.toMediaInfoList(): Array { - return map { MediaQueueItem.Builder(it.toMediaInfo()!!).build() }.toTypedArray() - } - - private fun Song.toMediaInfo(): MediaInfo? { + fun Song.toMediaInfo(): MediaInfo? { val song = this val baseUrl: URL try { diff --git a/app/src/main/java/code/name/monkey/retromusic/helper/MusicPlayerRemote.kt b/app/src/main/java/code/name/monkey/retromusic/helper/MusicPlayerRemote.kt index fb03f95a6..5947f294e 100644 --- a/app/src/main/java/code/name/monkey/retromusic/helper/MusicPlayerRemote.kt +++ b/app/src/main/java/code/name/monkey/retromusic/helper/MusicPlayerRemote.kt @@ -30,6 +30,7 @@ import code.name.monkey.retromusic.repository.SongRepository import code.name.monkey.retromusic.service.MusicService import code.name.monkey.retromusic.util.PreferenceUtil import code.name.monkey.retromusic.util.getExternalStorageDirectory +import com.google.android.gms.cast.framework.CastSession import org.koin.core.component.KoinComponent import org.koin.core.component.inject import java.io.File @@ -43,14 +44,6 @@ object MusicPlayerRemote : KoinComponent { private val songRepository by inject() - var isCasting: Boolean = false - set(value) { - field = value - if (value) { - musicService?.quit() - } - } - @JvmStatic val isPlaying: Boolean get() = musicService != null && musicService!!.isPlaying @@ -472,6 +465,14 @@ object MusicPlayerRemote : KoinComponent { .dropLastWhile { it.isEmpty() }.toTypedArray()[1] } + fun switchToRemotePlayback(castSession: CastSession) { + musicService?.switchToRemotePlayback(castSession) + } + + fun switchToLocalPlayback() { + musicService?.switchToLocalPlayback() + } + class ServiceBinder internal constructor(private val mCallback: ServiceConnection?) : ServiceConnection { diff --git a/app/src/main/java/code/name/monkey/retromusic/service/CastPlayer.kt b/app/src/main/java/code/name/monkey/retromusic/service/CastPlayer.kt new file mode 100644 index 000000000..ad9891a1f --- /dev/null +++ b/app/src/main/java/code/name/monkey/retromusic/service/CastPlayer.kt @@ -0,0 +1,109 @@ +package code.name.monkey.retromusic.service + +import code.name.monkey.retromusic.cast.CastHelper.toMediaInfo +import code.name.monkey.retromusic.model.Song +import code.name.monkey.retromusic.service.playback.Playback +import com.google.android.gms.cast.MediaLoadOptions +import com.google.android.gms.cast.MediaSeekOptions +import com.google.android.gms.cast.MediaStatus +import com.google.android.gms.cast.framework.CastSession +import com.google.android.gms.cast.framework.media.RemoteMediaClient + +class CastPlayer(castSession: CastSession) : Playback, + RemoteMediaClient.Callback() { + + override val isInitialized: Boolean = true + + private val remoteMediaClient: RemoteMediaClient? = castSession.remoteMediaClient + + init { + remoteMediaClient?.registerCallback(this) + } + + private var isActuallyPlaying = false + + override val isPlaying: Boolean + get() { + return remoteMediaClient?.isPlaying == true || isActuallyPlaying + } + + override val audioSessionId: Int = 0 + + private var callbacks: Playback.PlaybackCallbacks? = null + + override fun setDataSource( + song: Song, + force: Boolean, + completion: (success: Boolean) -> Unit, + ) { + try { + val mediaLoadOptions = + MediaLoadOptions.Builder().setPlayPosition(0).setAutoplay(true).build() + remoteMediaClient?.load(song.toMediaInfo()!!, mediaLoadOptions) + completion(true) + } catch (e: Exception) { + e.printStackTrace() + completion(false) + } + } + + override fun setNextDataSource(path: String?) {} + + override fun setCallbacks(callbacks: Playback.PlaybackCallbacks) { + this.callbacks = callbacks + } + + override fun start(): Boolean { + isActuallyPlaying = true + remoteMediaClient?.play() + return true + } + + override fun stop() { + isActuallyPlaying = false + remoteMediaClient?.stop() + } + + override fun release() { + stop() + } + + override fun pause(): Boolean { + isActuallyPlaying = false + remoteMediaClient?.pause() + return true + } + + override fun duration(): Int { + return remoteMediaClient?.streamDuration?.toInt() ?: 0 + } + + override fun position(): Int { + return remoteMediaClient?.approximateStreamPosition?.toInt() ?: 0 + } + + override fun seek(whereto: Int): Int { + remoteMediaClient?.seek(MediaSeekOptions.Builder().setPosition(whereto.toLong()).build()) + return whereto + } + + override fun setVolume(vol: Float) = true + + override fun setAudioSessionId(sessionId: Int) = true + + override fun setCrossFadeDuration(duration: Int) {} + + override fun onStatusUpdated() { + when (remoteMediaClient?.playerState) { + MediaStatus.PLAYER_STATE_IDLE -> { + val idleReason = remoteMediaClient.idleReason + if (idleReason == MediaStatus.IDLE_REASON_FINISHED) { + callbacks?.onTrackEnded() + } + } + MediaStatus.PLAYER_STATE_PLAYING, MediaStatus.PLAYER_STATE_PAUSED -> { + callbacks?.onPlayStateChanged() + } + } + } +} \ No newline at end of file diff --git a/app/src/main/res/layout/cast_mini_controller.xml b/app/src/main/res/layout/cast_mini_controller.xml deleted file mode 100644 index 49e7789ed..000000000 --- a/app/src/main/res/layout/cast_mini_controller.xml +++ /dev/null @@ -1,102 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/app/src/main/res/layout/sliding_music_panel_layout.xml b/app/src/main/res/layout/sliding_music_panel_layout.xml index faf3cd16e..2c1838985 100644 --- a/app/src/main/res/layout/sliding_music_panel_layout.xml +++ b/app/src/main/res/layout/sliding_music_panel_layout.xml @@ -11,8 +11,8 @@ android:name="androidx.navigation.fragment.NavHostFragment" android:layout_width="match_parent" android:layout_height="match_parent" - app:defaultNavHost="true" android:background="?attr/colorSurface" + app:defaultNavHost="true" app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior" tools:layout="@layout/fragment_home" /> @@ -39,12 +39,6 @@ android:layout_height="@dimen/mini_player_height" tools:layout="@layout/fragment_mini_player" /> - -