• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2 * Copyright (c) 2021-2022 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 audio from '@ohos.multimedia.audio';
17import { BusinessError } from '@ohos.base';
18import Log from '../../../../../../../../common/src/main/ets/default/Log';
19import getSingleInstance, { getAudioManager
20} from '../../../../../../../../common/src/main/ets/default/SingleInstanceHelper';
21import { AudioVolumeType, VolumeInfo } from '../common/Constants';
22
23const TAG = 'VolumePanelModel';
24
25export interface VolumeListener {
26  updateVolumeInfo(status: VolumeInfo): void;
27}
28
29export interface VolumeCallQueueItemData {
30  interfaceName: InterfaceName,
31  params: boolean | number[],
32
33  callbackFunction(err: BusinessError, data?: boolean | number): void;
34}
35
36enum InterfaceName {
37  isMute,
38  mute,
39  getVolume,
40  setVolume
41}
42
43export class VolumePanelService {
44  mIsStart = false;
45  mListeners = new Set<VolumeListener>();
46  mAudioManager = getAudioManager();
47  mInterfaceCallQueue: VolumeCallQueueItemData[] = [] ;
48
49  constructor() {
50    Log.showInfo(TAG, 'constructor');
51  }
52
53  startService(): void {
54    if (this.mIsStart) {
55      return;
56    }
57    this.mIsStart = true;
58    Log.showInfo(TAG, 'startService');
59    this.mAudioManager.on('volumeChange', this.onVolumeChange.bind(this));
60  }
61
62  stopService(): void {
63    if (!this.mIsStart) {
64      return;
65    }
66    Log.showInfo(TAG, 'stopService');
67    this.mIsStart = false;
68  }
69
70  registerListener(listener: VolumeListener): void {
71    let res = this.mListeners.add(listener);
72    Log.showInfo(TAG, `registser VolumeListener ${res}`);
73  }
74
75  unregisterListener(listener: VolumeListener): void {
76    let res = this.mListeners.delete(listener);
77    Log.showInfo(TAG, `unregistser VolumeListener ${res}`);
78  }
79
80  async onVolumeChange(data): Promise<void> {
81    Log.showInfo(TAG, 'onVolumeChange');
82    let volumeType = this.formatAudioVolumeTypeFromInterface(data.volumeType);
83    this.isMute(volumeType, (volumeType2: AudioVolumeType, data2: boolean) => {
84      Log.showInfo(TAG, `onVolumeChange->isMute, volumeType2: ${volumeType2} data2: ${String(data2)}`);
85      let volumeInfo: VolumeInfo = {
86        volumeType: volumeType,
87        volume: data.volume,
88        isMute: data2,
89        updateUi: data.updateUi
90      };
91      this.mListeners.forEach(listener => listener.updateVolumeInfo(volumeInfo));
92    });
93  }
94
95  isMute(volumeType: AudioVolumeType, callback: (volumeType: AudioVolumeType, data: boolean) => void): void {
96    Log.showInfo(TAG, `isMute, volumeType: ${volumeType}`);
97    let interfaceVolumeType = this.formatAudioVolumeTypeToInterface(volumeType);
98    this.addInterfaceCallQueue({
99      interfaceName: InterfaceName.isMute,
100      params: [interfaceVolumeType],
101      callbackFunction: (err, data: boolean) => {
102        Log.showInfo(TAG, `isMute, err: ${err} data: ${JSON.stringify(data)}`);
103        if (err) {
104          return;
105        }
106        callback(volumeType, data);
107      }
108    });
109  }
110
111  getVolumeInfo(volumeType: AudioVolumeType, callback?: (volumeInfo: VolumeInfo) => void): void {
112    Log.showInfo(TAG, `getVolumeInfo, volumeType: ${volumeType}`);
113    this.getVolume(volumeType, (volumeType: AudioVolumeType, data: number) => {
114      Log.showInfo(TAG, `getVolumeInfo->getVolume`);
115      this.isMute(volumeType, (volumeType2: AudioVolumeType, data2: boolean) => {
116        Log.showInfo(TAG, `getVolumeInfo->isMute`);
117        let volumeInfo: VolumeInfo = {
118          volumeType: volumeType,
119          volume: data,
120          isMute: data2,
121          updateUi: false
122        };
123        this.mListeners.forEach(listener => listener.updateVolumeInfo(volumeInfo));
124        if (callback) {
125          callback(volumeInfo);
126        }
127      });
128    });
129  }
130
131  isActive(volumeType: AudioVolumeType, callback: (volumeType: AudioVolumeType, data: boolean) => void): void {
132    Log.showDebug(TAG, `isActive, volumeType: ${volumeType}`);
133
134    let interfaceVolumeType = this.formatAudioVolumeTypeToInterface(volumeType);
135    this.mAudioManager.isActive(interfaceVolumeType, (err: BusinessError, data: boolean) => {
136      Log.showDebug(TAG, `isActive, err: ${err} data: ${JSON.stringify(data)}`);
137      if (err) {
138        return;
139      }
140      callback(volumeType, data);
141    });
142  }
143
144  getVolume(volumeType: AudioVolumeType, callback: (volumeType: AudioVolumeType, data: number) => void): void {
145    Log.showDebug(TAG, `getVolume, volumeType: ${volumeType}`);
146    let interfaceVolumeType = this.formatAudioVolumeTypeToInterface(volumeType);
147    this.addInterfaceCallQueue({
148      interfaceName: InterfaceName.getVolume,
149      params: [interfaceVolumeType],
150      callbackFunction: (err: BusinessError, data: number) => {
151        Log.showDebug(TAG, `getVolume, err: ${JSON.stringify(err)} data: ${JSON.stringify(data)}`);
152        if (err) {
153          return;
154        }
155        callback(volumeType, data);
156      }
157    });
158  }
159
160  getMaxVolume(volumeType: AudioVolumeType, callback: (volumeType: AudioVolumeType, data: number) => void): void {
161    Log.showInfo(TAG, `getMaxVolume, volumeType: ${volumeType}`);
162    let interfaceVolumeType = this.formatAudioVolumeTypeToInterface(volumeType);
163    this.mAudioManager.getMaxVolume(interfaceVolumeType, (err: BusinessError, data: number) => {
164      Log.showInfo(TAG, `getMaxVolume, err: ${JSON.stringify(err)} data: ${JSON.stringify(data)}`);
165      if (err) {
166        return;
167      }
168      callback(volumeType, data);
169    });
170  }
171
172  getMinVolume(volumeType: AudioVolumeType, callback: (volumeType: AudioVolumeType, data: number) => void): void {
173    Log.showInfo(TAG, `getMinVolume, volumeType: ${volumeType}`);
174    let interfaceVolumeType = this.formatAudioVolumeTypeToInterface(volumeType);
175    this.mAudioManager.getMinVolume(interfaceVolumeType, (err: BusinessError, data: number) => {
176      Log.showInfo(TAG, `getMinVolume, err: ${JSON.stringify(err)} data: ${JSON.stringify(data)}`);
177      if (err) {
178        return;
179      }
180      callback(volumeType, data);
181    });
182  }
183
184  setVolumeAndMute(volumeType: AudioVolumeType, volume: number, mute: boolean, callback?: () => void): void {
185    Log.showInfo(TAG, `setVolumeAndMute, volumeType: ${volumeType} volume: ${volume} mute: ${mute}`);
186    if (volume !== undefined && mute !== undefined) {
187      this.setVolume(volumeType, volume, () => {
188        Log.showInfo(TAG, `setVolume`);
189        this.setMute(volumeType, mute, callback);
190      });
191    } else if (volume !== undefined) {
192      this.setVolume(volumeType, volume);
193    } else if (mute !== undefined) {
194      this.setMute(volumeType, mute, callback);
195    }
196  }
197
198  setVolume(volumeType: AudioVolumeType, volume: number, callback?: () => void): void {
199    Log.showDebug(TAG, `setVolume, volumeType: ${volumeType} volume: ${volume}`);
200    let interfaceVolumeType = this.formatAudioVolumeTypeToInterface(volumeType);
201    this.addInterfaceCallQueue({
202      interfaceName: InterfaceName.setVolume,
203      params: [interfaceVolumeType, volume],
204      callbackFunction: (err: BusinessError) => {
205        Log.showDebug(TAG, `setVolume, callback err: ${err} `);
206        if (err) {
207          return;
208        }
209        if (callback) {
210          callback();
211        }
212      }
213    });
214  }
215
216  setMute(volumeType: AudioVolumeType, mute: boolean, callback?: () => void): void {
217    Log.showDebug(TAG, `setMute, volumeType: ${volumeType} mute: ${mute}`);
218    let interfaceVolumeType = this.formatAudioVolumeTypeToInterface(volumeType);
219    this.addInterfaceCallQueue({
220      interfaceName: InterfaceName.mute,
221      params: [interfaceVolumeType, mute],
222      callbackFunction: (err: BusinessError) => {
223        Log.showDebug(TAG, `setMute, err: ${JSON.stringify(err)}`);
224        if (err) {
225          return;
226        }
227        this.getVolumeInfo(volumeType, (volumeInfo: VolumeInfo) => {
228          Log.showDebug(TAG, `setMute, volumeInfo: ${JSON.stringify(volumeInfo)}`);
229          if (callback) {
230            callback();
231          }
232        });
233      }
234    });
235  }
236
237  formatAudioVolumeTypeFromInterface(audioVolumeType): AudioVolumeType {
238    let formatValue: AudioVolumeType;
239    if (audioVolumeType == audio.AudioVolumeType.VOICE_CALL) {
240      formatValue = AudioVolumeType.VOICE_CALL;
241    } else if (audioVolumeType == audio.AudioVolumeType.RINGTONE) {
242      formatValue = AudioVolumeType.RINGTONE;
243    } else if (audioVolumeType == audio.AudioVolumeType.MEDIA) {
244      formatValue = AudioVolumeType.MEDIA;
245    } else if (audioVolumeType == audio.AudioVolumeType.VOICE_ASSISTANT) {
246      formatValue = AudioVolumeType.VOICE_ASSISTANT;
247    }
248    return formatValue;
249  }
250
251  formatAudioVolumeTypeToInterface(audioVolumeType: AudioVolumeType) {
252    let formatValue;
253    if (audioVolumeType == AudioVolumeType.VOICE_CALL) {
254      formatValue = audio.AudioVolumeType.VOICE_CALL;
255    } else if (audioVolumeType == AudioVolumeType.RINGTONE) {
256      formatValue = audio.AudioVolumeType.RINGTONE;
257    } else if (audioVolumeType == AudioVolumeType.MEDIA) {
258      formatValue = audio.AudioVolumeType.MEDIA;
259    } else if (audioVolumeType == AudioVolumeType.VOICE_ASSISTANT) {
260      formatValue = audio.AudioVolumeType.VOICE_ASSISTANT;
261    }
262    return formatValue;
263  }
264
265  addInterfaceCallQueue(data: VolumeCallQueueItemData): void {
266    Log.showDebug(TAG, `addInterfaceCallQueue, interfaceName: ${data.interfaceName} params: ${JSON.stringify(data.params)}`);
267    this.mInterfaceCallQueue.push(data);
268    if (this.mInterfaceCallQueue.length == 1) {
269      this.execInterfaceCallQueueFirst();
270    }
271  }
272
273  execInterfaceCallQueueFirst(): void {
274    Log.showInfo(TAG, `execInterfaceCallQueueFirst, ${this.mInterfaceCallQueue.length}`);
275    let queueData = this.mInterfaceCallQueue[0];
276    if (queueData.interfaceName == InterfaceName.isMute) {
277      this.mAudioManager.isMute(queueData.params[0], (err: BusinessError, data: boolean) => {
278        Log.showInfo(TAG, 'execInterfaceCallQueueFirst, isMute callback');
279        this.execInterfaceCallQueueNext().then(() => {
280        }).catch((e) => {
281        });
282        queueData.callbackFunction(err, data);
283      });
284    } else if (queueData.interfaceName == InterfaceName.mute) {
285      this.mAudioManager.mute(queueData.params[0], queueData.params[1], (err: BusinessError) => {
286        Log.showInfo(TAG, 'execInterfaceCallQueueFirst, mute callback');
287        this.execInterfaceCallQueueNext().then(() => {
288        }).catch((e) => {
289        });
290        queueData.callbackFunction(err);
291      });
292    } else if (queueData.interfaceName == InterfaceName.getVolume) {
293      this.mAudioManager.getVolume(queueData.params[0], (err: BusinessError, data: number) => {
294        Log.showInfo(TAG, 'execInterfaceCallQueueFirst, getVolume callback');
295        this.execInterfaceCallQueueNext().then(() => {
296        }).catch((e) => {
297        });
298        queueData.callbackFunction(err, data);
299      });
300    } else if (queueData.interfaceName == InterfaceName.setVolume) {
301      this.mAudioManager.setVolume(queueData.params[0], queueData.params[1], (err: BusinessError) => {
302        Log.showInfo(TAG, 'execInterfaceCallQueueFirst, setVolume callback');
303        this.execInterfaceCallQueueNext().then(() => {
304        }).catch((e) => {
305        });
306        queueData.callbackFunction(err);
307      });
308    }
309  }
310
311  async execInterfaceCallQueueNext(): Promise<void> {
312    Log.showInfo(TAG, `execInterfaceCallQueueNext, ${this.mInterfaceCallQueue.length}`);
313    this.mInterfaceCallQueue.splice(0, 1);
314    if (this.mInterfaceCallQueue.length > 0) {
315      this.execInterfaceCallQueueFirst();
316    }
317  }
318}
319
320let volumePanelService = getSingleInstance(VolumePanelService, TAG);
321
322export default volumePanelService;