package audio.funkwhale.ffa.playback import android.app.Notification import android.app.PendingIntent import android.app.PendingIntent.FLAG_IMMUTABLE import android.app.Service import android.content.Intent import android.support.v4.media.session.MediaSessionCompat import android.support.v4.media.session.PlaybackStateCompat import androidx.core.app.NotificationCompat import androidx.core.app.NotificationManagerCompat import androidx.media.app.NotificationCompat.MediaStyle import androidx.media.session.MediaButtonReceiver import audio.funkwhale.ffa.R import audio.funkwhale.ffa.activities.MainActivity import audio.funkwhale.ffa.model.Track import audio.funkwhale.ffa.utils.AppContext import audio.funkwhale.ffa.utils.maybeNormalizeUrl import com.squareup.picasso.Picasso import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers.Default import kotlinx.coroutines.launch import org.koin.java.KoinJavaComponent.inject class MediaControlsManager( val context: Service, private val scope: CoroutineScope, private val mediaSession: MediaSessionCompat ) { companion object { const val NOTIFICATION_ACTION_OPEN_QUEUE = 0 } private val ffaMediaSession: MediaSession by inject(MediaSession::class.java) private var notification: Notification? = null 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 } scope.launch(Default) { val openIntent = Intent(context, MainActivity::class.java).apply { action = NOTIFICATION_ACTION_OPEN_QUEUE.toString() } val openPendingIntent = PendingIntent.getActivity(context, 0, openIntent, FLAG_IMMUTABLE) val coverUrl = maybeNormalizeUrl(track.album?.cover()) notification = NotificationCompat.Builder( context, AppContext.NOTIFICATION_CHANNEL_MEDIA_CONTROL ) .setShowWhen(false) .setVisibility(NotificationCompat.VISIBILITY_PUBLIC) .setStyle( MediaStyle() .setMediaSession(mediaSession.sessionToken) .setShowActionsInCompactView(0, 1, 2) ) .setSmallIcon(R.drawable.funkwhaleshape) .run { coverUrl?.let { try { setLargeIcon(Picasso.get().load(coverUrl).get()) } catch (_: Exception) { } return@run this } this } .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), PlaybackStateCompat.ACTION_SKIP_TO_PREVIOUS ) ) .addAction( action( stateIcon, context.getString(R.string.control_toggle), PlaybackStateCompat.ACTION_PLAY_PAUSE ) ) .addAction( action( R.drawable.next, context.getString(R.string.control_next), PlaybackStateCompat.ACTION_SKIP_TO_NEXT ) ) .build() notification?.let { if (playing) { context.startForeground(AppContext.NOTIFICATION_MEDIA_CONTROL, it) } else { NotificationManagerCompat.from(context) .notify(AppContext.NOTIFICATION_MEDIA_CONTROL, it) } } ffaMediaSession.connector.invalidateMediaSessionMetadata() } } } fun remove() { NotificationManagerCompat.from(context).cancel(AppContext.NOTIFICATION_MEDIA_CONTROL) } private fun action(icon: Int, title: String, id: Long): NotificationCompat.Action { return MediaButtonReceiver.buildMediaButtonPendingIntent(context, id).run { NotificationCompat.Action.Builder(icon, title, this).build() } } }