Release GPS2Audio v2.5.44 POI category fix
This commit is contained in:
@@ -23,6 +23,7 @@ import de.waypointaudio.data.PlaybackMode
|
||||
import de.waypointaudio.data.TourAudioSettings
|
||||
import de.waypointaudio.data.TourMusicStore
|
||||
import de.waypointaudio.data.Waypoint
|
||||
import de.waypointaudio.data.activeClips
|
||||
import de.waypointaudio.repository.WaypointRepository
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
@@ -157,6 +158,9 @@ class WaypointLocationService : Service() {
|
||||
private fun stopTracking() {
|
||||
fusedLocationClient.removeLocationUpdates(locationCallback)
|
||||
audioPlayer.stop()
|
||||
WaypointAudioInterruptionCoordinator.unregister(
|
||||
WaypointAudioInterruptionCoordinator.Source.GPS
|
||||
)
|
||||
stopForeground(STOP_FOREGROUND_REMOVE)
|
||||
stopSelf()
|
||||
Log.i(TAG, "GPS-Tracking gestoppt")
|
||||
@@ -206,9 +210,10 @@ class WaypointLocationService : Service() {
|
||||
val msg = getString(R.string.notification_waypoint_reached, waypoint.name)
|
||||
updateNotification(msg)
|
||||
|
||||
// Ton nur abspielen wenn Audiodatei vorhanden und Abspielregeln erfuellt
|
||||
if (waypoint.soundUri.isBlank()) {
|
||||
Log.d(TAG, "Kein Ton fuer Wegpunkt '${waypoint.name}' - keine Audiodatei")
|
||||
// v2.5.12 — Effektive Clipliste prüfen. activeClips() berücksichtigt
|
||||
// sowohl das neue audioClips-Modell als auch Legacy-soundUri.
|
||||
if (waypoint.activeClips().isEmpty()) {
|
||||
Log.d(TAG, "Kein Ton fuer Wegpunkt '${waypoint.name}' - keine aktiven Audioclips")
|
||||
return
|
||||
}
|
||||
|
||||
@@ -246,21 +251,28 @@ class WaypointLocationService : Service() {
|
||||
/**
|
||||
* Spielt den Wegpunkt-Ton ab (Begleitmusik-Sequenz).
|
||||
* Kann direkt oder nach PTT-Ende aufgerufen werden.
|
||||
*
|
||||
* v2.5.12 — Multi-Clip:
|
||||
* - Es werden ALLE aktiven Clips des Wegpunkts der Reihe nach abgespielt.
|
||||
* - Inaktive Clips werden übersprungen (siehe [Waypoint.activeClips]).
|
||||
* - Begleitmusik wird einmalig vor dem ersten Clip pausiert/geduckt
|
||||
* und einmalig nach dem letzten Clip wiederhergestellt — nicht zwischen
|
||||
* den Clips, damit die Sequenz nahtlos wirkt.
|
||||
* - playCount wird genau einmal pro Eintrittsereignis erhöht, nachdem
|
||||
* der letzte Clip natürlich endete (keine Erhöhung bei Fehler).
|
||||
* - Bei einem Fehler eines Clips wird abgebrochen, Begleitmusik wieder
|
||||
* hergestellt; playCount bleibt unverändert.
|
||||
*/
|
||||
private fun playWaypointAudio(waypoint: Waypoint) {
|
||||
// Begleitmusik-Sequenz:
|
||||
// 1. beforeWaypointAudio() - Begleitmusik pausieren/ducken/faden
|
||||
// 2. audioPlayer.play() - Wegpunkt-Ton starten
|
||||
// 3a. onCompletion - nach naturalem Ende: afterWaypointAudio() + playCount++
|
||||
// 3b. onError - bei Fehler: afterWaypointAudio() (kein playCount++)
|
||||
//
|
||||
// Alles laeuft im Main-Dispatcher, da ExoPlayer (Begleitmusik) Main erfordert.
|
||||
// Die Callbacks von AudioPlayer kommen auf dem MediaPlayer-Thread und werden
|
||||
// per serviceScope.launch(Dispatchers.Main) weitergeleitet.
|
||||
|
||||
serviceScope.launch(Dispatchers.Main) {
|
||||
val mgr = musicManager
|
||||
|
||||
val clipUris = waypoint.activeClips().map { it.uri }
|
||||
if (clipUris.isEmpty()) {
|
||||
Log.d(TAG, "playWaypointAudio: keine aktiven Clips für '${waypoint.name}'")
|
||||
return@launch
|
||||
}
|
||||
|
||||
// Tour-Einstellungen laden
|
||||
val settings: TourAudioSettings? = if (mgr != null) {
|
||||
runCatching {
|
||||
@@ -269,7 +281,7 @@ class WaypointLocationService : Service() {
|
||||
}.getOrNull()
|
||||
} else null
|
||||
|
||||
// 1. Begleitmusik vor Wegpunkt-Audio anpassen
|
||||
// 1. Begleitmusik einmalig vor erstem Clip anpassen
|
||||
if (mgr != null && settings != null && settings.enabled) {
|
||||
runCatching {
|
||||
mgr.currentSettings = settings
|
||||
@@ -279,35 +291,85 @@ class WaypointLocationService : Service() {
|
||||
}
|
||||
}
|
||||
|
||||
// 2. Wegpunkt-Ton abspielen
|
||||
// onCompletion und onError werden auf dem MediaPlayer-Thread aufgerufen;
|
||||
// wir leiten sie zurueck in den Main-Dispatcher fuer ExoPlayer-Zugriffe.
|
||||
audioPlayer.play(
|
||||
context = applicationContext,
|
||||
soundUri = waypoint.soundUri,
|
||||
onCompletion = {
|
||||
// Natuerliches Ende: Begleitmusik wiederherstellen + Zaehler erhoehen
|
||||
serviceScope.launch(Dispatchers.Main) {
|
||||
Log.d(TAG, "Wegpunkt-Ton beendet (natural completion): ${waypoint.name}")
|
||||
restoreBackgroundMusic(mgr, settings)
|
||||
}
|
||||
// playCount auf IO-Thread inkrementieren (Repository-Zugriff)
|
||||
serviceScope.launch(Dispatchers.IO) {
|
||||
runCatching {
|
||||
repository.incrementPlayCount(waypoint.id)
|
||||
}.onFailure { e ->
|
||||
Log.e(TAG, "Fehler beim Inkrementieren von playCount fuer ${waypoint.name}", e)
|
||||
}
|
||||
}
|
||||
},
|
||||
onError = { e ->
|
||||
// Fehler: Begleitmusik trotzdem wiederherstellen; kein playCount++
|
||||
serviceScope.launch(Dispatchers.Main) {
|
||||
Log.w(TAG, "Wegpunkt-Ton Fehler (${waypoint.name}): ${e?.message}")
|
||||
restoreBackgroundMusic(mgr, settings)
|
||||
}
|
||||
}
|
||||
// 2. Beim PTT-Coordinator registrieren – über die gesamte
|
||||
// Multi-Clip-Sequenz hinweg. Pause/Resume betreffen immer
|
||||
// den aktuell aktiven MediaPlayer im AudioPlayer-Wrapper.
|
||||
WaypointAudioInterruptionCoordinator.register(
|
||||
source = WaypointAudioInterruptionCoordinator.Source.GPS,
|
||||
isCurrentlyPlaying = { audioPlayer.isPlaying },
|
||||
pause = { audioPlayer.pause() },
|
||||
resume = { audioPlayer.resume() }
|
||||
)
|
||||
|
||||
// 3. Clips sequenziell abspielen.
|
||||
playClipSequence(
|
||||
waypoint = waypoint,
|
||||
clipUris = clipUris,
|
||||
index = 0,
|
||||
mgr = mgr,
|
||||
settings = settings
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* v2.5.12 — Spielt den Clip mit Index [index] und ruft sich selbst nach
|
||||
* natürlichem Ende für den nächsten Clip auf. Bei Fehler oder am Ende
|
||||
* der Liste wird die Begleitmusik wiederhergestellt; der Coordinator
|
||||
* abgemeldet; und bei natürlichem Ende der gesamten Sequenz wird
|
||||
* playCount inkrementiert.
|
||||
*/
|
||||
private fun playClipSequence(
|
||||
waypoint: Waypoint,
|
||||
clipUris: List<String>,
|
||||
index: Int,
|
||||
mgr: BackgroundMusicManager?,
|
||||
settings: TourAudioSettings?
|
||||
) {
|
||||
if (index !in clipUris.indices) {
|
||||
// Sequenz erfolgreich durchlaufen
|
||||
finishSequence(waypoint, mgr, settings, incrementPlayCount = true)
|
||||
return
|
||||
}
|
||||
|
||||
val uri = clipUris[index]
|
||||
audioPlayer.play(
|
||||
context = applicationContext,
|
||||
soundUri = uri,
|
||||
onCompletion = {
|
||||
serviceScope.launch(Dispatchers.Main) {
|
||||
Log.d(TAG, "Clip ${index + 1}/${clipUris.size} beendet (${waypoint.name})")
|
||||
playClipSequence(waypoint, clipUris, index + 1, mgr, settings)
|
||||
}
|
||||
},
|
||||
onError = { e ->
|
||||
Log.w(TAG, "Clip ${index + 1}/${clipUris.size} Fehler (${waypoint.name}): ${e?.message}")
|
||||
// Bei Fehler abbrechen, Begleitmusik wiederherstellen, KEIN playCount++
|
||||
serviceScope.launch(Dispatchers.Main) {
|
||||
finishSequence(waypoint, mgr, settings, incrementPlayCount = false)
|
||||
}
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
private fun finishSequence(
|
||||
waypoint: Waypoint,
|
||||
mgr: BackgroundMusicManager?,
|
||||
settings: TourAudioSettings?,
|
||||
incrementPlayCount: Boolean
|
||||
) {
|
||||
WaypointAudioInterruptionCoordinator.unregister(
|
||||
WaypointAudioInterruptionCoordinator.Source.GPS
|
||||
)
|
||||
restoreBackgroundMusic(mgr, settings)
|
||||
if (incrementPlayCount) {
|
||||
serviceScope.launch(Dispatchers.IO) {
|
||||
runCatching {
|
||||
repository.incrementPlayCount(waypoint.id)
|
||||
}.onFailure { e ->
|
||||
Log.e(TAG, "Fehler beim Inkrementieren von playCount fuer ${waypoint.name}", e)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user