added slider for alarm volume

remotes/origin/devel
yattoz 2020-08-05 17:55:52 +02:00
parent 99ab795320
commit 0b7b5dd2f1
10 changed files with 180 additions and 126 deletions

View File

@ -29,8 +29,8 @@ android {
applicationId "fr.forum_thalie.tsumugi" applicationId "fr.forum_thalie.tsumugi"
minSdkVersion 16 minSdkVersion 16
targetSdkVersion 30 targetSdkVersion 30
versionCode 115 versionCode 116
versionName "1.1.5" versionName "1.1.6"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
vectorDrawables.useSupportLibrary = true vectorDrawables.useSupportLibrary = true
} }

View File

@ -454,12 +454,13 @@ class RadioService : MediaBrowserServiceCompat() {
// this function is playing the stream if available, or a default sound if there's a problem. // this function is playing the stream if available, or a default sound if there's a problem.
private fun beginPlayingOrFallback() private fun beginPlayingOrFallback()
{ {
PlayerStore.instance.volume.value = 100 // we set the max volume for exoPlayer to be sure it rings correctly. PlayerStore.instance.volume.value = PreferenceManager.getDefaultSharedPreferences(this).getInt("alarmVolume", 100)
// we set the max volume for exoPlayer to be sure it rings correctly.
beginPlaying(isRinging = true, isFallback = false) beginPlaying(isRinging = true, isFallback = false)
val wait: (Any?) -> Any = { val wait: (Any?) -> Any = {
/* /*
Here we lower the isAlarmStopped flag and we wait for 17s. (seems like 12 could be a bit too short since I increased the buffer!!) Here we lower the isAlarmStopped flag and we wait for 17s. (seems like 12 could be a bit too short since I increased the buffer!!)
If the player stops the alarm (by calling an intent), the isAlarmStopped flag will be raised. If the user stops the alarm (by calling an intent), the isAlarmStopped flag will be raised.
*/ */
isAlarmStopped = false // reset the flag isAlarmStopped = false // reset the flag
var i = 0 var i = 0
@ -513,8 +514,11 @@ class RadioService : MediaBrowserServiceCompat() {
return return
} }
if (mediaSession.controller.playbackState.state == PlaybackStateCompat.STATE_PLAYING && !isRinging) // TODO: Remove this
if (mediaSession.controller.playbackState.state == PlaybackStateCompat.STATE_PLAYING && !isRinging && isAlarmStopped)
return // nothing to do here return // nothing to do here
isAlarmStopped = true
PlayerStore.instance.playbackState.value = PlaybackStateCompat.STATE_PLAYING PlayerStore.instance.playbackState.value = PlaybackStateCompat.STATE_PLAYING
// Reinitialize media player. Otherwise the playback doesn't resume when beginPlaying. Dunno why. // Reinitialize media player. Otherwise the playback doesn't resume when beginPlaying. Dunno why.
@ -554,7 +558,6 @@ class RadioService : MediaBrowserServiceCompat() {
if (mediaSession.controller.playbackState.state == PlaybackStateCompat.STATE_STOPPED) if (mediaSession.controller.playbackState.state == PlaybackStateCompat.STATE_STOPPED)
return // nothing to do here return // nothing to do here
if (PlayerStore.instance.playbackState.value == PlaybackStateCompat.STATE_PLAYING)
isAlarmStopped = true isAlarmStopped = true
PlayerStore.instance.playbackState.value = PlaybackStateCompat.STATE_STOPPED PlayerStore.instance.playbackState.value = PlaybackStateCompat.STATE_STOPPED

View File

@ -1,33 +0,0 @@
package fr.forum_thalie.tsumugi.alarm
import android.content.Context
import android.content.Intent
import fr.forum_thalie.tsumugi.Actions
import fr.forum_thalie.tsumugi.RadioService
fun playOnFallback(c: Context) {
val a = Actions.PLAY_OR_FALLBACK
val i = Intent(c, RadioService::class.java)
i.putExtra("action", a.name)
c.startService(i)
}
fun resume(c: Context)
{
}
fun resumeStop(c: Context) {
val a = Actions.PLAY
val i = Intent(c, RadioService::class.java)
i.putExtra("action", a.name)
c.startService(i)
}
fun resumePlay(c: Context) {
val a = Actions.PLAY
val i = Intent(c, RadioService::class.java)
i.putExtra("action", a.name)
c.startService(i)
}

View File

@ -0,0 +1,129 @@
package fr.forum_thalie.tsumugi.preferences
import android.content.Context
import android.content.Intent
import android.media.AudioManager
import android.os.Bundle
import android.view.KeyEvent
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import androidx.preference.PreferenceFragmentCompat
import androidx.preference.PreferenceManager
import androidx.preference.SeekBarPreference
import androidx.preference.SwitchPreferenceCompat
import fr.forum_thalie.tsumugi.Actions
import fr.forum_thalie.tsumugi.R
import fr.forum_thalie.tsumugi.RadioService
import fr.forum_thalie.tsumugi.playerstore.PlayerStore
import kotlinx.coroutines.*
import kotlin.coroutines.CoroutineContext
import kotlin.math.max
import kotlin.math.min
class AlarmAdjustVolumeFragment : PreferenceFragmentCompat() {
override fun onAttach(context: Context) {
(activity as AppCompatActivity).supportActionBar?.title = context.getString(R.string.test_alarm_volume)
super.onAttach(context)
}
// get previous state: if it's playing, we'll resume playing as multimedia; if it was stopped, we'll stop
private var isPlayingMultimedia: Boolean = PlayerStore.instance.isPlaying.value ?: false
override fun onStop() {
if (isPlayingMultimedia)
{
actionOnService(Actions.PLAY)
} else {
actionOnService(Actions.PAUSE)
}
PlayerStore.instance.volume.value = PreferenceManager.getDefaultSharedPreferences(requireContext()).getInt("volume", 100)
super.onStop()
}
override fun onResume() {
isPlayingMultimedia = PlayerStore.instance.isPlaying.value ?: false
// start as alarm
actionOnService(Actions.PLAY_OR_FALLBACK)
super.onResume()
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
fun <T> debounce(delayMs: Long = 500L,
coroutineContext: CoroutineContext,
f: (T) -> Unit): (T) -> Unit {
var debounceJob: Job? = null
return { param: T ->
if (debounceJob?.isCompleted != false) {
debounceJob = CoroutineScope(coroutineContext).launch {
delay(delayMs)
f(param)
}
}
}
}
val adjustAlarmVolume: (Int) -> Unit = debounce<Int>(50, GlobalScope.coroutineContext) {
android.util.Log.d(tag, "button $it pushed")
val keyCode = it
val audioManager = requireContext().getSystemService(Context.AUDIO_SERVICE) as AudioManager
audioManager.apply {
val currentVolume = this.getStreamVolume(AudioManager.STREAM_ALARM)
val minVolume = 0 // audioManager.getStreamMinVolume(AudioManager.STREAM_ALARM) <- require API28+
val maxVolume = this.getStreamMaxVolume(AudioManager.STREAM_ALARM)
if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {
this.setStreamVolume(AudioManager.STREAM_ALARM, max(currentVolume - 1, minVolume), AudioManager.FLAG_SHOW_UI)
} else if (keyCode == KeyEvent.KEYCODE_VOLUME_UP){
this.setStreamVolume(AudioManager.STREAM_ALARM, min(currentVolume + 1, maxVolume), AudioManager.FLAG_SHOW_UI)
} else {
}
}
}
view.isFocusableInTouchMode = true;
view.requestFocus();
view.setOnKeyListener { _, i, event ->
if (i == KeyEvent.KEYCODE_VOLUME_DOWN || i == KeyEvent.KEYCODE_VOLUME_UP) {
adjustAlarmVolume(i)
true
} else {
false
}
}
}
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
setPreferencesFromResource(R.xml.alarm_adjust_volume_preferences, rootKey)
val alarmVolumeSeekBar = findPreference<SeekBarPreference>("alarmVolume")
alarmVolumeSeekBar?.apply {
min = 0
max = 100
updatesContinuously = true
setOnPreferenceChangeListener { _, newValue ->
actionOnService(Actions.VOLUME, newValue as Int)
true
}
}
}
private fun actionOnService(a: Actions, v: Int = 0)
{
val i = Intent(requireContext(), RadioService::class.java)
i.putExtra("action", a.name)
i.putExtra("value", v)
//[REMOVE LOG CALLS]Log.d(tag, "Sending intent ${a.name}")
requireContext().startService(i)
}
}

View File

@ -143,88 +143,10 @@ class AlarmFragment : PreferenceFragmentCompat() {
true true
} }
val testAlarmVolume: Preference? = findPreference("testAlarmVolume")
testAlarmVolume!!.onPreferenceClickListener = Preference.OnPreferenceClickListener {
// get previous state: if it's playing, we'll resume playing as multimedia; if it was stopped, we'll stop
val isPlayingMultimedia: Boolean = PlayerStore.instance.isPlaying.value ?: false
val builder1 = AlertDialog.Builder(requireContext())
builder1.setTitle(R.string.test_alarm_volume)
builder1.setMessage(R.string.popupTestAlarmVolume)
builder1.setCancelable(false)
builder1.setPositiveButton(
getString(R.string.finished)
) { dialog, _ ->
// put the radio back to media sound, or off if it was off.
if (isPlayingMultimedia)
{
actionOnService(Actions.PLAY)
} else {
actionOnService(Actions.STOP)
}
dialog.cancel()
}
val adjustAlarmVolume: (Int) -> Unit = debounce<Int>(50, coroutineContext) {
val keyCode = it
val audioManager = requireContext().getSystemService(Context.AUDIO_SERVICE) as AudioManager
val currentVolume = audioManager.getStreamVolume(AudioManager.STREAM_ALARM)
val minVolume = 0 // audioManager.getStreamMinVolume(AudioManager.STREAM_ALARM) <- require API28+
val maxVolume = audioManager.getStreamMaxVolume(AudioManager.STREAM_ALARM)
Log.d(tag, "current, max = $currentVolume, $maxVolume")
if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {
audioManager.setStreamVolume(AudioManager.STREAM_ALARM, max(currentVolume - 1, minVolume), AudioManager.FLAG_SHOW_UI)
} else if (keyCode == KeyEvent.KEYCODE_VOLUME_UP){
audioManager.setStreamVolume(AudioManager.STREAM_ALARM, min(currentVolume + 1, maxVolume), AudioManager.FLAG_SHOW_UI)
}
}
builder1.setOnKeyListener { dialogInterface, i, event ->
adjustAlarmVolume(i)
true
}
val alert11 = builder1.create()
// start as alarm
actionOnService(Actions.PLAY_OR_FALLBACK)
alert11.show()
true
}
alarmDays?.isEnabled = isWakingUp?.isChecked ?: false alarmDays?.isEnabled = isWakingUp?.isChecked ?: false
timeSet?.isEnabled = isWakingUp?.isChecked ?: false timeSet?.isEnabled = isWakingUp?.isChecked ?: false
snoozeDuration?.isEnabled = isWakingUp?.isChecked ?: false snoozeDuration?.isEnabled = isWakingUp?.isChecked ?: false
} }
private fun actionOnService (a: Actions) {
// start as alarm
val i = Intent(requireContext(), RadioService::class.java)
i.putExtra("action", a.name)
requireContext().startService(i)
}
private fun <T> debounce(delayMs: Long = 500L,
coroutineContext: CoroutineContext,
f: (T) -> Unit): (T) -> Unit {
var debounceJob: Job? = null
return { param: T ->
if (debounceJob?.isCompleted != false) {
debounceJob = CoroutineScope(coroutineContext).launch {
delay(delayMs)
f(param)
}
}
}
}
} }

