Removed MediaPlayerWrapper, ExoPlayerWrapper. GaplessExoPlayerWrapper is

the way forward!
This commit is contained in:
casey langen 2018-01-23 18:57:25 -08:00
parent 5b356c4991
commit b96934dbfc
8 changed files with 41 additions and 665 deletions

View File

@ -6,9 +6,7 @@ import io.casey.musikcube.remote.injection.DaggerPlaybackComponent
import io.casey.musikcube.remote.service.gapless.GaplessHeaderService import io.casey.musikcube.remote.service.gapless.GaplessHeaderService
import io.casey.musikcube.remote.service.gapless.db.GaplessDb import io.casey.musikcube.remote.service.gapless.db.GaplessDb
import io.casey.musikcube.remote.service.gapless.db.GaplessTrack import io.casey.musikcube.remote.service.gapless.db.GaplessTrack
import io.casey.musikcube.remote.service.playback.impl.player.ExoPlayerWrapper
import io.casey.musikcube.remote.service.playback.impl.player.GaplessExoPlayerWrapper import io.casey.musikcube.remote.service.playback.impl.player.GaplessExoPlayerWrapper
import io.casey.musikcube.remote.service.playback.impl.player.MediaPlayerWrapper
import io.casey.musikcube.remote.service.playback.impl.streaming.StreamProxy import io.casey.musikcube.remote.service.playback.impl.streaming.StreamProxy
import io.casey.musikcube.remote.service.playback.impl.streaming.db.OfflineDb import io.casey.musikcube.remote.service.playback.impl.streaming.db.OfflineDb
import io.casey.musikcube.remote.service.playback.impl.streaming.db.OfflineTrack import io.casey.musikcube.remote.service.playback.impl.streaming.db.OfflineTrack
@ -33,19 +31,6 @@ abstract class PlayerWrapper {
.build().inject(this) .build().inject(this)
} }
private enum class Type(prefIndex: Int) {
ExoPlayer(0), ExoPlayerGapless(1), MediaPlayer(2);
companion object {
fun fromPrefIndex(index: Int): Type =
when(index) {
2 -> MediaPlayer
1 -> ExoPlayerGapless
else -> ExoPlayer
}
}
}
enum class State { enum class State {
Stopped, Stopped,
Preparing, Preparing,
@ -108,8 +93,8 @@ abstract class PlayerWrapper {
} }
companion object { companion object {
private val DUCK_COEF = 0.2f /* volume = 20% when ducked */ private const val DUCK_COEF = 0.2f /* volume = 20% when ducked */
private val DUCK_NONE = -1.0f private const val DUCK_NONE = -1.0f
private val activePlayers = HashSet<PlayerWrapper>() private val activePlayers = HashSet<PlayerWrapper>()
private var globalVolume = 1.0f private var globalVolume = 1.0f
@ -175,17 +160,7 @@ abstract class PlayerWrapper {
} }
} }
fun newInstance(prefs: SharedPreferences): PlayerWrapper { fun newInstance(): PlayerWrapper = GaplessExoPlayerWrapper()
val type = prefs.getInt(
Prefs.Key.PLAYBACK_ENGINE_INDEX,
Prefs.Default.PLAYBACK_ENGINE_INDEX)
return when (Type.fromPrefIndex(type)) {
Type.ExoPlayer -> ExoPlayerWrapper()
Type.ExoPlayerGapless -> GaplessExoPlayerWrapper()
Type.MediaPlayer -> MediaPlayerWrapper()
}
}
fun addActivePlayer(player: PlayerWrapper) { fun addActivePlayer(player: PlayerWrapper) {
Preconditions.throwIfNotOnMainThread() Preconditions.throwIfNotOnMainThread()

View File

@ -1,309 +0,0 @@
package io.casey.musikcube.remote.service.playback.impl.player
import android.content.Context
import android.content.SharedPreferences
import android.net.Uri
import android.util.Log
import com.danikula.videocache.CacheListener
import com.google.android.exoplayer2.*
import com.google.android.exoplayer2.extractor.DefaultExtractorsFactory
import com.google.android.exoplayer2.extractor.ExtractorsFactory
import com.google.android.exoplayer2.source.ExtractorMediaSource
import com.google.android.exoplayer2.source.MediaSource
import com.google.android.exoplayer2.source.TrackGroupArray
import com.google.android.exoplayer2.trackselection.AdaptiveTrackSelection
import com.google.android.exoplayer2.trackselection.DefaultTrackSelector
import com.google.android.exoplayer2.trackselection.TrackSelectionArray
import com.google.android.exoplayer2.upstream.DataSource
import com.google.android.exoplayer2.upstream.DefaultBandwidthMeter
import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory
import com.google.android.exoplayer2.util.Util
import io.casey.musikcube.remote.Application
import io.casey.musikcube.remote.service.playback.PlayerWrapper
import io.casey.musikcube.remote.service.playback.impl.streaming.StreamProxy
import io.casey.musikcube.remote.service.websocket.model.ITrack
import io.casey.musikcube.remote.ui.settings.constants.Prefs
import io.casey.musikcube.remote.util.Preconditions
import okhttp3.OkHttpClient
import java.io.File
class ExoPlayerWrapper : PlayerWrapper() {
private val prefs: SharedPreferences
private var datasources: DataSource.Factory? = null
private val extractors: ExtractorsFactory
private var source: MediaSource? = null
private val player: SimpleExoPlayer?
private var metadata: ITrack? = null
private var prefetch: Boolean = false
private val context: Context
private var lastPosition: Long = -1
private var percentAvailable = 0
private var originalUri: String? = null
private var proxyUri: String? = null
private val transcoding: Boolean
init {
this.context = Application.instance!!
val bandwidth = DefaultBandwidthMeter()
val trackFactory = AdaptiveTrackSelection.Factory(bandwidth)
val trackSelector = DefaultTrackSelector(trackFactory)
this.player = ExoPlayerFactory.newSimpleInstance(this.context, trackSelector)
this.extractors = DefaultExtractorsFactory()
this.datasources = DefaultDataSourceFactory(context, Util.getUserAgent(context, "musikdroid"))
this.prefs = Application.instance!!.getSharedPreferences(Prefs.NAME, Context.MODE_PRIVATE)
this.transcoding = this.prefs.getInt(Prefs.Key.TRANSCODER_BITRATE_INDEX, 0) != 0
}
override fun play(uri: String, metadata: ITrack, offsetMs: Int) {
Preconditions.throwIfNotOnMainThread()
if (!dead()) {
this.metadata = metadata
this.originalUri = uri
this.proxyUri = streamProxy.getProxyUrl(uri)
Log.d("ExoPlayerWrapper", "originalUri: ${this.originalUri} proxyUri: ${this.proxyUri}")
addCacheListener()
this.source = ExtractorMediaSource(Uri.parse(proxyUri), datasources, extractors, null, null)
this.player!!.playWhenReady = true
this.player.prepare(this.source)
addActivePlayer(this)
state = State.Preparing
}
}
override fun prefetch(uri: String, metadata: ITrack) {
Preconditions.throwIfNotOnMainThread()
if (!dead()) {
this.metadata = metadata
this.originalUri = uri
this.proxyUri = streamProxy.getProxyUrl(uri)
Log.d("ExoPlayerWrapper", "originalUri: ${this.originalUri} proxyUri: ${this.proxyUri}")
this.prefetch = true
addCacheListener()
this.source = ExtractorMediaSource(Uri.parse(proxyUri), datasources, extractors, null, null)
this.player!!.playWhenReady = false
this.player.prepare(this.source)
addActivePlayer(this)
state = State.Preparing
}
}
override fun pause() {
Preconditions.throwIfNotOnMainThread()
this.prefetch = true
if (this.state == State.Playing) {
this.player!!.playWhenReady = false
state = State.Paused
}
}
override fun resume() {
Preconditions.throwIfNotOnMainThread()
prefetch = false
when (state) {
State.Paused,
State.Prepared -> {
player!!.playWhenReady = true
state = State.Playing
}
State.Error -> {
player!!.playWhenReady = lastPosition == -1L
player.prepare(source)
state = State.Preparing
}
else -> { }
}
}
override val uri get() = originalUri ?: ""
override var position: Int
get(): Int {
Preconditions.throwIfNotOnMainThread()
return this.player!!.currentPosition.toInt()
}
set(millis) {
Preconditions.throwIfNotOnMainThread()
this.lastPosition = -1
if (this.player!!.playbackState != ExoPlayer.STATE_IDLE) {
if (this.player.isCurrentWindowSeekable) {
var offset = millis.toLong()
/* if we're transcoding we don't want to seek arbitrarily because it may put
a lot of pressure on the backend. just allow seeking up to what we currently
have buffered! */
if (transcoding && percentAvailable != 100) {
/* give ourselves 2% wiggle room! */
val percent = Math.max(0, percentAvailable - 2).toFloat() / 100.0f
val totalMs = this.player.duration
val available = (totalMs.toFloat() * percent).toLong()
offset = Math.min(millis.toLong(), available)
}
this.player.seekTo(offset)
}
}
}
override val duration: Int
get() {
Preconditions.throwIfNotOnMainThread()
return this.player!!.duration.toInt()
}
override val bufferedPercent: Int
get() {
return if (transcoding) percentAvailable else 100
}
override fun updateVolume() {
Preconditions.throwIfNotOnMainThread()
this.player!!.volume = getVolume()
}
override fun setNextMediaPlayer(wrapper: PlayerWrapper?) {
Preconditions.throwIfNotOnMainThread()
}
override fun dispose() {
Preconditions.throwIfNotOnMainThread()
if (!dead()) {
state = State.Killing
removeActivePlayer(this)
removeCacheListener()
this.player?.playWhenReady = false
this.player?.removeListener(eventListener)
this.player?.stop()
this.player?.release()
state = State.Disposed
}
}
private fun dead(): Boolean {
val state = state
return state == State.Killing || state == State.Disposed
}
private fun addCacheListener() {
if (streamProxy.isCached(this.originalUri!!)) {
percentAvailable = 100
if (originalUri != null && metadata != null) {
storeOffline(originalUri!!, metadata!!)
}
}
else {
streamProxy.registerCacheListener(this.cacheListener, this.originalUri!!)
}
}
private fun removeCacheListener() {
streamProxy.unregisterCacheListener(this.cacheListener)
}
private val cacheListener = CacheListener { _: File, _: String, percent: Int ->
percentAvailable = percent
if (percentAvailable >= 100) {
if (originalUri != null && metadata != null) {
storeOffline(originalUri!!, metadata!!)
}
}
}
private var eventListener = object : Player.EventListener {
override fun onTimelineChanged(timeline: Timeline, manifest: Any?) {
}
override fun onTracksChanged(trackGroups: TrackGroupArray, trackSelections: TrackSelectionArray) {
}
override fun onLoadingChanged(isLoading: Boolean) {
}
override fun onSeekProcessed() {
}
override fun onShuffleModeEnabledChanged(shuffleModeEnabled: Boolean) {
}
override fun onPlayerStateChanged(playWhenReady: Boolean, playbackState: Int) {
Preconditions.throwIfNotOnMainThread()
if (playbackState == ExoPlayer.STATE_BUFFERING) {
state = State.Buffering
}
else if (playbackState == ExoPlayer.STATE_READY) {
if (dead()) {
dispose()
}
else {
state = State.Prepared
player!!.volume = getVolume()
if (lastPosition != -1L) {
player.seekTo(lastPosition)
lastPosition = -1
}
if (!prefetch) {
player.playWhenReady = true
state = State.Playing
}
else {
state = State.Paused
}
}
}
else if (playbackState == ExoPlayer.STATE_ENDED) {
state = State.Finished
dispose()
}
}
override fun onPlayerError(error: ExoPlaybackException) {
Preconditions.throwIfNotOnMainThread()
lastPosition = player!!.currentPosition
when (state) {
State.Preparing,
State.Prepared,
State.Playing,
State.Paused ->
state = State.Error
else -> { }
}
}
override fun onPositionDiscontinuity(type: Int) {
}
override fun onPlaybackParametersChanged(playbackParameters: PlaybackParameters) {
}
override fun onRepeatModeChanged(repeatMode: Int) {
}
}
init {
this.player!!.addListener(eventListener)
}
}

View File

@ -1,233 +0,0 @@
package io.casey.musikcube.remote.service.playback.impl.player
import android.content.Context
import android.content.SharedPreferences
import android.media.AudioManager
import android.media.MediaPlayer
import android.net.Uri
import android.os.PowerManager
import android.util.Base64
import android.util.Log
import io.casey.musikcube.remote.Application
import io.casey.musikcube.remote.service.websocket.model.ITrack
import io.casey.musikcube.remote.service.playback.PlayerWrapper
import io.casey.musikcube.remote.service.playback.impl.streaming.StreamProxy
import io.casey.musikcube.remote.util.Preconditions
import io.casey.musikcube.remote.ui.settings.constants.Prefs
import java.io.IOException
import java.util.*
class MediaPlayerWrapper : PlayerWrapper() {
private val player = MediaPlayer()
private var seekTo: Int = 0
private var prefetching: Boolean = false
private val context = Application.instance
private val prefs: SharedPreferences
private var metadata: ITrack? = null
private var proxyUri: String? = null
private var originalUri: String? = null
override var bufferedPercent: Int = 0
init {
this.prefs = context!!.getSharedPreferences(Prefs.NAME, Context.MODE_PRIVATE)
}
override fun play(uri: String, metadata: ITrack, offsetMs: Int) {
Preconditions.throwIfNotOnMainThread()
try {
state = State.Preparing
val userPass = "default:" + prefs.getString(Prefs.Key.PASSWORD, Prefs.Default.PASSWORD)!!
val encoded = Base64.encodeToString(userPass.toByteArray(), Base64.NO_WRAP)
val headers = HashMap<String, String>()
headers.put("Authorization", "Basic " + encoded)
this.metadata = metadata
this.originalUri = uri
this.proxyUri = streamProxy.getProxyUrl(uri)
player.setDataSource(context, Uri.parse(proxyUri), headers)
player.setAudioStreamType(AudioManager.STREAM_MUSIC)
player.setOnPreparedListener(onPrepared)
player.setOnErrorListener(onError)
player.setOnCompletionListener(onCompleted)
player.setOnBufferingUpdateListener(onBuffering)
player.setWakeMode(Application.instance, PowerManager.PARTIAL_WAKE_LOCK)
player.prepareAsync()
}
catch (e: IOException) {
Log.e(TAG, "setDataSource failed: " + e.toString())
}
}
override fun prefetch(uri: String, metadata: ITrack) {
Preconditions.throwIfNotOnMainThread()
this.prefetching = true
play(uri, metadata)
}
override fun pause() {
Preconditions.throwIfNotOnMainThread()
if (isPreparedOrPlaying) {
player.pause()
state = State.Paused
}
}
override var position: Int
get() {
Preconditions.throwIfNotOnMainThread()
return if (isPreparedOrPlaying) this.player.currentPosition else 0
}
set(millis) {
Preconditions.throwIfNotOnMainThread()
if (isPreparedOrPlaying) {
this.player.seekTo(millis)
this.seekTo = 0
}
else {
this.seekTo = millis
}
}
override val duration: Int
get() {
Preconditions.throwIfNotOnMainThread()
return if (isPreparedOrPlaying) this.player.duration else 0
}
override fun resume() {
Preconditions.throwIfNotOnMainThread()
if (state === State.Prepared || state === State.Paused) {
player.start()
this.state = State.Playing
}
else {
prefetching = false
}
}
override fun setNextMediaPlayer(wrapper: PlayerWrapper?) {
Preconditions.throwIfNotOnMainThread()
if (isPreparedOrPlaying) {
try {
if (wrapper is MediaPlayerWrapper) {
this.player.setNextMediaPlayer(wrapper.player)
}
}
catch (ex: IllegalStateException) {
Log.d(TAG, "invalid state for setNextMediaPlayer")
}
}
}
override fun updateVolume() {
Preconditions.throwIfNotOnMainThread()
val state = state
if (state !== State.Preparing && state !== State.Disposed) {
val volume = getVolume()
player.setVolume(volume, volume)
}
}
override val uri get() = originalUri ?: ""
private val isPreparedOrPlaying: Boolean
get() = (state === State.Playing || state === State.Prepared)
override fun dispose() {
Preconditions.throwIfNotOnMainThread()
removeActivePlayer(this)
if (state !== State.Preparing) {
try {
this.player.setNextMediaPlayer(null)
}
catch (ex: IllegalStateException) {
Log.d(TAG, "failed to setNextMediaPlayer(null)")
}
try {
this.player.stop()
}
catch (ex: IllegalStateException) {
Log.d(TAG, "failed to stop()")
}
try {
this.player.reset()
}
catch (ex: IllegalStateException) {
Log.d(TAG, "failed to reset()")
}
this.player.release()
setOnStateChangedListener(null)
state = State.Disposed
}
else {
state = State.Killing
}
}
private val onPrepared = { _: MediaPlayer ->
if (this.state === State.Killing) {
dispose()
}
else {
val volume = getVolume()
player.setVolume(volume, volume)
addActivePlayer(this)
if (prefetching) {
state = State.Prepared
}
else {
this.player.start()
if (this.seekTo != 0) {
position = this.seekTo
}
state = State.Playing
}
this.prefetching = false
}
}
private val onError = { _: MediaPlayer, _: Int, _: Int ->
state = State.Error
dispose()
true
}
private val onCompleted = { _: MediaPlayer ->
state = State.Finished
dispose()
}
private val onBuffering = { _: MediaPlayer, percent: Int ->
bufferedPercent = percent
if (bufferedPercent >= 100) {
if (originalUri != null && metadata != null) {
storeOffline(originalUri!!, metadata!!)
}
}
}
companion object {
private val TAG = "MediaPlayerWrapper"
}
}

View File

@ -642,7 +642,7 @@ class StreamingPlaybackService(context: Context) : IPlaybackService {
if (uri != null && uri != playContext.nextPlayer?.uri) { if (uri != null && uri != playContext.nextPlayer?.uri) {
playContext.reset(playContext.nextPlayer) playContext.reset(playContext.nextPlayer)
playContext.nextPlayer = PlayerWrapper.newInstance(prefs) playContext.nextPlayer = PlayerWrapper.newInstance()
playContext.nextPlayer?.setOnStateChangedListener(onNextPlayerStateChanged) playContext.nextPlayer?.setOnStateChangedListener(onNextPlayerStateChanged)
playContext.nextPlayer?.prefetch(uri, playContext.nextMetadata!!) playContext.nextPlayer?.prefetch(uri, playContext.nextMetadata!!)
} }
@ -740,7 +740,7 @@ class StreamingPlaybackService(context: Context) : IPlaybackService {
val uri = getUri(playContext.currentMetadata) val uri = getUri(playContext.currentMetadata)
if (uri != null) { if (uri != null) {
playContext.currentPlayer = PlayerWrapper.newInstance(prefs) playContext.currentPlayer = PlayerWrapper.newInstance()
playContext.currentPlayer?.setOnStateChangedListener(onCurrentPlayerStateChanged) playContext.currentPlayer?.setOnStateChangedListener(onCurrentPlayerStateChanged)
playContext.currentPlayer?.play(uri, playContext.currentMetadata!!, offsetMs) playContext.currentPlayer?.play(uri, playContext.currentMetadata!!, offsetMs)
} }

View File

@ -45,13 +45,10 @@ class SettingsActivity : BaseActivity() {
private lateinit var certCheckbox: CheckBox private lateinit var certCheckbox: CheckBox
private lateinit var bitrateSpinner: Spinner private lateinit var bitrateSpinner: Spinner
private lateinit var cacheSpinner: Spinner private lateinit var cacheSpinner: Spinner
private lateinit var playbackEngineSpinner: Spinner
private lateinit var prefs: SharedPreferences private lateinit var prefs: SharedPreferences
private lateinit var playback: PlaybackMixin private lateinit var playback: PlaybackMixin
private lateinit var data: DataProviderMixin private lateinit var data: DataProviderMixin
private var engineType = -1
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
data = mixin(DataProviderMixin()) data = mixin(DataProviderMixin())
playback = mixin(PlaybackMixin()) playback = mixin(PlaybackMixin())
@ -142,21 +139,6 @@ class SettingsActivity : BaseActivity() {
cacheSpinner.setSelection(prefs.getInt( cacheSpinner.setSelection(prefs.getInt(
Keys.DISK_CACHE_SIZE_INDEX, Defaults.DISK_CACHE_SIZE_INDEX)) Keys.DISK_CACHE_SIZE_INDEX, Defaults.DISK_CACHE_SIZE_INDEX))
/* playback engine */
val engines = ArrayAdapter.createFromResource(
this, R.array.playback_engine_array, android.R.layout.simple_spinner_item)
engines.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item)
val engineType = prefs.getInt(Keys.PLAYBACK_ENGINE_INDEX, Defaults.PLAYBACK_ENGINE_INDEX)
if (this.engineType == -1) {
this.engineType = engineType
}
playbackEngineSpinner.adapter = engines
playbackEngineSpinner.setSelection(engineType)
/* advanced */ /* advanced */
albumArtCheckbox.isChecked = prefs.getBoolean( albumArtCheckbox.isChecked = prefs.getBoolean(
Keys.LASTFM_ENABLED, Defaults.LASTFM_ENABLED) Keys.LASTFM_ENABLED, Defaults.LASTFM_ENABLED)
@ -212,7 +194,6 @@ class SettingsActivity : BaseActivity() {
this.softwareVolume = findViewById(R.id.software_volume) this.softwareVolume = findViewById(R.id.software_volume)
this.bitrateSpinner = findViewById(R.id.transcoder_bitrate_spinner) this.bitrateSpinner = findViewById(R.id.transcoder_bitrate_spinner)
this.cacheSpinner = findViewById(R.id.streaming_disk_cache_spinner) this.cacheSpinner = findViewById(R.id.streaming_disk_cache_spinner)
this.playbackEngineSpinner = findViewById(R.id.streaming_playback_engine)
this.sslCheckbox = findViewById(R.id.ssl_checkbox) this.sslCheckbox = findViewById(R.id.ssl_checkbox)
this.certCheckbox = findViewById(R.id.cert_validation) this.certCheckbox = findViewById(R.id.cert_validation)
} }
@ -271,12 +252,6 @@ class SettingsActivity : BaseActivity() {
val password = passwordText.text.toString() val password = passwordText.text.toString()
try { try {
val engineType = playbackEngineSpinner.selectedItemPosition
val streaming = prefs.getBoolean(
Prefs.Key.STREAMING_PLAYBACK,
Prefs.Default.STREAMING_PLAYBACK)
prefs.edit() prefs.edit()
.putString(Keys.ADDRESS, addr) .putString(Keys.ADDRESS, addr)
.putInt(Keys.MAIN_PORT, if (port.isNotEmpty()) port.toInt() else 0) .putInt(Keys.MAIN_PORT, if (port.isNotEmpty()) port.toInt() else 0)
@ -289,17 +264,12 @@ class SettingsActivity : BaseActivity() {
.putBoolean(Keys.CERT_VALIDATION_DISABLED, certCheckbox.isChecked) .putBoolean(Keys.CERT_VALIDATION_DISABLED, certCheckbox.isChecked)
.putInt(Keys.TRANSCODER_BITRATE_INDEX, bitrateSpinner.selectedItemPosition) .putInt(Keys.TRANSCODER_BITRATE_INDEX, bitrateSpinner.selectedItemPosition)
.putInt(Keys.DISK_CACHE_SIZE_INDEX, cacheSpinner.selectedItemPosition) .putInt(Keys.DISK_CACHE_SIZE_INDEX, cacheSpinner.selectedItemPosition)
.putInt(Keys.PLAYBACK_ENGINE_INDEX, engineType)
.apply() .apply()
if (!softwareVolume.isChecked) { if (!softwareVolume.isChecked) {
PlayerWrapper.setVolume(1.0f) PlayerWrapper.setVolume(1.0f)
} }
if (streaming && engineType != this.engineType) {
playback.service.stop()
}
streamProxy.reload() streamProxy.reload()
data.wss.disconnect() data.wss.disconnect()
@ -352,8 +322,8 @@ class SettingsActivity : BaseActivity() {
} }
companion object { companion object {
private val LEARN_MORE_URL = "https://github.com/clangen/musikcube/wiki/ssl-server-setup" private const val LEARN_MORE_URL = "https://github.com/clangen/musikcube/wiki/ssl-server-setup"
val TAG = "ssl_alert_dialog_tag" const val TAG = "ssl_alert_dialog_tag"
fun newInstance(): SslAlertDialog { fun newInstance(): SslAlertDialog {
return SslAlertDialog() return SslAlertDialog()
@ -377,7 +347,7 @@ class SettingsActivity : BaseActivity() {
} }
companion object { companion object {
val TAG = "disable_cert_verify_dialog" const val TAG = "disable_cert_verify_dialog"
fun newInstance(): DisableCertValidationAlertDialog { fun newInstance(): DisableCertValidationAlertDialog {
return DisableCertValidationAlertDialog() return DisableCertValidationAlertDialog()
@ -398,8 +368,8 @@ class SettingsActivity : BaseActivity() {
} }
companion object { companion object {
val TAG = "invalid_connection_dialog" const val TAG = "invalid_connection_dialog"
private val EXTRA_MESSAGE_ID = "extra_message_id" private const val EXTRA_MESSAGE_ID = "extra_message_id"
fun newInstance(messageId: Int = R.string.settings_invalid_connection_message): InvalidConnectionDialog { fun newInstance(messageId: Int = R.string.settings_invalid_connection_message): InvalidConnectionDialog {
val args = Bundle() val args = Bundle()
args.putInt(EXTRA_MESSAGE_ID, messageId) args.putInt(EXTRA_MESSAGE_ID, messageId)
@ -429,8 +399,8 @@ class SettingsActivity : BaseActivity() {
} }
companion object { companion object {
val TAG = "confirm_overwrite_dialog" const val TAG = "confirm_overwrite_dialog"
private val EXTRA_CONNECTION = "extra_connection" private const val EXTRA_CONNECTION = "extra_connection"
fun newInstance(connection: Connection): ConfirmOverwriteDialog { fun newInstance(connection: Connection): ConfirmOverwriteDialog {
val args = Bundle() val args = Bundle()
@ -473,7 +443,7 @@ class SettingsActivity : BaseActivity() {
} }
companion object { companion object {
val TAG = "save_as_dialog" const val TAG = "save_as_dialog"
fun newInstance(): SaveAsDialog { fun newInstance(): SaveAsDialog {
return SaveAsDialog() return SaveAsDialog()
@ -482,7 +452,7 @@ class SettingsActivity : BaseActivity() {
} }
companion object { companion object {
val CONNECTIONS_REQUEST_CODE = 1000 const val CONNECTIONS_REQUEST_CODE = 1000
fun getStartIntent(context: Context): Intent { fun getStartIntent(context: Context): Intent {
return Intent(context, SettingsActivity::class.java) return Intent(context, SettingsActivity::class.java)
@ -512,7 +482,7 @@ private class SaveAsTask(val db: ConnectionsDb,
} }
companion object { companion object {
val NAME = "SaveAsTask" const val NAME = "SaveAsTask"
fun nameFor(connection: Connection): String { fun nameFor(connection: Connection): String {
return "$NAME.${connection.name}" return "$NAME.${connection.name}"

View File

@ -3,42 +3,40 @@ package io.casey.musikcube.remote.ui.settings.constants
class Prefs { class Prefs {
interface Key { interface Key {
companion object { companion object {
val ADDRESS = "address" const val ADDRESS = "address"
val MAIN_PORT = "port" const val MAIN_PORT = "port"
val AUDIO_PORT = "http_port" const val AUDIO_PORT = "http_port"
val PASSWORD = "password" const val PASSWORD = "password"
val LASTFM_ENABLED = "lastfm_enabled" const val LASTFM_ENABLED = "lastfm_enabled"
val MESSAGE_COMPRESSION_ENABLED = "message_compression_enabled" const val MESSAGE_COMPRESSION_ENABLED = "message_compression_enabled"
val STREAMING_PLAYBACK = "streaming_playback" const val STREAMING_PLAYBACK = "streaming_playback"
val SOFTWARE_VOLUME = "software_volume" const val SOFTWARE_VOLUME = "software_volume"
val SSL_ENABLED = "ssl_enabled" const val SSL_ENABLED = "ssl_enabled"
val CERT_VALIDATION_DISABLED = "cert_validation_disabled" const val CERT_VALIDATION_DISABLED = "cert_validation_disabled"
val TRANSCODER_BITRATE_INDEX = "transcoder_bitrate_index" const val TRANSCODER_BITRATE_INDEX = "transcoder_bitrate_index"
val DISK_CACHE_SIZE_INDEX = "disk_cache_size_index" const val DISK_CACHE_SIZE_INDEX = "disk_cache_size_index"
val UPDATE_DIALOG_SUPPRESSED_VERSION = "update_dialog_suppressed_version" const val UPDATE_DIALOG_SUPPRESSED_VERSION = "update_dialog_suppressed_version"
val PLAYBACK_ENGINE_INDEX = "playback_engine_index"
} }
} }
interface Default { interface Default {
companion object { companion object {
val ADDRESS = "192.168.1.100" const val ADDRESS = "192.168.1.100"
val MAIN_PORT = 7905 const val MAIN_PORT = 7905
val AUDIO_PORT = 7906 const val AUDIO_PORT = 7906
val PASSWORD = "" const val PASSWORD = ""
val LASTFM_ENABLED = true const val LASTFM_ENABLED = true
val MESSAGE_COMPRESSION_ENABLED = true const val MESSAGE_COMPRESSION_ENABLED = true
val STREAMING_PLAYBACK = false const val STREAMING_PLAYBACK = false
val SOFTWARE_VOLUME = false const val SOFTWARE_VOLUME = false
val SSL_ENABLED = false const val SSL_ENABLED = false
val CERT_VALIDATION_DISABLED = false const val CERT_VALIDATION_DISABLED = false
val TRANSCODER_BITRATE_INDEX = 0 const val TRANSCODER_BITRATE_INDEX = 0
val DISK_CACHE_SIZE_INDEX = 2 const val DISK_CACHE_SIZE_INDEX = 2
val PLAYBACK_ENGINE_INDEX = 1
} }
} }
companion object { companion object {
val NAME = "prefs" const val NAME = "prefs"
} }
} }

View File

@ -168,23 +168,6 @@
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="16dp"/> android:layout_height="16dp"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_marginRight="8dp"
android:text="@string/settings_playback_engine"/>
<Spinner
android:id="@+id/streaming_playback_engine"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_marginLeft="24dp"/>
<android.support.v4.widget.Space
android:layout_width="0dp"
android:layout_height="16dp"/>
<TextView <TextView
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"

View File

@ -1,8 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string-array name="playback_engine_array">
<item>@string/settings_playback_engine_exo</item>
<item>@string/settings_playback_engine_exo_gapless</item>
<item>@string/settings_playback_engine_mp</item>
</string-array>
</resources>