|
@@ -2,15 +2,29 @@ package fr.forum_thalie.tsumugi.preferences
|
2
|
2
|
|
3
|
3
|
import android.app.TimePickerDialog
|
4
|
4
|
import android.content.Context
|
|
5
|
+import android.content.Intent
|
|
6
|
+import android.media.AudioManager
|
5
|
7
|
import android.os.Bundle
|
6
|
8
|
import android.util.Log
|
|
9
|
+import android.view.KeyEvent
|
|
10
|
+import androidx.appcompat.app.AlertDialog
|
7
|
11
|
import androidx.appcompat.app.AppCompatActivity
|
8
|
12
|
import androidx.core.content.edit
|
9
|
13
|
import androidx.preference.*
|
10
|
14
|
import fr.forum_thalie.tsumugi.*
|
11
|
15
|
import fr.forum_thalie.tsumugi.R
|
12
|
16
|
import fr.forum_thalie.tsumugi.alarm.RadioAlarm
|
|
17
|
+import fr.forum_thalie.tsumugi.playerstore.PlayerStore
|
|
18
|
+import kotlinx.coroutines.CoroutineScope
|
|
19
|
+import kotlinx.coroutines.GlobalScope.coroutineContext
|
|
20
|
+import kotlinx.coroutines.Job
|
|
21
|
+import kotlinx.coroutines.delay
|
|
22
|
+import kotlinx.coroutines.launch
|
13
|
23
|
import java.util.*
|
|
24
|
+import kotlin.coroutines.CoroutineContext
|
|
25
|
+import kotlin.math.max
|
|
26
|
+import kotlin.math.min
|
|
27
|
+
|
14
|
28
|
|
15
|
29
|
class AlarmFragment : PreferenceFragmentCompat() {
|
16
|
30
|
|
|
@@ -130,11 +144,87 @@ class AlarmFragment : PreferenceFragmentCompat() {
|
130
|
144
|
}
|
131
|
145
|
|
132
|
146
|
|
|
147
|
+ val testAlarmVolume: Preference? = findPreference("testAlarmVolume")
|
|
148
|
+ testAlarmVolume!!.onPreferenceClickListener = Preference.OnPreferenceClickListener {
|
|
149
|
+
|
|
150
|
+ // get previous state: if it's playing, we'll resume playing as multimedia; if it was stopped, we'll stop
|
|
151
|
+ val isPlayingMultimedia: Boolean = PlayerStore.instance.isPlaying.value ?: false
|
|
152
|
+
|
|
153
|
+ val builder1 = AlertDialog.Builder(requireContext())
|
|
154
|
+ builder1.setTitle(R.string.test_alarm_volume)
|
|
155
|
+ builder1.setMessage(R.string.popupTestAlarmVolume)
|
|
156
|
+ builder1.setCancelable(false)
|
|
157
|
+ builder1.setPositiveButton(
|
|
158
|
+ getString(R.string.finished)
|
|
159
|
+ ) { dialog, _ ->
|
|
160
|
+ // put the radio back to media sound, or off if it was off.
|
|
161
|
+ if (isPlayingMultimedia)
|
|
162
|
+ {
|
|
163
|
+ actionOnService(Actions.PLAY)
|
|
164
|
+ } else {
|
|
165
|
+ actionOnService(Actions.STOP)
|
|
166
|
+ }
|
|
167
|
+ dialog.cancel()
|
|
168
|
+ }
|
|
169
|
+
|
|
170
|
+ val adjustAlarmVolume: (Int) -> Unit = debounce<Int>(50, coroutineContext) {
|
|
171
|
+ val keyCode = it
|
|
172
|
+
|
|
173
|
+ val audioManager = requireContext().getSystemService(Context.AUDIO_SERVICE) as AudioManager
|
|
174
|
+ val currentVolume = audioManager.getStreamVolume(AudioManager.STREAM_ALARM)
|
|
175
|
+ val minVolume = 0 // audioManager.getStreamMinVolume(AudioManager.STREAM_ALARM) <- require API28+
|
|
176
|
+ val maxVolume = audioManager.getStreamMaxVolume(AudioManager.STREAM_ALARM)
|
|
177
|
+ Log.d(tag, "current, max = $currentVolume, $maxVolume")
|
|
178
|
+ if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {
|
|
179
|
+ audioManager.setStreamVolume(AudioManager.STREAM_ALARM, max(currentVolume - 1, minVolume), AudioManager.FLAG_SHOW_UI)
|
|
180
|
+
|
|
181
|
+ } else if (keyCode == KeyEvent.KEYCODE_VOLUME_UP){
|
|
182
|
+ audioManager.setStreamVolume(AudioManager.STREAM_ALARM, min(currentVolume + 1, maxVolume), AudioManager.FLAG_SHOW_UI)
|
|
183
|
+ }
|
|
184
|
+
|
|
185
|
+ }
|
|
186
|
+
|
|
187
|
+ builder1.setOnKeyListener { dialogInterface, i, event ->
|
|
188
|
+ adjustAlarmVolume(i)
|
|
189
|
+ true
|
|
190
|
+ }
|
|
191
|
+
|
|
192
|
+ val alert11 = builder1.create()
|
|
193
|
+
|
|
194
|
+ // start as alarm
|
|
195
|
+ actionOnService(Actions.PLAY_OR_FALLBACK)
|
|
196
|
+
|
|
197
|
+ alert11.show()
|
|
198
|
+
|
|
199
|
+ true
|
|
200
|
+ }
|
|
201
|
+
|
133
|
202
|
alarmDays?.isEnabled = isWakingUp?.isChecked ?: false
|
134
|
203
|
timeSet?.isEnabled = isWakingUp?.isChecked ?: false
|
135
|
204
|
snoozeDuration?.isEnabled = isWakingUp?.isChecked ?: false
|
136
|
205
|
|
137
|
206
|
}
|
138
|
207
|
|
|
208
|
+ private fun actionOnService (a: Actions) {
|
|
209
|
+ // start as alarm
|
|
210
|
+ val i = Intent(requireContext(), RadioService::class.java)
|
|
211
|
+ i.putExtra("action", a.name)
|
|
212
|
+ requireContext().startService(i)
|
|
213
|
+ }
|
|
214
|
+
|
|
215
|
+ private fun <T> debounce(delayMs: Long = 500L,
|
|
216
|
+ coroutineContext: CoroutineContext,
|
|
217
|
+ f: (T) -> Unit): (T) -> Unit {
|
|
218
|
+ var debounceJob: Job? = null
|
|
219
|
+ return { param: T ->
|
|
220
|
+ if (debounceJob?.isCompleted != false) {
|
|
221
|
+ debounceJob = CoroutineScope(coroutineContext).launch {
|
|
222
|
+ delay(delayMs)
|
|
223
|
+ f(param)
|
|
224
|
+ }
|
|
225
|
+ }
|
|
226
|
+ }
|
|
227
|
+ }
|
|
228
|
+
|
139
|
229
|
|
140
|
230
|
}
|