View File

@ -166,10 +166,10 @@ class NowPlayingFragment : Fragment() {
} }
}) })
seekBarVolume.setOnSeekBarChangeListener(nowPlayingViewModel.seekBarChangeListener)
seekBarVolume.progress = PlayerStore.instance.volume.value!! seekBarVolume.progress = PlayerStore.instance.volume.value!!
progressBar.max = 1000 seekBarVolume.setOnSeekBarChangeListener(nowPlayingViewModel.seekBarChangeListener)
progressBar.max = 100
progressBar.progress = 0 progressBar.progress = 0
syncPlayPauseButtonImage(root) syncPlayPauseButtonImage(root)

View File

@ -58,7 +58,11 @@
<string name="settings">Paramètres</string> <string name="settings">Paramètres</string>
<string name="test_alarm_volume">Tester et ajuster le volume de l\'alarme</string> <string name="test_alarm_volume">Tester et ajuster le volume de l\'alarme</string>
<string name="test_alarm_volume_summary">Touchez pour écouter et régler le volume</string> <string name="test_alarm_volume_summary">Touchez pour écouter et régler le volume</string>
<string name="popupTestAlarmVolume">La radio est à présent lancée en mode alarme. Ajustez le volume avec les boutons de volume de votre appareil.</string> <string name="popupTestAlarmVolume">La radio est à présent lancée en mode alarme. Ajustez le volume avec les boutons de volume de votre appareil. Vous pouvez faire un réglage plus fin du volume avec la réglette ci-dessous.</string>
<string name="finished">Terminé</string> <string name="finished">Terminé</string>
<string name="alarmVolumeSeekBar">Ajuster le volume de l\'alarme</string>
<string name="setupAlarmClockVolume">Régler le volume de l\'alarme</string>
<string name="alarm_volume">Volume de l\'alarme</string>
</resources> </resources>

