Merge pull request #3208 from team-spotube/fix/ios-startup-crash

fix: crash at startup from a Koin cycle in DeviceAudioPlayerQueue
This commit is contained in:
Kingkor Roy Tirtho 2026-11-03 19:08:23 +06:00 committed by GitHub
commit 68fdd68cb9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -18,10 +18,7 @@
package org.spotube.spotube.core.audioplayer package org.spotube.spotube.core.audioplayer
import org.spotube.plugin_interfaces.plugin_apis.audio.StreamProtocol import org.spotube.plugin_interfaces.plugin_apis.audio.StreamProtocol
import org.spotube.spotube.PlatformType
import org.spotube.spotube.getPlatform
import org.spotube.spotube.core.di.injectLogger import org.spotube.spotube.core.di.injectLogger
import org.spotube.spotube.core.server.StreamingUrlRepository
import org.spotube.spotube.modules.blacklist.BlacklistRepository import org.spotube.spotube.modules.blacklist.BlacklistRepository
import org.spotube.spotube.modules.library.local_tracks.media.LocalMediaCacheRepository import org.spotube.spotube.modules.library.local_tracks.media.LocalMediaCacheRepository
import org.spotube.spotube.modules.plugin.PluginProvider import org.spotube.spotube.modules.plugin.PluginProvider
@ -54,7 +51,6 @@ class DeviceAudioPlayerQueue(
private val blacklistRepository: BlacklistRepository) : AudioPlayerQueue, KoinComponent { private val blacklistRepository: BlacklistRepository) : AudioPlayerQueue, KoinComponent {
private val logger by injectLogger<DeviceAudioPlayerQueue>() private val logger by injectLogger<DeviceAudioPlayerQueue>()
private val streamingUrlRepository = get<StreamingUrlRepository>()
private val scope = CoroutineScope(Dispatchers.IO + SupervisorJob()) private val scope = CoroutineScope(Dispatchers.IO + SupervisorJob())
@ -519,25 +515,7 @@ class DeviceAudioPlayerQueue(
private suspend fun QueueEntry.toMediaItem(): MediaItem? { private suspend fun QueueEntry.toMediaItem(): MediaItem? {
return when (this) { return when (this) {
is QueueEntry.StreamingTrack -> { is QueueEntry.StreamingTrack -> {
val isIos = getPlatform().type == PlatformType.IOS val resolvedUrl = url.ifBlank { buildStreamingUrl(track.id, protocol) }
val requiresIosResolution = isIos && (
url.isBlank() ||
url.startsWith("http://127.0.0.1") ||
url.startsWith("https://127.0.0.1") ||
url.startsWith("http://[::1]") ||
url.startsWith("https://[::1]") ||
url.startsWith("http://localhost") ||
url.startsWith("https://localhost"))
val resolvedStream = if (requiresIosResolution) {
streamingUrlRepository.resolveStreamInfo(track)
} else {
null
}
val resolvedUrl = if (requiresIosResolution) {
resolvedStream?.url ?: buildStreamingUrl(track.id, protocol)
} else {
url.ifBlank { buildStreamingUrl(track.id, protocol) }
}
if (resolvedUrl.isBlank()) return null if (resolvedUrl.isBlank()) return null
MediaItem( MediaItem(
title = track.title, title = track.title,
@ -546,7 +524,7 @@ class DeviceAudioPlayerQueue(
duration = track.durationMs.milliseconds, duration = track.durationMs.milliseconds,
coverURL = artworkUrl.orEmpty(), coverURL = artworkUrl.orEmpty(),
url = resolvedUrl, url = resolvedUrl,
protocol = resolvedStream?.protocol ?: protocol) protocol = protocol)
} }
is QueueEntry.LocalTrack -> { is QueueEntry.LocalTrack -> {