1 /*
2  * Copyright (c) 2023 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 <cstdio>
17 #include <cstring>
18 #include <cstdlib>
19 #include <unistd.h>
20 #include <cerrno>
21 #include <fcntl.h>
22 #include <csignal>
23 #include <sys/stat.h>
24 
25 #include <iostream>
26 #include <string>
27 
28 #include <securec.h>
29 #include "unistd.h"
30 #include "distributedaudiotest.h"
31 #include "daudio_errorcode.h"
32 #include "daudio_log.h"
33 
34 using OHOS::HDI::DistributedAudio::Audio::V1_0::IAudioAdapter;
35 using OHOS::HDI::DistributedAudio::Audio::V1_0::AudioAdapterDescriptor;
36 using OHOS::HDI::DistributedAudio::Audio::V1_0::AudioFormat;
37 using OHOS::HDI::DistributedAudio::Audio::V1_0::AudioPort;
38 using OHOS::HDI::DistributedAudio::Audio::V1_0::AudioPortDirection;
39 using OHOS::HDI::DistributedAudio::Audio::V1_0::IAudioManager;
40 using OHOS::HDI::DistributedAudio::Audio::V1_0::IAudioRender;
41 using OHOS::HDI::DistributedAudio::Audio::V1_0::IAudioCapture;
42 using OHOS::HDI::DistributedAudio::Audio::V1_0::AudioSampleAttributes;
43 using OHOS::HDI::DistributedAudio::Audio::V1_0::AudioDeviceDescriptor;
44 using OHOS::HDI::DistributedAudio::Audio::V1_0::AudioCategory;
45 using OHOS::HDI::DistributedAudio::Audio::V1_0::AudioRouteNode;
46 using OHOS::HDI::DistributedAudio::Audio::V1_0::AudioExtParamKey;
47 using OHOS::HDI::DistributedAudio::Audio::V1_0::AudioRoute;
48 using OHOS::HDI::DistributedAudio::Audio::V1_0::AudioSceneDescriptor;
49 using OHOS::HDI::DistributedAudio::Audio::V1_0::IAudioCallback;
50 using OHOS::HDI::DistributedAudio::Audio::V1_0::AudioPortPin;
51 using OHOS::HDI::DistributedAudio::Audio::V1_0::AudioPortType;
52 using OHOS::HDI::DistributedAudio::Audio::V1_0::AudioPortRole;
53 using OHOS::HDI::DistributedAudio::Audio::V1_0::AudioCallbackType;
54 
55 namespace {
56 using namespace OHOS::DistributedHardware;
57 static int32_t ParamEventCallback(AudioExtParamKey key, const char *condition, const char *value, void *reserved,
58     void *cookie);
59 
60 class AudioParamCallbackImpl final : public IAudioCallback {
61 public:
AudioParamCallbackImpl()62     AudioParamCallbackImpl() {}
~AudioParamCallbackImpl()63     ~AudioParamCallbackImpl() override {}
64 
65     int32_t RenderCallback(AudioCallbackType type, int8_t &reserved, int8_t &cookie) override;
66     int32_t ParamCallback(AudioExtParamKey key, const std::string &condition, const std::string &value,
67         int8_t &reserved, int8_t cookie) override;
68 };
69 
RenderCallback(AudioCallbackType type,int8_t & reserved,int8_t & cookie)70 int32_t AudioParamCallbackImpl::RenderCallback(AudioCallbackType type, int8_t &reserved, int8_t &cookie)
71 {
72     (void) type;
73     (void) reserved;
74     (void) cookie;
75     return DH_SUCCESS;
76 }
77 
ParamCallback(AudioExtParamKey key,const std::string & condition,const std::string & value,int8_t & reserved,int8_t cookie)78 int32_t AudioParamCallbackImpl::ParamCallback(AudioExtParamKey key, const std::string &condition,
79     const std::string &value, int8_t &reserved, int8_t cookie)
80 {
81     (void) cookie;
82     void *cookies = nullptr;
83     ParamEventCallback(static_cast<::AudioExtParamKey>(key), condition.c_str(),
84         value.c_str(), static_cast<void *>(&reserved), cookies);
85     return DH_SUCCESS;
86 }
87 
88 const int32_t CMD_QUIT = 0;
89 const int32_t CMD_FIND = 9;
90 const int32_t CMD_OPEN_SPK = 1;
91 const int32_t CMD_CLOSE_SPK = 2;
92 const int32_t CMD_START_SPK = 3;
93 const int32_t CMD_STOP_SPK = 4;
94 const int32_t CMD_OPEN_MIC = 5;
95 const int32_t CMD_CLOSE_MIC = 6;
96 const int32_t CMD_START_MIC = 7;
97 const int32_t CMD_STOP_MIC = 8;
98 const int32_t CMD_SET_VOL = 11;
99 const int32_t CMD_GET_VOL = 12;
100 
101 const char DEV_TYPE_SPK = '1';
102 const char DEV_TYPE_MIC = '2';
103 const char SPK_FILE_PATH[128] = "/data/test.wav";
104 const char MIC_FILE_PATH[128] = "/data/mic.pcm";
105 constexpr int32_t TYPE_OFFSET = 12;
106 constexpr int32_t AUDIO_SAMPLE_RATE = 48000;
107 constexpr int32_t VOLUME_MIN = 0;
108 constexpr int32_t VOLUME_MAX = 15;
109 constexpr int32_t RENDER_FRAME_SIZE = 3840;
110 constexpr int32_t RENDER_INTER_LEAVED = 1;
111 constexpr int32_t RENDER_STREAM_ID = 0;
112 constexpr int32_t RENDER_CHANNEL_MASK = 2;
113 constexpr int32_t CAPTURE_INTER_LEAVED = 1;
114 constexpr int32_t CAPTURE_STREAM_ID = 2;
115 constexpr int32_t CAPTURE_CHANNEL_MASK = 2;
116 constexpr int64_t AUDIO_FRAME_TIME_INTERFAL_DEFAULT = 21333;
117 
118 static OHOS::sptr<IAudioManager> g_manager = nullptr;
119 static OHOS::sptr<IAudioAdapter> g_adapter = nullptr;
120 static OHOS::sptr<IAudioRender> g_render = nullptr;
121 static OHOS::sptr<IAudioCapture> g_capture = nullptr;
122 static std::vector<AudioAdapterDescriptor> g_devices;
123 static OHOS::sptr<IAudioCallback> g_callbackStub = nullptr;
124 static std::string g_devId = "";
125 
126 static constexpr const char* PLAY_THREAD = "playThread";
127 static constexpr const char* CAPTURE_THREAD = "captureThread";
128 
129 uint32_t g_renderId = 0;
130 uint32_t g_captureId = 0;
131 int32_t g_frameNum = 0;
132 int32_t g_frameIndex = 0;
133 int32_t g_micFrameNum = 0;
134 bool g_isInitRenderData = false;
135 static std::vector<uint8_t*> renderData;
136 
137 static DeviceStatus g_spkStatus = DeviceStatus::DEVICE_IDLE;
138 static DeviceStatus g_micStatus = DeviceStatus::DEVICE_IDLE;
139 
140 static std::thread g_playingThread;
141 static std::thread g_capingThread;
142 FILE *g_micFile = nullptr;
143 
144 static void CloseSpk();
145 static void CloseMic();
146 
GetNowTimeUs()147 static int64_t GetNowTimeUs()
148 {
149     std::chrono::microseconds nowUs =
150         std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::system_clock::now().time_since_epoch());
151     return nowUs.count();
152 }
153 
GetUserInput()154 static int32_t GetUserInput()
155 {
156     int32_t res = -1;
157     size_t count = 3;
158     std::cout << ">>";
159     int ret = scanf_s("%d", &res);
160     if (ret == -1) {
161         std::cout << "get input error" << std::endl;
162     }
163     while (std::cin.fail() && count > 0) {
164         std::cin.clear();
165         std::cin.ignore();
166         std::cout << "invalid input, not a number! Please retry with a number." << std::endl;
167         std::cout << ">>";
168         ret = scanf_s("%d", &res);
169         if (ret == -1) {
170             std::cout << "get input error" << std::endl;
171         }
172         count--;
173     }
174     return res;
175 }
176 
FindAudioDevice()177 static void FindAudioDevice()
178 {
179     if (g_manager == nullptr) {
180         std::cout << "Audio manager is null, Please Check network!" << std::endl;
181         return;
182     }
183     int32_t ret = g_manager->GetAllAdapters(g_devices);
184     if (ret != DH_SUCCESS) {
185         std::cout << "Get audio devices failed!" << std::endl;
186         return;
187     }
188     for (uint32_t index = 0; index < g_devices.size(); index++) {
189         const AudioAdapterDescriptor desc = g_devices[index];
190         if (index == 0) {
191             g_devId = desc.adapterName;
192             break;
193         }
194     }
195 }
196 
InitTestDemo()197 static int32_t InitTestDemo()
198 {
199     std::cout << "**********************************************************************************" << std::endl;
200     std::cout << "Distributed Audio Test Demo Bin v1.3." << std::endl;
201     std::cout << "**********************************************************************************" << std::endl;
202     std::cout << std::endl;
203     std::cout << "Init distributed audio hdf service." << std::endl;
204     g_manager = IAudioManager::Get("daudio_primary_service", false);
205     if (g_manager == nullptr) {
206         std::cout << "Distributed audio manager is null, Please Check network!" << std::endl;
207         return ERR_DH_AUDIO_FAILED;
208     }
209     std::cout << "Load audio manager success." << std::endl;
210     FindAudioDevice();
211     if (g_devId.empty()) {
212         std::cout << "Cannot find distributed device. Please input 9 to query distribtued device." << std::endl;
213     } else {
214         std::cout << "Find one distributed device: " << g_devId << std::endl;
215     }
216     return DH_SUCCESS;
217 }
218 
HandleDevError(const char * condition,const char * value)219 static void HandleDevError(const char *condition, const char *value)
220 {
221     if (condition[TYPE_OFFSET] == DEV_TYPE_SPK && g_spkStatus != DeviceStatus::DEVICE_IDLE) {
222         CloseSpk();
223     }
224 
225     if (condition[TYPE_OFFSET] == DEV_TYPE_MIC && g_micStatus == DeviceStatus::DEVICE_IDLE) {
226         CloseMic();
227     }
228 
229     std::cout << "Receive abnormal event, Demo quit." << std::endl;
230 }
231 
ParamEventCallback(AudioExtParamKey key,const char * condition,const char * value,void * reserved,void * cookie)232 static int32_t ParamEventCallback(AudioExtParamKey key, const char *condition, const char *value, void *reserved,
233     void *cookie)
234 {
235     std::string val(value);
236     std::string con(condition);
237     std::cout << std::endl;
238     std::cout << "**********************************************************************************" << std::endl;
239     std::cout << "Event recived: " << key << std::endl;
240     std::cout << "Condition: " << con << std::endl;
241     std::cout << "Value: " << val << std::endl;
242     std::cout << "**********************************************************************************" << std::endl;
243     std::cout << std::endl;
244 
245     if (key == AudioExtParamKey::AUDIO_EXT_PARAM_KEY_STATUS && con.rfind("ERR_EVENT", 0) == 0) {
246         HandleDevError(condition, value);
247     }
248     return DH_SUCCESS;
249 }
250 
LoadSpkDev(const std::string & devId)251 static int32_t LoadSpkDev(const std::string &devId)
252 {
253     struct AudioAdapterDescriptor dev;
254     for (uint32_t index = 0; index < g_devices.size(); index++) {
255         struct AudioAdapterDescriptor desc = g_devices[index];
256         if (desc.adapterName == devId) {
257             dev = desc;
258             break;
259         }
260     }
261     if (dev.adapterName.data() == nullptr) {
262         std::cout << "Input device id is wrong." << std::endl;
263         FindAudioDevice();
264         return ERR_DH_AUDIO_FAILED;
265     }
266     if (g_manager == nullptr) {
267         return ERR_DH_AUDIO_FAILED;
268     }
269     if (g_adapter == nullptr) {
270         int32_t ret = g_manager->LoadAdapter(dev, g_adapter);
271         if (ret != DH_SUCCESS || g_adapter == nullptr) {
272             std::cout << "Load audio device failed, ret: " << ret << std::endl;
273             return ERR_DH_AUDIO_FAILED;
274         }
275     }
276     return DH_SUCCESS;
277 }
278 
OpenSpk(const std::string & devId)279 static void OpenSpk(const std::string &devId)
280 {
281     if (g_spkStatus != DeviceStatus::DEVICE_IDLE) {
282         std::cout << "Speaker device is already opened." << std::endl;
283         return;
284     }
285     if (LoadSpkDev(devId) != DH_SUCCESS) {
286         std::cout << "Load spk failed" << std::endl;
287         return;
288     }
289 
290     g_callbackStub = OHOS::sptr<IAudioCallback>(new AudioParamCallbackImpl());
291     if (g_adapter == nullptr) {
292         return;
293     }
294     int32_t ret = g_adapter->RegExtraParamObserver(g_callbackStub, 0);
295     if (ret != DH_SUCCESS) {
296         std::cout << "Register observer failed, ret: " << ret << std::endl;
297         return;
298     }
299 
300     struct AudioDeviceDescriptor renderDesc;
301     renderDesc.pins = AudioPortPin::PIN_OUT_SPEAKER;
302     renderDesc.desc = "";
303     AudioSampleAttributes g_rattrs = {};
304     g_rattrs.type = AudioCategory::AUDIO_IN_MEDIA;
305     g_rattrs.interleaved = RENDER_INTER_LEAVED;
306     g_rattrs.streamId = RENDER_STREAM_ID;
307     g_rattrs.channelCount = RENDER_CHANNEL_MASK;
308     g_rattrs.sampleRate = AUDIO_SAMPLE_RATE;
309     g_rattrs.format = AudioFormat::AUDIO_FORMAT_TYPE_PCM_16_BIT;
310     ret = g_adapter->CreateRender(renderDesc, g_rattrs, g_render, g_renderId);
311     if (ret != DH_SUCCESS || g_render == nullptr) {
312         std::cout << "Open SPK device failed, ret: " << ret << std::endl;
313         return;
314     }
315     g_spkStatus = DeviceStatus::DEVICE_OPEN;
316     std::cout << "Open SPK device success." << std::endl;
317 }
318 
WriteStreamWait(const int64_t & startTime)319 static void WriteStreamWait(const int64_t &startTime)
320 {
321     int64_t endTime = GetNowTimeUs();
322     int64_t passTime = endTime - startTime;
323 
324     if (passTime > AUDIO_FRAME_TIME_INTERFAL_DEFAULT) {
325         return;
326     }
327     int64_t remainTime = AUDIO_FRAME_TIME_INTERFAL_DEFAULT - passTime;
328     std::this_thread::sleep_for(std::chrono::microseconds(remainTime));
329 }
330 
Play()331 static void Play()
332 {
333     if (g_render == nullptr) {
334         std::cout << "SPK device is null." << std::endl;
335         return;
336     }
337     if (pthread_setname_np(pthread_self(), PLAY_THREAD) != DH_SUCCESS) {
338         std::cout << "Play thread setname failed." << std::endl;
339     }
340     std::cout << "Playing thread started." << std::endl;
341     g_render->Start();
342     g_spkStatus = DeviceStatus::DEVICE_START;
343 
344     uint64_t size = 0;
345     while (g_spkStatus == DeviceStatus::DEVICE_START) {
346         int64_t startTime = GetNowTimeUs();
347 
348         std::vector<int8_t> frameHal(RENDER_FRAME_SIZE);
349         int32_t ret = memcpy_s(frameHal.data(), RENDER_FRAME_SIZE, renderData[g_frameIndex], RENDER_FRAME_SIZE);
350         if (ret != EOK) {
351             DHLOGE("Copy render frame failed, error code %{public}d.", ret);
352             return;
353         }
354         ret = g_render->RenderFrame(frameHal, size);
355         if (ret != DH_SUCCESS) {
356             std::cout<<"RenderFrame failed, index: "<< g_frameIndex << ", ret:  " << ret << std::endl;
357         }
358         g_frameIndex++;
359         if (g_frameNum != 0 && g_frameIndex == g_frameNum) {
360             g_frameIndex = 0;
361         }
362         WriteStreamWait(startTime);
363     }
364     std::cout << "Playing thread stopped." << std::endl;
365 }
366 
StartRender()367 static void StartRender()
368 {
369     if (g_spkStatus == DeviceStatus::DEVICE_IDLE) {
370         std::cout << "Speaker device is not opened, start render failed." << std::endl;
371         return;
372     }
373 
374     if (g_spkStatus == DeviceStatus::DEVICE_OPEN) {
375         WavHdr wavHeader;
376         size_t headerSize = sizeof(WavHdr);
377         if (!g_isInitRenderData) {
378             struct stat statbuf;
379             stat(SPK_FILE_PATH, &statbuf);
380             int32_t size = statbuf.st_size;
381             g_frameNum = (size - static_cast<int32_t>(headerSize)) / RENDER_FRAME_SIZE;
382             std::cout << "Audio file frame num: " << g_frameNum << std::endl;
383             for (int32_t j = 0; j < g_frameNum; j++) {
384                 uint8_t *frame = new uint8_t[RENDER_FRAME_SIZE]();
385                 renderData.push_back(frame);
386             }
387             g_isInitRenderData = true;
388         }
389         FILE *wavFile = fopen(SPK_FILE_PATH, "rb");
390         fread(&wavHeader, 1, headerSize, wavFile);
391         for (int32_t i = 0; i < g_frameNum; i++) {
392             fread(renderData[i], 1, RENDER_FRAME_SIZE, wavFile);
393         }
394         fclose(wavFile);
395         g_frameIndex = 0;
396         g_playingThread = std::thread(Play);
397         return;
398     }
399     if (g_spkStatus == DeviceStatus::DEVICE_START) {
400         std::cout << "Speaker device is started." << std::endl;
401         return;
402     }
403     if (g_spkStatus == DeviceStatus::DEVICE_STOP) {
404         g_playingThread = std::thread(Play);
405     }
406 }
407 
StopRender()408 static void StopRender()
409 {
410     if (g_render == nullptr) {
411         std::cout << "SPK device is null." << std::endl;
412         return;
413     }
414 
415     if (g_spkStatus == DeviceStatus::DEVICE_IDLE) {
416         std::cout << "Speaker device is not opened." << std::endl;
417         return;
418     }
419 
420     if (g_spkStatus == DeviceStatus::DEVICE_OPEN) {
421         std::cout << "Speaker device is not started." << std::endl;
422         return;
423     }
424 
425     if (g_spkStatus == DeviceStatus::DEVICE_STOP) {
426         std::cout << "Speaker device is already stoped." << std::endl;
427         return;
428     }
429 
430     g_spkStatus = DeviceStatus::DEVICE_STOP;
431     if (g_playingThread.joinable()) {
432         g_playingThread.join();
433     }
434     g_render->Stop();
435 }
436 
CloseSpk()437 static void CloseSpk()
438 {
439     if (g_spkStatus == DeviceStatus::DEVICE_IDLE) {
440         std::cout << "Speaker device is not opened." << std::endl;
441         return;
442     }
443 
444     if (g_spkStatus == DeviceStatus::DEVICE_START) {
445         StopRender();
446     }
447 
448     if (g_adapter != nullptr) {
449         int32_t ret = g_adapter->DestroyRender(g_renderId);
450         if (ret != DH_SUCCESS) {
451             std::cout << "Close speaker failed" << std::endl;
452             return;
453         }
454     }
455     if (g_micStatus == DeviceStatus::DEVICE_IDLE && g_manager != nullptr) {
456         g_manager->UnloadAdapter(g_devId);
457         g_adapter = nullptr;
458     }
459     g_spkStatus = DeviceStatus::DEVICE_IDLE;
460 
461     if (g_isInitRenderData) {
462         for (auto &p : renderData) {
463             delete[] p;
464         }
465         renderData.clear();
466         g_isInitRenderData = false;
467     }
468     std::cout << "Close SPK device success." << std::endl;
469 }
470 
LoadMicDev(const std::string & devId)471 static int32_t LoadMicDev(const std::string &devId)
472 {
473     struct AudioAdapterDescriptor dev;
474     for (uint32_t index = 0; index < g_devices.size(); index++) {
475         struct AudioAdapterDescriptor desc = g_devices[index];
476         if (desc.adapterName == devId) {
477             dev = desc;
478             break;
479         }
480     }
481     if (dev.adapterName.data() == nullptr) {
482         std::cout << "Input device id is wrong." << std::endl;
483         FindAudioDevice();
484         return ERR_DH_AUDIO_FAILED;
485     }
486     if (g_manager == nullptr) {
487         return ERR_DH_AUDIO_FAILED;
488     }
489     if (g_adapter == nullptr) {
490         int32_t ret = g_manager->LoadAdapter(dev, g_adapter);
491         if (ret != DH_SUCCESS || g_adapter == nullptr) {
492             std::cout << "Load audio device failed, ret: " << ret << std::endl;
493             return ERR_DH_AUDIO_FAILED;
494         }
495     }
496     return DH_SUCCESS;
497 }
498 
OpenMic(const std::string & devId)499 static void OpenMic(const std::string &devId)
500 {
501     if (g_micStatus != DeviceStatus::DEVICE_IDLE) {
502         std::cout << "Mic device is already opened." << std::endl;
503         return;
504     }
505     if (LoadMicDev(devId) != DH_SUCCESS) {
506         std::cout << "Load audio device failed." << std::endl;
507         return;
508     }
509 
510     AudioDeviceDescriptor captureDesc;
511     captureDesc.pins = AudioPortPin::PIN_IN_MIC;
512     captureDesc.desc = "";
513     AudioSampleAttributes captureAttr;
514     captureAttr.type = AudioCategory::AUDIO_IN_MEDIA;
515     captureAttr.interleaved = CAPTURE_INTER_LEAVED;
516     captureAttr.streamId = CAPTURE_STREAM_ID;
517     captureAttr.channelCount = CAPTURE_CHANNEL_MASK;
518     captureAttr.sampleRate = AUDIO_SAMPLE_RATE;
519     captureAttr.format = AudioFormat::AUDIO_FORMAT_TYPE_PCM_16_BIT;
520     if (g_adapter == nullptr) {
521         return;
522     }
523     int32_t ret = g_adapter->CreateCapture(captureDesc, captureAttr, g_capture, g_captureId);
524     if (ret != DH_SUCCESS || g_capture == nullptr) {
525         std::cout << "Open MIC device failed." << std::endl;
526         return;
527     }
528     g_micStatus = DeviceStatus::DEVICE_OPEN;
529     std::cout << "Open MIC device success." << std::endl;
530 }
531 
ReadStreamWait(const int64_t & startTime)532 static void ReadStreamWait(const int64_t &startTime)
533 {
534     int64_t endTime = GetNowTimeUs();
535     int32_t passTime = endTime - startTime;
536 
537     if (passTime > AUDIO_FRAME_TIME_INTERFAL_DEFAULT) {
538         return;
539     }
540     int64_t remainTime = AUDIO_FRAME_TIME_INTERFAL_DEFAULT - passTime;
541     std::this_thread::sleep_for(std::chrono::microseconds(remainTime));
542 }
543 
Capture()544 static void Capture()
545 {
546     if (g_capture == nullptr) {
547         std::cout << "MIC device is null." << std::endl;
548         return;
549     }
550     if (pthread_setname_np(pthread_self(), CAPTURE_THREAD) != DH_SUCCESS) {
551         std::cout << "Capture thread setname failed." << std::endl;
552     }
553     std::cout << "Capturing thread started." << std::endl;
554     g_capture->Start();
555     g_micStatus = DeviceStatus::DEVICE_START;
556 
557     uint64_t size = 0;
558     while (g_micStatus == DeviceStatus::DEVICE_START) {
559         std::vector<int8_t> data(RENDER_FRAME_SIZE);
560         int64_t startTime = GetNowTimeUs();
561         int32_t ret = g_capture->CaptureFrame(data, size);
562         if (ret != DH_SUCCESS) {
563             std::cout << "CaptureFrame failed, ret: " << ret << std::endl;
564             return;
565         }
566         size_t writeCnt = fwrite(data.data(), 1, RENDER_FRAME_SIZE, g_micFile);
567         if (static_cast<int32_t>(writeCnt) != RENDER_FRAME_SIZE) {
568             std::cout << "fwrite data failed." << std::endl;
569         }
570         g_micFrameNum++;
571         ReadStreamWait(startTime);
572     }
573     std::cout << "Capturing thread stopped." << std::endl;
574 }
575 
StartCapture()576 static void StartCapture()
577 {
578     if (g_micStatus == DeviceStatus::DEVICE_IDLE) {
579         std::cout << "Mic device is not opened, start capture failed." << std::endl;
580         return;
581     }
582 
583     if (g_micStatus == DeviceStatus::DEVICE_OPEN) {
584         g_micFile = fopen(MIC_FILE_PATH, "ab+");
585         if (g_micFile == nullptr) {
586             std::cout << "Open pcm file failed." << std::endl;
587             return;
588         }
589         g_capingThread = std::thread(Capture);
590         return;
591     }
592 
593     if (g_micStatus == DeviceStatus::DEVICE_START) {
594         std::cout << "Mic device is already started." << std::endl;
595         return;
596     }
597 
598     if (g_micStatus == DeviceStatus::DEVICE_STOP) {
599         g_capingThread = std::thread(Capture);
600     }
601 }
602 
StopCapture()603 static void StopCapture()
604 {
605     if (g_capture == nullptr) {
606         std::cout << "MIC device is null." << std::endl;
607         return;
608     }
609     if (g_micStatus == DeviceStatus::DEVICE_IDLE) {
610         std::cout << "Mic device is not opened." << std::endl;
611         return;
612     }
613     if (g_micStatus == DeviceStatus::DEVICE_OPEN) {
614         std::cout << "Mic device is not started." << std::endl;
615         return;
616     }
617     if (g_micStatus == DeviceStatus::DEVICE_STOP) {
618         std::cout << "Mic device is already started." << std::endl;
619         return;
620     }
621     g_micStatus = DeviceStatus::DEVICE_STOP;
622     if (g_capingThread.joinable()) {
623         g_capingThread.join();
624     }
625     g_capture->Stop();
626 }
627 
CloseMic()628 static void CloseMic()
629 {
630     if (g_micStatus == DeviceStatus::DEVICE_IDLE) {
631         std::cout << "Mic device is not opened." << std::endl;
632         return;
633     }
634 
635     if (g_micStatus == DeviceStatus::DEVICE_START) {
636         StopCapture();
637     }
638 
639     if (g_adapter != nullptr) {
640         int32_t ret = g_adapter->DestroyCapture(g_captureId);
641         if (ret != DH_SUCCESS) {
642             std::cout << "Close mic failed." << std::endl;
643             return;
644         }
645     }
646     if (g_spkStatus == DeviceStatus::DEVICE_IDLE && g_manager != nullptr) {
647         g_manager->UnloadAdapter(g_devId);
648         g_adapter = nullptr;
649     }
650     if (g_micFile != nullptr) {
651         fclose(g_micFile);
652         g_micFile = nullptr;
653     }
654     g_micStatus = DeviceStatus::DEVICE_IDLE;
655     std::cout << "Close MIC device success." << std::endl;
656 }
657 
SetVolume()658 static void SetVolume()
659 {
660     if (g_spkStatus == DeviceStatus::DEVICE_IDLE) {
661         std::cout << "Speaker is not opened, can not set volume." << std::endl;
662         return;
663     }
664     std::cout << "Please input volum to set [0,15]." << std::endl;
665     int32_t volInt = GetUserInput();
666     if (volInt < VOLUME_MIN || volInt > VOLUME_MAX) {
667         std::cout << "Volume is invalid." << std::endl;
668         return;
669     }
670     std::cout << "Set volume: " << volInt << std::endl;
671     AudioExtParamKey key = AudioExtParamKey::AUDIO_EXT_PARAM_KEY_VOLUME;
672     std::string condition = "EVENT_TYPE=1;VOLUME_GROUP_ID=1;AUDIO_VOLUME_TYPE=1;";
673     std::string volStr = std::to_string(volInt);
674     if (g_adapter != nullptr) {
675     int32_t ret = g_adapter->SetExtraParams(key, condition, volStr);
676         if (ret != DH_SUCCESS) {
677             std::cout << "Set volume failed" << std::endl;
678         }
679     }
680 }
681 
GetVolume()682 static void GetVolume()
683 {
684     if (g_spkStatus == DeviceStatus::DEVICE_IDLE) {
685         std::cout << "Speaker is not opened, can not get volume." << std::endl;
686         return;
687     }
688     AudioExtParamKey key = AudioExtParamKey::AUDIO_EXT_PARAM_KEY_VOLUME;
689     std::string condition = "EVENT_TYPE=1;VOLUME_GROUP_ID=1;AUDIO_VOLUME_TYPE=1;";
690     std::string vol;
691     if (g_adapter != nullptr) {
692         int32_t ret = g_adapter->GetExtraParams(key, condition.c_str(), vol);
693         if (ret != DH_SUCCESS) {
694             std::cout << "Get Volume failed." << std::endl;
695             return;
696         }
697     }
698     std::cout << "Get volume success. volume: " << vol <<std::endl;
699 }
700 
HandleAudioEvent(const int32_t cmd)701 static void HandleAudioEvent(const int32_t cmd)
702 {
703     switch (cmd) {
704         case CMD_FIND:
705             FindAudioDevice();
706             break;
707         case CMD_OPEN_SPK:
708             OpenSpk(g_devId);
709             break;
710         case CMD_START_SPK:
711             StartRender();
712             break;
713         case CMD_STOP_SPK:
714             StopRender();
715             break;
716         case CMD_CLOSE_SPK:
717             CloseSpk();
718             break;
719         case CMD_OPEN_MIC:
720             OpenMic(g_devId);
721             break;
722         case CMD_START_MIC:
723             StartCapture();
724             break;
725         case CMD_STOP_MIC:
726             StopCapture();
727             break;
728         case CMD_CLOSE_MIC:
729             CloseMic();
730             break;
731         case CMD_SET_VOL:
732             SetVolume();
733             break;
734         case CMD_GET_VOL:
735             GetVolume();
736             break;
737         default:
738             std::cout << "Unkown opeartion." << std::endl;
739             break;
740     }
741 }
742 
PrintInteractiveUsage()743 static void PrintInteractiveUsage()
744 {
745     std::cout << std::endl << "=============== InteractiveRunTestSelect ================" << std::endl;
746     std::cout << "You can respond to instructions for corresponding option:" << std::endl;
747     std::cout <<  "\t enter 1 to open spk. " << std::endl;
748     std::cout <<  "\t enter 2 to close spk. " << std::endl;
749     std::cout <<  "\t enter 3 to start play. " << std::endl;
750     std::cout <<  "\t enter 4 to stop play. " << std::endl;
751     std::cout <<  "\t enter 5 to open mic. " << std::endl;
752     std::cout <<  "\t enter 6 to clsoe mic. " << std::endl;
753     std::cout <<  "\t enter 7 to start record. " << std::endl;
754     std::cout <<  "\t enter 8 to stop record. " << std::endl;
755     std::cout <<  "\t enter 9 to manullt find device. " << std::endl;
756     std::cout <<  "\t enter 11 to set volume. " << std::endl;
757     std::cout <<  "\t enter 12 to get volume. " << std::endl;
758     std::cout <<  "\t enter 0 to exit. " << std::endl;
759 }
760 }
761 
main(int argc,char * argv[])762 int main(int argc, char *argv[])
763 {
764     if (InitTestDemo() != DH_SUCCESS) {
765         return ERR_DH_AUDIO_FAILED;
766     }
767     while (true) {
768         PrintInteractiveUsage();
769         int32_t cmd = GetUserInput();
770         if (cmd == CMD_QUIT) {
771             CloseSpk();
772             CloseMic();
773             break;
774         }
775         HandleAudioEvent(cmd);
776     }
777     return 0;
778 }