1/*
2 * Copyright (C) 2021 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
16#include "audio_player.h"
17
18#include "audio_control_manager.h"
19#include "audio_system_manager.h"
20#include "call_manager_errors.h"
21#include "telephony_log_wrapper.h"
22
23namespace OHOS {
24namespace Telephony {
25bool AudioPlayer::InitRenderer(const wav_hdr &wavHeader, AudioStandard::AudioStreamType streamType)
26{
27    AudioStandard::AudioRendererParams rendererParams;
28    rendererParams.sampleFormat = AudioStandard::AudioSampleFormat::SAMPLE_S16LE;
29    rendererParams.sampleRate = static_cast<AudioStandard::AudioSamplingRate>(wavHeader.SamplesPerSec);
30    rendererParams.channelCount = static_cast<AudioStandard::AudioChannel>(wavHeader.NumOfChan);
31    rendererParams.encodingType = static_cast<AudioStandard::AudioEncodingType>(AudioStandard::ENCODING_PCM);
32    audioRenderer_ = AudioStandard::AudioRenderer::Create(streamType);
33    if (audioRenderer_ == nullptr) {
34        TELEPHONY_LOGE("audio renderer create failed");
35        return false;
36    }
37    if (audioRenderer_->SetParams(rendererParams) != TELEPHONY_SUCCESS) {
38        TELEPHONY_LOGE("audio renderer set params failed");
39        return false;
40    }
41    callback_ = std::make_shared<CallAudioRendererCallback>();
42    if (callback_ == nullptr) {
43        TELEPHONY_LOGE("callback_ is nullptr");
44        return false;
45    }
46    audioRenderer_->SetRendererCallback(callback_);
47    if (!audioRenderer_->Start()) {
48        TELEPHONY_LOGE("audio renderer start failed");
49        return false;
50    }
51    if (audioRenderer_->GetBufferSize(bufferLen)) {
52        TELEPHONY_LOGE("audio renderer get buffer size failed");
53        return false;
54    }
55    uint32_t frameCount;
56    if (audioRenderer_->GetFrameCount(frameCount)) {
57        TELEPHONY_LOGE("audio renderer get frame count failed");
58        return false;
59    }
60    isRenderInitialized_ = true;
61    return true;
62}
63
64bool AudioPlayer::InitRenderer()
65{
66    AudioStandard::AudioRendererOptions rendererOptions;
67    rendererOptions.streamInfo.samplingRate = AudioStandard::AudioSamplingRate::SAMPLE_RATE_96000;
68    rendererOptions.streamInfo.encoding = AudioStandard::AudioEncodingType::ENCODING_PCM;
69    rendererOptions.streamInfo.format = AudioStandard::AudioSampleFormat::SAMPLE_U8;
70    rendererOptions.streamInfo.channels = AudioStandard::AudioChannel::MONO;
71    rendererOptions.rendererInfo.contentType = AudioStandard::ContentType::CONTENT_TYPE_SPEECH;
72    rendererOptions.rendererInfo.streamUsage = AudioStandard::StreamUsage::STREAM_USAGE_VOICE_MODEM_COMMUNICATION;
73    rendererOptions.rendererInfo.rendererFlags = RENDERER_FLAG;
74    audioRenderer_ = AudioStandard::AudioRenderer::Create(rendererOptions);
75    if (audioRenderer_ == nullptr) {
76        TELEPHONY_LOGE("audio renderer create failed");
77        return false;
78    }
79    if (!audioRenderer_->Start()) {
80        TELEPHONY_LOGE("audio renderer start failed");
81        return false;
82    }
83    uint32_t frameCount;
84    if (audioRenderer_->GetFrameCount(frameCount)) {
85        TELEPHONY_LOGE("audio renderer get frame count failed");
86        return false;
87    }
88    isRenderInitialized_ = true;
89    return true;
90}
91
92bool AudioPlayer::InitCapturer()
93{
94    AudioStandard::AudioCapturerOptions capturerOptions;
95    capturerOptions.streamInfo.samplingRate = AudioStandard::AudioSamplingRate::SAMPLE_RATE_96000;
96    capturerOptions.streamInfo.encoding = AudioStandard::AudioEncodingType::ENCODING_PCM;
97    capturerOptions.streamInfo.format = AudioStandard::AudioSampleFormat::SAMPLE_U8;
98    capturerOptions.streamInfo.channels = AudioStandard::AudioChannel::MONO;
99    capturerOptions.capturerInfo.sourceType = AudioStandard::SourceType::SOURCE_TYPE_VIRTUAL_CAPTURE;
100    capturerOptions.capturerInfo.capturerFlags = CAPTURER_FLAG;
101    audioCapturer_ = AudioStandard::AudioCapturer::Create(capturerOptions);
102    if (audioCapturer_ == nullptr) {
103        TELEPHONY_LOGE("audio capturer create failed");
104        return false;
105    }
106    if (!audioCapturer_->Start()) {
107        TELEPHONY_LOGE("audio capturer start failed");
108        return false;
109    }
110    uint32_t frameCount;
111    if (audioCapturer_->GetFrameCount(frameCount)) {
112        TELEPHONY_LOGE("audio capturer get frame count failed");
113        return false;
114    }
115    isCapturerInitialized_ = true;
116    return true;
117}
118
119int32_t AudioPlayer::Play(const std::string &path, AudioStandard::AudioStreamType streamType, PlayerType playerType)
120{
121    wav_hdr wavHeader;
122    std::string realPath = "";
123    if (!GetRealPath(path, realPath) || realPath.empty()) {
124        TELEPHONY_LOGE("path or realPath is NULL");
125        return TELEPHONY_ERR_ARGUMENT_INVALID;
126    }
127    FILE *wavFile = fopen(realPath.c_str(), "rb");
128    if (wavFile == nullptr) {
129        TELEPHONY_LOGE("open audio file failed");
130        return TELEPHONY_ERR_LOCAL_PTR_NULL;
131    }
132    (void)fread(&wavHeader, READ_SIZE, sizeof(wav_hdr), wavFile);
133    SetStop(playerType, false);
134    if (!InitRenderer(wavHeader, streamType)) {
135        TELEPHONY_LOGE("audio renderer and capturer init failed");
136        (void)fclose(wavFile);
137        return TELEPHONY_ERR_UNINIT;
138    }
139    uint8_t *buffer = (uint8_t *)malloc(bufferLen + bufferLen);
140    if (buffer == nullptr) {
141        TELEPHONY_LOGE("audio malloc buffer failed");
142        (void)fclose(wavFile);
143        return TELEPHONY_ERR_LOCAL_PTR_NULL;
144    }
145    size_t bytesToWrite = 0, bytesWritten = 0;
146    TELEPHONY_LOGI("start audio rendering");
147    while (!isStop_) {
148        if (IsStop(playerType)) {
149            break;
150        } else if (feof(wavFile)) {
151            fseek(wavFile, 0, SEEK_SET); // jump back to the beginning of the file
152            fread(&wavHeader, READ_SIZE, sizeof(wav_hdr), wavFile); // skip the wav header
153        }
154        bytesToWrite = fread(buffer, READ_SIZE, bufferLen, wavFile);
155        bytesWritten = 0;
156        while ((bytesWritten < bytesToWrite) && ((bytesToWrite - bytesWritten) > MIN_BYTES)) {
157            if (IsStop(playerType)) {
158                break;
159            }
160            bytesWritten += static_cast<size_t>(
161                    audioRenderer_->Write(buffer + bytesWritten, bytesToWrite - bytesWritten));
162        }
163    }
164    free(buffer);
165    (void)fclose(wavFile);
166    TELEPHONY_LOGI("audio renderer playback done");
167    return TELEPHONY_SUCCESS;
168}
169
170int32_t AudioPlayer::Play(PlayerType playerType)
171{
172    SetStop(playerType, false);
173    if (!InitRenderer() || !InitCapturer()) {
174        TELEPHONY_LOGE("audio renderer and capturer init failed");
175        return TELEPHONY_ERR_UNINIT;
176    }
177    return TELEPHONY_SUCCESS;
178}
179
180void AudioPlayer::SetStop(PlayerType playerType, bool state)
181{
182    switch (playerType) {
183        case PlayerType::TYPE_RING:
184            isRingStop_ = state;
185            if (isRingStop_) {
186                DelayedSingleton<AudioControlManager>::GetInstance()->SetRingState(RingState::STOPPED);
187            } else {
188                DelayedSingleton<AudioControlManager>::GetInstance()->SetRingState(RingState::RINGING);
189            }
190            break;
191        case PlayerType::TYPE_TONE:
192            isToneStop_ = state;
193            if (isToneStop_) {
194                DelayedSingleton<AudioControlManager>::GetInstance()->SetToneState(ToneState::STOPPED);
195            } else {
196                DelayedSingleton<AudioControlManager>::GetInstance()->SetToneState(ToneState::TONEING);
197            }
198            break;
199        case PlayerType::TYPE_SOUND:
200            isSoundStop_ = state;
201            if (isSoundStop_) {
202                DelayedSingleton<AudioControlManager>::GetInstance()->SetSoundState(SoundState::STOPPED);
203            } else {
204                DelayedSingleton<AudioControlManager>::GetInstance()->SetSoundState(SoundState::SOUNDING);
205            }
206            break;
207        default:
208            break;
209    }
210}
211
212bool AudioPlayer::IsStop(PlayerType playerType)
213{
214    bool ret = false;
215    switch (playerType) {
216        case PlayerType::TYPE_RING:
217            ret = isRingStop_;
218            break;
219        case PlayerType::TYPE_TONE:
220            ret = isToneStop_;
221            break;
222        case PlayerType::TYPE_SOUND:
223            ret = isSoundStop_;
224            break;
225        default:
226            break;
227    }
228    return ret;
229}
230
231void AudioPlayer::ReleaseRenderer()
232{
233    if (!isRenderInitialized_) {
234        return;
235    }
236    audioRenderer_->Flush();
237    audioRenderer_->Drain();
238    audioRenderer_->Stop();
239    audioRenderer_->Release();
240    isRenderInitialized_ = false;
241}
242
243void AudioPlayer::ReleaseCapturer()
244{
245    if (!isCapturerInitialized_) {
246        return;
247    }
248    audioCapturer_->Flush();
249    audioCapturer_->Stop();
250    audioCapturer_->Release();
251    isCapturerInitialized_ = false;
252}
253
254bool AudioPlayer::GetRealPath(const std::string &profilePath, std::string &realPath)
255{
256    if (profilePath.empty()) {
257        TELEPHONY_LOGE("profilePath is empty");
258        return false;
259    }
260
261    char path[PATH_MAX] = { '\0' };
262    if (realpath(profilePath.c_str(), path) == nullptr) {
263        TELEPHONY_LOGE("get real path fail");
264        return false;
265    }
266    realPath = path;
267    return true;
268}
269
270void AudioPlayer::CallAudioRendererCallback::OnInterrupt(const AudioStandard::InterruptEvent &interruptEvent)
271{
272    if (interruptEvent.forceType == AudioStandard::INTERRUPT_FORCE) {
273        switch (interruptEvent.hintType) {
274            case AudioStandard::INTERRUPT_HINT_PAUSE:
275                break;
276            case AudioStandard::INTERRUPT_HINT_STOP:
277                if (DelayedSingleton<AudioControlManager>::GetInstance()->IsCurrentRinging() &&
278                    DelayedSingleton<AudioControlManager>::GetInstance()->IsSoundPlaying()) {
279                    DelayedSingleton<AudioControlManager>::GetInstance()->StopRingtone();
280                }
281                break;
282            default:
283                break;
284        }
285    }
286}
287
288void AudioPlayer::RingCallback::OnInterrupt(const AudioStandard::InterruptEvent &interruptEvent)
289{
290    if (interruptEvent.forceType == AudioStandard::INTERRUPT_FORCE) {
291        switch (interruptEvent.hintType) {
292            case AudioStandard::INTERRUPT_HINT_PAUSE:
293                break;
294            case AudioStandard::INTERRUPT_HINT_STOP:
295                if (DelayedSingleton<AudioControlManager>::GetInstance()->IsCurrentRinging() &&
296                    DelayedSingleton<AudioControlManager>::GetInstance()->IsSoundPlaying()) {
297                    DelayedSingleton<AudioControlManager>::GetInstance()->StopRingtone();
298                }
299                break;
300            default:
301                break;
302        }
303    }
304}
305
306void AudioPlayer::RegisterRingCallback(std::shared_ptr<Media::RingtonePlayer> &RingtonePlayer)
307{
308    std::lock_guard<std::mutex> lock(mutex_);
309    ringCallback_ = std::make_shared<RingCallback>();
310    if (ringCallback_ == nullptr) {
311        TELEPHONY_LOGE("ringCallback_ is nullptr");
312        return;
313    }
314    if (RingtonePlayer == nullptr) {
315        TELEPHONY_LOGE("RingtonePlayer is nullptr");
316        return;
317    }
318    RingtonePlayer->SetRingtonePlayerInterruptCallback(ringCallback_);
319}
320
321int32_t AudioPlayer::SetMute()
322{
323    if (audioRenderer_ == nullptr) {
324        TELEPHONY_LOGE("audioRenderer_ is nullptr");
325        return TELEPHONY_ERR_LOCAL_PTR_NULL;
326    }
327    float volume = 0.0f;
328    return audioRenderer_->SetVolume(volume);
329}
330} // namespace Telephony
331} // namespace OHOS
332