fix(ios): resolve compileKotlinIosArm64 type mismatches in IosMediaSession and stub getRadioMix

Co-Authored-By: pgwiz <pgwiz@users.noreply.github.com>
This commit is contained in:
pgwiz 2026-10-28 10:05:38 +03:00
parent 02d903e5ed
commit 7254a8e35d
2 changed files with 40 additions and 50 deletions

View File

@ -23,8 +23,7 @@ import kotlinx.cinterop.ExperimentalForeignApi
import platform.AVFAudio.AVAudioSession import platform.AVFAudio.AVAudioSession
import platform.AVFAudio.AVAudioSessionCategoryPlayback import platform.AVFAudio.AVAudioSessionCategoryPlayback
import platform.AVFAudio.AVAudioSessionModeDefault import platform.AVFAudio.AVAudioSessionModeDefault
import platform.Foundation.NSDictionary import platform.AVFAudio.AVAudioSessionSetActiveOptionNotifyOthersOnDeactivation
import platform.Foundation.NSMutableDictionary
import platform.Foundation.NSNotificationCenter import platform.Foundation.NSNotificationCenter
import platform.Foundation.NSOperationQueue import platform.Foundation.NSOperationQueue
import platform.MediaPlayer.MPChangePlaybackPositionCommandEvent import platform.MediaPlayer.MPChangePlaybackPositionCommandEvent
@ -73,21 +72,32 @@ internal class IosMediaSession {
if (configured) return if (configured) return
configured = true configured = true
audioSession.setCategory( runCatching {
category = AVAudioSessionCategoryPlayback, audioSession.setCategory(
mode = AVAudioSessionModeDefault, category = AVAudioSessionCategoryPlayback,
options = 0u, mode = AVAudioSessionModeDefault,
error = null) options = 0u,
error = null
)
}
registerAudioSessionNotifications() registerAudioSessionNotifications()
registerRemoteCommands() registerRemoteCommands()
} }
fun activate() { fun activate() {
audioSession.setActive(true, error = null) runCatching {
audioSession.setActive(active = true, withOptions = 0u, error = null)
}
} }
fun deactivate() { fun deactivate() {
audioSession.setActive(false, error = null) runCatching {
audioSession.setActive(
active = false,
withOptions = AVAudioSessionSetActiveOptionNotifyOthersOnDeactivation,
error = null
)
}
} }
fun update( fun update(
@ -101,21 +111,21 @@ internal class IosMediaSession {
return return
} }
val info = NSMutableDictionary() val info = mutableMapOf<Any?, Any?>()
info.setObject(item.title, forKey = MPMediaItemPropertyTitle) info[MPMediaItemPropertyTitle] = item.title
info.setObject(item.artist, forKey = MPMediaItemPropertyArtist) info[MPMediaItemPropertyArtist] = item.artist
item.album.takeIf { it.isNotBlank() }?.let { item.album.takeIf { it.isNotBlank() }?.let {
info.setObject(it, forKey = MPMediaItemPropertyAlbumTitle) info[MPMediaItemPropertyAlbumTitle] = it
} }
if (durationSeconds.isFinite() && durationSeconds > 0) { if (durationSeconds.isFinite() && durationSeconds > 0) {
info.setObject(durationSeconds, forKey = MPMediaItemPropertyPlaybackDuration) info[MPMediaItemPropertyPlaybackDuration] = durationSeconds
} }
if (positionSeconds.isFinite() && positionSeconds >= 0) { if (positionSeconds.isFinite() && positionSeconds >= 0) {
info.setObject(positionSeconds, forKey = MPNowPlayingInfoPropertyElapsedPlaybackTime) info[MPNowPlayingInfoPropertyElapsedPlaybackTime] = positionSeconds
} }
info.setObject(if (isPlaying) 1.0 else 0.0, forKey = MPNowPlayingInfoPropertyPlaybackRate) info[MPNowPlayingInfoPropertyPlaybackRate] = if (isPlaying) 1.0 else 0.0
lastIsPlaying = isPlaying lastIsPlaying = isPlaying
nowPlayingInfoCenter.nowPlayingInfo = info as NSDictionary nowPlayingInfoCenter.nowPlayingInfo = info
} }
fun clear() { fun clear() {
@ -137,17 +147,20 @@ internal class IosMediaSession {
notificationTokens += notificationCenter.addObserverForName( notificationTokens += notificationCenter.addObserverForName(
name = platform.AVFAudio.AVAudioSessionInterruptionNotification, name = platform.AVFAudio.AVAudioSessionInterruptionNotification,
`object` = audioSession, `object` = audioSession,
queue = NSOperationQueue.mainQueue()) { notification -> queue = NSOperationQueue.mainQueue()
val type = notification?.userInfo?.get( ) { notification ->
platform.AVFAudio.AVAudioSessionInterruptionTypeKey) as? Number val type = (notification?.userInfo?.get(
if (type?.intValue == platform.AVFAudio.AVAudioSessionInterruptionTypeBegan) { platform.AVFAudio.AVAudioSessionInterruptionTypeKey
) as? Number)?.toLong()?.toULong()
if (type == platform.AVFAudio.AVAudioSessionInterruptionTypeBegan) {
onPause?.invoke() onPause?.invoke()
} else if (type?.intValue == platform.AVFAudio.AVAudioSessionInterruptionTypeEnded) { } else if (type == platform.AVFAudio.AVAudioSessionInterruptionTypeEnded) {
activate() activate()
val options = notification?.userInfo?.get( val options = (notification?.userInfo?.get(
platform.AVFAudio.AVAudioSessionInterruptionOptionKey) as? Number platform.AVFAudio.AVAudioSessionInterruptionOptionKey
val shouldResume = (options?.intValue ?: 0) and ) as? Number)?.toLong()?.toULong() ?: 0uL
platform.AVFAudio.AVAudioSessionInterruptionOptionShouldResume.toInt() != 0 val shouldResume = (options and
platform.AVFAudio.AVAudioSessionInterruptionOptionShouldResume) != 0uL
if (shouldResume) onPlay?.invoke() if (shouldResume) onPlay?.invoke()
} }
} }

View File

@ -88,29 +88,6 @@ actual class NewPipeService {
} }
actual suspend fun getRadioMix(videoId: String): List<VideoSearchResult> { actual suspend fun getRadioMix(videoId: String): List<VideoSearchResult> {
return withContext(Dispatchers.IO) { return emptyList()
runCatching {
val extractor = YouTube.getPlaylistExtractor("https://www.youtube.com/watch?v=$videoId&list=RD$videoId")
extractor.fetchPage()
val results = extractor.initialPage
results.items.mapNotNull { item ->
if (item is StreamInfoItem) {
VideoSearchResult(
title = item.name,
url = item.url,
uploader = item.uploaderName ?: "Unknown",
durationMs = secondsToMs(item.duration),
thumbnailUrl = item.thumbnails.firstOrNull()?.url.orEmpty(),
id = runCatching { Url(item.url).parameters["v"] }.getOrNull()
?: item.url.substringAfter("watch?v=", "").substringBefore("&")
.takeIf { it.isNotEmpty() }
?: item.url.substringAfterLast("/")
)
} else {
null
}
}
}.getOrDefault(emptyList())
}
} }
} }