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