1 /*
2 * Copyright (c) 2024 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 "dspeaker_client.h"
17
18 #include "cJSON.h"
19
20 #include "daudio_constants.h"
21 #include "daudio_hisysevent.h"
22 #include "daudio_sink_hidumper.h"
23 #include "daudio_util.h"
24 #include "daudio_sink_manager.h"
25
26 #undef DH_LOG_TAG
27 #define DH_LOG_TAG "DSpeakerClient"
28
29 namespace OHOS {
30 namespace DistributedHardware {
~DSpeakerClient()31 DSpeakerClient::~DSpeakerClient()
32 {
33 DHLOGD("Release speaker client.");
34 }
35
OnEngineTransEvent(const AVTransEvent & event)36 void DSpeakerClient::OnEngineTransEvent(const AVTransEvent &event)
37 {
38 if (event.type == EventType::EVENT_START_SUCCESS) {
39 OnStateChange(DATA_OPENED);
40 } else if ((event.type == EventType::EVENT_STOP_SUCCESS) ||
41 (event.type == EventType::EVENT_CHANNEL_CLOSED) ||
42 (event.type == EventType::EVENT_START_FAIL)) {
43 OnStateChange(DATA_CLOSED);
44 }
45 }
46
OnEngineTransMessage(const std::shared_ptr<AVTransMessage> & message)47 void DSpeakerClient::OnEngineTransMessage(const std::shared_ptr<AVTransMessage> &message)
48 {
49 CHECK_NULL_VOID(message);
50 DHLOGI("On Engine message, type : %{public}s.", GetEventNameByType(message->type_).c_str());
51 DAudioSinkManager::GetInstance().HandleDAudioNotify(message->dstDevId_, message->dstDevId_,
52 static_cast<int32_t>(message->type_), message->content_);
53 }
54
OnEngineTransDataAvailable(const std::shared_ptr<AudioData> & audioData)55 void DSpeakerClient::OnEngineTransDataAvailable(const std::shared_ptr<AudioData> &audioData)
56 {
57 DHLOGD("On Engine Data available");
58 OnDecodeTransDataDone(audioData);
59 }
60
InitReceiverEngine(IAVEngineProvider * providerPtr)61 int32_t DSpeakerClient::InitReceiverEngine(IAVEngineProvider *providerPtr)
62 {
63 DHLOGI("InitReceiverEngine enter.");
64 if (speakerTrans_ == nullptr) {
65 speakerTrans_ = std::make_shared<AVTransReceiverTransport>(devId_, shared_from_this());
66 }
67 int32_t ret = speakerTrans_->InitEngine(providerPtr);
68 if (ret != DH_SUCCESS) {
69 DHLOGE("Spk client initialize av receiver adapter failed.");
70 return ERR_DH_AUDIO_NULLPTR;
71 }
72 return DH_SUCCESS;
73 }
74
InitCtrlTrans()75 int32_t DSpeakerClient::InitCtrlTrans()
76 {
77 DHLOGI("InitCtrlTrans enter");
78 if (speakerCtrlTrans_ == nullptr) {
79 speakerCtrlTrans_ = std::make_shared<DaudioSinkCtrlTrans>(devId_,
80 SESSIONNAME_SPK_SINK, SESSIONNAME_SPK_SOURCE, shared_from_this());
81 }
82 int32_t ret = speakerCtrlTrans_->SetUp(shared_from_this());
83 CHECK_AND_RETURN_RET_LOG(ret != DH_SUCCESS, ret, "Speaker ctrl SetUp failed.");
84 return DH_SUCCESS;
85 }
86
OnCtrlTransEvent(const AVTransEvent & event)87 void DSpeakerClient::OnCtrlTransEvent(const AVTransEvent &event)
88 {
89 if (event.type == EventType::EVENT_START_SUCCESS) {
90 OnStateChange(DATA_OPENED);
91 } else if ((event.type == EventType::EVENT_STOP_SUCCESS) ||
92 (event.type == EventType::EVENT_CHANNEL_CLOSED) ||
93 (event.type == EventType::EVENT_START_FAIL)) {
94 OnStateChange(DATA_CLOSED);
95 }
96 }
97
OnCtrlTransMessage(const std::shared_ptr<AVTransMessage> & message)98 void DSpeakerClient::OnCtrlTransMessage(const std::shared_ptr<AVTransMessage> &message)
99 {
100 CHECK_NULL_VOID(message);
101 DHLOGI("On Engine message, type : %{public}s.", GetEventNameByType(message->type_).c_str());
102 DAudioSinkManager::GetInstance().HandleDAudioNotify(message->dstDevId_, message->dstDevId_,
103 static_cast<int32_t>(message->type_), message->content_);
104 }
105
CreateAudioRenderer(const AudioParam & param)106 int32_t DSpeakerClient::CreateAudioRenderer(const AudioParam ¶m)
107 {
108 DHLOGD("Set up spk client: {sampleRate: %{public}d, bitFormat: %{public}d, channelMask: %{public}d,"
109 "frameSize: %{public}d, contentType: %{public}d, renderFlags: %{public}d, streamUsage: %{public}d}.",
110 param.comParam.sampleRate, param.comParam.bitFormat, param.comParam.channelMask, param.comParam.frameSize,
111 param.renderOpts.contentType, param.renderOpts.renderFlags, param.renderOpts.streamUsage);
112 audioParam_ = param;
113 AudioStandard::AudioRendererOptions rendererOptions = {
114 {
115 static_cast<AudioStandard::AudioSamplingRate>(audioParam_.comParam.sampleRate),
116 AudioStandard::AudioEncodingType::ENCODING_PCM,
117 static_cast<AudioStandard::AudioSampleFormat>(audioParam_.comParam.bitFormat),
118 static_cast<AudioStandard::AudioChannel>(audioParam_.comParam.channelMask),
119 },
120 {
121 static_cast<AudioStandard::ContentType>(audioParam_.renderOpts.contentType),
122 static_cast<AudioStandard::StreamUsage>(audioParam_.renderOpts.streamUsage),
123 audioParam_.renderOpts.renderFlags == MMAP_MODE ? AudioStandard::STREAM_FLAG_FAST : 0,
124 }
125 };
126 std::lock_guard<std::mutex> lck(devMtx_);
127 audioRenderer_ = AudioStandard::AudioRenderer::Create(rendererOptions);
128 CHECK_NULL_RETURN(audioRenderer_, ERR_DH_AUDIO_CLIENT_RENDER_CREATE_FAILED);
129
130 audioRenderer_ ->SetRendererCallback(shared_from_this());
131 if (audioParam_.renderOpts.renderFlags != MMAP_MODE) {
132 return DH_SUCCESS;
133 }
134 int32_t ret = audioRenderer_->SetRendererWriteCallback(shared_from_this());
135 if (ret != DH_SUCCESS) {
136 DHLOGE("Client save write callback failed.");
137 return ERR_DH_AUDIO_CLIENT_RENDER_CREATE_FAILED;
138 }
139 return DH_SUCCESS;
140 }
141
OnWriteData(size_t length)142 void DSpeakerClient::OnWriteData(size_t length)
143 {
144 AudioStandard::BufferDesc bufDesc;
145 CHECK_NULL_VOID(audioRenderer_);
146 if (audioRenderer_->GetBufferDesc(bufDesc) != DH_SUCCESS || bufDesc.bufLength == 0) {
147 DHLOGE("Get buffer desc failed.");
148 return;
149 }
150 CHECK_NULL_VOID(bufDesc.buffer);
151
152 std::shared_ptr<AudioData> audioData = nullptr;
153 {
154 std::unique_lock<std::mutex> spkLck(dataQueueMtx_);
155 if (dataQueue_.empty()) {
156 audioData = std::make_shared<AudioData>(bufDesc.bufLength);
157 DHLOGD("Pop spk data, dataQueue is empty. write empty data.");
158 } else {
159 audioData = dataQueue_.front();
160 dataQueue_.pop();
161 uint64_t queueSize = static_cast<uint64_t>(dataQueue_.size());
162 DHLOGD("Pop spk data, dataQueue size: %{public}" PRIu64, queueSize);
163 }
164 }
165 if ((audioData != nullptr) && (audioData->Capacity() != bufDesc.bufLength)) {
166 uint64_t capacity = static_cast<uint64_t>(audioData->Capacity());
167 uint64_t bufLength = static_cast<uint64_t>(bufDesc.bufLength);
168 DHLOGE("Audio data length is not equal to buflength. datalength: %{public}" PRIu64
169 ", bufLength: %{public}" PRIu64, capacity, bufLength);
170 }
171 if (memcpy_s(bufDesc.buffer, bufDesc.bufLength, audioData->Data(), audioData->Capacity()) != EOK) {
172 DHLOGE("Copy audio data failed.");
173 }
174 audioRenderer_->Enqueue(bufDesc);
175 }
176
SetUp(const AudioParam & param)177 int32_t DSpeakerClient::SetUp(const AudioParam ¶m)
178 {
179 int32_t ret = CreateAudioRenderer(param);
180 if (ret != DH_SUCCESS) {
181 DHLOGE("Set up failed, Create Audio renderer failed.");
182 return ret;
183 }
184 DumpFileUtil::OpenDumpFile(DUMP_SERVER_PARA, DUMP_DAUDIO_SPK_AFTER_TRANS_NAME, &dumpFile_);
185 CHECK_NULL_RETURN(speakerTrans_, ERR_DH_AUDIO_NULLPTR);
186 ret = speakerTrans_->SetUp(audioParam_, audioParam_, shared_from_this(), CAP_SPK);
187 if (ret != DH_SUCCESS) {
188 DHLOGE("Speaker trans setup failed.");
189 return ret;
190 }
191 ret = speakerTrans_->Start();
192 if (ret != DH_SUCCESS) {
193 DHLOGE("Speaker trans start failed.");
194 return ret;
195 }
196 auto pid = getprocpid();
197 ret = AudioStandard::AudioSystemManager::GetInstance()->RegisterVolumeKeyEventCallback(pid, shared_from_this());
198 if (ret != DH_SUCCESS) {
199 DHLOGE("Failed to register volume key event callback.");
200 return ret;
201 }
202 clientStatus_ = AudioStatus::STATUS_READY;
203 return DH_SUCCESS;
204 }
205
Release()206 int32_t DSpeakerClient::Release()
207 {
208 DHLOGI("Release spk client.");
209 std::lock_guard<std::mutex> lck(devMtx_);
210 if (clientStatus_ != AudioStatus::STATUS_READY && clientStatus_ != AudioStatus::STATUS_STOP) {
211 DHLOGE("Speaker status %{public}d is wrong.", (int32_t)clientStatus_);
212 return ERR_DH_AUDIO_SA_STATUS_ERR;
213 }
214 bool isSucess = true;
215 if (speakerTrans_ != nullptr) {
216 if (speakerTrans_->Stop() != DH_SUCCESS) {
217 DHLOGE("Speaker trans stop failed.");
218 isSucess = false;
219 }
220 if (speakerTrans_->Release() != DH_SUCCESS) {
221 DHLOGE("Speaker trans release failed.");
222 isSucess = false;
223 }
224 speakerTrans_ = nullptr;
225 }
226 if (speakerCtrlTrans_ != nullptr) {
227 if (speakerCtrlTrans_->Release() != DH_SUCCESS) {
228 DHLOGE("Speaker trans release failed.");
229 isSucess = false;
230 }
231 }
232
233 int32_t ret = AudioStandard::AudioSystemManager::GetInstance()->UnregisterVolumeKeyEventCallback(getprocpid());
234 if (ret != DH_SUCCESS) {
235 DHLOGE("Failed to unregister volume key event callback, error code %{public}d.", ret);
236 isSucess = false;
237 }
238 if (audioRenderer_ != nullptr && !audioRenderer_->Release()) {
239 DHLOGE("Audio renderer release failed.");
240 isSucess = false;
241 audioRenderer_ = nullptr;
242 }
243 clientStatus_ = AudioStatus::STATUS_IDLE;
244 DumpFileUtil::CloseDumpFile(&dumpFile_);
245 return isSucess ? DH_SUCCESS : ERR_DH_AUDIO_CLIENT_RENDER_RELEASE_FAILED;
246 }
247
StartRender()248 int32_t DSpeakerClient::StartRender()
249 {
250 DHLOGI("Start spk client.");
251 std::lock_guard<std::mutex> lck(devMtx_);
252 CHECK_NULL_RETURN(audioRenderer_, ERR_DH_AUDIO_SA_STATUS_ERR);
253
254 if (!audioRenderer_->Start()) {
255 DHLOGE("Audio renderer start failed.");
256 DAudioHisysevent::GetInstance().SysEventWriteFault(DAUDIO_OPT_FAIL, ERR_DH_AUDIO_CLIENT_RENDER_STARTUP_FAILURE,
257 "daudio renderer start failed.");
258 return ERR_DH_AUDIO_CLIENT_RENDER_STARTUP_FAILURE;
259 }
260 if (audioParam_.renderOpts.renderFlags != MMAP_MODE) {
261 isRenderReady_.store(true);
262 renderDataThread_ = std::thread([this]() { this->PlayThreadRunning(); });
263 }
264 clientStatus_ = AudioStatus::STATUS_START;
265 return DH_SUCCESS;
266 }
267
StopRender()268 int32_t DSpeakerClient::StopRender()
269 {
270 DHLOGI("Stop spk client.");
271 std::lock_guard<std::mutex> lck(devMtx_);
272 if (clientStatus_ != AudioStatus::STATUS_START) {
273 DHLOGE("Renderer is not start or spk status wrong, status: %{public}d.", (int32_t)clientStatus_);
274 DAudioHisysevent::GetInstance().SysEventWriteFault(DAUDIO_OPT_FAIL, ERR_DH_AUDIO_SA_STATUS_ERR,
275 "daudio renderer is not start or spk status wrong.");
276 return ERR_DH_AUDIO_SA_STATUS_ERR;
277 }
278 if (audioRenderer_ == nullptr) {
279 DHLOGE("Audio renderer is nullptr.");
280 DAudioHisysevent::GetInstance().SysEventWriteFault(DAUDIO_OPT_FAIL, ERR_DH_AUDIO_NULLPTR,
281 "daudio renderer is nullptr.");
282 return ERR_DH_AUDIO_NULLPTR;
283 }
284
285 if (audioParam_.renderOpts.renderFlags != MMAP_MODE) {
286 if (isRenderReady_.load()) {
287 isRenderReady_.store(false);
288 if (renderDataThread_.joinable()) {
289 renderDataThread_.join();
290 }
291 }
292 }
293
294 if (!audioRenderer_->Stop()) {
295 DHLOGE("Audio renderer stop failed");
296 DAudioHisysevent::GetInstance().SysEventWriteFault(DAUDIO_OPT_FAIL, ERR_DH_AUDIO_CLIENT_RENDER_STOP_FAILED,
297 "daudio renderer stop failed.");
298 return ERR_DH_AUDIO_CLIENT_RENDER_STOP_FAILED;
299 }
300 clientStatus_ = AudioStatus::STATUS_STOP;
301 return DH_SUCCESS;
302 }
303
PlayThreadRunning()304 void DSpeakerClient::PlayThreadRunning()
305 {
306 DHLOGD("Start the renderer thread.");
307 if (pthread_setname_np(pthread_self(), RENDERTHREAD) != DH_SUCCESS) {
308 DHLOGE("Render data thread setname failed.");
309 }
310
311 FillJitterQueue();
312 while (audioRenderer_ != nullptr && isRenderReady_.load()) {
313 int64_t startTime = GetNowTimeUs();
314 std::shared_ptr<AudioData> audioData = nullptr;
315 {
316 std::unique_lock<std::mutex> spkLck(dataQueueMtx_);
317 dataQueueCond_.wait_for(spkLck, std::chrono::milliseconds(REQUEST_DATA_WAIT),
318 [this]() { return !dataQueue_.empty(); });
319 if (dataQueue_.empty()) {
320 continue;
321 }
322 audioData = dataQueue_.front();
323 dataQueue_.pop();
324 uint64_t queueSize = static_cast<uint64_t>(dataQueue_.size());
325 DHLOGD("Pop spk data, dataqueue size: %{public}" PRIu64, queueSize);
326 }
327 if (audioData == nullptr) {
328 continue;
329 }
330 DumpFileUtil::WriteDumpFile(dumpFile_, static_cast<void *>(audioData->Data()), audioData->Size());
331 int32_t writeOffSet = 0;
332 while (writeOffSet < static_cast<int32_t>(audioData->Capacity())) {
333 int32_t writeLen = audioRenderer_->Write(audioData->Data() + writeOffSet,
334 static_cast<int32_t>(audioData->Capacity()) - writeOffSet);
335 uint64_t capacity = static_cast<uint64_t>(audioData->Capacity());
336 DHLOGD("Write audio render, write len: %{public}d, raw len: %{public}" PRIu64", offset: %{public}d",
337 writeLen, capacity, writeOffSet);
338 if (writeLen < 0) {
339 break;
340 }
341 writeOffSet += writeLen;
342 }
343 int64_t endTime = GetNowTimeUs();
344 if (IsOutDurationRange(startTime, endTime, lastPlayStartTime_)) {
345 DHLOGD("This time play spend: %{public}" PRId64" us, The interval of play this time and "
346 "the last time: %{public}" PRId64" us", endTime - startTime, startTime - lastPlayStartTime_);
347 }
348 lastPlayStartTime_ = startTime;
349 }
350 }
351
FillJitterQueue()352 void DSpeakerClient::FillJitterQueue()
353 {
354 while (isRenderReady_.load()) {
355 {
356 std::lock_guard<std::mutex> lock(dataQueueMtx_);
357 if (dataQueue_.size() >= DATA_QUEUE_SIZE) {
358 break;
359 }
360 }
361 usleep(SLEEP_TIME);
362 }
363 }
364
FlushJitterQueue()365 void DSpeakerClient::FlushJitterQueue()
366 {
367 while (isRenderReady_.load()) {
368 {
369 std::lock_guard<std::mutex> lock(dataQueueMtx_);
370 if (dataQueue_.empty()) {
371 break;
372 }
373 }
374 usleep(SLEEP_TIME);
375 }
376 }
377
OnDecodeTransDataDone(const std::shared_ptr<AudioData> & audioData)378 int32_t DSpeakerClient::OnDecodeTransDataDone(const std::shared_ptr<AudioData> &audioData)
379 {
380 DHLOGD("Write stream buffer.");
381 int64_t startTime = GetNowTimeUs();
382 CHECK_NULL_RETURN(audioData, ERR_DH_AUDIO_NULLPTR);
383
384 std::lock_guard<std::mutex> lock(dataQueueMtx_);
385 while (dataQueue_.size() > DATA_QUEUE_MAX_SIZE) {
386 DHLOGD("Data queue overflow.");
387 dataQueue_.pop();
388 }
389 dataQueue_.push(audioData);
390 dataQueueCond_.notify_all();
391 uint64_t queueSize = static_cast<uint64_t>(dataQueue_.size());
392 DHLOGD("Push new spk data, buf len: %{public}" PRIu64, queueSize);
393 int64_t endTime = GetNowTimeUs();
394 if (IsOutDurationRange(startTime, endTime, lastReceiveStartTime_)) {
395 DHLOGD("This time receivce data spend: %{public}" PRId64" us, Receivce data this time and "
396 "the last time: %{public}" PRId64" us", endTime - startTime, startTime - lastReceiveStartTime_);
397 }
398 lastReceiveStartTime_ = startTime;
399 return DH_SUCCESS;
400 }
401
OnStateChange(const AudioEventType type)402 int32_t DSpeakerClient::OnStateChange(const AudioEventType type)
403 {
404 DHLOGD("On state change. type: %{public}d", type);
405 AudioEvent event;
406 switch (type) {
407 case AudioEventType::DATA_OPENED: {
408 event.type = AudioEventType::SPEAKER_OPENED;
409 event.content = GetVolumeLevel();
410 break;
411 }
412 case AudioEventType::DATA_CLOSED: {
413 event.type = AudioEventType::SPEAKER_CLOSED;
414 event.content = GetCJsonString(KEY_DH_ID, std::to_string(dhId_).c_str());
415 break;
416 }
417 default:
418 DHLOGE("Invalid parameter type: %{public}d.", type);
419 return ERR_DH_AUDIO_NOT_SUPPORT;
420 }
421
422 std::shared_ptr<IAudioEventCallback> cbObj = eventCallback_.lock();
423 CHECK_NULL_RETURN(cbObj, ERR_DH_AUDIO_NULLPTR);
424 cbObj->NotifyEvent(event);
425 return DH_SUCCESS;
426 }
427
GetVolumeLevel()428 string DSpeakerClient::GetVolumeLevel()
429 {
430 DHLOGD("Get the volume level.");
431 AudioStandard::AudioStreamType streamType = AudioStandard::AudioStreamType::STREAM_DEFAULT;
432 auto volumeType = static_cast<AudioStandard::AudioVolumeType>(1);
433 int32_t volumeLevel = AudioStandard::AudioSystemManager::GetInstance()->GetVolume(volumeType);
434 int32_t maxVolumeLevel = AudioStandard::AudioSystemManager::GetInstance()->GetMaxVolume(volumeType);
435 int32_t minVolumeLevel = AudioStandard::AudioSystemManager::GetInstance()->GetMinVolume(volumeType);
436 bool isUpdateUi = false;
437 cJSON *jParam = cJSON_CreateObject();
438 CHECK_NULL_RETURN(jParam, "");
439
440 cJSON_AddStringToObject(jParam, KEY_DH_ID, std::to_string(dhId_).c_str());
441 cJSON_AddStringToObject(jParam, KEY_CHANGE_TYPE, FIRST_VOLUME_CHANAGE);
442 cJSON_AddStringToObject(jParam, AUDIO_STREAM_TYPE, std::to_string(streamType).c_str());
443 cJSON_AddStringToObject(jParam, VOLUME_LEVEL.c_str(), std::to_string(volumeLevel).c_str());
444 cJSON_AddStringToObject(jParam, IS_UPDATEUI, std::to_string(isUpdateUi).c_str());
445 cJSON_AddStringToObject(jParam, MAX_VOLUME_LEVEL, std::to_string(maxVolumeLevel).c_str());
446 cJSON_AddStringToObject(jParam, MIN_VOLUME_LEVEL, std::to_string(minVolumeLevel).c_str());
447 char *jsonData = cJSON_PrintUnformatted(jParam);
448 if (jsonData == nullptr) {
449 DHLOGE("Failed to create JSON data.");
450 cJSON_Delete(jParam);
451 return "";
452 }
453 std::string str(jsonData);
454 cJSON_Delete(jParam);
455 cJSON_free(jsonData);
456 DHLOGD("Get the volume level result, event: %{public}s.", str.c_str());
457 return str;
458 }
459
OnVolumeKeyEvent(AudioStandard::VolumeEvent volumeEvent)460 void DSpeakerClient::OnVolumeKeyEvent(AudioStandard::VolumeEvent volumeEvent)
461 {
462 DHLOGD("Volume change event.");
463 std::shared_ptr<IAudioEventCallback> cbObj = eventCallback_.lock();
464 CHECK_NULL_VOID(cbObj);
465
466 cJSON *jParam = cJSON_CreateObject();
467 CHECK_NULL_VOID(jParam);
468
469 cJSON_AddStringToObject(jParam, KEY_DH_ID, std::to_string(dhId_).c_str());
470 cJSON_AddStringToObject(jParam, KEY_CHANGE_TYPE, VOLUME_CHANAGE);
471 cJSON_AddStringToObject(jParam, AUDIO_STREAM_TYPE, std::to_string(volumeEvent.volumeType).c_str());
472 cJSON_AddStringToObject(jParam, VOLUME_LEVEL.c_str(), std::to_string(volumeEvent.volume).c_str());
473 cJSON_AddStringToObject(jParam, IS_UPDATEUI, std::to_string(volumeEvent.updateUi).c_str());
474 cJSON_AddStringToObject(jParam, VOLUME_GROUP_ID, std::to_string(volumeEvent.volumeGroupId).c_str());
475 char *jsonData = cJSON_PrintUnformatted(jParam);
476 if (jsonData == nullptr) {
477 DHLOGE("Failed to create JSON data.");
478 cJSON_Delete(jParam);
479 return;
480 }
481 std::string str(jsonData);
482 cJSON_Delete(jParam);
483 cJSON_free(jsonData);
484 DHLOGD("Volume change notification result, event: %{public}s.", str.c_str());
485
486 AudioEvent audioEvent(VOLUME_CHANGE, str);
487 cbObj->NotifyEvent(audioEvent);
488 }
489
OnInterrupt(const AudioStandard::InterruptEvent & interruptEvent)490 void DSpeakerClient::OnInterrupt(const AudioStandard::InterruptEvent &interruptEvent)
491 {
492 DHLOGD("Audio focus interrupt event.");
493 std::shared_ptr<IAudioEventCallback> cbObj = eventCallback_.lock();
494 CHECK_NULL_VOID(cbObj);
495
496 cJSON *jParam = cJSON_CreateObject();
497 CHECK_NULL_VOID(jParam);
498
499 cJSON_AddStringToObject(jParam, KEY_DH_ID, std::to_string(dhId_).c_str());
500 cJSON_AddStringToObject(jParam, KEY_CHANGE_TYPE, INTERRUPT_EVENT);
501 cJSON_AddStringToObject(jParam, VOLUME_EVENT_TYPE, std::to_string(interruptEvent.eventType).c_str());
502 cJSON_AddStringToObject(jParam, FORCE_TYPE, std::to_string(interruptEvent.forceType).c_str());
503 cJSON_AddStringToObject(jParam, HINT_TYPE, std::to_string(interruptEvent.hintType).c_str());
504 char *jsonData = cJSON_PrintUnformatted(jParam);
505 if (jsonData == nullptr) {
506 DHLOGE("Failed to create JSON data.");
507 cJSON_Delete(jParam);
508 return;
509 }
510 std::string str(jsonData);
511 cJSON_Delete(jParam);
512 cJSON_free(jsonData);
513 DHLOGD("Audio focus oninterrupt notification result, event: %{public}s.", str.c_str());
514
515 AudioEvent audioEvent(AUDIO_FOCUS_CHANGE, str);
516 cbObj->NotifyEvent(audioEvent);
517 }
518
OnStateChange(const AudioStandard::RendererState state,const AudioStandard::StateChangeCmdType cmdType)519 void DSpeakerClient::OnStateChange(const AudioStandard::RendererState state,
520 const AudioStandard::StateChangeCmdType __attribute__((unused)) cmdType)
521 {
522 DHLOGD("On render state change. state: %{public}d", state);
523 std::shared_ptr<IAudioEventCallback> cbObj = eventCallback_.lock();
524 CHECK_NULL_VOID(cbObj);
525
526 cJSON *jParam = cJSON_CreateObject();
527 CHECK_NULL_VOID(jParam);
528
529 cJSON_AddStringToObject(jParam, KEY_DH_ID, std::to_string(dhId_).c_str());
530 cJSON_AddStringToObject(jParam, KEY_CHANGE_TYPE, RENDER_STATE_CHANGE_EVENT);
531 cJSON_AddStringToObject(jParam, KEY_STATE, std::to_string(state).c_str());
532 char *jsonData = cJSON_PrintUnformatted(jParam);
533 if (jsonData == nullptr) {
534 DHLOGE("Failed to create JSON data.");
535 cJSON_Delete(jParam);
536 return;
537 }
538 std::string str(jsonData);
539 cJSON_Delete(jParam);
540 cJSON_free(jsonData);
541 DHLOGD("Audio render state changes notification result, event: %{public}s.", str.c_str());
542
543 AudioEvent audioEvent(AUDIO_RENDER_STATE_CHANGE, str);
544 cbObj->NotifyEvent(audioEvent);
545 }
546
SetAudioParameters(const AudioEvent & event)547 int32_t DSpeakerClient::SetAudioParameters(const AudioEvent &event)
548 {
549 DHLOGD("Set the volume, arg: %{public}s.", event.content.c_str());
550
551 int32_t audioVolumeType;
552 int32_t ret = GetAudioParamInt(event.content, AUDIO_VOLUME_TYPE, audioVolumeType);
553 if (ret != DH_SUCCESS) {
554 DHLOGE("Get audio volume type failed.");
555 return ret;
556 }
557 auto volumeType = static_cast<AudioStandard::AudioVolumeType>(audioVolumeType);
558 DHLOGD("Audio volume type, volumeType = %{public}d.", volumeType);
559 if (event.type != VOLUME_SET) {
560 DHLOGE("Invalid parameter.");
561 return ERR_DH_AUDIO_CLIENT_PARAM_ERROR;
562 }
563
564 int32_t audioVolumeLevel;
565 ret = GetAudioParamInt(event.content, VOLUME_LEVEL, audioVolumeLevel);
566 if (ret != DH_SUCCESS) {
567 DHLOGE("Get audio volume level failed.");
568 return ret;
569 }
570 DHLOGD("volume level = %{public}d.", audioVolumeLevel);
571 ret = AudioStandard::AudioSystemManager::GetInstance()->SetVolume(volumeType, audioVolumeLevel);
572 if (ret != DH_SUCCESS) {
573 DHLOGE("Voloume set failed.");
574 return ERR_DH_AUDIO_CLIENT_SET_VOLUME_FAILED;
575 }
576 return DH_SUCCESS;
577 }
578
SetMute(const AudioEvent & event)579 int32_t DSpeakerClient::SetMute(const AudioEvent &event)
580 {
581 DHLOGD("Set mute, arg: %{public}s.", event.content.c_str());
582 int32_t audioVolumeType;
583 int32_t ret = GetAudioParamInt(event.content, AUDIO_VOLUME_TYPE, audioVolumeType);
584 if (ret != DH_SUCCESS) {
585 DHLOGE("Get audio volume type failed.");
586 return ret;
587 }
588
589 bool muteStatus = false;
590 ret = GetAudioParamBool(event.content, STREAM_MUTE_STATUS, muteStatus);
591 if (ret != DH_SUCCESS) {
592 DHLOGE("Get mute status failed.");
593 return ret;
594 }
595
596 auto volumeType = static_cast<AudioStandard::AudioVolumeType>(audioVolumeType);
597 DHLOGD("Audio volume type, volumeType = %{public}d.", volumeType);
598 if (event.type != VOLUME_MUTE_SET) {
599 DHLOGE("Invalid parameter.");
600 return ERR_DH_AUDIO_CLIENT_PARAM_ERROR;
601 }
602 ret = AudioStandard::AudioSystemManager::GetInstance()->SetMute(volumeType, muteStatus);
603 if (ret != DH_SUCCESS) {
604 DHLOGE("Mute set failed.");
605 return ERR_DH_AUDIO_CLIENT_SET_MUTE_FAILED;
606 }
607 return DH_SUCCESS;
608 }
609
Pause()610 void DSpeakerClient::Pause()
611 {
612 DHLOGI("Pause and flush");
613 FlushJitterQueue();
614 if (audioParam_.renderOpts.renderFlags != MMAP_MODE) {
615 isRenderReady_.store(false);
616 if (renderDataThread_.joinable()) {
617 renderDataThread_.join();
618 }
619 }
620
621 if (speakerTrans_ == nullptr || speakerTrans_->Pause() != DH_SUCCESS) {
622 DHLOGE("Speaker trans Pause failed.");
623 }
624 if (audioRenderer_ != nullptr) {
625 audioRenderer_->Flush();
626 audioRenderer_->Pause();
627 }
628 clientStatus_ = AudioStatus::STATUS_START;
629 isRenderReady_.store(true);
630 }
631
ReStart()632 void DSpeakerClient::ReStart()
633 {
634 DHLOGI("ReStart");
635 if (speakerTrans_ == nullptr || speakerTrans_->Restart(audioParam_, audioParam_) != DH_SUCCESS) {
636 DHLOGE("Speaker trans Restart failed.");
637 }
638 if (audioParam_.renderOpts.renderFlags != MMAP_MODE) {
639 isRenderReady_.store(true);
640 renderDataThread_ = std::thread([this]() { this->PlayThreadRunning(); });
641 }
642 if (audioRenderer_ != nullptr) {
643 audioRenderer_->Start();
644 }
645 clientStatus_ = AudioStatus::STATUS_START;
646 }
647
SendMessage(uint32_t type,std::string content,std::string dstDevId)648 int32_t DSpeakerClient::SendMessage(uint32_t type, std::string content, std::string dstDevId)
649 {
650 DHLOGD("Send message to remote.");
651 if (type != static_cast<uint32_t>(NOTIFY_OPEN_SPEAKER_RESULT) &&
652 type != static_cast<uint32_t>(NOTIFY_OPEN_CTRL_RESULT) &&
653 type != static_cast<uint32_t>(NOTIFY_CLOSE_SPEAKER_RESULT) &&
654 type != static_cast<uint32_t>(VOLUME_CHANGE) &&
655 type != static_cast<uint32_t>(AUDIO_FOCUS_CHANGE) &&
656 type != static_cast<uint32_t>(AUDIO_RENDER_STATE_CHANGE)) {
657 DHLOGE("event type is not NOTIFY_OPEN_SPK or NOTIFY_CLOSE_SPK or OPEN_CTRL. type:%{public}u", type);
658 return ERR_DH_AUDIO_NULLPTR;
659 }
660 CHECK_NULL_RETURN(speakerCtrlTrans_, ERR_DH_AUDIO_NULLPTR);
661 speakerCtrlTrans_->SendAudioEvent(type, content, dstDevId);
662 return DH_SUCCESS;
663 }
664
PlayStatusChange(const std::string & args)665 void DSpeakerClient::PlayStatusChange(const std::string &args)
666 {
667 DHLOGI("Play status change, args: %{public}s.", args.c_str());
668 std::string changeType = ParseStringFromArgs(args, KEY_CHANGE_TYPE);
669 if (changeType == AUDIO_EVENT_RESTART) {
670 ReStart();
671 } else if (changeType == AUDIO_EVENT_PAUSE) {
672 Pause();
673 } else {
674 DHLOGE("Play status error.");
675 }
676 }
677
SetAttrs(const std::string & devId,const std::shared_ptr<IAudioEventCallback> & callback)678 void DSpeakerClient::SetAttrs(const std::string &devId, const std::shared_ptr<IAudioEventCallback> &callback)
679 {
680 DHLOGE("Set attrs, not support yet.");
681 }
682 } // DistributedHardware
683 } // OHOS
684