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 "tone.h"
17
18#include <thread>
19
20#include "telephony_log_wrapper.h"
21
22namespace OHOS {
23namespace Telephony {
24using AudioPlay = int32_t (AudioPlayer::*)(const std::string &, AudioStandard::AudioStreamType, PlayerType);
25
26Tone::Tone() : audioPlayer_(new (std::nothrow) AudioPlayer()) {}
27
28Tone::Tone(ToneDescriptor tone) : audioPlayer_(new (std::nothrow) AudioPlayer())
29{
30    currentToneDescriptor_ = tone;
31}
32
33Tone::~Tone()
34{
35    if (audioPlayer_ != nullptr) {
36        delete audioPlayer_;
37        audioPlayer_ = nullptr;
38    }
39}
40
41void Tone::Init() {}
42
43int32_t Tone::Play()
44{
45    if (currentToneDescriptor_ == TONE_UNKNOWN) {
46        TELEPHONY_LOGE("tone descriptor unknown");
47        return CALL_ERR_AUDIO_UNKNOWN_TONE;
48    }
49    if (IsUseTonePlayer(currentToneDescriptor_)) {
50        TELEPHONY_LOGI("currentToneDescriptor = %{public}d", currentToneDescriptor_);
51        if (!InitTonePlayer()) {
52            TELEPHONY_LOGE("InitTonePlayer failed");
53            return TELEPHONY_ERROR;
54        }
55        if (currentToneDescriptor_ == ToneDescriptor::TONE_FINISHED) {
56            if (!tonePlayer_->StartTone()) {
57                return CALL_ERR_AUDIO_TONE_PLAY_FAILED;
58            }
59            return TELEPHONY_SUCCESS;
60        }
61        std::shared_ptr<AudioStandard::TonePlayer> tonePlayerPtr = tonePlayer_;
62        std::thread play([tonePlayerPtr]() {
63            pthread_setname_np(pthread_self(), TONE_PLAY_THREAD);
64            tonePlayerPtr->StartTone();
65        });
66        play.detach();
67    } else {
68        AudioPlay audioPlay = &AudioPlayer::Play;
69        if (audioPlayer_ == nullptr) {
70            TELEPHONY_LOGE("audioPlayer_ is nullptr");
71            return TELEPHONY_ERR_LOCAL_PTR_NULL;
72        }
73        std::thread play(audioPlay, audioPlayer_, GetToneDescriptorPath(currentToneDescriptor_),
74            AudioStandard::AudioStreamType::STREAM_MUSIC, PlayerType::TYPE_TONE);
75        pthread_setname_np(play.native_handle(), TONE_PLAY_THREAD);
76        play.detach();
77    }
78    return TELEPHONY_SUCCESS;
79}
80
81int32_t Tone::Stop()
82{
83    std::lock_guard<std::mutex> lock(mutex_);
84    if (currentToneDescriptor_ == TONE_UNKNOWN) {
85        TELEPHONY_LOGE("tone descriptor unknown");
86        return CALL_ERR_AUDIO_UNKNOWN_TONE;
87    }
88    if (IsUseTonePlayer(currentToneDescriptor_)) {
89        if (tonePlayer_ != nullptr) {
90            tonePlayer_->StopTone();
91            tonePlayer_->Release();
92        }
93    } else {
94        if (audioPlayer_ == nullptr) {
95            TELEPHONY_LOGE("audioPlayer_ is nullptr");
96            return TELEPHONY_ERR_LOCAL_PTR_NULL;
97        }
98        audioPlayer_->SetStop(PlayerType::TYPE_TONE, true);
99    }
100    return TELEPHONY_SUCCESS;
101}
102
103bool Tone::InitTonePlayer()
104{
105    using namespace OHOS::AudioStandard;
106    if (tonePlayer_ == nullptr) {
107        StreamUsage streamUsage = GetStreamUsageByToneType(currentToneDescriptor_);
108        AudioRendererInfo rendererInfo = {};
109        rendererInfo.contentType = ContentType::CONTENT_TYPE_UNKNOWN;
110        rendererInfo.streamUsage = streamUsage;
111        rendererInfo.rendererFlags = 0;
112        tonePlayer_ = TonePlayer::Create(rendererInfo);
113        if (tonePlayer_ == nullptr) {
114            return false;
115        }
116        ToneType toneType = ConvertToneDescriptorToToneType(currentToneDescriptor_);
117        if (!tonePlayer_->LoadTone(toneType)) {
118            return false;
119        }
120    }
121    return true;
122}
123
124ToneDescriptor Tone::ConvertDigitToTone(char digit)
125{
126    ToneDescriptor dtmf = ToneDescriptor::TONE_UNKNOWN;
127    switch (digit) {
128        case '0':
129            dtmf = ToneDescriptor::TONE_DTMF_CHAR_0;
130            break;
131        case '1':
132            dtmf = ToneDescriptor::TONE_DTMF_CHAR_1;
133            break;
134        case '2':
135            dtmf = ToneDescriptor::TONE_DTMF_CHAR_2;
136            break;
137        case '3':
138            dtmf = ToneDescriptor::TONE_DTMF_CHAR_3;
139            break;
140        case '4':
141            dtmf = ToneDescriptor::TONE_DTMF_CHAR_4;
142            break;
143        case '5':
144            dtmf = ToneDescriptor::TONE_DTMF_CHAR_5;
145            break;
146        case '6':
147            dtmf = ToneDescriptor::TONE_DTMF_CHAR_6;
148            break;
149        case '7':
150            dtmf = ToneDescriptor::TONE_DTMF_CHAR_7;
151            break;
152        case '8':
153            dtmf = ToneDescriptor::TONE_DTMF_CHAR_8;
154            break;
155        case '9':
156            dtmf = ToneDescriptor::TONE_DTMF_CHAR_9;
157            break;
158        case '*':
159            dtmf = ToneDescriptor::TONE_DTMF_CHAR_P;
160            break;
161        case '#':
162            dtmf = ToneDescriptor::TONE_DTMF_CHAR_W;
163            break;
164        default:
165            break;
166    }
167    return dtmf;
168}
169
170AudioStandard::ToneType Tone::ConvertToneDescriptorToToneType(ToneDescriptor tone)
171{
172    using namespace OHOS::AudioStandard;
173    ToneType tonType = ToneType::NUM_TONES;
174    switch (tone) {
175        case ToneDescriptor::TONE_DTMF_CHAR_0:
176            tonType = ToneType::TONE_TYPE_DIAL_0;
177            break;
178        case ToneDescriptor::TONE_DTMF_CHAR_1:
179            tonType = ToneType::TONE_TYPE_DIAL_1;
180            break;
181        case ToneDescriptor::TONE_DTMF_CHAR_2:
182            tonType = ToneType::TONE_TYPE_DIAL_2;
183            break;
184        case ToneDescriptor::TONE_DTMF_CHAR_3:
185            tonType = ToneType::TONE_TYPE_DIAL_3;
186            break;
187        case ToneDescriptor::TONE_DTMF_CHAR_4:
188            tonType = ToneType::TONE_TYPE_DIAL_4;
189            break;
190        case ToneDescriptor::TONE_DTMF_CHAR_5:
191            tonType = ToneType::TONE_TYPE_DIAL_5;
192            break;
193        case ToneDescriptor::TONE_DTMF_CHAR_6:
194            tonType = ToneType::TONE_TYPE_DIAL_6;
195            break;
196        case ToneDescriptor::TONE_DTMF_CHAR_7:
197            tonType = ToneType::TONE_TYPE_DIAL_7;
198            break;
199        case ToneDescriptor::TONE_DTMF_CHAR_8:
200            tonType = ToneType::TONE_TYPE_DIAL_8;
201            break;
202        case ToneDescriptor::TONE_DTMF_CHAR_9:
203            tonType = ToneType::TONE_TYPE_DIAL_9;
204            break;
205        case ToneDescriptor::TONE_DTMF_CHAR_P:
206            tonType = ToneType::TONE_TYPE_DIAL_S;
207            break;
208        case ToneDescriptor::TONE_DTMF_CHAR_W:
209            tonType = ToneType::TONE_TYPE_DIAL_P;
210            break;
211        default:
212            tonType = ConvertCallToneDescriptorToToneType(tone);
213            break;
214    }
215    return tonType;
216}
217
218AudioStandard::ToneType Tone::ConvertCallToneDescriptorToToneType(ToneDescriptor tone)
219{
220    using namespace OHOS::AudioStandard;
221    ToneType tonType = ToneType::NUM_TONES;
222    switch (tone) {
223        case ToneDescriptor::TONE_RINGBACK:
224            tonType = ToneType::TONE_TYPE_COMMON_SUPERVISORY_RINGTONE;
225            break;
226        case ToneDescriptor::TONE_WAITING:
227            tonType = ToneType::TONE_TYPE_COMMON_SUPERVISORY_CALL_WAITING;
228            break;
229        case ToneDescriptor::TONE_FINISHED:
230            tonType = ToneType::TONE_TYPE_COMMON_PROPRIETARY_PROMPT;
231            break;
232        default:
233            break;
234    }
235    return tonType;
236}
237
238AudioStandard::StreamUsage Tone::GetStreamUsageByToneType(ToneDescriptor descriptor)
239{
240    AudioStandard::StreamUsage streamUsage = AudioStandard::StreamUsage::STREAM_USAGE_UNKNOWN;
241    switch (descriptor) {
242        case ToneDescriptor::TONE_DTMF_CHAR_0:
243        case ToneDescriptor::TONE_DTMF_CHAR_1:
244        case ToneDescriptor::TONE_DTMF_CHAR_2:
245        case ToneDescriptor::TONE_DTMF_CHAR_3:
246        case ToneDescriptor::TONE_DTMF_CHAR_4:
247        case ToneDescriptor::TONE_DTMF_CHAR_5:
248        case ToneDescriptor::TONE_DTMF_CHAR_6:
249        case ToneDescriptor::TONE_DTMF_CHAR_7:
250        case ToneDescriptor::TONE_DTMF_CHAR_8:
251        case ToneDescriptor::TONE_DTMF_CHAR_9:
252        case ToneDescriptor::TONE_DTMF_CHAR_P:
253        case ToneDescriptor::TONE_DTMF_CHAR_W:
254            streamUsage = AudioStandard::StreamUsage::STREAM_USAGE_DTMF;
255            break;
256        case ToneDescriptor::TONE_RINGBACK:
257        case ToneDescriptor::TONE_WAITING:
258            streamUsage = AudioStandard::StreamUsage::STREAM_USAGE_VOICE_MODEM_COMMUNICATION;
259            break;
260        case ToneDescriptor::TONE_FINISHED:
261            streamUsage = AudioStandard::StreamUsage::STREAM_USAGE_VOICE_RINGTONE;
262            break;
263        default:
264            break;
265    }
266    return streamUsage;
267}
268
269bool Tone::IsUseTonePlayer(ToneDescriptor tone)
270{
271    bool ret = false;
272    switch (tone) {
273        case ToneDescriptor::TONE_DTMF_CHAR_0:
274        case ToneDescriptor::TONE_DTMF_CHAR_1:
275        case ToneDescriptor::TONE_DTMF_CHAR_2:
276        case ToneDescriptor::TONE_DTMF_CHAR_3:
277        case ToneDescriptor::TONE_DTMF_CHAR_4:
278        case ToneDescriptor::TONE_DTMF_CHAR_5:
279        case ToneDescriptor::TONE_DTMF_CHAR_6:
280        case ToneDescriptor::TONE_DTMF_CHAR_7:
281        case ToneDescriptor::TONE_DTMF_CHAR_8:
282        case ToneDescriptor::TONE_DTMF_CHAR_9:
283        case ToneDescriptor::TONE_DTMF_CHAR_P:
284        case ToneDescriptor::TONE_DTMF_CHAR_W:
285            ret = true;
286            break;
287        case ToneDescriptor::TONE_RINGBACK:
288        case ToneDescriptor::TONE_WAITING:
289        case ToneDescriptor::TONE_FINISHED:
290            ret = true;
291            break;
292        default:
293            break;
294    }
295    return ret;
296}
297
298std::string Tone::GetToneDescriptorPath(ToneDescriptor tone)
299{
300#ifdef ABILITY_AUDIO_SUPPORT
301    return DelayedSingleton<AudioProxy>::GetInstance()->GetToneDescriptorPath(tone);
302#endif
303    return DelayedSingleton<AudioProxy>::GetInstance()->GetDefaultTonePath();
304}
305
306void Tone::ReleaseRenderer()
307{
308    if (audioPlayer_ == nullptr) {
309        TELEPHONY_LOGE("audioPlayer_ is nullptr");
310        return;
311    }
312    audioPlayer_->ReleaseRenderer();
313}
314
315ToneDescriptor Tone::getCurrentToneType()
316{
317    return currentToneDescriptor_;
318}
319} // namespace Telephony
320} // namespace OHOS
321