* Copyright (C) 2021 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "tone.h"
#include <thread>
#include "call_control_manager.h"
#include "telephony_log_wrapper.h"
#ifdef SUPPORT_DSOFTBUS
#include "distributed_communication_manager.h"
#endif
namespace OHOS {
namespace Telephony {
using AudioPlay = int32_t (AudioPlayer::*)(const std::string &, AudioStandard::AudioStreamType, PlayerType);
Tone::Tone() : audioPlayer_(new (std::nothrow) AudioPlayer()) {}
Tone::Tone(ToneDescriptor tone) : audioPlayer_(new (std::nothrow) AudioPlayer())
{
currentToneDescriptor_ = tone;
}
Tone::~Tone()
{
if (audioPlayer_ != nullptr) {
delete audioPlayer_;
audioPlayer_ = nullptr;
}
}
void Tone::Init() {}
int32_t Tone::Play()
{
if (currentToneDescriptor_ == TONE_UNKNOWN) {
TELEPHONY_LOGE("tone descriptor unknown");
return CALL_ERR_AUDIO_UNKNOWN_TONE;
}
if (IsUseTonePlayer(currentToneDescriptor_)) {
TELEPHONY_LOGI("currentToneDescriptor = %{public}d", currentToneDescriptor_);
if (!InitTonePlayer()) {
TELEPHONY_LOGE("InitTonePlayer failed");
return TELEPHONY_ERROR;
}
if (currentToneDescriptor_ == ToneDescriptor::TONE_FINISHED) {
if (!tonePlayer_->StartTone()) {
return CALL_ERR_AUDIO_TONE_PLAY_FAILED;
}
return TELEPHONY_SUCCESS;
}
std::shared_ptr<AudioStandard::TonePlayer> tonePlayerPtr = tonePlayer_;
std::thread play([tonePlayerPtr]() {
pthread_setname_np(pthread_self(), TONE_PLAY_THREAD);
tonePlayerPtr->StartTone();
});
play.detach();
}
return TELEPHONY_SUCCESS;
}
int32_t Tone::Stop()
{
std::lock_guard<ffrt::mutex> lock(mutex_);
if (currentToneDescriptor_ == TONE_UNKNOWN) {
TELEPHONY_LOGE("tone descriptor unknown");
return CALL_ERR_AUDIO_UNKNOWN_TONE;
}
if (IsUseTonePlayer(currentToneDescriptor_)) {
if (tonePlayer_ != nullptr) {
tonePlayer_->StopTone();
tonePlayer_->Release();
}
} else {
if (audioPlayer_ == nullptr) {
TELEPHONY_LOGE("audioPlayer_ is nullptr");
return TELEPHONY_ERR_LOCAL_PTR_NULL;
}
audioPlayer_->SetStop(PlayerType::TYPE_TONE, true);
}
return TELEPHONY_SUCCESS;
}
bool Tone::InitTonePlayer()
{
using namespace OHOS::AudioStandard;
if (tonePlayer_ == nullptr) {
StreamUsage streamUsage = GetStreamUsageByToneType(currentToneDescriptor_);
AudioRendererInfo rendererInfo = {};
rendererInfo.contentType = ContentType::CONTENT_TYPE_UNKNOWN;
rendererInfo.streamUsage = streamUsage;
rendererInfo.rendererFlags = 0;
tonePlayer_ = TonePlayer::Create(rendererInfo);
if (tonePlayer_ == nullptr) {
return false;
}
ToneType toneType = ConvertToneDescriptorToToneType(currentToneDescriptor_);
if (!tonePlayer_->LoadTone(toneType)) {
return false;
}
}
return true;
}
ToneDescriptor Tone::ConvertDigitToTone(char digit)
{
ToneDescriptor dtmf = ToneDescriptor::TONE_UNKNOWN;
switch (digit) {
case '0':
dtmf = ToneDescriptor::TONE_DTMF_CHAR_0;
break;
case '1':
dtmf = ToneDescriptor::TONE_DTMF_CHAR_1;
break;
case '2':
dtmf = ToneDescriptor::TONE_DTMF_CHAR_2;
break;
case '3':
dtmf = ToneDescriptor::TONE_DTMF_CHAR_3;
break;
case '4':
dtmf = ToneDescriptor::TONE_DTMF_CHAR_4;
break;
case '5':
dtmf = ToneDescriptor::TONE_DTMF_CHAR_5;
break;
case '6':
dtmf = ToneDescriptor::TONE_DTMF_CHAR_6;
break;
case '7':
dtmf = ToneDescriptor::TONE_DTMF_CHAR_7;
break;
case '8':
dtmf = ToneDescriptor::TONE_DTMF_CHAR_8;
break;
case '9':
dtmf = ToneDescriptor::TONE_DTMF_CHAR_9;
break;
case '*':
dtmf = ToneDescriptor::TONE_DTMF_CHAR_P;
break;
case '#':
dtmf = ToneDescriptor::TONE_DTMF_CHAR_W;
break;
default:
break;
}
return dtmf;
}
AudioStandard::ToneType Tone::ConvertToneDescriptorToToneType(ToneDescriptor tone)
{
using namespace OHOS::AudioStandard;
ToneType tonType = ToneType::NUM_TONES;
switch (tone) {
case ToneDescriptor::TONE_DTMF_CHAR_0:
tonType = ToneType::TONE_TYPE_DIAL_0;
break;
case ToneDescriptor::TONE_DTMF_CHAR_1:
tonType = ToneType::TONE_TYPE_DIAL_1;
break;
case ToneDescriptor::TONE_DTMF_CHAR_2:
tonType = ToneType::TONE_TYPE_DIAL_2;
break;
case ToneDescriptor::TONE_DTMF_CHAR_3:
tonType = ToneType::TONE_TYPE_DIAL_3;
break;
case ToneDescriptor::TONE_DTMF_CHAR_4:
tonType = ToneType::TONE_TYPE_DIAL_4;
break;
case ToneDescriptor::TONE_DTMF_CHAR_5:
tonType = ToneType::TONE_TYPE_DIAL_5;
break;
case ToneDescriptor::TONE_DTMF_CHAR_6:
tonType = ToneType::TONE_TYPE_DIAL_6;
break;
case ToneDescriptor::TONE_DTMF_CHAR_7:
tonType = ToneType::TONE_TYPE_DIAL_7;
break;
case ToneDescriptor::TONE_DTMF_CHAR_8:
tonType = ToneType::TONE_TYPE_DIAL_8;
break;
case ToneDescriptor::TONE_DTMF_CHAR_9:
tonType = ToneType::TONE_TYPE_DIAL_9;
break;
case ToneDescriptor::TONE_DTMF_CHAR_P:
tonType = ToneType::TONE_TYPE_DIAL_S;
break;
case ToneDescriptor::TONE_DTMF_CHAR_W:
tonType = ToneType::TONE_TYPE_DIAL_P;
break;
default:
tonType = ConvertCallToneDescriptorToToneType(tone);
break;
}
return tonType;
}
AudioStandard::ToneType Tone::ConvertCallToneDescriptorToToneType(ToneDescriptor tone)
{
using namespace OHOS::AudioStandard;
ToneType tonType = ToneType::NUM_TONES;
switch (tone) {
case ToneDescriptor::TONE_RINGBACK:
tonType = ToneType::TONE_TYPE_COMMON_SUPERVISORY_RINGTONE;
break;
case ToneDescriptor::TONE_WAITING:
tonType = ToneType::TONE_TYPE_COMMON_SUPERVISORY_CALL_WAITING;
break;
case ToneDescriptor::TONE_FINISHED:
tonType = ToneType::TONE_TYPE_COMMON_PROPRIETARY_PROMPT;
break;
default:
break;
}
return tonType;
}
AudioStandard::StreamUsage Tone::GetStreamUsageByToneType(ToneDescriptor descriptor)
{
AudioStandard::StreamUsage streamUsage = AudioStandard::StreamUsage::STREAM_USAGE_UNKNOWN;
switch (descriptor) {
case ToneDescriptor::TONE_DTMF_CHAR_0:
case ToneDescriptor::TONE_DTMF_CHAR_1:
case ToneDescriptor::TONE_DTMF_CHAR_2:
case ToneDescriptor::TONE_DTMF_CHAR_3:
case ToneDescriptor::TONE_DTMF_CHAR_4:
case ToneDescriptor::TONE_DTMF_CHAR_5:
case ToneDescriptor::TONE_DTMF_CHAR_6:
case ToneDescriptor::TONE_DTMF_CHAR_7:
case ToneDescriptor::TONE_DTMF_CHAR_8:
case ToneDescriptor::TONE_DTMF_CHAR_9:
case ToneDescriptor::TONE_DTMF_CHAR_P:
case ToneDescriptor::TONE_DTMF_CHAR_W:
streamUsage = AudioStandard::StreamUsage::STREAM_USAGE_DTMF;
break;
case ToneDescriptor::TONE_RINGBACK:
streamUsage = AudioStandard::StreamUsage::STREAM_USAGE_VOICE_MODEM_COMMUNICATION;
break;
case ToneDescriptor::TONE_WAITING:
streamUsage = AudioStandard::StreamUsage::STREAM_USAGE_VOICE_MODEM_COMMUNICATION;
int32_t state;
DelayedSingleton<CallControlManager>::GetInstance()->GetVoIPCallState(state);
if (state == (int32_t)CallStateToApp::CALL_STATE_RINGING ||
state == (int32_t)CallStateToApp::CALL_STATE_OFFHOOK ||
state == (int32_t)CallStateToApp::CALL_STATE_ANSWERED) {
streamUsage = AudioStandard::StreamUsage::STREAM_USAGE_VOICE_COMMUNICATION;
}
break;
case ToneDescriptor::TONE_FINISHED:
streamUsage = AudioStandard::StreamUsage::STREAM_USAGE_VOICE_RINGTONE;
break;
default:
break;
}
#ifdef SUPPORT_DSOFTBUS
bool isVoipCall = false;
auto dcMgrInstance = DelayedSingleton<DistributedCommunicationManager>::GetInstance();
if (dcMgrInstance != nullptr) {
isVoipCall = dcMgrInstance->IsSinkRole() && dcMgrInstance->IsConnected();
}
if (isVoipCall && streamUsage == AudioStandard::StreamUsage::STREAM_USAGE_VOICE_MODEM_COMMUNICATION) {
streamUsage = AudioStandard::StreamUsage::STREAM_USAGE_VOICE_COMMUNICATION;
TELEPHONY_LOGI("dc use voip");
}
#endif
return streamUsage;
}
bool Tone::IsUseTonePlayer(ToneDescriptor tone)
{
bool ret = false;
switch (tone) {
case ToneDescriptor::TONE_DTMF_CHAR_0:
case ToneDescriptor::TONE_DTMF_CHAR_1:
case ToneDescriptor::TONE_DTMF_CHAR_2:
case ToneDescriptor::TONE_DTMF_CHAR_3:
case ToneDescriptor::TONE_DTMF_CHAR_4:
case ToneDescriptor::TONE_DTMF_CHAR_5:
case ToneDescriptor::TONE_DTMF_CHAR_6:
case ToneDescriptor::TONE_DTMF_CHAR_7:
case ToneDescriptor::TONE_DTMF_CHAR_8:
case ToneDescriptor::TONE_DTMF_CHAR_9:
case ToneDescriptor::TONE_DTMF_CHAR_P:
case ToneDescriptor::TONE_DTMF_CHAR_W:
ret = true;
break;
case ToneDescriptor::TONE_RINGBACK:
case ToneDescriptor::TONE_WAITING:
case ToneDescriptor::TONE_FINISHED:
ret = true;
break;
default:
break;
}
return ret;
}
void Tone::ReleaseRenderer()
{
if (audioPlayer_ == nullptr) {
TELEPHONY_LOGE("audioPlayer_ is nullptr");
return;
}
audioPlayer_->ReleaseRenderer();
}
ToneDescriptor Tone::getCurrentToneType()
{
TELEPHONY_LOGI("currentToneDescriptor_ = %{public}d", currentToneDescriptor_);
return currentToneDescriptor_;
}
}
}