2021-07-12 10:14:26 +02:00
|
|
|
package audio.funkwhale.ffa.playback
|
2019-08-19 16:50:33 +02:00
|
|
|
|
|
|
|
import android.app.Notification
|
|
|
|
import android.app.PendingIntent
|
|
|
|
import android.app.Service
|
|
|
|
import android.content.Intent
|
|
|
|
import android.support.v4.media.session.MediaSessionCompat
|
2020-07-12 18:28:50 +02:00
|
|
|
import android.support.v4.media.session.PlaybackStateCompat
|
2019-08-19 16:50:33 +02:00
|
|
|
import androidx.core.app.NotificationCompat
|
|
|
|
import androidx.core.app.NotificationManagerCompat
|
|
|
|
import androidx.media.app.NotificationCompat.MediaStyle
|
2020-07-12 18:28:50 +02:00
|
|
|
import androidx.media.session.MediaButtonReceiver
|
2021-07-12 10:14:26 +02:00
|
|
|
import audio.funkwhale.ffa.R
|
|
|
|
import audio.funkwhale.ffa.activities.MainActivity
|
2021-08-22 09:48:33 +02:00
|
|
|
import audio.funkwhale.ffa.model.Track
|
2021-09-09 09:56:15 +02:00
|
|
|
import audio.funkwhale.ffa.utils.AppContext
|
2021-07-12 10:14:26 +02:00
|
|
|
import audio.funkwhale.ffa.utils.maybeNormalizeUrl
|
2019-08-19 16:50:33 +02:00
|
|
|
import com.squareup.picasso.Picasso
|
2020-06-25 01:26:15 +02:00
|
|
|
import kotlinx.coroutines.CoroutineScope
|
|
|
|
import kotlinx.coroutines.Dispatchers.Default
|
2019-08-19 16:50:33 +02:00
|
|
|
import kotlinx.coroutines.launch
|
2021-08-09 06:50:46 +02:00
|
|
|
import org.koin.java.KoinJavaComponent.inject
|
2019-08-19 16:50:33 +02:00
|
|
|
|
2020-06-25 01:26:15 +02:00
|
|
|
class MediaControlsManager(val context: Service, private val scope: CoroutineScope, private val mediaSession: MediaSessionCompat) {
|
2021-08-09 06:50:46 +02:00
|
|
|
|
2019-08-19 16:50:33 +02:00
|
|
|
companion object {
|
|
|
|
const val NOTIFICATION_ACTION_OPEN_QUEUE = 0
|
|
|
|
}
|
|
|
|
|
2021-08-09 06:50:46 +02:00
|
|
|
private val ffaMediaSession: MediaSession by inject(MediaSession::class.java)
|
|
|
|
|
2019-10-21 11:51:32 +02:00
|
|
|
private var notification: Notification? = null
|
2019-08-19 16:50:33 +02:00
|
|
|
|
|
|
|
fun updateNotification(track: Track?, playing: Boolean) {
|
|
|
|
if (notification == null && !playing) return
|
|
|
|
|
|
|
|
track?.let {
|
|
|
|
val stateIcon = when (playing) {
|
|
|
|
true -> R.drawable.pause
|
|
|
|
false -> R.drawable.play
|
|
|
|
}
|
|
|
|
|
2020-06-25 01:26:15 +02:00
|
|
|
scope.launch(Default) {
|
2019-08-19 16:50:33 +02:00
|
|
|
val openIntent = Intent(context, MainActivity::class.java).apply { action = NOTIFICATION_ACTION_OPEN_QUEUE.toString() }
|
|
|
|
val openPendingIntent = PendingIntent.getActivity(context, 0, openIntent, 0)
|
|
|
|
|
2020-08-08 14:51:39 +02:00
|
|
|
val coverUrl = maybeNormalizeUrl(track.album?.cover())
|
2019-08-19 16:50:33 +02:00
|
|
|
|
|
|
|
notification = NotificationCompat.Builder(
|
|
|
|
context,
|
|
|
|
AppContext.NOTIFICATION_CHANNEL_MEDIA_CONTROL
|
|
|
|
)
|
|
|
|
.setShowWhen(false)
|
2020-06-01 17:29:15 +02:00
|
|
|
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
|
2019-08-19 16:50:33 +02:00
|
|
|
.setStyle(
|
|
|
|
MediaStyle()
|
|
|
|
.setMediaSession(mediaSession.sessionToken)
|
|
|
|
.setShowActionsInCompactView(0, 1, 2)
|
|
|
|
)
|
2021-07-01 13:11:11 +02:00
|
|
|
.setSmallIcon(R.drawable.funkwhaleshape)
|
2019-10-22 21:56:33 +02:00
|
|
|
.run {
|
2020-07-08 12:46:52 +02:00
|
|
|
coverUrl?.let {
|
2020-07-09 23:01:35 +02:00
|
|
|
try {
|
|
|
|
setLargeIcon(Picasso.get().load(coverUrl).get())
|
|
|
|
} catch (_: Exception) {
|
|
|
|
}
|
2020-07-08 12:46:52 +02:00
|
|
|
|
|
|
|
return@run this
|
|
|
|
}
|
2020-06-10 10:51:23 +02:00
|
|
|
|
2020-07-08 12:46:52 +02:00
|
|
|
this
|
2019-10-22 21:56:33 +02:00
|
|
|
}
|
2019-08-19 16:50:33 +02:00
|
|
|
.setContentTitle(track.title)
|
|
|
|
.setContentText(track.artist.name)
|
|
|
|
.setContentIntent(openPendingIntent)
|
|
|
|
.setChannelId(AppContext.NOTIFICATION_CHANNEL_MEDIA_CONTROL)
|
|
|
|
.addAction(
|
|
|
|
action(
|
|
|
|
R.drawable.previous, context.getString(R.string.control_previous),
|
2020-07-12 18:28:50 +02:00
|
|
|
PlaybackStateCompat.ACTION_SKIP_TO_PREVIOUS
|
2019-08-19 16:50:33 +02:00
|
|
|
)
|
|
|
|
)
|
|
|
|
.addAction(
|
|
|
|
action(
|
|
|
|
stateIcon, context.getString(R.string.control_toggle),
|
2020-07-12 18:28:50 +02:00
|
|
|
PlaybackStateCompat.ACTION_PLAY_PAUSE
|
2019-08-19 16:50:33 +02:00
|
|
|
)
|
|
|
|
)
|
|
|
|
.addAction(
|
|
|
|
action(
|
|
|
|
R.drawable.next, context.getString(R.string.control_next),
|
2020-07-12 18:28:50 +02:00
|
|
|
PlaybackStateCompat.ACTION_SKIP_TO_NEXT
|
2019-08-19 16:50:33 +02:00
|
|
|
)
|
|
|
|
)
|
|
|
|
.build()
|
|
|
|
|
|
|
|
notification?.let {
|
2020-07-09 23:01:35 +02:00
|
|
|
if (playing) {
|
|
|
|
context.startForeground(AppContext.NOTIFICATION_MEDIA_CONTROL, it)
|
|
|
|
} else {
|
|
|
|
NotificationManagerCompat.from(context).notify(AppContext.NOTIFICATION_MEDIA_CONTROL, it)
|
|
|
|
}
|
2019-08-19 16:50:33 +02:00
|
|
|
}
|
2020-07-15 15:55:50 +02:00
|
|
|
|
2021-08-09 06:50:46 +02:00
|
|
|
ffaMediaSession.connector.invalidateMediaSessionMetadata()
|
2019-08-19 16:50:33 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-09-02 12:04:42 +02:00
|
|
|
fun remove() {
|
|
|
|
NotificationManagerCompat.from(context).cancel(AppContext.NOTIFICATION_MEDIA_CONTROL)
|
|
|
|
}
|
|
|
|
|
2020-07-12 18:28:50 +02:00
|
|
|
private fun action(icon: Int, title: String, id: Long): NotificationCompat.Action {
|
|
|
|
return MediaButtonReceiver.buildMediaButtonPendingIntent(context, id).run {
|
|
|
|
NotificationCompat.Action.Builder(icon, title, this).build()
|
2019-08-19 16:50:33 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|