• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2* Copyright (C) 2023 Huawei Device Co., Ltd.
3* Licensed under the Apache License, Version 2.0 (the "License");
4* you may not use this file except in compliance with the License.
5* You may obtain a copy of the License at
6*
7* http://www.apache.org/licenses/LICENSE-2.0
8*
9* Unless required by applicable law or agreed to in writing, software
10* distributed under the License is distributed on an "AS IS" BASIS,
11* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12* See the License for the specific language governing permissions and
13* limitations under the License.
14*/
15
16import AVSessionManager from '@ohos.multimedia.avsession';
17import bundle from '@ohos.bundle';
18import Log from '../common/Logger';
19
20const TAG = "ControllerComponent";
21
22export default class control {
23  private isPlaying: boolean = false;
24  private isLyric: boolean = false;
25  private bundleNameMap: Map<string, string> = new Map();
26  private controllerMap: Map<string, AVSessionManager.AVSessionController> = new Map();
27  private metaDataMap: Map<string, AVSessionManager.AVMetadata> = new Map();
28  private playStateMap: Map<string, AVSessionManager.AVMetadata> = new Map();
29  private queueTitleMap: Map<string, string> = new Map();
30  private queueItemsMap: Map<string, Array<AVSessionManager.AVQueueItem>> = new Map();
31  private lyricMap: Map<string, string> = new Map();
32  private sessionArray: Array<string> = new Array();
33  private isPlayingLink: SubscribedAbstractProperty<undefined | boolean> | undefined = undefined;
34  private isLyricLink: SubscribedAbstractProperty<undefined | boolean> | undefined = undefined;
35  private bundleNameMapLink: SubscribedAbstractProperty<undefined | Map<string, string>> | undefined = undefined;
36  private metaDataMapLink: SubscribedAbstractProperty<undefined | Map<string, AVSessionManager.AVMetadata>> | undefined = undefined;
37  private playStateMapLink: SubscribedAbstractProperty<undefined | Map<string, AVSessionManager.AVMetadata>> | undefined = undefined;
38  private queueTitleMapLink: SubscribedAbstractProperty<undefined | Map<string, string>> | undefined = undefined;
39  private queueItemsMapLink: SubscribedAbstractProperty<undefined | Map<string, AVSessionManager.AVQueueItem[]>> | undefined = undefined;
40  private lyricMapLink: SubscribedAbstractProperty<undefined | Map<string, string>> | undefined = undefined;
41  private sessionArrayLink: SubscribedAbstractProperty<undefined | string[]> | undefined = undefined;
42
43  constructor() {
44    Log.info(TAG, 'constructor');
45    this.initLink();
46    Log.info(TAG, 'constructor done');
47    this.interval();
48  }
49
50  async initLink(): Promise<void> {
51    Log.info(TAG, 'initLink');
52    this.isPlayingLink = AppStorage.setAndLink<undefined | boolean>('isPlaying', undefined);
53    this.isLyricLink = AppStorage.setAndLink<undefined | boolean>('isLyric', undefined);
54    this.bundleNameMapLink = AppStorage.setAndLink<undefined | Map<string, string>>('bundleNameMap', undefined);
55    this.metaDataMapLink = AppStorage.setAndLink<undefined | Map<string, AVSessionManager.AVMetadata>>('metaDataMap', undefined);
56    this.playStateMapLink = AppStorage.setAndLink<undefined | Map<string, AVSessionManager.AVMetadata>>('playStateMap', undefined);
57    this.queueItemsMapLink = AppStorage.setAndLink<undefined | Map<string, AVSessionManager.AVQueueItem[]>>('queueItemsMap', undefined);
58    this.queueTitleMapLink = AppStorage.setAndLink<undefined | Map<string, string>>('queueTitleMap', undefined);
59    this.lyricMapLink = AppStorage.setAndLink<undefined | Map<string, string>>('lyricMap', undefined);
60    this.sessionArrayLink = AppStorage.setAndLink<undefined | string[]>('sessionArray', undefined);
61    Log.info(TAG, 'initLink done');
62  }
63
64  async startControl(): Promise<void> {
65    Log.info(TAG, 'startControl');
66    let sessionDesList: Array<AVSessionManager.AVSessionDescriptor> = await AVSessionManager.getAllSessionDescriptors();
67    Log.info(TAG, 'session des length : ' + sessionDesList.length);
68    for (let i = 0; i < sessionDesList.length; i++) {
69      let descriptor: AVSessionManager.AVSessionDescriptor = sessionDesList[i];
70      let sessionId: string = descriptor.sessionId;
71      Log.info(TAG, 'session des sessionId : ' + sessionId);
72      let controller: AVSessionManager.AVSessionController = await AVSessionManager.createController(sessionId);
73      await this.getBundleName(descriptor);
74      Log.info(TAG, 'getBundleName done : ' + sessionId);
75      await this.makeListener(controller);
76      Log.info(TAG, 'makeListener done : ' + sessionId);
77      await this.getMetaData(controller);
78      Log.info(TAG, 'makeListener done : ' + sessionId);
79      this.sessionArray[i] = sessionId;
80      this.controllerMap[sessionId] = controller;
81    }
82    let hisSessionDesList: Array<AVSessionManager.AVSessionDescriptor> =
83      await AVSessionManager.getHistoricalSessionDescriptors();
84    Log.info(TAG, 'historical session des length : ' + hisSessionDesList.length);
85    for (let j = 0; j < hisSessionDesList.length; j++) {
86      let descriptor: AVSessionManager.AVSessionDescriptor = hisSessionDesList[j];
87      let sessionId: string = descriptor.sessionId;
88      Log.info(TAG, 'historical session des sessionId : ' + sessionId);
89      if (this.sessionArray.indexOf(sessionId) >= 0) {
90        Log.info(TAG, 'historical session already exist quit :  sessionId : ' + sessionId);
91        continue;
92      }
93      await this.getBundleName(descriptor);
94      this.sessionArray.push(sessionId);
95      this.metaDataMap[sessionId] = {
96        title: '未在播放',
97        artist: '',
98        assetId: ''
99      }
100    }
101    this.isPlayingLink!.set(this.isPlaying);
102    Log.info(TAG, 'session info done to link isPlaying');
103    this.metaDataMapLink!.set(this.metaDataMap);
104    Log.info(TAG, 'session info done to link metaDataMap');
105    this.playStateMapLink!.set(this.playStateMap);
106    Log.info(TAG, 'session info done to link playStateMap');
107    this.queueItemsMapLink!.set(this.queueItemsMap);
108    Log.info(TAG, 'session info done to link queueItemsMap');
109    this.queueTitleMapLink!.set(this.queueTitleMap);
110    Log.info(TAG, 'session info done to link queueTitleMap');
111    this.bundleNameMapLink!.set(this.bundleNameMap);
112    Log.info(TAG, 'session info done to link bundleNameMap');
113    this.lyricMapLink!.set(this.lyricMap);
114    Log.info(TAG, 'session info done to link lyricMap');
115    this.sessionArrayLink!.set(this.sessionArray);
116    Log.info(TAG, 'session info done to link sessionArray');
117    Log.info(TAG, 'startControl done ');
118  }
119
120  async getBundleName(descriptor: AVSessionManager.AVSessionDescriptor): Promise<void> {
121    Log.info(TAG, 'getBundleName sessionId  : ' + descriptor.sessionId);
122    let bundleAppName: string = await bundle.getAbilityLabel(descriptor.elementName.bundleName,
123      descriptor.elementName.abilityName);
124    Log.info(TAG, 'getBundleName name : ' + bundleAppName);
125    this.bundleNameMap[descriptor.sessionId] = '来自 ' + bundleAppName;
126    Log.info(TAG, 'getBundleName name finished');
127  }
128
129  async getMetaData(controller: AVSessionManager.AVSessionController): Promise<void> {
130    let that = this;
131    let sessionId: string = controller.sessionId;
132    let metadata: AVSessionManager.AVMetadata = await controller.getAVMetadata();
133    that.metaDataMap[sessionId] = metadata;
134    Log.info(TAG, 'get metadata  : ' + metadata.title + ' for session :' + sessionId);
135    let queueTitle: string = await controller.getAVQueueTitle();
136    Log.info(TAG, 'get queue queueTitle  : ' + queueTitle);
137    that.queueTitleMap[sessionId] = queueTitle;
138    let queueItems: Array<AVSessionManager.AVQueueItem> = await controller.getAVQueueItems();
139    Log.info(TAG, 'get queue items  : ' + queueItems.length);
140    that.queueItemsMap[sessionId] = queueItems;
141    let avPlayState: AVSessionManager.AVPlaybackState = await controller.getAVPlaybackState();
142    let playState: AVSessionManager.PlaybackState | undefined = avPlayState.state;
143    that.playStateMap[sessionId] = playState;
144    that.isPlaying = (playState == AVSessionManager.PlaybackState.PLAYBACK_STATE_PLAY);
145    Log.info(TAG, 'get playState  : ' + that.isPlaying);
146  }
147
148  async makeListener(controller: AVSessionManager.AVSessionController): Promise<void> {
149    let that = this;
150    let sessionId: string = controller.sessionId;
151    controller.on('metadataChange', 'all', (metadata: AVSessionManager.AVMetadata) => {
152      Log.info(TAG, 'get metadata: ' + metadata.title + ' for session :' + sessionId);
153      let dataMap: Map<string, AVSessionManager.AVMetadata> | undefined = that.metaDataMapLink?.get();
154      that.metaDataMapLink?.set(null);
155      Log.info(TAG, 'get metadata check link first: ' + JSON.stringify(that.metaDataMapLink?.get()));
156      dataMap?.set(sessionId, metadata);
157      if (that.metaDataMapLink?.get() == null) {
158        Log.info(TAG, 'get metadata check link NULL');
159      } else {
160        Log.info(TAG, 'get metadata check link second: ' +
161          JSON.stringify((that.metaDataMapLink?.get()?.get(sessionId))));
162      }
163      if (dataMap) {
164        Log.info(TAG, 'get metadata check map: ' + JSON.stringify((dataMap)));
165      } else {
166        Log.info(TAG, 'get metadata check map NULL');
167      }
168
169      that.metaDataMapLink?.set(dataMap);
170      if (that.metaDataMapLink?.get() == null) {
171        Log.info(TAG, 'get metadata check link NULL');
172      } else {
173        Log.info(TAG, 'get metadata check link end: ' +
174          JSON.stringify((that.metaDataMapLink?.get()?.get(sessionId))?.title));
175      }
176    });
177    controller.on('playbackStateChange', 'all', async (playState: AVSessionManager.AVPlaybackState) => {
178      Log.info(TAG, 'get playbackState: ' + playState.state + ' for session:' + sessionId);
179      that.playStateMap[sessionId] = playState.state;
180      that.isPlaying = (playState.state == AVSessionManager.PlaybackState.PLAYBACK_STATE_PLAY);
181      that.isPlayingLink!.set(that.isPlaying);
182      that.playStateMapLink!.set(that.playStateMap);
183    });
184    controller.on('queueItemsChange', (items: Array<AVSessionManager.AVQueueItem>) => {
185      Log.info(TAG, 'get queueItems: ' + items.length + ' for session :' + sessionId);
186      that.queueItemsMap[sessionId] = items;
187      that.queueItemsMapLink!.set(that.queueItemsMap);
188    });
189    controller.on('queueTitleChange', (title: string) => {
190      Log.info(TAG, 'get queueTitle  : ' + title + ' for session :' + sessionId);
191      that.queueTitleMap[sessionId] = title;
192      that.queueTitleMapLink!.set(that.queueTitleMap);
193    });
194    controller.on('sessionEvent', async (sessionEvent: string, args) => {
195      let lyricStruct = await controller.getExtras();
196      let lyricLineNum: number = Number(lyricStruct.lyricsLineNumber);
197      that.lyricMap[sessionId] = String(lyricLineNum + ' : ' + args!.lyrics);
198      that.lyricMapLink!.set(that.lyricMap);
199    });
200  }
201
202  async play(sessionId: string): Promise<void> {
203    let command: AVSessionManager.AVControlCommand = {
204      command: 'play',
205      parameter: undefined
206    }
207    let controller: AVSessionManager.AVSessionController = this.controllerMap[sessionId];
208    await controller.sendControlCommand(command);
209  }
210
211  async pause(sessionId: string): Promise<void> {
212    let command: AVSessionManager.AVControlCommand = {
213      command: 'pause',
214      parameter: undefined
215    }
216    let controller: AVSessionManager.AVSessionController = this.controllerMap[sessionId];
217    await controller.sendControlCommand(command);
218  }
219
220  async next(sessionId: string): Promise<void> {
221    let command: AVSessionManager.AVControlCommand = {
222      command: 'playNext',
223      parameter: undefined
224    }
225    let controller: AVSessionManager.AVSessionController = this.controllerMap[sessionId];
226    await controller.sendControlCommand(command);
227  }
228
229  async previous(sessionId: string): Promise<void> {
230    let command: AVSessionManager.AVControlCommand = {
231      command: 'playPrevious',
232      parameter: undefined
233    }
234    let controller: AVSessionManager.AVSessionController = this.controllerMap[sessionId];
235    await controller.sendControlCommand(command);
236  }
237
238  async skip(sessionId: string, itemId: number): Promise<void> {
239    let controller: AVSessionManager.AVSessionController = this.controllerMap[sessionId];
240    Log.info(TAG, 'on skip to : ' + controller + ' | ' + itemId)
241    await controller.skipToQueueItem(itemId);
242  }
243
244  async getLyric(sessionId: string): Promise<void> {
245    let controller: AVSessionManager.AVSessionController = this.controllerMap[sessionId];
246    this.isLyric = !this.isLyric;
247    this.isLyricLink!.set(this.isLyric);
248    await controller.sendCommonCommand('lyrics', {
249      'lyrics': this.isLyric
250    });
251  }
252
253  async interval(): Promise<void> {
254    setInterval(async () => {
255      await this.controllerMap[this.sessionArray[0]].sendCommonCommand('lyrics', {
256        'lyrics': this.isLyric
257      });
258    }, 1000)
259  }
260}