fix photo cache and setting config
This commit is contained in:
+2
-1
@@ -23,6 +23,7 @@ import com.zhushenwudi.lovelivemusicplayer.platform.AppLog
|
||||
import com.zhushenwudi.lovelivemusicplayer.platform.PlatformServices
|
||||
import java.io.File
|
||||
import kotlin.random.Random
|
||||
import kotlin.time.Duration.Companion.milliseconds
|
||||
|
||||
actual class PlayerController(context: Context) {
|
||||
private val appContext = context.applicationContext
|
||||
@@ -114,7 +115,7 @@ actual class PlayerController(context: Context) {
|
||||
durationMs = player.duration.coerceAtLeast(0),
|
||||
)
|
||||
}
|
||||
delay(200)
|
||||
delay(200.milliseconds)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -284,8 +284,10 @@ internal val DeStrings: Map<String, String> = mapOf(
|
||||
"now_playing_song" to "Läuft gerade: %s",
|
||||
"fetch_songs_fail_or_net" to "Datenfehler oder Netzwerkfehler",
|
||||
"explain_songs_data_kmp" to "Songdaten: Bibliotheksmetadaten, Version",
|
||||
"explain_user_data_kmp" to "Benutzerdaten: Likes/Verlauf/Playlists/Cache, dann beenden",
|
||||
"explain_image_cache" to "Bildcache: heruntergeladene Cover, danach neu laden",
|
||||
"explain_user_data_kmp" to "Benutzerdaten: Likes/Verlauf/Playlists/Cache",
|
||||
"remove_songs_data_kmp" to "Songdaten löschen",
|
||||
"clear_image_cache" to "Bildcache löschen",
|
||||
"remove_user_data_kmp" to "Benutzerdaten löschen",
|
||||
"confirm_delete_from_menu_short" to "Aus Playlist löschen?",
|
||||
"play_text" to "Spielen,Pausierte",
|
||||
|
||||
@@ -284,8 +284,10 @@ internal val EnStrings: Map<String, String> = mapOf(
|
||||
"now_playing_song" to "Now Playing: %s",
|
||||
"fetch_songs_fail_or_net" to "Data error or network failure",
|
||||
"explain_songs_data_kmp" to "Song data: library metadata, version",
|
||||
"explain_user_data_kmp" to "User data: likes/history/playlists/cache, then quit",
|
||||
"explain_image_cache" to "Image cache: downloaded covers, reloaded after clearing",
|
||||
"explain_user_data_kmp" to "User data: likes/history/playlists/cache",
|
||||
"remove_songs_data_kmp" to "Clear song data",
|
||||
"clear_image_cache" to "Clear image cache",
|
||||
"remove_user_data_kmp" to "Clear user data",
|
||||
"confirm_delete_from_menu_short" to "Delete from playlist?",
|
||||
"play_text" to "Playing,Paused",
|
||||
|
||||
@@ -284,8 +284,10 @@ internal val JaStrings: Map<String, String> = mapOf(
|
||||
"now_playing_song" to "再生中:%s",
|
||||
"fetch_songs_fail_or_net" to "データ異常またはネットワーク失敗",
|
||||
"explain_songs_data_kmp" to "曲データ:ライブラリメタデータ、バージョン",
|
||||
"explain_user_data_kmp" to "ユーザーデータ:好き/履歴/プレイリスト/キャッシュを削除して終了",
|
||||
"explain_image_cache" to "画像キャッシュ:ダウンロード済みカバー。削除後に再読み込み",
|
||||
"explain_user_data_kmp" to "ユーザーデータ:好き/履歴/プレイリスト/キャッシュ",
|
||||
"remove_songs_data_kmp" to "曲データを削除",
|
||||
"clear_image_cache" to "画像キャッシュを削除",
|
||||
"remove_user_data_kmp" to "ユーザーデータを削除",
|
||||
"confirm_delete_from_menu_short" to "プレイリストから削除しますか?",
|
||||
"play_text" to "放送中,停止しました",
|
||||
|
||||
@@ -284,8 +284,10 @@ internal val ZhStrings: Map<String, String> = mapOf(
|
||||
"now_playing_song" to "正在播放:%s",
|
||||
"fetch_songs_fail_or_net" to "数据异常或网络失败",
|
||||
"explain_songs_data_kmp" to "歌曲数据:曲库元数据、版本号",
|
||||
"explain_user_data_kmp" to "用户数据:喜欢/历史/歌单/缓存,并退出应用",
|
||||
"explain_image_cache" to "图片缓存:已下载的封面,清除后重新加载",
|
||||
"explain_user_data_kmp" to "用户数据:喜欢/历史/歌单/缓存",
|
||||
"remove_songs_data_kmp" to "清除歌曲数据",
|
||||
"clear_image_cache" to "清除图片缓存",
|
||||
"remove_user_data_kmp" to "清除用户数据",
|
||||
"confirm_delete_from_menu_short" to "确认从歌单删除?",
|
||||
"play_text" to "播放中,已暂停",
|
||||
|
||||
+2
-1
@@ -7,6 +7,7 @@ import kotlinx.coroutines.flow.MutableStateFlow
|
||||
import kotlinx.coroutines.flow.StateFlow
|
||||
import kotlinx.coroutines.flow.asStateFlow
|
||||
import kotlinx.coroutines.launch
|
||||
import kotlin.time.Duration.Companion.seconds
|
||||
|
||||
class SleepTimer(
|
||||
private val scope: CoroutineScope,
|
||||
@@ -23,7 +24,7 @@ class SleepTimer(
|
||||
_remainingMs.value = left
|
||||
job = scope.launch {
|
||||
while (left > 0) {
|
||||
delay(1_000)
|
||||
delay(1.seconds)
|
||||
left -= 1_000
|
||||
_remainingMs.value = left.coerceAtLeast(0)
|
||||
}
|
||||
|
||||
+35
-2
@@ -1,6 +1,8 @@
|
||||
package com.zhushenwudi.lovelivemusicplayer.player
|
||||
|
||||
import kotlinx.cinterop.CValue
|
||||
import kotlinx.cinterop.ExperimentalForeignApi
|
||||
import kotlinx.cinterop.useContents
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.Job
|
||||
@@ -40,9 +42,13 @@ import platform.AVFoundation.rate
|
||||
import platform.AVFoundation.replaceCurrentItemWithPlayerItem
|
||||
import platform.AVFoundation.resourceLoader
|
||||
import platform.AVFoundation.seekToTime
|
||||
import platform.CoreGraphics.CGRectMake
|
||||
import platform.CoreGraphics.CGSize
|
||||
import platform.CoreGraphics.CGSizeMake
|
||||
import platform.CoreMedia.CMTimeGetSeconds
|
||||
import platform.CoreMedia.CMTimeMake
|
||||
import platform.Foundation.NSBundle
|
||||
import platform.Foundation.NSThread
|
||||
import platform.Foundation.NSError
|
||||
import platform.Foundation.NSMutableURLRequest
|
||||
import platform.Foundation.NSNotification
|
||||
@@ -69,6 +75,9 @@ import platform.MediaPlayer.MPRemoteCommandHandlerStatus
|
||||
import platform.MediaPlayer.MPRemoteCommandHandlerStatusCommandFailed
|
||||
import platform.MediaPlayer.MPRemoteCommandHandlerStatusSuccess
|
||||
import platform.MediaPlayer.MPSeekCommandEvent
|
||||
import platform.UIKit.UIGraphicsBeginImageContextWithOptions
|
||||
import platform.UIKit.UIGraphicsEndImageContext
|
||||
import platform.UIKit.UIGraphicsGetImageFromCurrentImageContext
|
||||
import platform.UIKit.UIImage
|
||||
import platform.darwin.dispatch_async
|
||||
import platform.darwin.dispatch_get_main_queue
|
||||
@@ -455,6 +464,10 @@ actual class PlayerController {
|
||||
* 封面 + 专辑信息启用灵动岛媒体胶囊。
|
||||
*/
|
||||
private fun updateNowPlayingInfo() {
|
||||
if (!NSThread.isMainThread) {
|
||||
dispatch_async(dispatch_get_main_queue()) { updateNowPlayingInfo() }
|
||||
return
|
||||
}
|
||||
val s = _state.value
|
||||
val current = s.current ?: return
|
||||
val songName = current.musicName ?: return
|
||||
@@ -502,12 +515,32 @@ actual class PlayerController {
|
||||
else -> raw
|
||||
}
|
||||
val image = UIImage.imageWithContentsOfFile(path) ?: return null
|
||||
val artwork = MPMediaItemArtwork(boundsSize = image.size) { _ -> image }
|
||||
val artwork = coverArtwork(image)
|
||||
cachedArtworkMusicId = id
|
||||
cachedArtwork = artwork
|
||||
return artwork
|
||||
}
|
||||
|
||||
/**
|
||||
* 系统会按锁屏 / 控制中心要的尺寸回调。直接交原图时,负一屏封面会空白。
|
||||
*/
|
||||
private fun coverArtwork(image: UIImage): MPMediaItemArtwork {
|
||||
return MPMediaItemArtwork(boundsSize = image.size) { requested ->
|
||||
scaledCover(image, requested)
|
||||
}
|
||||
}
|
||||
|
||||
private fun scaledCover(image: UIImage, requested: CValue<CGSize>): UIImage {
|
||||
val width = requested.useContents { this.width }
|
||||
val height = requested.useContents { this.height }
|
||||
if (width < 1.0 || height < 1.0) return image
|
||||
UIGraphicsBeginImageContextWithOptions(CGSizeMake(width, height), false, 0.0)
|
||||
image.drawInRect(CGRectMake(0.0, 0.0, width, height))
|
||||
val scaled = UIGraphicsGetImageFromCurrentImageContext()
|
||||
UIGraphicsEndImageContext()
|
||||
return scaled ?: image
|
||||
}
|
||||
|
||||
private fun prefetchHttpArtwork(musicId: String, url: String) {
|
||||
if (musicId == coverFetchingMusicId) return
|
||||
if (musicId == cachedArtworkMusicId && cachedArtwork != null) return
|
||||
@@ -537,7 +570,7 @@ actual class PlayerController {
|
||||
return@dispatch_async
|
||||
}
|
||||
if (_state.value.current?.musicId != musicId) return@dispatch_async
|
||||
val artwork = MPMediaItemArtwork(boundsSize = image.size) { _ -> image }
|
||||
val artwork = coverArtwork(image)
|
||||
cachedArtworkMusicId = musicId
|
||||
cachedArtwork = artwork
|
||||
updateNowPlayingInfo()
|
||||
|
||||
Reference in New Issue
Block a user