View File

@ -78,7 +78,10 @@
<string name="settings">Settings</string> <string name="settings">Settings</string>
<string name="test_alarm_volume">Test and change alarm volume</string> <string name="test_alarm_volume">Test and change alarm volume</string>
<string name="test_alarm_volume_summary">Touch this to listen to the alarm volume and set it up</string> <string name="test_alarm_volume_summary">Touch this to listen to the alarm volume and set it up</string>
<string name="popupTestAlarmVolume">The radio stream is now started in alarm mode. Adjust the volume with the volume buttons on your device.</string> <string name="popupTestAlarmVolume">The radio stream is now started in alarm mode. Adjust the volume with the volume buttons on your device. You can make a finer adjustment of the volume with the slider below.</string>
<string name="finished">Done</string> <string name="finished">Done</string>
<string name="alarmVolumeSeekBar">Adjust alarm volume</string>
<string name="setupAlarmClockVolume">Set up alarm volume</string>
<string name="alarm_volume">Alarm volume</string>
</resources> </resources>

View File

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<Preference
app:key="alarmAdjustText"
app:iconSpaceReserved="false"
app:title=""
android:selectable="false"
android:persistent="false"
app:summary="@string/popupTestAlarmVolume"
app:singleLineTitle="false"
/>
<SeekBarPreference
app:key="alarmVolume"
app:iconSpaceReserved="false"
app:title="@string/alarm_volume"
app:defaultValue="100"
app:showSeekBarValue="true"
/>
</PreferenceScreen>

View File

@ -38,9 +38,12 @@
/> />
<Preference <Preference
app:iconSpaceReserved="false" app:iconSpaceReserved="true"
android:key="testAlarmVolume" android:key="testAlarmVolume"
android:title="@string/test_alarm_volume" android:title="@string/test_alarm_volume"
android:summary="@string/test_alarm_volume_summary" /> android:summary="@string/test_alarm_volume_summary"
app:icon="@drawable/ic_volume_high"
app:fragment="fr.forum_thalie.tsumugi.preferences.AlarmAdjustVolumeFragment"
/>
</PreferenceScreen> </PreferenceScreen>