Created
March 18, 2019 11:46
-
-
Save dimkinware/f063bb94a6ecf6c0b28df67ca364f464 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.dimkinware.mediacast | |
import android.content.Context | |
import android.database.ContentObserver | |
import android.media.AudioManager | |
import android.os.Handler | |
import android.provider.Settings | |
import android.widget.SeekBar | |
import androidx.lifecycle.Lifecycle | |
import androidx.lifecycle.LifecycleObserver | |
import androidx.lifecycle.OnLifecycleEvent | |
import com.google.android.gms.cast.Cast | |
import com.google.android.gms.cast.framework.CastContext | |
import com.google.android.gms.cast.framework.CastSession | |
import com.google.android.gms.cast.framework.Session | |
import com.google.android.gms.cast.framework.SessionManagerListener | |
import com.google.android.gms.cast.framework.SessionManager | |
interface CastSessionManagerListenerAdapter<T : Session> : SessionManagerListener<T> { | |
override fun onSessionStarted(session: T?, sessionId: String?) = Unit | |
override fun onSessionResumeFailed(session: T?, error: Int) = Unit | |
override fun onSessionSuspended(session: T?, reason: Int) = Unit | |
override fun onSessionEnded(session: T?, error: Int) = Unit | |
override fun onSessionResumed(session: T?, wasSuspended: Boolean) = Unit | |
override fun onSessionStarting(session: T?) = Unit | |
override fun onSessionResuming(session: T?, sessionId: String?) = Unit | |
override fun onSessionEnding(session: T?) = Unit | |
override fun onSessionStartFailed(session: T?, error: Int) = Unit | |
} | |
/** | |
* Base class for specific volume controller | |
*/ | |
private abstract class Volumizer(val volumeListener: OnVolumeChangedListener) { | |
interface OnVolumeChangedListener { | |
fun onVolumeChanged(currentValue: Int, maxValue: Int) | |
} | |
abstract fun start() | |
abstract fun stop() | |
abstract fun setVolume(value: Int) | |
abstract fun getVolume(): Int | |
abstract fun getMaxVolume(): Int | |
} | |
/** | |
* Volume controller for AudioManager.STREAM_MUSIC | |
*/ | |
private class MusicVolumizer(val context: Context, listener: OnVolumeChangedListener) : Volumizer(listener) { | |
private val audioManager = context.getSystemService(Context.AUDIO_SERVICE) as AudioManager | |
private val contentObserver = object : ContentObserver(Handler()) { | |
override fun onChange(selfChange: Boolean) { | |
super.onChange(selfChange) | |
volumeListener.onVolumeChanged(getVolume(), getMaxVolume()) | |
} | |
} | |
override fun start() { | |
volumeListener.onVolumeChanged(getVolume(), getMaxVolume()) | |
context.applicationContext.contentResolver.registerContentObserver(Settings.System.CONTENT_URI, true, contentObserver) | |
} | |
override fun stop() { | |
context.applicationContext.contentResolver.unregisterContentObserver(contentObserver) | |
} | |
override fun setVolume(value: Int) { | |
audioManager.setStreamVolume(AudioManager.STREAM_MUSIC, value, AudioManager.FLAG_PLAY_SOUND) | |
} | |
override fun getVolume(): Int = audioManager.getStreamVolume(AudioManager.STREAM_MUSIC) | |
override fun getMaxVolume(): Int = audioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC) | |
} | |
/** | |
* Volume controller for cast session | |
*/ | |
private class CastVolumizer(val session: CastSession, listener: OnVolumeChangedListener) : Volumizer(listener) { | |
private val VOLUME_STEP = 0.05 | |
private val VOLUME_MAX = 20 | |
private val castListener = object : Cast.Listener() { | |
override fun onVolumeChanged() { | |
volumeListener.onVolumeChanged(getVolume(), getMaxVolume()) | |
} | |
} | |
override fun start() { | |
volumeListener.onVolumeChanged(getVolume(), getMaxVolume()) | |
session.addCastListener(castListener) | |
} | |
override fun stop() { | |
session.removeCastListener(castListener) | |
} | |
override fun setVolume(value: Int) { | |
session.volume = VOLUME_STEP * value | |
} | |
override fun getVolume(): Int = (session.volume / VOLUME_STEP).toInt() | |
override fun getMaxVolume(): Int = VOLUME_MAX | |
} | |
class SeekBarCastAwareVolumizer(private val context: Context, | |
private val lifecycle: Lifecycle, | |
private val seekBar: SeekBar) : CastSessionManagerListenerAdapter<CastSession>, | |
SeekBar.OnSeekBarChangeListener, | |
Volumizer.OnVolumeChangedListener, | |
LifecycleObserver { | |
private val castSessionManager : SessionManager = CastContext.getSharedInstance(context).sessionManager | |
private var volumizer: Volumizer | |
init { | |
lifecycle.addObserver(this) | |
seekBar.isSaveEnabled = false | |
volumizer = if (castSessionManager.currentCastSession != null) { | |
CastVolumizer(castSessionManager.currentCastSession, this) | |
} else { | |
MusicVolumizer(context, this) | |
} | |
} | |
fun muteVolume() { | |
volumizer.setVolume(0) | |
} | |
fun maximizeVolume() { | |
volumizer.setVolume(volumizer.getMaxVolume()) | |
} | |
@OnLifecycleEvent(Lifecycle.Event.ON_START) | |
fun onStart() { | |
volumizer.start() | |
seekBar.setOnSeekBarChangeListener(this) | |
castSessionManager.addSessionManagerListener(this, CastSession::class.java) | |
} | |
@OnLifecycleEvent(Lifecycle.Event.ON_STOP) | |
fun onStop() { | |
volumizer.stop() | |
seekBar.setOnSeekBarChangeListener(null) | |
castSessionManager.removeSessionManagerListener(this, CastSession::class.java) | |
} | |
override fun onSessionStarted(session: CastSession?, sessionId: String?) { | |
session?.let { | |
changeVolumizerTo(CastVolumizer(session, this)) | |
} | |
} | |
override fun onSessionEnded(session: CastSession?, error: Int) { | |
changeVolumizerTo(MusicVolumizer(context, this)) | |
} | |
override fun onVolumeChanged(currentValue: Int, maxValue: Int) { | |
setupSeekBar(currentValue, maxValue) | |
} | |
private fun changeVolumizerTo(newVolumizer: Volumizer) { | |
volumizer.stop() | |
volumizer = newVolumizer | |
volumizer.start() | |
} | |
private fun setupSeekBar(curValue: Int, maxValue: Int) { | |
seekBar.setOnSeekBarChangeListener(null) | |
seekBar.max = maxValue | |
seekBar.progress = curValue | |
seekBar.setOnSeekBarChangeListener(this) | |
} | |
override fun onProgressChanged(seekBar: SeekBar?, progress: Int, fromUser: Boolean) { | |
volumizer.setVolume(progress) | |
} | |
override fun onStartTrackingTouch(seekBar: SeekBar?) = Unit | |
override fun onStopTrackingTouch(seekBar: SeekBar?) = Unit | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment