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 media from '@ohos.multimedia.media'
17import fileIO from '@ohos.fileio'
18
19import { Action } from '../../redux/actions/Action'
20import { Log } from '../../utils/Log'
21import { EventBus } from '../../worker/eventbus/EventBus'
22import { EventBusManager } from '../../worker/eventbus/EventBusManager'
23import { SettingManager } from '../../setting/SettingManager'
24import { Voice } from '../../setting/settingitem/Voice'
25
26export class PlaySound {
27  private TAG: string = '[PlaySound]:'
28  private appEventBus: EventBus = EventBusManager.getInstance().getEventBus()
29  private settingManager = SettingManager.getInstance()
30  private fdNumber: number = 0
31  private fdPath
32  // @ts-ignore
33  private mAVPlayer: media.AVPlayer
34  private static sInstancePlaySound: PlaySound;
35
36  constructor() {
37    Log.info(`${this.TAG} constructor start, enroll playCapture to ACTION_CAPTURE`)
38    this.appEventBus.on(Action.ACTION_CAPTURE, this.playCapture.bind(this))
39    // @ts-ignore
40    media.createAVPlayer().then((avPlayer) => {
41      Log.info(`${this.TAG} createAVPlayer then ${avPlayer}`)
42      this.mAVPlayer = avPlayer;
43      this.setAVPlayerCallback();
44    })
45  }
46
47  setAVPlayerCallback(): void {
48    Log.info(`${this.TAG} setAudioCallback`)
49    this.mAVPlayer.on('stateChange', async (state, reason) => {
50      switch (state) {
51        case 'idle':
52          Log.info(`${this.TAG} stateChange idle state`)
53          break;
54        case 'initialized':
55          Log.info(`${this.TAG} stateChange initialized state`)
56          this.mAVPlayer.prepare().then(() => {}, (err) => {
57            Log.error(`${this.TAG} case prepare error`)
58          })
59          break;
60        case 'prepared':
61          Log.info(`${this.TAG} stateChange prepared state`)
62          if (this.settingManager.getCaptureMute() == Voice.SOUND) {
63            this.mAVPlayer.play()
64          }
65          break;
66        case 'playing':
67          Log.info(`${this.TAG} stateChange playing state`)
68          break;
69        case 'completed':
70          Log.info(`${this.TAG} stateChange completed state`)
71          if (this.fdNumber !== 0) {
72            fileIO.closeSync(this.fdNumber)
73            Log.info(`${this.TAG} fileIO closeSync success`)
74          }
75          this.mAVPlayer.stop()
76          break;
77        case 'stopped':
78          Log.info(`${this.TAG} stateChange stopped state`)
79          this.mAVPlayer.reset()
80          break;
81        case 'error':
82          Log.info(`${this.TAG} case error called, err is: ${reason}`)
83          break;
84        default:
85          Log.info(`${this.TAG} unknow state: ${state}`)
86          break;
87      }
88    })
89  }
90
91  public static getInstance(): PlaySound {
92    if (!PlaySound.sInstancePlaySound) {
93      PlaySound.sInstancePlaySound = new PlaySound();
94    }
95    return PlaySound.sInstancePlaySound;
96  }
97  private playCapture(data): void {
98    Log.info(`${this.TAG} playCapture invoke E`);
99    if (this.settingManager.getCaptureMute() == Voice.SOUND) {
100      this.playSound(Voice.CAPTURE_URI)
101    }
102    Log.info(`${this.TAG} playCapture invoke X`);
103  }
104
105  private async playSound(soundUri) {
106    Log.info(`${this.TAG} playSound invoke E`)
107    this.fdPath = 'fd://'
108    fileIO.open(Voice.CAPTURE_URI).then((fdData) => {
109      this.fdPath = this.fdPath + '' + fdData
110      this.mAVPlayer.url = this.fdPath
111      this.fdNumber = fdData
112      Log.info(`${this.TAG} fileIO open then ${this.fdPath}`);
113    }).catch((err) => {
114      Log.info(`${this.TAG} open soundUri failed, err: ${err}`)
115    })
116    Log.info(`${this.TAG} playSound invoke X`)
117  }
118}