• 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 'basic';
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.showInfo(TAG, `isActive, volumeType: ${volumeType}`);
133    let interfaceVolumeType = this.formatAudioVolumeTypeToInterface(volumeType);
134    this.mAudioManager.isActive(interfaceVolumeType, (err: BusinessError, data: boolean) => {
135      Log.showInfo(TAG, `isActive, err: ${err} data: ${JSON.stringify(data)}`);
136      if (err) {
137        return;
138      }
139      callback(volumeType, data);
140    });
141  }
142
143  getVolume(volumeType: AudioVolumeType, callback: (volumeType: AudioVolumeType, data: number) => void): void {
144    Log.showInfo(TAG, `getVolume, volumeType: ${volumeType}`);
145    let interfaceVolumeType = this.formatAudioVolumeTypeToInterface(volumeType);
146    this.addInterfaceCallQueue({
147      interfaceName: InterfaceName.getVolume,
148      params: [interfaceVolumeType],
149      callbackFunction: (err: BusinessError, data: number) => {
150        Log.showInfo(TAG, `getVolume, err: ${JSON.stringify(err)} data: ${JSON.stringify(data)}`);
151        if (err) {
152          return;
153        }
154        callback(volumeType, data);
155      }
156    });
157  }
158
159  getMaxVolume(volumeType: AudioVolumeType, callback: (volumeType: AudioVolumeType, data: number) => void): void {
160    Log.showInfo(TAG, `getMaxVolume, volumeType: ${volumeType}`);
161    let interfaceVolumeType = this.formatAudioVolumeTypeToInterface(volumeType);
162    this.mAudioManager.getMaxVolume(interfaceVolumeType, (err: BusinessError, data: number) => {
163      Log.showInfo(TAG, `getMaxVolume, err: ${JSON.stringify(err)} data: ${JSON.stringify(data)}`);
164      if (err) {
165        return;
166      }
167      callback(volumeType, data);
168    });
169  }
170
171  getMinVolume(volumeType: AudioVolumeType, callback: (volumeType: AudioVolumeType, data: number) => void): void {
172    Log.showInfo(TAG, `getMinVolume, volumeType: ${volumeType}`);
173    let interfaceVolumeType = this.formatAudioVolumeTypeToInterface(volumeType);
174    this.mAudioManager.getMinVolume(interfaceVolumeType, (err: BusinessError, data: number) => {
175      Log.showInfo(TAG, `getMinVolume, err: ${JSON.stringify(err)} data: ${JSON.stringify(data)}`);
176      if (err) {
177        return;
178      }
179      callback(volumeType, data);
180    });
181  }
182
183  setVolumeAndMute(volumeType: AudioVolumeType, volume: number, mute: boolean, callback?: () => void): void {
184    Log.showInfo(TAG, `setVolumeAndMute, volumeType: ${volumeType} volume: ${volume} mute: ${mute}`);
185    if (volume !== undefined && mute !== undefined) {
186      this.setVolume(volumeType, volume, () => {
187        Log.showInfo(TAG, `setVolume`);
188        this.setMute(volumeType, mute, callback);
189      });
190    } else if (volume !== undefined) {
191      this.setVolume(volumeType, volume);
192    } else if (mute !== undefined) {
193      this.setMute(volumeType, mute, callback);
194    }
195  }
196
197  setVolume(volumeType: AudioVolumeType, volume: number, callback?: () => void): void {
198    Log.showInfo(TAG, `setVolume, volumeType: ${volumeType} volume: ${volume}`);
199    let interfaceVolumeType = this.formatAudioVolumeTypeToInterface(volumeType);
200    this.addInterfaceCallQueue({
201      interfaceName: InterfaceName.setVolume,
202      params: [interfaceVolumeType, volume],
203      callbackFunction: (err: BusinessError) => {
204        Log.showInfo(TAG, `setVolume, callback err: ${err} `);
205        if (err) {
206          return;
207        }
208        if (callback) {
209          callback();
210        }
211      }
212    });
213  }
214
215  setMute(volumeType: AudioVolumeType, mute: boolean, callback?: () => void): void {
216    Log.showInfo(TAG, `setMute, volumeType: ${volumeType} mute: ${mute}`);
217    let interfaceVolumeType = this.formatAudioVolumeTypeToInterface(volumeType);
218    this.addInterfaceCallQueue({
219      interfaceName: InterfaceName.mute,
220      params: [interfaceVolumeType, mute],
221      callbackFunction: (err: BusinessError) => {
222        Log.showInfo(TAG, `setMute, err: ${JSON.stringify(err)}`);
223        if (err) {
224          return;
225        }
226        this.getVolumeInfo(volumeType, (volumeInfo: VolumeInfo) => {
227          Log.showInfo(TAG, `setMute, volumeInfo: ${JSON.stringify(volumeInfo)}`);
228          if (callback) {
229            callback();
230          }
231        });
232      }
233    });
234  }
235
236  formatAudioVolumeTypeFromInterface(audioVolumeType): AudioVolumeType {
237    let formatValue: AudioVolumeType;
238    if (audioVolumeType == audio.AudioVolumeType.VOICE_CALL) {
239      formatValue = AudioVolumeType.VOICE_CALL;
240    } else if (audioVolumeType == audio.AudioVolumeType.RINGTONE) {
241      formatValue = AudioVolumeType.RINGTONE;
242    } else if (audioVolumeType == audio.AudioVolumeType.MEDIA) {
243      formatValue = AudioVolumeType.MEDIA;
244    } else if (audioVolumeType == audio.AudioVolumeType.VOICE_ASSISTANT) {
245      formatValue = AudioVolumeType.VOICE_ASSISTANT;
246    }
247    return formatValue;
248  }
249
250  formatAudioVolumeTypeToInterface(audioVolumeType: AudioVolumeType) {
251    let formatValue;
252    if (audioVolumeType == AudioVolumeType.VOICE_CALL) {
253      formatValue = audio.AudioVolumeType.VOICE_CALL;
254    } else if (audioVolumeType == AudioVolumeType.RINGTONE) {
255      formatValue = audio.AudioVolumeType.RINGTONE;
256    } else if (audioVolumeType == AudioVolumeType.MEDIA) {
257      formatValue = audio.AudioVolumeType.MEDIA;
258    } else if (audioVolumeType == AudioVolumeType.VOICE_ASSISTANT) {
259      formatValue = audio.AudioVolumeType.VOICE_ASSISTANT;
260    }
261    return formatValue;
262  }
263
264  addInterfaceCallQueue(data: VolumeCallQueueItemData): void {
265    Log.showDebug(TAG, `addInterfaceCallQueue, interfaceName: ${data.interfaceName} params: ${JSON.stringify(data.params)}`);
266    this.mInterfaceCallQueue.push(data);
267    if (this.mInterfaceCallQueue.length == 1) {
268      this.execInterfaceCallQueueFirst();
269    }
270  }
271
272  execInterfaceCallQueueFirst(): void {
273    Log.showInfo(TAG, `execInterfaceCallQueueFirst, ${this.mInterfaceCallQueue.length}`);
274    let queueData = this.mInterfaceCallQueue[0];
275    if (queueData.interfaceName == InterfaceName.isMute) {
276      this.mAudioManager.isMute(queueData.params[0], (err: BusinessError, data: boolean) => {
277        Log.showInfo(TAG, 'execInterfaceCallQueueFirst, isMute callback');
278        this.execInterfaceCallQueueNext().then(() => {
279        }).catch((e) => {
280        });
281        queueData.callbackFunction(err, data);
282      });
283    } else if (queueData.interfaceName == InterfaceName.mute) {
284      this.mAudioManager.mute(queueData.params[0], queueData.params[1], (err: BusinessError) => {
285        Log.showInfo(TAG, 'execInterfaceCallQueueFirst, mute callback');
286        this.execInterfaceCallQueueNext().then(() => {
287        }).catch((e) => {
288        });
289        queueData.callbackFunction(err);
290      });
291    } else if (queueData.interfaceName == InterfaceName.getVolume) {
292      this.mAudioManager.getVolume(queueData.params[0], (err: BusinessError, data: number) => {
293        Log.showInfo(TAG, 'execInterfaceCallQueueFirst, getVolume callback');
294        this.execInterfaceCallQueueNext().then(() => {
295        }).catch((e) => {
296        });
297        queueData.callbackFunction(err, data);
298      });
299    } else if (queueData.interfaceName == InterfaceName.setVolume) {
300      this.mAudioManager.setVolume(queueData.params[0], queueData.params[1], (err: BusinessError) => {
301        Log.showInfo(TAG, 'execInterfaceCallQueueFirst, setVolume callback');
302        this.execInterfaceCallQueueNext().then(() => {
303        }).catch((e) => {
304        });
305        queueData.callbackFunction(err);
306      });
307    }
308  }
309
310  async execInterfaceCallQueueNext(): Promise<void> {
311    Log.showInfo(TAG, `execInterfaceCallQueueNext, ${this.mInterfaceCallQueue.length}`);
312    this.mInterfaceCallQueue.splice(0, 1);
313    if (this.mInterfaceCallQueue.length > 0) {
314      this.execInterfaceCallQueueFirst();
315    }
316  }
317}
318
319let volumePanelService = getSingleInstance(VolumePanelService, TAG);
320
321export default volumePanelService;