added slider for alarm volume
parent
99ab795320
commit
0b7b5dd2f1
|
|
@ -29,8 +29,8 @@ android {
|
|||
applicationId "fr.forum_thalie.tsumugi"
|
||||
minSdkVersion 16
|
||||
targetSdkVersion 30
|
||||
versionCode 115
|
||||
versionName "1.1.5"
|
||||
versionCode 116
|
||||
versionName "1.1.6"
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
vectorDrawables.useSupportLibrary = true
|
||||
}
|
||||
|
|
|
|||
|
|
@ -454,12 +454,13 @@ class RadioService : MediaBrowserServiceCompat() {
|
|||
// this function is playing the stream if available, or a default sound if there's a problem.
|
||||
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)
|
||||
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!!)
|
||||
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
|
||||
var i = 0
|
||||
|
|
@ -513,8 +514,11 @@ class RadioService : MediaBrowserServiceCompat() {
|
|||
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
|
||||
isAlarmStopped = true
|
||||
|
||||
PlayerStore.instance.playbackState.value = PlaybackStateCompat.STATE_PLAYING
|
||||
|
||||
// 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)
|
||||
return // nothing to do here
|
||||
|
||||
if (PlayerStore.instance.playbackState.value == PlaybackStateCompat.STATE_PLAYING)
|
||||
isAlarmStopped = true
|
||||
|
||||
PlayerStore.instance.playbackState.value = PlaybackStateCompat.STATE_STOPPED
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
}
|
||||
|
|
@ -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)
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -143,88 +143,10 @@ class AlarmFragment : PreferenceFragmentCompat() {
|
|||
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
|
||||
timeSet?.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)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -166,10 +166,10 @@ class NowPlayingFragment : Fragment() {
|
|||
}
|
||||
})
|
||||
|
||||
|
||||
seekBarVolume.setOnSeekBarChangeListener(nowPlayingViewModel.seekBarChangeListener)
|
||||
seekBarVolume.progress = PlayerStore.instance.volume.value!!
|
||||
progressBar.max = 1000
|
||||
seekBarVolume.setOnSeekBarChangeListener(nowPlayingViewModel.seekBarChangeListener)
|
||||
|
||||
progressBar.max = 100
|
||||
progressBar.progress = 0
|
||||
|
||||
syncPlayPauseButtonImage(root)
|
||||
|
|
|
|||
|
|
@ -58,7 +58,11 @@
|
|||
<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_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="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>
|
||||
|
|
|
|||
|
|
@ -78,7 +78,10 @@
|
|||
<string name="settings">Settings</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="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="alarmVolumeSeekBar">Adjust alarm volume</string>
|
||||
<string name="setupAlarmClockVolume">Set up alarm volume</string>
|
||||
<string name="alarm_volume">Alarm volume</string>
|
||||
|
||||
</resources>
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
@ -38,9 +38,12 @@
|
|||
/>
|
||||
|
||||
<Preference
|
||||
app:iconSpaceReserved="false"
|
||||
app:iconSpaceReserved="true"
|
||||
android:key="testAlarmVolume"
|
||||
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>
|
||||
Loading…
Reference in New Issue