|
|
@@ -119,7 +119,9 @@ import { deviceInfo } from '@kit.BasicServicesKit';
|
|
|
import '../common/network/RemoteCacheRegistry';
|
|
|
import { shouldWrapLocalMusicMenuInScroll } from '../common/util/LocalMusicMenuScrollHelper';
|
|
|
import { ServerLogUtil } from '../common/util/ServerLogUtil';
|
|
|
-import { MusicPlaybackController, MusicPlaybackControllerActions } from '../controller/MusicPlaybackController';
|
|
|
+import { MusicPlaybackController } from '../controller/MusicPlaybackController';
|
|
|
+import { PlaybackCoordinator, PlaybackRuntime } from '../controller/PlaybackCoordinator'
|
|
|
+import { PlaybackStateBridge } from '../controller/PlaybackStateBridge'
|
|
|
import { lyricService, SongData } from '../common/service/LyricService';
|
|
|
import { shouldResolveRemoteLyricOnPlay, tryResolveRemotePlaybackLyric } from '../common/util/RemotePlaybackLyricUtil';
|
|
|
import { resolvePlayerDismissMorphTarget } from '../common/util/PlayerDismissHelper';
|
|
|
@@ -146,7 +148,6 @@ import {
|
|
|
} from '../common/util/RemotePlayerUtil';
|
|
|
import {
|
|
|
PlaylistPlayRequest,
|
|
|
- consumePendingPlaylistPlay,
|
|
|
clearPendingPlaylistPlay
|
|
|
} from '../common/util/PlaylistPlayRequestStore';
|
|
|
import { resolvePlaylistDisplayCount } from '../common/util/PlaylistPlayDispatchHelper'
|
|
|
@@ -485,21 +486,39 @@ export struct LocalMusic {
|
|
|
private contentNode?: ComponentContent<Object> = undefined;
|
|
|
private skipNextPlaylistPersist: boolean = false
|
|
|
private playbackController: MusicPlaybackController = MusicPlaybackController.getInstance()
|
|
|
- private playbackControllerActions: MusicPlaybackControllerActions = {
|
|
|
- playOrPause: (): void => {
|
|
|
- this.playOrPause()
|
|
|
+ private playbackCoordinator: PlaybackCoordinator = PlaybackCoordinator.getInstance()
|
|
|
+ private playbackStateBridge: PlaybackStateBridge = PlaybackStateBridge.getInstance()
|
|
|
+ private playbackRuntime: PlaybackRuntime = {
|
|
|
+ playQueue: async (queue: VideoItem[], startIndex: number, source: string) => {
|
|
|
+ const safeIndex = queue.length <= 0 ? -1 : Math.max(0, Math.min(startIndex, queue.length - 1))
|
|
|
+ if (safeIndex < 0) {
|
|
|
+ return
|
|
|
+ }
|
|
|
+ this.songList = [...queue]
|
|
|
+ this.currentSongList = [...queue]
|
|
|
+ this.sonDataSource.pushArrayData(this.songList)
|
|
|
+ this.curIndex = safeIndex
|
|
|
+ this.currentSong = queue[safeIndex]
|
|
|
+ AppStorage.setOrCreate('currentSong', this.currentSong)
|
|
|
+ await this.doPlay(queue[safeIndex], safeIndex, false, source === 'controller-open')
|
|
|
+ this.playbackStateBridge.replaceQueue(this.songList, this.curIndex)
|
|
|
+ this.playbackStateBridge.updatePlaybackState(
|
|
|
+ this.CONTROL_PlayStatus === PlayStatus.PLAY,
|
|
|
+ this.mIjkMediaPlayer.getCurrentPosition(),
|
|
|
+ this.getActiveDuration()
|
|
|
+ )
|
|
|
},
|
|
|
- playNext: (): Promise<void> => {
|
|
|
- return this.playNext()
|
|
|
+ playOrPause: async () => {
|
|
|
+ await this.playOrPause()
|
|
|
},
|
|
|
- playPrevious: (): Promise<void> => {
|
|
|
- return this.playPrevious()
|
|
|
+ playNext: async () => {
|
|
|
+ await this.playNext()
|
|
|
},
|
|
|
- setLoopMode: (): void => {
|
|
|
- this.setLoopMode()
|
|
|
+ playPrevious: async () => {
|
|
|
+ await this.playPrevious()
|
|
|
},
|
|
|
- seekTo: (value: string, source?: string): Promise<void> => {
|
|
|
- return this.seekTo(value, source)
|
|
|
+ seekTo: async (value: string, source?: string) => {
|
|
|
+ await this.seekTo(value, source ?? 'coordinator')
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@@ -1046,7 +1065,7 @@ export struct LocalMusic {
|
|
|
}
|
|
|
// 组件生命周期
|
|
|
aboutToAppear() {
|
|
|
- this.playbackController.setActions(this.playbackControllerActions)
|
|
|
+ this.playbackCoordinator.setRuntime(this.playbackRuntime)
|
|
|
|
|
|
console.info('onecold aboutToAppear sdkApiVersion = '+deviceInfo.sdkApiVersion)
|
|
|
if(ArrayUtil.isNotEmpty(this.videoLocalList)&&this.modeType==0){
|
|
|
@@ -1110,44 +1129,6 @@ export struct LocalMusic {
|
|
|
}
|
|
|
});
|
|
|
|
|
|
- // 监听歌单播放请求事件
|
|
|
- let eventPlaylistPlay: emitter.InnerEvent = { eventId: EventConstants.EVENT_PLAYLIST_PLAY }
|
|
|
- emitter.on(eventPlaylistPlay, async (eventData: emitter.EventData) => {
|
|
|
- const data = eventData.data as Record<string, Object>
|
|
|
-
|
|
|
- if (!data) {
|
|
|
- Logger.error('heanup eventPlaylistPlay: eventData.data is undefined or null')
|
|
|
- return
|
|
|
- }
|
|
|
-
|
|
|
- // 检查歌单播放数据结构
|
|
|
- if (data.playlistId && data.songFilePaths && data.startIndex !== undefined) {
|
|
|
- const playlistData = new PlaylistPlayRequest(
|
|
|
- data.playlistId as string,
|
|
|
- data.playlistName as string,
|
|
|
- data.songCount as number,
|
|
|
- data.startIndex as number,
|
|
|
- data.songFilePaths as string[],
|
|
|
- data.isJump as boolean,
|
|
|
- data.playType as number
|
|
|
- )
|
|
|
-
|
|
|
- await this.dispatchPlaylistPlayRequest(playlistData)
|
|
|
- return
|
|
|
- }
|
|
|
-
|
|
|
- Logger.error('heanup eventPlaylistPlay: 接收到无效的数据结构')
|
|
|
- });
|
|
|
- Promise.resolve().then(async (): Promise<void> => {
|
|
|
- const pendingPlaylistRequest = consumePendingPlaylistPlay();
|
|
|
- if (!pendingPlaylistRequest) {
|
|
|
- return;
|
|
|
- }
|
|
|
- Logger.info(TAG,
|
|
|
- `检测到待处理播放请求,准备补偿执行: ${pendingPlaylistRequest.playlistName}, startIndex=${pendingPlaylistRequest.startIndex}`);
|
|
|
- await this.dispatchPlaylistPlayRequest(pendingPlaylistRequest);
|
|
|
- });
|
|
|
-
|
|
|
let eventRefreshSort: emitter.InnerEvent = { eventId: EventConstants.EVENT_PLAYLIST_REFRESH_SORT }
|
|
|
// 监听广播事件(通用设置配置更新)
|
|
|
emitter.on(eventRefreshSort, (eventData: emitter.EventData) => {
|
|
|
@@ -2293,7 +2274,7 @@ export struct LocalMusic {
|
|
|
// 组件消失生命周期
|
|
|
aboutToDisappear() {
|
|
|
console.info('LifeCycleComponent aboutToDisappear');
|
|
|
- this.playbackController.clearActions(this.playbackControllerActions)
|
|
|
+ this.playbackCoordinator.clearRuntime(this.playbackRuntime)
|
|
|
if (this.alphaBetHideTimer) {
|
|
|
clearTimeout(this.alphaBetHideTimer);
|
|
|
this.alphaBetHideTimer = 0;
|
|
|
@@ -2334,7 +2315,6 @@ export struct LocalMusic {
|
|
|
emitter.off(EventConstants.EVENT_SETTING_UPDATE);
|
|
|
emitter.off(EventConstants.EVENT_WEBDAV_METADATA_UPDATED);
|
|
|
emitter.off(EventConstants.EVENT_EQUALIZER_CHANGED);
|
|
|
- emitter.off(EventConstants.EVENT_PLAYLIST_PLAY);
|
|
|
emitter.off(EventConstants.EVENT_PLAYLIST_REFRESH_SORT);
|
|
|
emitter.off(EventConstants.EVENT_PLAY_QUEUE_REFRESH);
|
|
|
emitter.off(EventConstants.EVENT_OPEN_LOCAL_SPECIAL_LIST);
|
|
|
@@ -17685,6 +17665,15 @@ export struct LocalMusic {
|
|
|
|
|
|
}
|
|
|
|
|
|
+ try {
|
|
|
+ this.playbackStateBridge.updatePlaybackState(
|
|
|
+ this.CONTROL_PlayStatus === PlayStatus.PLAY,
|
|
|
+ position,
|
|
|
+ duration
|
|
|
+ )
|
|
|
+ } catch (error) {
|
|
|
+ // setProgress 频率较高,这里仅做兜底避免影响主流程
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
private startProgressTask() {
|
|
|
@@ -17779,6 +17768,7 @@ export struct LocalMusic {
|
|
|
this.curIndex = index
|
|
|
this.currentSong = this.songList[this.curIndex]
|
|
|
this.applyCurrentSongMetadata(this.currentSong)
|
|
|
+ this.playbackStateBridge.replaceQueue(this.songList, this.curIndex)
|
|
|
}
|
|
|
|
|
|
private ensureSongQueued(song: VideoItem): number {
|
|
|
@@ -18955,6 +18945,15 @@ export struct LocalMusic {
|
|
|
} catch (error) {
|
|
|
Logger.error('heanup 发送播放状态变化事件失败: ' + error)
|
|
|
}
|
|
|
+ try {
|
|
|
+ this.playbackStateBridge.updatePlaybackState(
|
|
|
+ this.CONTROL_PlayStatus === PlayStatus.PLAY,
|
|
|
+ this.getActivePlaybackPositionMs(),
|
|
|
+ this.getActiveDuration()
|
|
|
+ )
|
|
|
+ } catch (error) {
|
|
|
+ Logger.warn(TAG, `回写 PlaybackStateBridge 失败: ${error}`)
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
private setPlaybackStateChangeListener(): void {
|