150a07fd2Sopenharmony_ci/*
250a07fd2Sopenharmony_ci * Copyright (c) 2023 Huawei Device Co., Ltd.
350a07fd2Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License");
450a07fd2Sopenharmony_ci * you may not use this file except in compliance with the License.
550a07fd2Sopenharmony_ci * You may obtain a copy of the License at
650a07fd2Sopenharmony_ci *
750a07fd2Sopenharmony_ci *     http://www.apache.org/licenses/LICENSE-2.0
850a07fd2Sopenharmony_ci *
950a07fd2Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software
1050a07fd2Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS,
1150a07fd2Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1250a07fd2Sopenharmony_ci * See the License for the specific language governing permissions and
1350a07fd2Sopenharmony_ci * limitations under the License.
1450a07fd2Sopenharmony_ci */
1550a07fd2Sopenharmony_ci
1650a07fd2Sopenharmony_ci#include <cstdio>
1750a07fd2Sopenharmony_ci#include <cstring>
1850a07fd2Sopenharmony_ci#include <cstdlib>
1950a07fd2Sopenharmony_ci#include <unistd.h>
2050a07fd2Sopenharmony_ci#include <cerrno>
2150a07fd2Sopenharmony_ci#include <fcntl.h>
2250a07fd2Sopenharmony_ci#include <csignal>
2350a07fd2Sopenharmony_ci#include <sys/stat.h>
2450a07fd2Sopenharmony_ci
2550a07fd2Sopenharmony_ci#include <iostream>
2650a07fd2Sopenharmony_ci#include <string>
2750a07fd2Sopenharmony_ci
2850a07fd2Sopenharmony_ci#include <securec.h>
2950a07fd2Sopenharmony_ci#include "unistd.h"
3050a07fd2Sopenharmony_ci#include "distributedaudiotest.h"
3150a07fd2Sopenharmony_ci#include "daudio_errorcode.h"
3250a07fd2Sopenharmony_ci#include "daudio_log.h"
3350a07fd2Sopenharmony_ci
3450a07fd2Sopenharmony_ciusing OHOS::HDI::DistributedAudio::Audio::V1_0::IAudioAdapter;
3550a07fd2Sopenharmony_ciusing OHOS::HDI::DistributedAudio::Audio::V1_0::AudioAdapterDescriptor;
3650a07fd2Sopenharmony_ciusing OHOS::HDI::DistributedAudio::Audio::V1_0::AudioFormat;
3750a07fd2Sopenharmony_ciusing OHOS::HDI::DistributedAudio::Audio::V1_0::AudioPort;
3850a07fd2Sopenharmony_ciusing OHOS::HDI::DistributedAudio::Audio::V1_0::AudioPortDirection;
3950a07fd2Sopenharmony_ciusing OHOS::HDI::DistributedAudio::Audio::V1_0::IAudioManager;
4050a07fd2Sopenharmony_ciusing OHOS::HDI::DistributedAudio::Audio::V1_0::IAudioRender;
4150a07fd2Sopenharmony_ciusing OHOS::HDI::DistributedAudio::Audio::V1_0::IAudioCapture;
4250a07fd2Sopenharmony_ciusing OHOS::HDI::DistributedAudio::Audio::V1_0::AudioSampleAttributes;
4350a07fd2Sopenharmony_ciusing OHOS::HDI::DistributedAudio::Audio::V1_0::AudioDeviceDescriptor;
4450a07fd2Sopenharmony_ciusing OHOS::HDI::DistributedAudio::Audio::V1_0::AudioCategory;
4550a07fd2Sopenharmony_ciusing OHOS::HDI::DistributedAudio::Audio::V1_0::AudioRouteNode;
4650a07fd2Sopenharmony_ciusing OHOS::HDI::DistributedAudio::Audio::V1_0::AudioExtParamKey;
4750a07fd2Sopenharmony_ciusing OHOS::HDI::DistributedAudio::Audio::V1_0::AudioRoute;
4850a07fd2Sopenharmony_ciusing OHOS::HDI::DistributedAudio::Audio::V1_0::AudioSceneDescriptor;
4950a07fd2Sopenharmony_ciusing OHOS::HDI::DistributedAudio::Audio::V1_0::IAudioCallback;
5050a07fd2Sopenharmony_ciusing OHOS::HDI::DistributedAudio::Audio::V1_0::AudioPortPin;
5150a07fd2Sopenharmony_ciusing OHOS::HDI::DistributedAudio::Audio::V1_0::AudioPortType;
5250a07fd2Sopenharmony_ciusing OHOS::HDI::DistributedAudio::Audio::V1_0::AudioPortRole;
5350a07fd2Sopenharmony_ciusing OHOS::HDI::DistributedAudio::Audio::V1_0::AudioCallbackType;
5450a07fd2Sopenharmony_ci
5550a07fd2Sopenharmony_cinamespace {
5650a07fd2Sopenharmony_ciusing namespace OHOS::DistributedHardware;
5750a07fd2Sopenharmony_cistatic int32_t ParamEventCallback(AudioExtParamKey key, const char *condition, const char *value, void *reserved,
5850a07fd2Sopenharmony_ci    void *cookie);
5950a07fd2Sopenharmony_ci
6050a07fd2Sopenharmony_ciclass AudioParamCallbackImpl final : public IAudioCallback {
6150a07fd2Sopenharmony_cipublic:
6250a07fd2Sopenharmony_ci    AudioParamCallbackImpl() {}
6350a07fd2Sopenharmony_ci    ~AudioParamCallbackImpl() override {}
6450a07fd2Sopenharmony_ci
6550a07fd2Sopenharmony_ci    int32_t RenderCallback(AudioCallbackType type, int8_t &reserved, int8_t &cookie) override;
6650a07fd2Sopenharmony_ci    int32_t ParamCallback(AudioExtParamKey key, const std::string &condition, const std::string &value,
6750a07fd2Sopenharmony_ci        int8_t &reserved, int8_t cookie) override;
6850a07fd2Sopenharmony_ci};
6950a07fd2Sopenharmony_ci
7050a07fd2Sopenharmony_ciint32_t AudioParamCallbackImpl::RenderCallback(AudioCallbackType type, int8_t &reserved, int8_t &cookie)
7150a07fd2Sopenharmony_ci{
7250a07fd2Sopenharmony_ci    (void) type;
7350a07fd2Sopenharmony_ci    (void) reserved;
7450a07fd2Sopenharmony_ci    (void) cookie;
7550a07fd2Sopenharmony_ci    return DH_SUCCESS;
7650a07fd2Sopenharmony_ci}
7750a07fd2Sopenharmony_ci
7850a07fd2Sopenharmony_ciint32_t AudioParamCallbackImpl::ParamCallback(AudioExtParamKey key, const std::string &condition,
7950a07fd2Sopenharmony_ci    const std::string &value, int8_t &reserved, int8_t cookie)
8050a07fd2Sopenharmony_ci{
8150a07fd2Sopenharmony_ci    (void) cookie;
8250a07fd2Sopenharmony_ci    void *cookies = nullptr;
8350a07fd2Sopenharmony_ci    ParamEventCallback(static_cast<::AudioExtParamKey>(key), condition.c_str(),
8450a07fd2Sopenharmony_ci        value.c_str(), static_cast<void *>(&reserved), cookies);
8550a07fd2Sopenharmony_ci    return DH_SUCCESS;
8650a07fd2Sopenharmony_ci}
8750a07fd2Sopenharmony_ci
8850a07fd2Sopenharmony_ciconst int32_t CMD_QUIT = 0;
8950a07fd2Sopenharmony_ciconst int32_t CMD_FIND = 9;
9050a07fd2Sopenharmony_ciconst int32_t CMD_OPEN_SPK = 1;
9150a07fd2Sopenharmony_ciconst int32_t CMD_CLOSE_SPK = 2;
9250a07fd2Sopenharmony_ciconst int32_t CMD_START_SPK = 3;
9350a07fd2Sopenharmony_ciconst int32_t CMD_STOP_SPK = 4;
9450a07fd2Sopenharmony_ciconst int32_t CMD_OPEN_MIC = 5;
9550a07fd2Sopenharmony_ciconst int32_t CMD_CLOSE_MIC = 6;
9650a07fd2Sopenharmony_ciconst int32_t CMD_START_MIC = 7;
9750a07fd2Sopenharmony_ciconst int32_t CMD_STOP_MIC = 8;
9850a07fd2Sopenharmony_ciconst int32_t CMD_SET_VOL = 11;
9950a07fd2Sopenharmony_ciconst int32_t CMD_GET_VOL = 12;
10050a07fd2Sopenharmony_ci
10150a07fd2Sopenharmony_ciconst char DEV_TYPE_SPK = '1';
10250a07fd2Sopenharmony_ciconst char DEV_TYPE_MIC = '2';
10350a07fd2Sopenharmony_ciconst char SPK_FILE_PATH[128] = "/data/test.wav";
10450a07fd2Sopenharmony_ciconst char MIC_FILE_PATH[128] = "/data/mic.pcm";
10550a07fd2Sopenharmony_ciconstexpr int32_t TYPE_OFFSET = 12;
10650a07fd2Sopenharmony_ciconstexpr int32_t AUDIO_SAMPLE_RATE = 48000;
10750a07fd2Sopenharmony_ciconstexpr int32_t VOLUME_MIN = 0;
10850a07fd2Sopenharmony_ciconstexpr int32_t VOLUME_MAX = 15;
10950a07fd2Sopenharmony_ciconstexpr int32_t RENDER_FRAME_SIZE = 3840;
11050a07fd2Sopenharmony_ciconstexpr int32_t RENDER_INTER_LEAVED = 1;
11150a07fd2Sopenharmony_ciconstexpr int32_t RENDER_STREAM_ID = 0;
11250a07fd2Sopenharmony_ciconstexpr int32_t RENDER_CHANNEL_MASK = 2;
11350a07fd2Sopenharmony_ciconstexpr int32_t CAPTURE_INTER_LEAVED = 1;
11450a07fd2Sopenharmony_ciconstexpr int32_t CAPTURE_STREAM_ID = 2;
11550a07fd2Sopenharmony_ciconstexpr int32_t CAPTURE_CHANNEL_MASK = 2;
11650a07fd2Sopenharmony_ciconstexpr int64_t AUDIO_FRAME_TIME_INTERFAL_DEFAULT = 21333;
11750a07fd2Sopenharmony_ci
11850a07fd2Sopenharmony_cistatic OHOS::sptr<IAudioManager> g_manager = nullptr;
11950a07fd2Sopenharmony_cistatic OHOS::sptr<IAudioAdapter> g_adapter = nullptr;
12050a07fd2Sopenharmony_cistatic OHOS::sptr<IAudioRender> g_render = nullptr;
12150a07fd2Sopenharmony_cistatic OHOS::sptr<IAudioCapture> g_capture = nullptr;
12250a07fd2Sopenharmony_cistatic std::vector<AudioAdapterDescriptor> g_devices;
12350a07fd2Sopenharmony_cistatic OHOS::sptr<IAudioCallback> g_callbackStub = nullptr;
12450a07fd2Sopenharmony_cistatic std::string g_devId = "";
12550a07fd2Sopenharmony_ci
12650a07fd2Sopenharmony_cistatic constexpr const char* PLAY_THREAD = "playThread";
12750a07fd2Sopenharmony_cistatic constexpr const char* CAPTURE_THREAD = "captureThread";
12850a07fd2Sopenharmony_ci
12950a07fd2Sopenharmony_ciuint32_t g_renderId = 0;
13050a07fd2Sopenharmony_ciuint32_t g_captureId = 0;
13150a07fd2Sopenharmony_ciint32_t g_frameNum = 0;
13250a07fd2Sopenharmony_ciint32_t g_frameIndex = 0;
13350a07fd2Sopenharmony_ciint32_t g_micFrameNum = 0;
13450a07fd2Sopenharmony_cibool g_isInitRenderData = false;
13550a07fd2Sopenharmony_cistatic std::vector<uint8_t*> renderData;
13650a07fd2Sopenharmony_ci
13750a07fd2Sopenharmony_cistatic DeviceStatus g_spkStatus = DeviceStatus::DEVICE_IDLE;
13850a07fd2Sopenharmony_cistatic DeviceStatus g_micStatus = DeviceStatus::DEVICE_IDLE;
13950a07fd2Sopenharmony_ci
14050a07fd2Sopenharmony_cistatic std::thread g_playingThread;
14150a07fd2Sopenharmony_cistatic std::thread g_capingThread;
14250a07fd2Sopenharmony_ciFILE *g_micFile = nullptr;
14350a07fd2Sopenharmony_ci
14450a07fd2Sopenharmony_cistatic void CloseSpk();
14550a07fd2Sopenharmony_cistatic void CloseMic();
14650a07fd2Sopenharmony_ci
14750a07fd2Sopenharmony_cistatic int64_t GetNowTimeUs()
14850a07fd2Sopenharmony_ci{
14950a07fd2Sopenharmony_ci    std::chrono::microseconds nowUs =
15050a07fd2Sopenharmony_ci        std::chrono::duration_cast<std::chrono::microseconds>(std::chrono::system_clock::now().time_since_epoch());
15150a07fd2Sopenharmony_ci    return nowUs.count();
15250a07fd2Sopenharmony_ci}
15350a07fd2Sopenharmony_ci
15450a07fd2Sopenharmony_cistatic int32_t GetUserInput()
15550a07fd2Sopenharmony_ci{
15650a07fd2Sopenharmony_ci    int32_t res = -1;
15750a07fd2Sopenharmony_ci    size_t count = 3;
15850a07fd2Sopenharmony_ci    std::cout << ">>";
15950a07fd2Sopenharmony_ci    int ret = scanf_s("%d", &res);
16050a07fd2Sopenharmony_ci    if (ret == -1) {
16150a07fd2Sopenharmony_ci        std::cout << "get input error" << std::endl;
16250a07fd2Sopenharmony_ci    }
16350a07fd2Sopenharmony_ci    while (std::cin.fail() && count > 0) {
16450a07fd2Sopenharmony_ci        std::cin.clear();
16550a07fd2Sopenharmony_ci        std::cin.ignore();
16650a07fd2Sopenharmony_ci        std::cout << "invalid input, not a number! Please retry with a number." << std::endl;
16750a07fd2Sopenharmony_ci        std::cout << ">>";
16850a07fd2Sopenharmony_ci        ret = scanf_s("%d", &res);
16950a07fd2Sopenharmony_ci        if (ret == -1) {
17050a07fd2Sopenharmony_ci            std::cout << "get input error" << std::endl;
17150a07fd2Sopenharmony_ci        }
17250a07fd2Sopenharmony_ci        count--;
17350a07fd2Sopenharmony_ci    }
17450a07fd2Sopenharmony_ci    return res;
17550a07fd2Sopenharmony_ci}
17650a07fd2Sopenharmony_ci
17750a07fd2Sopenharmony_cistatic void FindAudioDevice()
17850a07fd2Sopenharmony_ci{
17950a07fd2Sopenharmony_ci    if (g_manager == nullptr) {
18050a07fd2Sopenharmony_ci        std::cout << "Audio manager is null, Please Check network!" << std::endl;
18150a07fd2Sopenharmony_ci        return;
18250a07fd2Sopenharmony_ci    }
18350a07fd2Sopenharmony_ci    int32_t ret = g_manager->GetAllAdapters(g_devices);
18450a07fd2Sopenharmony_ci    if (ret != DH_SUCCESS) {
18550a07fd2Sopenharmony_ci        std::cout << "Get audio devices failed!" << std::endl;
18650a07fd2Sopenharmony_ci        return;
18750a07fd2Sopenharmony_ci    }
18850a07fd2Sopenharmony_ci    for (uint32_t index = 0; index < g_devices.size(); index++) {
18950a07fd2Sopenharmony_ci        const AudioAdapterDescriptor desc = g_devices[index];
19050a07fd2Sopenharmony_ci        if (index == 0) {
19150a07fd2Sopenharmony_ci            g_devId = desc.adapterName;
19250a07fd2Sopenharmony_ci            break;
19350a07fd2Sopenharmony_ci        }
19450a07fd2Sopenharmony_ci    }
19550a07fd2Sopenharmony_ci}
19650a07fd2Sopenharmony_ci
19750a07fd2Sopenharmony_cistatic int32_t InitTestDemo()
19850a07fd2Sopenharmony_ci{
19950a07fd2Sopenharmony_ci    std::cout << "**********************************************************************************" << std::endl;
20050a07fd2Sopenharmony_ci    std::cout << "Distributed Audio Test Demo Bin v1.3." << std::endl;
20150a07fd2Sopenharmony_ci    std::cout << "**********************************************************************************" << std::endl;
20250a07fd2Sopenharmony_ci    std::cout << std::endl;
20350a07fd2Sopenharmony_ci    std::cout << "Init distributed audio hdf service." << std::endl;
20450a07fd2Sopenharmony_ci    g_manager = IAudioManager::Get("daudio_primary_service", false);
20550a07fd2Sopenharmony_ci    if (g_manager == nullptr) {
20650a07fd2Sopenharmony_ci        std::cout << "Distributed audio manager is null, Please Check network!" << std::endl;
20750a07fd2Sopenharmony_ci        return ERR_DH_AUDIO_FAILED;
20850a07fd2Sopenharmony_ci    }
20950a07fd2Sopenharmony_ci    std::cout << "Load audio manager success." << std::endl;
21050a07fd2Sopenharmony_ci    FindAudioDevice();
21150a07fd2Sopenharmony_ci    if (g_devId.empty()) {
21250a07fd2Sopenharmony_ci        std::cout << "Cannot find distributed device. Please input 9 to query distribtued device." << std::endl;
21350a07fd2Sopenharmony_ci    } else {
21450a07fd2Sopenharmony_ci        std::cout << "Find one distributed device: " << g_devId << std::endl;
21550a07fd2Sopenharmony_ci    }
21650a07fd2Sopenharmony_ci    return DH_SUCCESS;
21750a07fd2Sopenharmony_ci}
21850a07fd2Sopenharmony_ci
21950a07fd2Sopenharmony_cistatic void HandleDevError(const char *condition, const char *value)
22050a07fd2Sopenharmony_ci{
22150a07fd2Sopenharmony_ci    if (condition[TYPE_OFFSET] == DEV_TYPE_SPK && g_spkStatus != DeviceStatus::DEVICE_IDLE) {
22250a07fd2Sopenharmony_ci        CloseSpk();
22350a07fd2Sopenharmony_ci    }
22450a07fd2Sopenharmony_ci
22550a07fd2Sopenharmony_ci    if (condition[TYPE_OFFSET] == DEV_TYPE_MIC && g_micStatus == DeviceStatus::DEVICE_IDLE) {
22650a07fd2Sopenharmony_ci        CloseMic();
22750a07fd2Sopenharmony_ci    }
22850a07fd2Sopenharmony_ci
22950a07fd2Sopenharmony_ci    std::cout << "Receive abnormal event, Demo quit." << std::endl;
23050a07fd2Sopenharmony_ci}
23150a07fd2Sopenharmony_ci
23250a07fd2Sopenharmony_cistatic int32_t ParamEventCallback(AudioExtParamKey key, const char *condition, const char *value, void *reserved,
23350a07fd2Sopenharmony_ci    void *cookie)
23450a07fd2Sopenharmony_ci{
23550a07fd2Sopenharmony_ci    std::string val(value);
23650a07fd2Sopenharmony_ci    std::string con(condition);
23750a07fd2Sopenharmony_ci    std::cout << std::endl;
23850a07fd2Sopenharmony_ci    std::cout << "**********************************************************************************" << std::endl;
23950a07fd2Sopenharmony_ci    std::cout << "Event recived: " << key << std::endl;
24050a07fd2Sopenharmony_ci    std::cout << "Condition: " << con << std::endl;
24150a07fd2Sopenharmony_ci    std::cout << "Value: " << val << std::endl;
24250a07fd2Sopenharmony_ci    std::cout << "**********************************************************************************" << std::endl;
24350a07fd2Sopenharmony_ci    std::cout << std::endl;
24450a07fd2Sopenharmony_ci
24550a07fd2Sopenharmony_ci    if (key == AudioExtParamKey::AUDIO_EXT_PARAM_KEY_STATUS && con.rfind("ERR_EVENT", 0) == 0) {
24650a07fd2Sopenharmony_ci        HandleDevError(condition, value);
24750a07fd2Sopenharmony_ci    }
24850a07fd2Sopenharmony_ci    return DH_SUCCESS;
24950a07fd2Sopenharmony_ci}
25050a07fd2Sopenharmony_ci
25150a07fd2Sopenharmony_cistatic int32_t LoadSpkDev(const std::string &devId)
25250a07fd2Sopenharmony_ci{
25350a07fd2Sopenharmony_ci    struct AudioAdapterDescriptor dev;
25450a07fd2Sopenharmony_ci    for (uint32_t index = 0; index < g_devices.size(); index++) {
25550a07fd2Sopenharmony_ci        struct AudioAdapterDescriptor desc = g_devices[index];
25650a07fd2Sopenharmony_ci        if (desc.adapterName == devId) {
25750a07fd2Sopenharmony_ci            dev = desc;
25850a07fd2Sopenharmony_ci            break;
25950a07fd2Sopenharmony_ci        }
26050a07fd2Sopenharmony_ci    }
26150a07fd2Sopenharmony_ci    if (dev.adapterName.data() == nullptr) {
26250a07fd2Sopenharmony_ci        std::cout << "Input device id is wrong." << std::endl;
26350a07fd2Sopenharmony_ci        FindAudioDevice();
26450a07fd2Sopenharmony_ci        return ERR_DH_AUDIO_FAILED;
26550a07fd2Sopenharmony_ci    }
26650a07fd2Sopenharmony_ci    if (g_manager == nullptr) {
26750a07fd2Sopenharmony_ci        return ERR_DH_AUDIO_FAILED;
26850a07fd2Sopenharmony_ci    }
26950a07fd2Sopenharmony_ci    if (g_adapter == nullptr) {
27050a07fd2Sopenharmony_ci        int32_t ret = g_manager->LoadAdapter(dev, g_adapter);
27150a07fd2Sopenharmony_ci        if (ret != DH_SUCCESS || g_adapter == nullptr) {
27250a07fd2Sopenharmony_ci            std::cout << "Load audio device failed, ret: " << ret << std::endl;
27350a07fd2Sopenharmony_ci            return ERR_DH_AUDIO_FAILED;
27450a07fd2Sopenharmony_ci        }
27550a07fd2Sopenharmony_ci    }
27650a07fd2Sopenharmony_ci    return DH_SUCCESS;
27750a07fd2Sopenharmony_ci}
27850a07fd2Sopenharmony_ci
27950a07fd2Sopenharmony_cistatic void OpenSpk(const std::string &devId)
28050a07fd2Sopenharmony_ci{
28150a07fd2Sopenharmony_ci    if (g_spkStatus != DeviceStatus::DEVICE_IDLE) {
28250a07fd2Sopenharmony_ci        std::cout << "Speaker device is already opened." << std::endl;
28350a07fd2Sopenharmony_ci        return;
28450a07fd2Sopenharmony_ci    }
28550a07fd2Sopenharmony_ci    if (LoadSpkDev(devId) != DH_SUCCESS) {
28650a07fd2Sopenharmony_ci        std::cout << "Load spk failed" << std::endl;
28750a07fd2Sopenharmony_ci        return;
28850a07fd2Sopenharmony_ci    }
28950a07fd2Sopenharmony_ci
29050a07fd2Sopenharmony_ci    g_callbackStub = OHOS::sptr<IAudioCallback>(new AudioParamCallbackImpl());
29150a07fd2Sopenharmony_ci    if (g_adapter == nullptr) {
29250a07fd2Sopenharmony_ci        return;
29350a07fd2Sopenharmony_ci    }
29450a07fd2Sopenharmony_ci    int32_t ret = g_adapter->RegExtraParamObserver(g_callbackStub, 0);
29550a07fd2Sopenharmony_ci    if (ret != DH_SUCCESS) {
29650a07fd2Sopenharmony_ci        std::cout << "Register observer failed, ret: " << ret << std::endl;
29750a07fd2Sopenharmony_ci        return;
29850a07fd2Sopenharmony_ci    }
29950a07fd2Sopenharmony_ci
30050a07fd2Sopenharmony_ci    struct AudioDeviceDescriptor renderDesc;
30150a07fd2Sopenharmony_ci    renderDesc.pins = AudioPortPin::PIN_OUT_SPEAKER;
30250a07fd2Sopenharmony_ci    renderDesc.desc = "";
30350a07fd2Sopenharmony_ci    AudioSampleAttributes g_rattrs = {};
30450a07fd2Sopenharmony_ci    g_rattrs.type = AudioCategory::AUDIO_IN_MEDIA;
30550a07fd2Sopenharmony_ci    g_rattrs.interleaved = RENDER_INTER_LEAVED;
30650a07fd2Sopenharmony_ci    g_rattrs.streamId = RENDER_STREAM_ID;
30750a07fd2Sopenharmony_ci    g_rattrs.channelCount = RENDER_CHANNEL_MASK;
30850a07fd2Sopenharmony_ci    g_rattrs.sampleRate = AUDIO_SAMPLE_RATE;
30950a07fd2Sopenharmony_ci    g_rattrs.format = AudioFormat::AUDIO_FORMAT_TYPE_PCM_16_BIT;
31050a07fd2Sopenharmony_ci    ret = g_adapter->CreateRender(renderDesc, g_rattrs, g_render, g_renderId);
31150a07fd2Sopenharmony_ci    if (ret != DH_SUCCESS || g_render == nullptr) {
31250a07fd2Sopenharmony_ci        std::cout << "Open SPK device failed, ret: " << ret << std::endl;
31350a07fd2Sopenharmony_ci        return;
31450a07fd2Sopenharmony_ci    }
31550a07fd2Sopenharmony_ci    g_spkStatus = DeviceStatus::DEVICE_OPEN;
31650a07fd2Sopenharmony_ci    std::cout << "Open SPK device success." << std::endl;
31750a07fd2Sopenharmony_ci}
31850a07fd2Sopenharmony_ci
31950a07fd2Sopenharmony_cistatic void WriteStreamWait(const int64_t &startTime)
32050a07fd2Sopenharmony_ci{
32150a07fd2Sopenharmony_ci    int64_t endTime = GetNowTimeUs();
32250a07fd2Sopenharmony_ci    int64_t passTime = endTime - startTime;
32350a07fd2Sopenharmony_ci
32450a07fd2Sopenharmony_ci    if (passTime > AUDIO_FRAME_TIME_INTERFAL_DEFAULT) {
32550a07fd2Sopenharmony_ci        return;
32650a07fd2Sopenharmony_ci    }
32750a07fd2Sopenharmony_ci    int64_t remainTime = AUDIO_FRAME_TIME_INTERFAL_DEFAULT - passTime;
32850a07fd2Sopenharmony_ci    std::this_thread::sleep_for(std::chrono::microseconds(remainTime));
32950a07fd2Sopenharmony_ci}
33050a07fd2Sopenharmony_ci
33150a07fd2Sopenharmony_cistatic void Play()
33250a07fd2Sopenharmony_ci{
33350a07fd2Sopenharmony_ci    if (g_render == nullptr) {
33450a07fd2Sopenharmony_ci        std::cout << "SPK device is null." << std::endl;
33550a07fd2Sopenharmony_ci        return;
33650a07fd2Sopenharmony_ci    }
33750a07fd2Sopenharmony_ci    if (pthread_setname_np(pthread_self(), PLAY_THREAD) != DH_SUCCESS) {
33850a07fd2Sopenharmony_ci        std::cout << "Play thread setname failed." << std::endl;
33950a07fd2Sopenharmony_ci    }
34050a07fd2Sopenharmony_ci    std::cout << "Playing thread started." << std::endl;
34150a07fd2Sopenharmony_ci    g_render->Start();
34250a07fd2Sopenharmony_ci    g_spkStatus = DeviceStatus::DEVICE_START;
34350a07fd2Sopenharmony_ci
34450a07fd2Sopenharmony_ci    uint64_t size = 0;
34550a07fd2Sopenharmony_ci    while (g_spkStatus == DeviceStatus::DEVICE_START) {
34650a07fd2Sopenharmony_ci        int64_t startTime = GetNowTimeUs();
34750a07fd2Sopenharmony_ci
34850a07fd2Sopenharmony_ci        std::vector<int8_t> frameHal(RENDER_FRAME_SIZE);
34950a07fd2Sopenharmony_ci        int32_t ret = memcpy_s(frameHal.data(), RENDER_FRAME_SIZE, renderData[g_frameIndex], RENDER_FRAME_SIZE);
35050a07fd2Sopenharmony_ci        if (ret != EOK) {
35150a07fd2Sopenharmony_ci            DHLOGE("Copy render frame failed, error code %{public}d.", ret);
35250a07fd2Sopenharmony_ci            return;
35350a07fd2Sopenharmony_ci        }
35450a07fd2Sopenharmony_ci        ret = g_render->RenderFrame(frameHal, size);
35550a07fd2Sopenharmony_ci        if (ret != DH_SUCCESS) {
35650a07fd2Sopenharmony_ci            std::cout<<"RenderFrame failed, index: "<< g_frameIndex << ", ret:  " << ret << std::endl;
35750a07fd2Sopenharmony_ci        }
35850a07fd2Sopenharmony_ci        g_frameIndex++;
35950a07fd2Sopenharmony_ci        if (g_frameNum != 0 && g_frameIndex == g_frameNum) {
36050a07fd2Sopenharmony_ci            g_frameIndex = 0;
36150a07fd2Sopenharmony_ci        }
36250a07fd2Sopenharmony_ci        WriteStreamWait(startTime);
36350a07fd2Sopenharmony_ci    }
36450a07fd2Sopenharmony_ci    std::cout << "Playing thread stopped." << std::endl;
36550a07fd2Sopenharmony_ci}
36650a07fd2Sopenharmony_ci
36750a07fd2Sopenharmony_cistatic void StartRender()
36850a07fd2Sopenharmony_ci{
36950a07fd2Sopenharmony_ci    if (g_spkStatus == DeviceStatus::DEVICE_IDLE) {
37050a07fd2Sopenharmony_ci        std::cout << "Speaker device is not opened, start render failed." << std::endl;
37150a07fd2Sopenharmony_ci        return;
37250a07fd2Sopenharmony_ci    }
37350a07fd2Sopenharmony_ci
37450a07fd2Sopenharmony_ci    if (g_spkStatus == DeviceStatus::DEVICE_OPEN) {
37550a07fd2Sopenharmony_ci        WavHdr wavHeader;
37650a07fd2Sopenharmony_ci        size_t headerSize = sizeof(WavHdr);
37750a07fd2Sopenharmony_ci        if (!g_isInitRenderData) {
37850a07fd2Sopenharmony_ci            struct stat statbuf;
37950a07fd2Sopenharmony_ci            stat(SPK_FILE_PATH, &statbuf);
38050a07fd2Sopenharmony_ci            int32_t size = statbuf.st_size;
38150a07fd2Sopenharmony_ci            g_frameNum = (size - static_cast<int32_t>(headerSize)) / RENDER_FRAME_SIZE;
38250a07fd2Sopenharmony_ci            std::cout << "Audio file frame num: " << g_frameNum << std::endl;
38350a07fd2Sopenharmony_ci            for (int32_t j = 0; j < g_frameNum; j++) {
38450a07fd2Sopenharmony_ci                uint8_t *frame = new uint8_t[RENDER_FRAME_SIZE]();
38550a07fd2Sopenharmony_ci                renderData.push_back(frame);
38650a07fd2Sopenharmony_ci            }
38750a07fd2Sopenharmony_ci            g_isInitRenderData = true;
38850a07fd2Sopenharmony_ci        }
38950a07fd2Sopenharmony_ci        FILE *wavFile = fopen(SPK_FILE_PATH, "rb");
39050a07fd2Sopenharmony_ci        fread(&wavHeader, 1, headerSize, wavFile);
39150a07fd2Sopenharmony_ci        for (int32_t i = 0; i < g_frameNum; i++) {
39250a07fd2Sopenharmony_ci            fread(renderData[i], 1, RENDER_FRAME_SIZE, wavFile);
39350a07fd2Sopenharmony_ci        }
39450a07fd2Sopenharmony_ci        fclose(wavFile);
39550a07fd2Sopenharmony_ci        g_frameIndex = 0;
39650a07fd2Sopenharmony_ci        g_playingThread = std::thread(Play);
39750a07fd2Sopenharmony_ci        return;
39850a07fd2Sopenharmony_ci    }
39950a07fd2Sopenharmony_ci    if (g_spkStatus == DeviceStatus::DEVICE_START) {
40050a07fd2Sopenharmony_ci        std::cout << "Speaker device is started." << std::endl;
40150a07fd2Sopenharmony_ci        return;
40250a07fd2Sopenharmony_ci    }
40350a07fd2Sopenharmony_ci    if (g_spkStatus == DeviceStatus::DEVICE_STOP) {
40450a07fd2Sopenharmony_ci        g_playingThread = std::thread(Play);
40550a07fd2Sopenharmony_ci    }
40650a07fd2Sopenharmony_ci}
40750a07fd2Sopenharmony_ci
40850a07fd2Sopenharmony_cistatic void StopRender()
40950a07fd2Sopenharmony_ci{
41050a07fd2Sopenharmony_ci    if (g_render == nullptr) {
41150a07fd2Sopenharmony_ci        std::cout << "SPK device is null." << std::endl;
41250a07fd2Sopenharmony_ci        return;
41350a07fd2Sopenharmony_ci    }
41450a07fd2Sopenharmony_ci
41550a07fd2Sopenharmony_ci    if (g_spkStatus == DeviceStatus::DEVICE_IDLE) {
41650a07fd2Sopenharmony_ci        std::cout << "Speaker device is not opened." << std::endl;
41750a07fd2Sopenharmony_ci        return;
41850a07fd2Sopenharmony_ci    }
41950a07fd2Sopenharmony_ci
42050a07fd2Sopenharmony_ci    if (g_spkStatus == DeviceStatus::DEVICE_OPEN) {
42150a07fd2Sopenharmony_ci        std::cout << "Speaker device is not started." << std::endl;
42250a07fd2Sopenharmony_ci        return;
42350a07fd2Sopenharmony_ci    }
42450a07fd2Sopenharmony_ci
42550a07fd2Sopenharmony_ci    if (g_spkStatus == DeviceStatus::DEVICE_STOP) {
42650a07fd2Sopenharmony_ci        std::cout << "Speaker device is already stoped." << std::endl;
42750a07fd2Sopenharmony_ci        return;
42850a07fd2Sopenharmony_ci    }
42950a07fd2Sopenharmony_ci
43050a07fd2Sopenharmony_ci    g_spkStatus = DeviceStatus::DEVICE_STOP;
43150a07fd2Sopenharmony_ci    if (g_playingThread.joinable()) {
43250a07fd2Sopenharmony_ci        g_playingThread.join();
43350a07fd2Sopenharmony_ci    }
43450a07fd2Sopenharmony_ci    g_render->Stop();
43550a07fd2Sopenharmony_ci}
43650a07fd2Sopenharmony_ci
43750a07fd2Sopenharmony_cistatic void CloseSpk()
43850a07fd2Sopenharmony_ci{
43950a07fd2Sopenharmony_ci    if (g_spkStatus == DeviceStatus::DEVICE_IDLE) {
44050a07fd2Sopenharmony_ci        std::cout << "Speaker device is not opened." << std::endl;
44150a07fd2Sopenharmony_ci        return;
44250a07fd2Sopenharmony_ci    }
44350a07fd2Sopenharmony_ci
44450a07fd2Sopenharmony_ci    if (g_spkStatus == DeviceStatus::DEVICE_START) {
44550a07fd2Sopenharmony_ci        StopRender();
44650a07fd2Sopenharmony_ci    }
44750a07fd2Sopenharmony_ci
44850a07fd2Sopenharmony_ci    if (g_adapter != nullptr) {
44950a07fd2Sopenharmony_ci        int32_t ret = g_adapter->DestroyRender(g_renderId);
45050a07fd2Sopenharmony_ci        if (ret != DH_SUCCESS) {
45150a07fd2Sopenharmony_ci            std::cout << "Close speaker failed" << std::endl;
45250a07fd2Sopenharmony_ci            return;
45350a07fd2Sopenharmony_ci        }
45450a07fd2Sopenharmony_ci    }
45550a07fd2Sopenharmony_ci    if (g_micStatus == DeviceStatus::DEVICE_IDLE && g_manager != nullptr) {
45650a07fd2Sopenharmony_ci        g_manager->UnloadAdapter(g_devId);
45750a07fd2Sopenharmony_ci        g_adapter = nullptr;
45850a07fd2Sopenharmony_ci    }
45950a07fd2Sopenharmony_ci    g_spkStatus = DeviceStatus::DEVICE_IDLE;
46050a07fd2Sopenharmony_ci
46150a07fd2Sopenharmony_ci    if (g_isInitRenderData) {
46250a07fd2Sopenharmony_ci        for (auto &p : renderData) {
46350a07fd2Sopenharmony_ci            delete[] p;
46450a07fd2Sopenharmony_ci        }
46550a07fd2Sopenharmony_ci        renderData.clear();
46650a07fd2Sopenharmony_ci        g_isInitRenderData = false;
46750a07fd2Sopenharmony_ci    }
46850a07fd2Sopenharmony_ci    std::cout << "Close SPK device success." << std::endl;
46950a07fd2Sopenharmony_ci}
47050a07fd2Sopenharmony_ci
47150a07fd2Sopenharmony_cistatic int32_t LoadMicDev(const std::string &devId)
47250a07fd2Sopenharmony_ci{
47350a07fd2Sopenharmony_ci    struct AudioAdapterDescriptor dev;
47450a07fd2Sopenharmony_ci    for (uint32_t index = 0; index < g_devices.size(); index++) {
47550a07fd2Sopenharmony_ci        struct AudioAdapterDescriptor desc = g_devices[index];
47650a07fd2Sopenharmony_ci        if (desc.adapterName == devId) {
47750a07fd2Sopenharmony_ci            dev = desc;
47850a07fd2Sopenharmony_ci            break;
47950a07fd2Sopenharmony_ci        }
48050a07fd2Sopenharmony_ci    }
48150a07fd2Sopenharmony_ci    if (dev.adapterName.data() == nullptr) {
48250a07fd2Sopenharmony_ci        std::cout << "Input device id is wrong." << std::endl;
48350a07fd2Sopenharmony_ci        FindAudioDevice();
48450a07fd2Sopenharmony_ci        return ERR_DH_AUDIO_FAILED;
48550a07fd2Sopenharmony_ci    }
48650a07fd2Sopenharmony_ci    if (g_manager == nullptr) {
48750a07fd2Sopenharmony_ci        return ERR_DH_AUDIO_FAILED;
48850a07fd2Sopenharmony_ci    }
48950a07fd2Sopenharmony_ci    if (g_adapter == nullptr) {
49050a07fd2Sopenharmony_ci        int32_t ret = g_manager->LoadAdapter(dev, g_adapter);
49150a07fd2Sopenharmony_ci        if (ret != DH_SUCCESS || g_adapter == nullptr) {
49250a07fd2Sopenharmony_ci            std::cout << "Load audio device failed, ret: " << ret << std::endl;
49350a07fd2Sopenharmony_ci            return ERR_DH_AUDIO_FAILED;
49450a07fd2Sopenharmony_ci        }
49550a07fd2Sopenharmony_ci    }
49650a07fd2Sopenharmony_ci    return DH_SUCCESS;
49750a07fd2Sopenharmony_ci}
49850a07fd2Sopenharmony_ci
49950a07fd2Sopenharmony_cistatic void OpenMic(const std::string &devId)
50050a07fd2Sopenharmony_ci{
50150a07fd2Sopenharmony_ci    if (g_micStatus != DeviceStatus::DEVICE_IDLE) {
50250a07fd2Sopenharmony_ci        std::cout << "Mic device is already opened." << std::endl;
50350a07fd2Sopenharmony_ci        return;
50450a07fd2Sopenharmony_ci    }
50550a07fd2Sopenharmony_ci    if (LoadMicDev(devId) != DH_SUCCESS) {
50650a07fd2Sopenharmony_ci        std::cout << "Load audio device failed." << std::endl;
50750a07fd2Sopenharmony_ci        return;
50850a07fd2Sopenharmony_ci    }
50950a07fd2Sopenharmony_ci
51050a07fd2Sopenharmony_ci    AudioDeviceDescriptor captureDesc;
51150a07fd2Sopenharmony_ci    captureDesc.pins = AudioPortPin::PIN_IN_MIC;
51250a07fd2Sopenharmony_ci    captureDesc.desc = "";
51350a07fd2Sopenharmony_ci    AudioSampleAttributes captureAttr;
51450a07fd2Sopenharmony_ci    captureAttr.type = AudioCategory::AUDIO_IN_MEDIA;
51550a07fd2Sopenharmony_ci    captureAttr.interleaved = CAPTURE_INTER_LEAVED;
51650a07fd2Sopenharmony_ci    captureAttr.streamId = CAPTURE_STREAM_ID;
51750a07fd2Sopenharmony_ci    captureAttr.channelCount = CAPTURE_CHANNEL_MASK;
51850a07fd2Sopenharmony_ci    captureAttr.sampleRate = AUDIO_SAMPLE_RATE;
51950a07fd2Sopenharmony_ci    captureAttr.format = AudioFormat::AUDIO_FORMAT_TYPE_PCM_16_BIT;
52050a07fd2Sopenharmony_ci    if (g_adapter == nullptr) {
52150a07fd2Sopenharmony_ci        return;
52250a07fd2Sopenharmony_ci    }
52350a07fd2Sopenharmony_ci    int32_t ret = g_adapter->CreateCapture(captureDesc, captureAttr, g_capture, g_captureId);
52450a07fd2Sopenharmony_ci    if (ret != DH_SUCCESS || g_capture == nullptr) {
52550a07fd2Sopenharmony_ci        std::cout << "Open MIC device failed." << std::endl;
52650a07fd2Sopenharmony_ci        return;
52750a07fd2Sopenharmony_ci    }
52850a07fd2Sopenharmony_ci    g_micStatus = DeviceStatus::DEVICE_OPEN;
52950a07fd2Sopenharmony_ci    std::cout << "Open MIC device success." << std::endl;
53050a07fd2Sopenharmony_ci}
53150a07fd2Sopenharmony_ci
53250a07fd2Sopenharmony_cistatic void ReadStreamWait(const int64_t &startTime)
53350a07fd2Sopenharmony_ci{
53450a07fd2Sopenharmony_ci    int64_t endTime = GetNowTimeUs();
53550a07fd2Sopenharmony_ci    int32_t passTime = endTime - startTime;
53650a07fd2Sopenharmony_ci
53750a07fd2Sopenharmony_ci    if (passTime > AUDIO_FRAME_TIME_INTERFAL_DEFAULT) {
53850a07fd2Sopenharmony_ci        return;
53950a07fd2Sopenharmony_ci    }
54050a07fd2Sopenharmony_ci    int64_t remainTime = AUDIO_FRAME_TIME_INTERFAL_DEFAULT - passTime;
54150a07fd2Sopenharmony_ci    std::this_thread::sleep_for(std::chrono::microseconds(remainTime));
54250a07fd2Sopenharmony_ci}
54350a07fd2Sopenharmony_ci
54450a07fd2Sopenharmony_cistatic void Capture()
54550a07fd2Sopenharmony_ci{
54650a07fd2Sopenharmony_ci    if (g_capture == nullptr) {
54750a07fd2Sopenharmony_ci        std::cout << "MIC device is null." << std::endl;
54850a07fd2Sopenharmony_ci        return;
54950a07fd2Sopenharmony_ci    }
55050a07fd2Sopenharmony_ci    if (pthread_setname_np(pthread_self(), CAPTURE_THREAD) != DH_SUCCESS) {
55150a07fd2Sopenharmony_ci        std::cout << "Capture thread setname failed." << std::endl;
55250a07fd2Sopenharmony_ci    }
55350a07fd2Sopenharmony_ci    std::cout << "Capturing thread started." << std::endl;
55450a07fd2Sopenharmony_ci    g_capture->Start();
55550a07fd2Sopenharmony_ci    g_micStatus = DeviceStatus::DEVICE_START;
55650a07fd2Sopenharmony_ci
55750a07fd2Sopenharmony_ci    uint64_t size = 0;
55850a07fd2Sopenharmony_ci    while (g_micStatus == DeviceStatus::DEVICE_START) {
55950a07fd2Sopenharmony_ci        std::vector<int8_t> data(RENDER_FRAME_SIZE);
56050a07fd2Sopenharmony_ci        int64_t startTime = GetNowTimeUs();
56150a07fd2Sopenharmony_ci        int32_t ret = g_capture->CaptureFrame(data, size);
56250a07fd2Sopenharmony_ci        if (ret != DH_SUCCESS) {
56350a07fd2Sopenharmony_ci            std::cout << "CaptureFrame failed, ret: " << ret << std::endl;
56450a07fd2Sopenharmony_ci            return;
56550a07fd2Sopenharmony_ci        }
56650a07fd2Sopenharmony_ci        size_t writeCnt = fwrite(data.data(), 1, RENDER_FRAME_SIZE, g_micFile);
56750a07fd2Sopenharmony_ci        if (static_cast<int32_t>(writeCnt) != RENDER_FRAME_SIZE) {
56850a07fd2Sopenharmony_ci            std::cout << "fwrite data failed." << std::endl;
56950a07fd2Sopenharmony_ci        }
57050a07fd2Sopenharmony_ci        g_micFrameNum++;
57150a07fd2Sopenharmony_ci        ReadStreamWait(startTime);
57250a07fd2Sopenharmony_ci    }
57350a07fd2Sopenharmony_ci    std::cout << "Capturing thread stopped." << std::endl;
57450a07fd2Sopenharmony_ci}
57550a07fd2Sopenharmony_ci
57650a07fd2Sopenharmony_cistatic void StartCapture()
57750a07fd2Sopenharmony_ci{
57850a07fd2Sopenharmony_ci    if (g_micStatus == DeviceStatus::DEVICE_IDLE) {
57950a07fd2Sopenharmony_ci        std::cout << "Mic device is not opened, start capture failed." << std::endl;
58050a07fd2Sopenharmony_ci        return;
58150a07fd2Sopenharmony_ci    }
58250a07fd2Sopenharmony_ci
58350a07fd2Sopenharmony_ci    if (g_micStatus == DeviceStatus::DEVICE_OPEN) {
58450a07fd2Sopenharmony_ci        g_micFile = fopen(MIC_FILE_PATH, "ab+");
58550a07fd2Sopenharmony_ci        if (g_micFile == nullptr) {
58650a07fd2Sopenharmony_ci            std::cout << "Open pcm file failed." << std::endl;
58750a07fd2Sopenharmony_ci            return;
58850a07fd2Sopenharmony_ci        }
58950a07fd2Sopenharmony_ci        g_capingThread = std::thread(Capture);
59050a07fd2Sopenharmony_ci        return;
59150a07fd2Sopenharmony_ci    }
59250a07fd2Sopenharmony_ci
59350a07fd2Sopenharmony_ci    if (g_micStatus == DeviceStatus::DEVICE_START) {
59450a07fd2Sopenharmony_ci        std::cout << "Mic device is already started." << std::endl;
59550a07fd2Sopenharmony_ci        return;
59650a07fd2Sopenharmony_ci    }
59750a07fd2Sopenharmony_ci
59850a07fd2Sopenharmony_ci    if (g_micStatus == DeviceStatus::DEVICE_STOP) {
59950a07fd2Sopenharmony_ci        g_capingThread = std::thread(Capture);
60050a07fd2Sopenharmony_ci    }
60150a07fd2Sopenharmony_ci}
60250a07fd2Sopenharmony_ci
60350a07fd2Sopenharmony_cistatic void StopCapture()
60450a07fd2Sopenharmony_ci{
60550a07fd2Sopenharmony_ci    if (g_capture == nullptr) {
60650a07fd2Sopenharmony_ci        std::cout << "MIC device is null." << std::endl;
60750a07fd2Sopenharmony_ci        return;
60850a07fd2Sopenharmony_ci    }
60950a07fd2Sopenharmony_ci    if (g_micStatus == DeviceStatus::DEVICE_IDLE) {
61050a07fd2Sopenharmony_ci        std::cout << "Mic device is not opened." << std::endl;
61150a07fd2Sopenharmony_ci        return;
61250a07fd2Sopenharmony_ci    }
61350a07fd2Sopenharmony_ci    if (g_micStatus == DeviceStatus::DEVICE_OPEN) {
61450a07fd2Sopenharmony_ci        std::cout << "Mic device is not started." << std::endl;
61550a07fd2Sopenharmony_ci        return;
61650a07fd2Sopenharmony_ci    }
61750a07fd2Sopenharmony_ci    if (g_micStatus == DeviceStatus::DEVICE_STOP) {
61850a07fd2Sopenharmony_ci        std::cout << "Mic device is already started." << std::endl;
61950a07fd2Sopenharmony_ci        return;
62050a07fd2Sopenharmony_ci    }
62150a07fd2Sopenharmony_ci    g_micStatus = DeviceStatus::DEVICE_STOP;
62250a07fd2Sopenharmony_ci    if (g_capingThread.joinable()) {
62350a07fd2Sopenharmony_ci        g_capingThread.join();
62450a07fd2Sopenharmony_ci    }
62550a07fd2Sopenharmony_ci    g_capture->Stop();
62650a07fd2Sopenharmony_ci}
62750a07fd2Sopenharmony_ci
62850a07fd2Sopenharmony_cistatic void CloseMic()
62950a07fd2Sopenharmony_ci{
63050a07fd2Sopenharmony_ci    if (g_micStatus == DeviceStatus::DEVICE_IDLE) {
63150a07fd2Sopenharmony_ci        std::cout << "Mic device is not opened." << std::endl;
63250a07fd2Sopenharmony_ci        return;
63350a07fd2Sopenharmony_ci    }
63450a07fd2Sopenharmony_ci
63550a07fd2Sopenharmony_ci    if (g_micStatus == DeviceStatus::DEVICE_START) {
63650a07fd2Sopenharmony_ci        StopCapture();
63750a07fd2Sopenharmony_ci    }
63850a07fd2Sopenharmony_ci
63950a07fd2Sopenharmony_ci    if (g_adapter != nullptr) {
64050a07fd2Sopenharmony_ci        int32_t ret = g_adapter->DestroyCapture(g_captureId);
64150a07fd2Sopenharmony_ci        if (ret != DH_SUCCESS) {
64250a07fd2Sopenharmony_ci            std::cout << "Close mic failed." << std::endl;
64350a07fd2Sopenharmony_ci            return;
64450a07fd2Sopenharmony_ci        }
64550a07fd2Sopenharmony_ci    }
64650a07fd2Sopenharmony_ci    if (g_spkStatus == DeviceStatus::DEVICE_IDLE && g_manager != nullptr) {
64750a07fd2Sopenharmony_ci        g_manager->UnloadAdapter(g_devId);
64850a07fd2Sopenharmony_ci        g_adapter = nullptr;
64950a07fd2Sopenharmony_ci    }
65050a07fd2Sopenharmony_ci    if (g_micFile != nullptr) {
65150a07fd2Sopenharmony_ci        fclose(g_micFile);
65250a07fd2Sopenharmony_ci        g_micFile = nullptr;
65350a07fd2Sopenharmony_ci    }
65450a07fd2Sopenharmony_ci    g_micStatus = DeviceStatus::DEVICE_IDLE;
65550a07fd2Sopenharmony_ci    std::cout << "Close MIC device success." << std::endl;
65650a07fd2Sopenharmony_ci}
65750a07fd2Sopenharmony_ci
65850a07fd2Sopenharmony_cistatic void SetVolume()
65950a07fd2Sopenharmony_ci{
66050a07fd2Sopenharmony_ci    if (g_spkStatus == DeviceStatus::DEVICE_IDLE) {
66150a07fd2Sopenharmony_ci        std::cout << "Speaker is not opened, can not set volume." << std::endl;
66250a07fd2Sopenharmony_ci        return;
66350a07fd2Sopenharmony_ci    }
66450a07fd2Sopenharmony_ci    std::cout << "Please input volum to set [0,15]." << std::endl;
66550a07fd2Sopenharmony_ci    int32_t volInt = GetUserInput();
66650a07fd2Sopenharmony_ci    if (volInt < VOLUME_MIN || volInt > VOLUME_MAX) {
66750a07fd2Sopenharmony_ci        std::cout << "Volume is invalid." << std::endl;
66850a07fd2Sopenharmony_ci        return;
66950a07fd2Sopenharmony_ci    }
67050a07fd2Sopenharmony_ci    std::cout << "Set volume: " << volInt << std::endl;
67150a07fd2Sopenharmony_ci    AudioExtParamKey key = AudioExtParamKey::AUDIO_EXT_PARAM_KEY_VOLUME;
67250a07fd2Sopenharmony_ci    std::string condition = "EVENT_TYPE=1;VOLUME_GROUP_ID=1;AUDIO_VOLUME_TYPE=1;";
67350a07fd2Sopenharmony_ci    std::string volStr = std::to_string(volInt);
67450a07fd2Sopenharmony_ci    if (g_adapter != nullptr) {
67550a07fd2Sopenharmony_ci    int32_t ret = g_adapter->SetExtraParams(key, condition, volStr);
67650a07fd2Sopenharmony_ci        if (ret != DH_SUCCESS) {
67750a07fd2Sopenharmony_ci            std::cout << "Set volume failed" << std::endl;
67850a07fd2Sopenharmony_ci        }
67950a07fd2Sopenharmony_ci    }
68050a07fd2Sopenharmony_ci}
68150a07fd2Sopenharmony_ci
68250a07fd2Sopenharmony_cistatic void GetVolume()
68350a07fd2Sopenharmony_ci{
68450a07fd2Sopenharmony_ci    if (g_spkStatus == DeviceStatus::DEVICE_IDLE) {
68550a07fd2Sopenharmony_ci        std::cout << "Speaker is not opened, can not get volume." << std::endl;
68650a07fd2Sopenharmony_ci        return;
68750a07fd2Sopenharmony_ci    }
68850a07fd2Sopenharmony_ci    AudioExtParamKey key = AudioExtParamKey::AUDIO_EXT_PARAM_KEY_VOLUME;
68950a07fd2Sopenharmony_ci    std::string condition = "EVENT_TYPE=1;VOLUME_GROUP_ID=1;AUDIO_VOLUME_TYPE=1;";
69050a07fd2Sopenharmony_ci    std::string vol;
69150a07fd2Sopenharmony_ci    if (g_adapter != nullptr) {
69250a07fd2Sopenharmony_ci        int32_t ret = g_adapter->GetExtraParams(key, condition.c_str(), vol);
69350a07fd2Sopenharmony_ci        if (ret != DH_SUCCESS) {
69450a07fd2Sopenharmony_ci            std::cout << "Get Volume failed." << std::endl;
69550a07fd2Sopenharmony_ci            return;
69650a07fd2Sopenharmony_ci        }
69750a07fd2Sopenharmony_ci    }
69850a07fd2Sopenharmony_ci    std::cout << "Get volume success. volume: " << vol <<std::endl;
69950a07fd2Sopenharmony_ci}
70050a07fd2Sopenharmony_ci
70150a07fd2Sopenharmony_cistatic void HandleAudioEvent(const int32_t cmd)
70250a07fd2Sopenharmony_ci{
70350a07fd2Sopenharmony_ci    switch (cmd) {
70450a07fd2Sopenharmony_ci        case CMD_FIND:
70550a07fd2Sopenharmony_ci            FindAudioDevice();
70650a07fd2Sopenharmony_ci            break;
70750a07fd2Sopenharmony_ci        case CMD_OPEN_SPK:
70850a07fd2Sopenharmony_ci            OpenSpk(g_devId);
70950a07fd2Sopenharmony_ci            break;
71050a07fd2Sopenharmony_ci        case CMD_START_SPK:
71150a07fd2Sopenharmony_ci            StartRender();
71250a07fd2Sopenharmony_ci            break;
71350a07fd2Sopenharmony_ci        case CMD_STOP_SPK:
71450a07fd2Sopenharmony_ci            StopRender();
71550a07fd2Sopenharmony_ci            break;
71650a07fd2Sopenharmony_ci        case CMD_CLOSE_SPK:
71750a07fd2Sopenharmony_ci            CloseSpk();
71850a07fd2Sopenharmony_ci            break;
71950a07fd2Sopenharmony_ci        case CMD_OPEN_MIC:
72050a07fd2Sopenharmony_ci            OpenMic(g_devId);
72150a07fd2Sopenharmony_ci            break;
72250a07fd2Sopenharmony_ci        case CMD_START_MIC:
72350a07fd2Sopenharmony_ci            StartCapture();
72450a07fd2Sopenharmony_ci            break;
72550a07fd2Sopenharmony_ci        case CMD_STOP_MIC:
72650a07fd2Sopenharmony_ci            StopCapture();
72750a07fd2Sopenharmony_ci            break;
72850a07fd2Sopenharmony_ci        case CMD_CLOSE_MIC:
72950a07fd2Sopenharmony_ci            CloseMic();
73050a07fd2Sopenharmony_ci            break;
73150a07fd2Sopenharmony_ci        case CMD_SET_VOL:
73250a07fd2Sopenharmony_ci            SetVolume();
73350a07fd2Sopenharmony_ci            break;
73450a07fd2Sopenharmony_ci        case CMD_GET_VOL:
73550a07fd2Sopenharmony_ci            GetVolume();
73650a07fd2Sopenharmony_ci            break;
73750a07fd2Sopenharmony_ci        default:
73850a07fd2Sopenharmony_ci            std::cout << "Unkown opeartion." << std::endl;
73950a07fd2Sopenharmony_ci            break;
74050a07fd2Sopenharmony_ci    }
74150a07fd2Sopenharmony_ci}
74250a07fd2Sopenharmony_ci
74350a07fd2Sopenharmony_cistatic void PrintInteractiveUsage()
74450a07fd2Sopenharmony_ci{
74550a07fd2Sopenharmony_ci    std::cout << std::endl << "=============== InteractiveRunTestSelect ================" << std::endl;
74650a07fd2Sopenharmony_ci    std::cout << "You can respond to instructions for corresponding option:" << std::endl;
74750a07fd2Sopenharmony_ci    std::cout <<  "\t enter 1 to open spk. " << std::endl;
74850a07fd2Sopenharmony_ci    std::cout <<  "\t enter 2 to close spk. " << std::endl;
74950a07fd2Sopenharmony_ci    std::cout <<  "\t enter 3 to start play. " << std::endl;
75050a07fd2Sopenharmony_ci    std::cout <<  "\t enter 4 to stop play. " << std::endl;
75150a07fd2Sopenharmony_ci    std::cout <<  "\t enter 5 to open mic. " << std::endl;
75250a07fd2Sopenharmony_ci    std::cout <<  "\t enter 6 to clsoe mic. " << std::endl;
75350a07fd2Sopenharmony_ci    std::cout <<  "\t enter 7 to start record. " << std::endl;
75450a07fd2Sopenharmony_ci    std::cout <<  "\t enter 8 to stop record. " << std::endl;
75550a07fd2Sopenharmony_ci    std::cout <<  "\t enter 9 to manullt find device. " << std::endl;
75650a07fd2Sopenharmony_ci    std::cout <<  "\t enter 11 to set volume. " << std::endl;
75750a07fd2Sopenharmony_ci    std::cout <<  "\t enter 12 to get volume. " << std::endl;
75850a07fd2Sopenharmony_ci    std::cout <<  "\t enter 0 to exit. " << std::endl;
75950a07fd2Sopenharmony_ci}
76050a07fd2Sopenharmony_ci}
76150a07fd2Sopenharmony_ci
76250a07fd2Sopenharmony_ciint main(int argc, char *argv[])
76350a07fd2Sopenharmony_ci{
76450a07fd2Sopenharmony_ci    if (InitTestDemo() != DH_SUCCESS) {
76550a07fd2Sopenharmony_ci        return ERR_DH_AUDIO_FAILED;
76650a07fd2Sopenharmony_ci    }
76750a07fd2Sopenharmony_ci    while (true) {
76850a07fd2Sopenharmony_ci        PrintInteractiveUsage();
76950a07fd2Sopenharmony_ci        int32_t cmd = GetUserInput();
77050a07fd2Sopenharmony_ci        if (cmd == CMD_QUIT) {
77150a07fd2Sopenharmony_ci            CloseSpk();
77250a07fd2Sopenharmony_ci            CloseMic();
77350a07fd2Sopenharmony_ci            break;
77450a07fd2Sopenharmony_ci        }
77550a07fd2Sopenharmony_ci        HandleAudioEvent(cmd);
77650a07fd2Sopenharmony_ci    }
77750a07fd2Sopenharmony_ci    return 0;
77850a07fd2Sopenharmony_ci}