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 speakerCtrlTrans_ = nullptr;
232 }
233
234 int32_t ret = AudioStandard::AudioSystemManager::GetInstance()->UnregisterVolumeKeyEventCallback(getprocpid());
235 if (ret != DH_SUCCESS) {
236 DHLOGE("Failed to unregister volume key event callback, error code %{public}d.", ret);
237 isSucess = false;
238 }
239 if (audioRenderer_ != nullptr && !audioRenderer_->Release()) {
240 DHLOGE("Audio renderer release failed.");
241 isSucess = false;
242 audioRenderer_ = nullptr;
243 }
244 clientStatus_ = AudioStatus::STATUS_IDLE;
245 DumpFileUtil::CloseDumpFile(&dumpFile_);
246 return isSucess ? DH_SUCCESS : ERR_DH_AUDIO_CLIENT_RENDER_RELEASE_FAILED;
247 }
248
StartRender()249 int32_t DSpeakerClient::StartRender()
250 {
251 DHLOGI("Start spk client.");
252 std::lock_guard<std::mutex> lck(devMtx_);
253 CHECK_NULL_RETURN(audioRenderer_, ERR_DH_AUDIO_SA_STATUS_ERR);
254
255 if (!audioRenderer_->Start()) {
256 DHLOGE("Audio renderer start failed.");
257 DAudioHisysevent::GetInstance().SysEventWriteFault(DAUDIO_OPT_FAIL, ERR_DH_AUDIO_CLIENT_RENDER_STARTUP_FAILURE,
258 "daudio renderer start failed.");
259 return ERR_DH_AUDIO_CLIENT_RENDER_STARTUP_FAILURE;
260 }
261 if (audioParam_.renderOpts.renderFlags != MMAP_MODE) {
262 isRenderReady_.store(true);
263 renderDataThread_ = std::thread([this]() { this->PlayThreadRunning(); });
264 }
265 clientStatus_ = AudioStatus::STATUS_START;
266 return DH_SUCCESS;
267 }
268
StopRender()269 int32_t DSpeakerClient::StopRender()
270 {
271 DHLOGI("Stop spk client.");
272 std::lock_guard<std::mutex> lck(devMtx_);
273 if (clientStatus_ != AudioStatus::STATUS_START) {
274 DHLOGE("Renderer is not start or spk status wrong, status: %{public}d.", (int32_t)clientStatus_);
275 DAudioHisysevent::GetInstance().SysEventWriteFault(DAUDIO_OPT_FAIL, ERR_DH_AUDIO_SA_STATUS_ERR,
276 "daudio renderer is not start or spk status wrong.");
277 return ERR_DH_AUDIO_SA_STATUS_ERR;
278 }
279 if (audioRenderer_ == nullptr) {
280 DHLOGE("Audio renderer is nullptr.");
281 DAudioHisysevent::GetInstance().SysEventWriteFault(DAUDIO_OPT_FAIL, ERR_DH_AUDIO_NULLPTR,
282 "daudio renderer is nullptr.");
283 return ERR_DH_AUDIO_NULLPTR;
284 }
285
286 if (audioParam_.renderOpts.renderFlags != MMAP_MODE) {
287 if (isRenderReady_.load()) {
288 isRenderReady_.store(false);
289 if (renderDataThread_.joinable()) {
290 renderDataThread_.join();
291 }
292 }
293 }
294
295 if (!audioRenderer_->Stop()) {
296 DHLOGE("Audio renderer stop failed");
297 DAudioHisysevent::GetInstance().SysEventWriteFault(DAUDIO_OPT_FAIL, ERR_DH_AUDIO_CLIENT_RENDER_STOP_FAILED,
298 "daudio renderer stop failed.");
299 return ERR_DH_AUDIO_CLIENT_RENDER_STOP_FAILED;
300 }
301 clientStatus_ = AudioStatus::STATUS_STOP;
302 return DH_SUCCESS;
303 }
304
PlayThreadRunning()305 void DSpeakerClient::PlayThreadRunning()
306 {
307 DHLOGD("Start the renderer thread.");
308 if (pthread_setname_np(pthread_self(), RENDERTHREAD) != DH_SUCCESS) {
309 DHLOGE("Render data thread setname failed.");
310 }
311
312 FillJitterQueue();
313 while (audioRenderer_ != nullptr && isRenderReady_.load()) {
314 int64_t startTime = GetNowTimeUs();
315 std::shared_ptr<AudioData> audioData = nullptr;
316 {
317 std::unique_lock<std::mutex> spkLck(dataQueueMtx_);
318 dataQueueCond_.wait_for(spkLck, std::chrono::milliseconds(REQUEST_DATA_WAIT),
319 [this]() { return !dataQueue_.empty(); });
320 if (dataQueue_.empty()) {
321 continue;
322 }
323 audioData = dataQueue_.front();
324 dataQueue_.pop();
325 uint64_t queueSize = static_cast<uint64_t>(dataQueue_.size());
326 DHLOGD("Pop spk data, dataqueue size: %{public}" PRIu64, queueSize);
327 }
328 if (audioData == nullptr) {
329 continue;
330 }
331 DumpFileUtil::WriteDumpFile(dumpFile_, static_cast<void *>(audioData->Data()), audioData->Size());
332 int32_t writeOffSet = 0;
333 while (writeOffSet < static_cast<int32_t>(audioData->Capacity())) {
334 int32_t writeLen = audioRenderer_->Write(audioData->Data() + writeOffSet,
335 static_cast<int32_t>(audioData->Capacity()) - writeOffSet);
336 uint64_t capacity = static_cast<uint64_t>(audioData->Capacity());
337 DHLOGD("Write audio render, write len: %{public}d, raw len: %{public}" PRIu64", offset: %{public}d",
338 writeLen, capacity, writeOffSet);
339 if (writeLen < 0) {
340 break;
341 }
342 writeOffSet += writeLen;
343 }
344 int64_t endTime = GetNowTimeUs();
345 if (IsOutDurationRange(startTime, endTime, lastPlayStartTime_)) {
346 DHLOGD("This time play spend: %{public}" PRId64" us, The interval of play this time and "
347 "the last time: %{public}" PRId64" us", endTime - startTime, startTime - lastPlayStartTime_);
348 }
349 lastPlayStartTime_ = startTime;
350 }
351 }
352
FillJitterQueue()353 void DSpeakerClient::FillJitterQueue()
354 {
355 while (isRenderReady_.load()) {
356 {
357 std::lock_guard<std::mutex> lock(dataQueueMtx_);
358 if (dataQueue_.size() >= DATA_QUEUE_SIZE) {
359 break;
360 }
361 }
362 usleep(SLEEP_TIME);
363 }
364 }
365
FlushJitterQueue()366 void DSpeakerClient::FlushJitterQueue()
367 {
368 while (isRenderReady_.load()) {
369 {
370 std::lock_guard<std::mutex> lock(dataQueueMtx_);
371 if (dataQueue_.empty()) {
372 break;
373 }
374 }
375 usleep(SLEEP_TIME);
376 }
377 }
378
OnDecodeTransDataDone(const std::shared_ptr<AudioData> & audioData)379 int32_t DSpeakerClient::OnDecodeTransDataDone(const std::shared_ptr<AudioData> &audioData)
380 {
381 DHLOGD("Write stream buffer.");
382 int64_t startTime = GetNowTimeUs();
383 CHECK_NULL_RETURN(audioData, ERR_DH_AUDIO_NULLPTR);
384
385 std::lock_guard<std::mutex> lock(dataQueueMtx_);
386 while (dataQueue_.size() > DATA_QUEUE_MAX_SIZE) {
387 DHLOGD("Data queue overflow.");
388 dataQueue_.pop();
389 }
390 dataQueue_.push(audioData);
391 dataQueueCond_.notify_all();
392 uint64_t queueSize = static_cast<uint64_t>(dataQueue_.size());
393 DHLOGD("Push new spk data, buf len: %{public}" PRIu64, queueSize);
394 int64_t endTime = GetNowTimeUs();
395 if (IsOutDurationRange(startTime, endTime, lastReceiveStartTime_)) {
396 DHLOGD("This time receivce data spend: %{public}" PRId64" us, Receivce data this time and "
397 "the last time: %{public}" PRId64" us", endTime - startTime, startTime - lastReceiveStartTime_);
398 }
399 lastReceiveStartTime_ = startTime;
400 return DH_SUCCESS;
401 }
402
OnStateChange(const AudioEventType type)403 int32_t DSpeakerClient::OnStateChange(const AudioEventType type)
404 {
405 DHLOGD("On state change. type: %{public}d", type);
406 AudioEvent event;
407 switch (type) {
408 case AudioEventType::DATA_OPENED: {
409 event.type = AudioEventType::SPEAKER_OPENED;
410 event.content = GetVolumeLevel();
411 break;
412 }
413 case AudioEventType::DATA_CLOSED: {
414 event.type = AudioEventType::SPEAKER_CLOSED;
415 event.content = GetCJsonString(KEY_DH_ID, std::to_string(dhId_).c_str());
416 break;
417 }
418 default:
419 DHLOGE("Invalid parameter type: %{public}d.", type);
420 return ERR_DH_AUDIO_NOT_SUPPORT;
421 }
422
423 std::shared_ptr<IAudioEventCallback> cbObj = eventCallback_.lock();
424 CHECK_NULL_RETURN(cbObj, ERR_DH_AUDIO_NULLPTR);
425 cbObj->NotifyEvent(event);
426 return DH_SUCCESS;
427 }
428
GetVolumeLevel()429 string DSpeakerClient::GetVolumeLevel()
430 {
431 DHLOGD("Get the volume level.");
432 AudioStandard::AudioStreamType streamType = AudioStandard::AudioStreamType::STREAM_DEFAULT;
433 auto volumeType = static_cast<AudioStandard::AudioVolumeType>(1);
434 int32_t volumeLevel = AudioStandard::AudioSystemManager::GetInstance()->GetVolume(volumeType);
435 int32_t maxVolumeLevel = AudioStandard::AudioSystemManager::GetInstance()->GetMaxVolume(volumeType);
436 int32_t minVolumeLevel = AudioStandard::AudioSystemManager::GetInstance()->GetMinVolume(volumeType);
437 bool isUpdateUi = false;
438 cJSON *jParam = cJSON_CreateObject();
439 CHECK_NULL_RETURN(jParam, "");
440
441 cJSON_AddStringToObject(jParam, KEY_DH_ID, std::to_string(dhId_).c_str());
442 cJSON_AddStringToObject(jParam, KEY_CHANGE_TYPE, FIRST_VOLUME_CHANAGE);
443 cJSON_AddStringToObject(jParam, AUDIO_STREAM_TYPE, std::to_string(streamType).c_str());
444 cJSON_AddStringToObject(jParam, VOLUME_LEVEL.c_str(), std::to_string(volumeLevel).c_str());
445 cJSON_AddStringToObject(jParam, IS_UPDATEUI, std::to_string(isUpdateUi).c_str());
446 cJSON_AddStringToObject(jParam, MAX_VOLUME_LEVEL, std::to_string(maxVolumeLevel).c_str());
447 cJSON_AddStringToObject(jParam, MIN_VOLUME_LEVEL, std::to_string(minVolumeLevel).c_str());
448 char *jsonData = cJSON_PrintUnformatted(jParam);
449 if (jsonData == nullptr) {
450 DHLOGE("Failed to create JSON data.");
451 cJSON_Delete(jParam);
452 return "";
453 }
454 std::string str(jsonData);
455 cJSON_Delete(jParam);
456 cJSON_free(jsonData);
457 DHLOGD("Get the volume level result, event: %{public}s.", str.c_str());
458 return str;
459 }
460
OnVolumeKeyEvent(AudioStandard::VolumeEvent volumeEvent)461 void DSpeakerClient::OnVolumeKeyEvent(AudioStandard::VolumeEvent volumeEvent)
462 {
463 DHLOGD("Volume change event.");
464 std::shared_ptr<IAudioEventCallback> cbObj = eventCallback_.lock();
465 CHECK_NULL_VOID(cbObj);
466
467 cJSON *jParam = cJSON_CreateObject();
468 CHECK_NULL_VOID(jParam);
469
470 cJSON_AddStringToObject(jParam, KEY_DH_ID, std::to_string(dhId_).c_str());
471 cJSON_AddStringToObject(jParam, KEY_CHANGE_TYPE, VOLUME_CHANAGE);
472 cJSON_AddStringToObject(jParam, AUDIO_STREAM_TYPE, std::to_string(volumeEvent.volumeType).c_str());
473 cJSON_AddStringToObject(jParam, VOLUME_LEVEL.c_str(), std::to_string(volumeEvent.volume).c_str());
474 cJSON_AddStringToObject(jParam, IS_UPDATEUI, std::to_string(volumeEvent.updateUi).c_str());
475 cJSON_AddStringToObject(jParam, VOLUME_GROUP_ID, std::to_string(volumeEvent.volumeGroupId).c_str());
476 char *jsonData = cJSON_PrintUnformatted(jParam);
477 if (jsonData == nullptr) {
478 DHLOGE("Failed to create JSON data.");
479 cJSON_Delete(jParam);
480 return;
481 }
482 std::string str(jsonData);
483 cJSON_Delete(jParam);
484 cJSON_free(jsonData);
485 DHLOGD("Volume change notification result, event: %{public}s.", str.c_str());
486
487 AudioEvent audioEvent(VOLUME_CHANGE, str);
488 cbObj->NotifyEvent(audioEvent);
489 }
490
OnInterrupt(const AudioStandard::InterruptEvent & interruptEvent)491 void DSpeakerClient::OnInterrupt(const AudioStandard::InterruptEvent &interruptEvent)
492 {
493 DHLOGD("Audio focus interrupt event.");
494 std::shared_ptr<IAudioEventCallback> cbObj = eventCallback_.lock();
495 CHECK_NULL_VOID(cbObj);
496
497 cJSON *jParam = cJSON_CreateObject();
498 CHECK_NULL_VOID(jParam);
499
500 cJSON_AddStringToObject(jParam, KEY_DH_ID, std::to_string(dhId_).c_str());
501 cJSON_AddStringToObject(jParam, KEY_CHANGE_TYPE, INTERRUPT_EVENT);
502 cJSON_AddStringToObject(jParam, VOLUME_EVENT_TYPE, std::to_string(interruptEvent.eventType).c_str());
503 cJSON_AddStringToObject(jParam, FORCE_TYPE, std::to_string(interruptEvent.forceType).c_str());
504 cJSON_AddStringToObject(jParam, HINT_TYPE, std::to_string(interruptEvent.hintType).c_str());
505 char *jsonData = cJSON_PrintUnformatted(jParam);
506 if (jsonData == nullptr) {
507 DHLOGE("Failed to create JSON data.");
508 cJSON_Delete(jParam);
509 return;
510 }
511 std::string str(jsonData);
512 cJSON_Delete(jParam);
513 cJSON_free(jsonData);
514 DHLOGD("Audio focus oninterrupt notification result, event: %{public}s.", str.c_str());
515
516 AudioEvent audioEvent(AUDIO_FOCUS_CHANGE, str);
517 cbObj->NotifyEvent(audioEvent);
518 }
519
OnStateChange(const AudioStandard::RendererState state,const AudioStandard::StateChangeCmdType cmdType)520 void DSpeakerClient::OnStateChange(const AudioStandard::RendererState state,
521 const AudioStandard::StateChangeCmdType __attribute__((unused)) cmdType)
522 {
523 DHLOGD("On render state change. state: %{public}d", state);
524 std::shared_ptr<IAudioEventCallback> cbObj = eventCallback_.lock();
525 CHECK_NULL_VOID(cbObj);
526
527 cJSON *jParam = cJSON_CreateObject();
528 CHECK_NULL_VOID(jParam);
529
530 cJSON_AddStringToObject(jParam, KEY_DH_ID, std::to_string(dhId_).c_str());
531 cJSON_AddStringToObject(jParam, KEY_CHANGE_TYPE, RENDER_STATE_CHANGE_EVENT);
532 cJSON_AddStringToObject(jParam, KEY_STATE, std::to_string(state).c_str());
533 char *jsonData = cJSON_PrintUnformatted(jParam);
534 if (jsonData == nullptr) {
535 DHLOGE("Failed to create JSON data.");
536 cJSON_Delete(jParam);
537 return;
538 }
539 std::string str(jsonData);
540 cJSON_Delete(jParam);
541 cJSON_free(jsonData);
542 DHLOGD("Audio render state changes notification result, event: %{public}s.", str.c_str());
543
544 AudioEvent audioEvent(AUDIO_RENDER_STATE_CHANGE, str);
545 cbObj->NotifyEvent(audioEvent);
546 }
547
SetAudioParameters(const AudioEvent & event)548 int32_t DSpeakerClient::SetAudioParameters(const AudioEvent &event)
549 {
550 DHLOGD("Set the volume, arg: %{public}s.", event.content.c_str());
551
552 int32_t audioVolumeType;
553 int32_t ret = GetAudioParamInt(event.content, AUDIO_VOLUME_TYPE, audioVolumeType);
554 if (ret != DH_SUCCESS) {
555 DHLOGE("Get audio volume type failed.");
556 return ret;
557 }
558 auto volumeType = static_cast<AudioStandard::AudioVolumeType>(audioVolumeType);
559 DHLOGD("Audio volume type, volumeType = %{public}d.", volumeType);
560 if (event.type != VOLUME_SET) {
561 DHLOGE("Invalid parameter.");
562 return ERR_DH_AUDIO_CLIENT_PARAM_ERROR;
563 }
564
565 int32_t audioVolumeLevel;
566 ret = GetAudioParamInt(event.content, VOLUME_LEVEL, audioVolumeLevel);
567 if (ret != DH_SUCCESS) {
568 DHLOGE("Get audio volume level failed.");
569 return ret;
570 }
571 DHLOGD("volume level = %{public}d.", audioVolumeLevel);
572 ret = AudioStandard::AudioSystemManager::GetInstance()->SetVolume(volumeType, audioVolumeLevel);
573 if (ret != DH_SUCCESS) {
574 DHLOGE("Voloume set failed.");
575 return ERR_DH_AUDIO_CLIENT_SET_VOLUME_FAILED;
576 }
577 return DH_SUCCESS;
578 }
579
SetMute(const AudioEvent & event)580 int32_t DSpeakerClient::SetMute(const AudioEvent &event)
581 {
582 DHLOGD("Set mute, arg: %{public}s.", event.content.c_str());
583 int32_t audioVolumeType;
584 int32_t ret = GetAudioParamInt(event.content, AUDIO_VOLUME_TYPE, audioVolumeType);
585 if (ret != DH_SUCCESS) {
586 DHLOGE("Get audio volume type failed.");
587 return ret;
588 }
589
590 bool muteStatus = false;
591 ret = GetAudioParamBool(event.content, STREAM_MUTE_STATUS, muteStatus);
592 if (ret != DH_SUCCESS) {
593 DHLOGE("Get mute status failed.");
594 return ret;
595 }
596
597 auto volumeType = static_cast<AudioStandard::AudioVolumeType>(audioVolumeType);
598 DHLOGD("Audio volume type, volumeType = %{public}d.", volumeType);
599 if (event.type != VOLUME_MUTE_SET) {
600 DHLOGE("Invalid parameter.");
601 return ERR_DH_AUDIO_CLIENT_PARAM_ERROR;
602 }
603 ret = AudioStandard::AudioSystemManager::GetInstance()->SetMute(volumeType, muteStatus);
604 if (ret != DH_SUCCESS) {
605 DHLOGE("Mute set failed.");
606 return ERR_DH_AUDIO_CLIENT_SET_MUTE_FAILED;
607 }
608 return DH_SUCCESS;
609 }
610
Pause()611 void DSpeakerClient::Pause()
612 {
613 DHLOGI("Pause and flush");
614 FlushJitterQueue();
615 if (audioParam_.renderOpts.renderFlags != MMAP_MODE) {
616 isRenderReady_.store(false);
617 if (renderDataThread_.joinable()) {
618 renderDataThread_.join();
619 }
620 }
621
622 if (speakerTrans_ == nullptr || speakerTrans_->Pause() != DH_SUCCESS) {
623 DHLOGE("Speaker trans Pause failed.");
624 }
625 if (audioRenderer_ != nullptr) {
626 audioRenderer_->Flush();
627 audioRenderer_->Pause();
628 }
629 clientStatus_ = AudioStatus::STATUS_START;
630 isRenderReady_.store(true);
631 }
632
ReStart()633 void DSpeakerClient::ReStart()
634 {
635 DHLOGI("ReStart");
636 if (speakerTrans_ == nullptr || speakerTrans_->Restart(audioParam_, audioParam_) != DH_SUCCESS) {
637 DHLOGE("Speaker trans Restart failed.");
638 }
639 if (audioParam_.renderOpts.renderFlags != MMAP_MODE) {
640 isRenderReady_.store(true);
641 renderDataThread_ = std::thread([this]() { this->PlayThreadRunning(); });
642 }
643 if (audioRenderer_ != nullptr) {
644 audioRenderer_->Start();
645 }
646 clientStatus_ = AudioStatus::STATUS_START;
647 }
648
SendMessage(uint32_t type,std::string content,std::string dstDevId)649 int32_t DSpeakerClient::SendMessage(uint32_t type, std::string content, std::string dstDevId)
650 {
651 DHLOGD("Send message to remote.");
652 if (type != static_cast<uint32_t>(NOTIFY_OPEN_SPEAKER_RESULT) &&
653 type != static_cast<uint32_t>(NOTIFY_OPEN_CTRL_RESULT) &&
654 type != static_cast<uint32_t>(NOTIFY_CLOSE_SPEAKER_RESULT) &&
655 type != static_cast<uint32_t>(VOLUME_CHANGE) &&
656 type != static_cast<uint32_t>(AUDIO_FOCUS_CHANGE) &&
657 type != static_cast<uint32_t>(AUDIO_RENDER_STATE_CHANGE)) {
658 DHLOGE("event type is not NOTIFY_OPEN_SPK or NOTIFY_CLOSE_SPK or OPEN_CTRL. type:%{public}u", type);
659 return ERR_DH_AUDIO_NULLPTR;
660 }
661 CHECK_NULL_RETURN(speakerCtrlTrans_, ERR_DH_AUDIO_NULLPTR);
662 speakerCtrlTrans_->SendAudioEvent(type, content, dstDevId);
663 return DH_SUCCESS;
664 }
665
PlayStatusChange(const std::string & args)666 void DSpeakerClient::PlayStatusChange(const std::string &args)
667 {
668 DHLOGI("Play status change, args: %{public}s.", args.c_str());
669 std::string changeType = ParseStringFromArgs(args, KEY_CHANGE_TYPE);
670 if (changeType == AUDIO_EVENT_RESTART) {
671 ReStart();
672 } else if (changeType == AUDIO_EVENT_PAUSE) {
673 Pause();
674 } else {
675 DHLOGE("Play status error.");
676 }
677 }
678
SetAttrs(const std::string & devId,const std::shared_ptr<IAudioEventCallback> & callback)679 void DSpeakerClient::SetAttrs(const std::string &devId, const std::shared_ptr<IAudioEventCallback> &callback)
680 {
681 DHLOGE("Set attrs, not support yet.");
682 }
683 } // DistributedHardware
684 } // OHOS
685