1/*
2 * Copyright (c) 2022-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 <dlfcn.h>
17#include <limits.h>
18#include <pthread.h>
19#include <securec.h>
20#include <signal.h>
21#include <stdio.h>
22#include <stdlib.h>
23#include <string.h>
24#include <sys/mman.h>
25#include <sys/stat.h>
26#include <unistd.h>
27#include "framework_common.h"
28#include "hdf_base.h"
29#include "inttypes.h"
30#include "osal_mem.h"
31#include "v4_0/audio_types.h"
32#include "v4_0/iaudio_manager.h"
33
34#define MAX_AUDIO_ADAPTER_DESC         5
35#define BUFFER_LEN                     256
36#define AUDIO_CHANNELCOUNT             2
37#define AUDIO_SAMPLE_RATE_48K          48000
38#define PATH_LEN                       256
39#define DEEP_BUFFER_RENDER_PERIOD_SIZE 4096
40#define INT_32_MAX                     0x7fffffff
41#define EXT_PARAMS_MAXLEN              107
42#define BITS_TO_FROMAT                 3
43
44struct StrPara {
45    struct IAudioRender *render;
46    FILE *file;
47    struct AudioSampleAttributes attrs;
48    uint64_t *replyBytes;
49    char *frame;
50    int32_t bufferSize;
51};
52
53struct IAudioRender *g_render = NULL;
54struct IAudioAdapter *g_adapter = NULL;
55static struct IAudioManager *g_audioManager = NULL;
56struct AudioDeviceDescriptor g_devDesc;
57struct AudioSampleAttributes g_attrs;
58struct AudioPort g_audioPort;
59struct AudioHeadInfo g_wavHeadInfo;
60static struct StrPara g_str;
61uint32_t g_renderId = 0;
62
63pthread_t g_tids;
64char *g_frame = NULL;
65FILE *g_file;
66
67char g_path[256];
68char g_adapterName[PATH_LEN] = {0};
69static int32_t g_closeEnd = 0;
70pthread_mutex_t g_mutex = PTHREAD_MUTEX_INITIALIZER;
71pthread_cond_t g_functionCond = PTHREAD_COND_INITIALIZER;
72bool g_waitSleep = false;
73bool g_isDirect = true;
74
75enum RenderMenuId {
76    RENDER_START = 1,
77    RENDER_STOP,
78    RENDER_RESUME,
79    RENDER_PAUSE,
80    SET_RENDER_VOLUME,
81    SET_RENDER_GAIN,
82    SET_RENDER_MUTE,
83    SET_RENDER_ATTRIBUTES,
84    SET_RENDER_SLECET_SCENE,
85    GET_RENDER_EXT_PARAMS,
86    GET_RENDER_POSITION,
87};
88
89enum RenderInputType {
90    INPUT_INT = 0,
91    INPUT_FLOAT,
92    INPUT_UINT32,
93};
94
95typedef int32_t (*AudioRenderOperation)(struct IAudioRender **);
96
97struct ProcessRenderMenuSwitchList {
98    enum RenderMenuId cmd;
99    AudioRenderOperation operation;
100};
101
102static int32_t CheckInputName(int type, void *val)
103{
104    if (val == NULL) {
105        return HDF_FAILURE;
106    }
107
108    int ret;
109    int inputInt = 0;
110    float inputFloat = 0.0;
111    uint32_t inputUint = 0;
112
113    printf("\n");
114    switch (type) {
115        case INPUT_INT:
116            ret = scanf_s("%d", &inputInt);
117            if (inputInt < 0 || inputInt > GET_RENDER_POSITION + 1) {
118                if (g_frame != NULL) {
119                    OsalMemFree(g_frame);
120                    g_frame = NULL;
121                }
122                AUDIO_FUNC_LOGE("Input failure");
123                return HDF_FAILURE;
124            }
125
126            *(int *)val = inputInt;
127            break;
128        case INPUT_FLOAT:
129            ret = scanf_s("%f", &inputFloat);
130
131            *(float *)val = inputFloat;
132            break;
133        case INPUT_UINT32:
134            ret = scanf_s("%u", &inputUint);
135            if (inputUint > 0xFFFFFFFF) {
136                return HDF_FAILURE;
137            }
138
139            *(uint32_t *)val = inputUint;
140            break;
141        default:
142            ret = EOF;
143            break;
144    }
145
146    if (ret == 0) {
147        CleanStdin();
148    } else if (ret == EOF) {
149        AUDIO_FUNC_LOGE("Input failure occurs!");
150        return HDF_FAILURE;
151    }
152    return HDF_SUCCESS;
153}
154
155static int32_t InitAttrs(struct AudioSampleAttributes *attrs)
156{
157    if (attrs == NULL) {
158        return HDF_FAILURE;
159    }
160    /* Initialization of audio parameters for playback */
161    attrs->format = AUDIO_FORMAT_TYPE_PCM_16_BIT;
162    attrs->channelCount = AUDIO_CHANNELCOUNT;
163    attrs->sampleRate = AUDIO_SAMPLE_RATE_48K;
164    attrs->interleaved = 0;
165    attrs->type = AUDIO_IN_MEDIA;
166    attrs->period = DEEP_BUFFER_RENDER_PERIOD_SIZE;
167    attrs->frameSize = PCM_16_BIT * attrs->channelCount / PCM_8_BIT;
168    attrs->isBigEndian = false;
169    attrs->isSignedData = true;
170    attrs->startThreshold = DEEP_BUFFER_RENDER_PERIOD_SIZE / (attrs->frameSize);
171    attrs->stopThreshold = INT_32_MAX;
172    attrs->silenceThreshold = 0;
173    return HDF_SUCCESS;
174}
175
176static int32_t InitDevDesc(struct AudioDeviceDescriptor *devDesc, uint32_t portId)
177{
178    if (devDesc == NULL) {
179        return HDF_FAILURE;
180    }
181    /* Initialization of audio parameters for playback */
182    devDesc->portId = portId;
183    devDesc->pins = PIN_OUT_SPEAKER;
184    devDesc->desc = strdup("cardname");
185    return HDF_SUCCESS;
186}
187
188static void StreamClose(int32_t sig)
189{
190    /* allow the stream to be closed gracefully */
191    (void)signal(sig, SIG_IGN);
192    g_closeEnd = 1;
193}
194
195static uint32_t PcmFramesToBytes(const struct AudioSampleAttributes attrs)
196{
197    return DEEP_BUFFER_RENDER_PERIOD_SIZE * attrs.channelCount * (PcmFormatToBits(attrs.format) >> BITS_TO_FROMAT);
198}
199
200static int32_t StopAudioFiles(struct IAudioRender **renderS)
201{
202    if (renderS == NULL) {
203        return HDF_FAILURE;
204    }
205    if (g_waitSleep) {
206        pthread_mutex_lock(&g_mutex);
207        g_waitSleep = false;
208        pthread_cond_signal(&g_functionCond);
209        pthread_mutex_unlock(&g_mutex);
210    }
211    if (!g_closeEnd) {
212        g_closeEnd = true;
213        usleep(100000); // sleep 100000us
214    }
215
216    struct IAudioRender *render = *renderS;
217    if (render == NULL) {
218        AUDIO_FUNC_LOGE("render is null");
219        return HDF_FAILURE;
220    }
221
222    int32_t ret = render->Stop((void *)render);
223    if (ret < 0) {
224        AUDIO_FUNC_LOGE("Stop Render!");
225    }
226
227    if (g_adapter == NULL || g_adapter->DestroyRender == NULL) {
228        return HDF_FAILURE;
229    }
230
231    ret = g_adapter->DestroyRender(g_adapter, g_renderId);
232    if (ret < 0) {
233        AUDIO_FUNC_LOGE("Destroy Render!");
234    }
235
236    IAudioRenderRelease(render, g_isDirect);
237
238    *renderS = NULL;
239    g_render = NULL;
240    if (g_frame != NULL) {
241        OsalMemFree(g_frame);
242        g_frame = NULL;
243    }
244
245    if (g_file != NULL) {
246        fclose(g_file);
247        g_file = NULL;
248    }
249    printf("Stop Successful\n");
250    return ret;
251}
252
253static int32_t FrameStartMmap(const struct StrPara *param)
254{
255    if (param == NULL) {
256        return HDF_FAILURE;
257    }
258    const struct StrPara *strParam = param;
259    struct IAudioRender *render = strParam->render;
260    struct AudioMmapBufferDescriptor mmapDesc;
261
262    (void)signal(SIGINT, StreamClose);
263
264    // get file length
265    char pathBuf[PATH_MAX] = {'\0'};
266    if (realpath(g_path, pathBuf) == NULL) {
267        return HDF_FAILURE;
268    }
269
270    // get fileSize
271    FILE *fp = fopen(pathBuf, "rb+");
272    if (fp == NULL) {
273        printf("Open file failed!\n");
274        return HDF_FAILURE;
275    }
276
277    int32_t ret = fseek(fp, 0, SEEK_END);
278    if (ret != 0) {
279        fclose(fp);
280        return HDF_FAILURE;
281    }
282
283    int32_t reqSize = (int32_t)ftell(fp);
284    if (reqSize < 0) {
285        fclose(fp);
286        return HDF_FAILURE;
287    }
288    (void)fclose(fp);
289    // Init param
290    mmapDesc.memoryFd = 0; // default 0
291    mmapDesc.filePath = strdup(pathBuf);
292    mmapDesc.isShareable = 1;                                        // 1:Shareable ,0:Don't share
293    mmapDesc.transferFrameSize = DEEP_BUFFER_RENDER_PERIOD_SIZE / 4; // One frame size 4 bit
294    mmapDesc.offset = sizeof(g_wavHeadInfo);
295
296    // start
297    if (render == NULL || render->ReqMmapBuffer == NULL) {
298        free(mmapDesc.filePath);
299        return HDF_FAILURE;
300    }
301
302    ret = render->ReqMmapBuffer(render, reqSize, &mmapDesc);
303    if (ret < 0 || reqSize <= 0) {
304        free(mmapDesc.filePath);
305        printf("Request map fail,please check.\n");
306        return HDF_FAILURE;
307    }
308
309    if (g_render != NULL) {
310        ret = StopAudioFiles(&render);
311        if (ret < 0) {
312            free(mmapDesc.filePath);
313            AUDIO_FUNC_LOGE("StopAudioFiles File!");
314        }
315    }
316    free(mmapDesc.filePath);
317    return HDF_SUCCESS;
318}
319
320static int32_t FrameStart(const struct StrPara *param)
321{
322    if (param == NULL) {
323        return HDF_FAILURE;
324    }
325
326    size_t numRead;
327    char *frame = param->frame;
328    int32_t bufferSize = param->bufferSize;
329    struct IAudioRender *render = param->render;
330    size_t remainingDataSize = g_wavHeadInfo.riffSize;
331
332    (void)signal(SIGINT, StreamClose);
333    if (g_file == NULL) {
334        return HDF_FAILURE;
335    }
336
337    if (render == NULL || render->RenderFrame == NULL || frame == NULL) {
338        return HDF_FAILURE;
339    }
340
341    do {
342        uint64_t replyBytes = 0;
343        size_t readSize = (remainingDataSize > bufferSize) ? (size_t)bufferSize : remainingDataSize;
344        numRead = fread(frame, 1, readSize, g_file);
345        if (numRead > 0) {
346            int32_t ret = render->RenderFrame(render, (int8_t *)frame, numRead, &replyBytes);
347            if (ret == HDF_ERR_INVALID_OBJECT) {
348                AUDIO_FUNC_LOGE("Render already stop!");
349                break;
350            }
351            remainingDataSize -= numRead;
352        }
353
354        while (g_waitSleep) {
355            printf("music pause now.\n");
356            pthread_cond_wait(&g_functionCond, &g_mutex);
357            printf("music resume now.\n");
358        }
359    } while (!g_closeEnd && numRead > 0 && remainingDataSize > 0);
360
361    if (!g_closeEnd) {
362        printf("\nPlay complete, please select input again\n");
363        (void)StopAudioFiles(&render);
364    }
365    return HDF_SUCCESS;
366}
367
368static int32_t InitPlayingAudioParam(struct IAudioRender *render)
369{
370    if (render == NULL) {
371        return HDF_FAILURE;
372    }
373    uint64_t frameSize = 0;
374    uint64_t frameCount = 0;
375    uint64_t bufferSize = 0;
376    if (render->GetFrameSize(render, &frameSize) != HDF_SUCCESS) {
377        AUDIO_FUNC_LOGE("get frame size failed");
378    }
379    if (render->GetFrameCount(render, &frameCount) != HDF_SUCCESS) {
380        AUDIO_FUNC_LOGE("get frame count failed");
381    }
382
383    bufferSize = frameCount * frameSize;
384    if (bufferSize == 0) {
385        bufferSize = PcmFramesToBytes(g_attrs);
386        AUDIO_FUNC_LOGE("buffer size by calc is %" PRIu64 "", bufferSize);
387    }
388
389    g_frame = (char *)OsalMemCalloc(bufferSize);
390    if (g_frame == NULL) {
391        return HDF_FAILURE;
392    }
393
394    (void)memset_s(&g_str, sizeof(struct StrPara), 0, sizeof(struct StrPara));
395
396    g_str.render = render;
397    g_str.bufferSize = (int32_t)bufferSize;
398    g_str.frame = g_frame;
399    return HDF_SUCCESS;
400}
401
402static void PrintPlayMode(void)
403{
404    printf(" ============= Play Render Mode ==========\n");
405    printf("| 1. Render non-mmap                     |\n");
406    printf("| 2. Render mmap                         |\n");
407    printf(" ======================================== \n");
408}
409
410static int32_t SelectPlayMode(int32_t *palyModeFlag)
411{
412    if (palyModeFlag == NULL) {
413        AUDIO_FUNC_LOGE("palyModeFlag is null");
414        return HDF_FAILURE;
415    }
416
417    int choice = 0;
418
419    system("clear");
420
421    PrintPlayMode();
422
423    printf("Please enter your choice:");
424
425    int32_t ret = CheckInputName(INPUT_INT, (void *)&choice);
426    if (ret < 0) {
427        AUDIO_FUNC_LOGE("CheckInputName Fail");
428        return HDF_FAILURE;
429    } else {
430        *palyModeFlag = choice;
431    }
432    return HDF_SUCCESS;
433}
434
435static int32_t StartPlayThread(int32_t palyModeFlag)
436{
437    pthread_attr_t tidsAttr;
438    pthread_attr_init(&tidsAttr);
439    pthread_attr_setdetachstate(&tidsAttr, PTHREAD_CREATE_DETACHED);
440    switch (palyModeFlag) {
441        case 1: // 1. Stander Loading
442            if (pthread_create(&g_tids, &tidsAttr, (void *)(&FrameStart), &g_str) != 0) {
443                AUDIO_FUNC_LOGE("Create Thread Fail");
444                return HDF_FAILURE;
445            }
446            break;
447        case 2: // 2. Low latency Loading
448            if (pthread_create(&g_tids, &tidsAttr, (void *)(&FrameStartMmap), &g_str) != 0) {
449                AUDIO_FUNC_LOGE("Create Thread Fail");
450                return HDF_FAILURE;
451            }
452            break;
453        default:
454            printf("Input error,Switched to non-mmap Mode for you.\n");
455            SystemInputFail();
456
457            if (pthread_create(&g_tids, &tidsAttr, (void *)(&FrameStart), &g_str) != 0) {
458                AUDIO_FUNC_LOGE("Create Thread Fail");
459                return HDF_FAILURE;
460            }
461            break;
462    }
463    return HDF_SUCCESS;
464}
465
466static int32_t PlayingAudioInitFile(void)
467{
468    if (g_file != NULL) {
469        AUDIO_FUNC_LOGE("the music is playing,please stop first");
470        return HDF_FAILURE;
471    }
472    g_closeEnd = false;
473
474    char pathBuf[PATH_MAX] = {'\0'};
475    if (realpath(g_path, pathBuf) == NULL) {
476        return HDF_FAILURE;
477    }
478
479    g_file = fopen(pathBuf, "rb");
480    if (g_file == NULL) {
481        printf("failed to open '%s'\n", g_path);
482        return HDF_FAILURE;
483    }
484
485    if (CheckWavFileHeader(g_file, &g_wavHeadInfo, &g_attrs) < 0) {
486        FileClose(&g_file);
487        return HDF_FAILURE;
488    }
489
490    (void)chmod(g_path, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
491
492    return HDF_SUCCESS;
493}
494
495static int32_t PlayingAudioInitRender(struct IAudioRender **renderTemp)
496{
497    if (renderTemp == NULL) {
498        AUDIO_FUNC_LOGE("render is null");
499        return HDF_FAILURE;
500    }
501    struct IAudioRender *render = NULL;
502    if (g_adapter == NULL || g_adapter->CreateRender == NULL) {
503        return HDF_FAILURE;
504    }
505    int32_t ret = g_adapter->CreateRender(g_adapter, &g_devDesc, &g_attrs, &render, &g_renderId);
506    if (render == NULL || ret < 0 || render->RenderFrame == NULL) {
507        AUDIO_FUNC_LOGE("AudioDeviceCreateRender failed or RenderFrame is null");
508        return HDF_FAILURE;
509    }
510
511    // Playing audio files
512    if (render->Start((void *)render)) {
513        AUDIO_FUNC_LOGE("Start Bind Fail!");
514        g_adapter->DestroyRender(g_adapter, g_renderId);
515        IAudioRenderRelease(render, g_isDirect);
516        return HDF_FAILURE;
517    }
518
519    if (InitPlayingAudioParam(render) < 0) {
520        g_adapter->DestroyRender(g_adapter, g_renderId);
521        IAudioRenderRelease(render, g_isDirect);
522        return HDF_FAILURE;
523    }
524    *renderTemp = render;
525    return HDF_SUCCESS;
526}
527
528static int32_t PlayingAudioFiles(struct IAudioRender **renderS)
529{
530    if (renderS == NULL || g_adapter == NULL) {
531        return HDF_FAILURE;
532    }
533
534    if (PlayingAudioInitFile() < 0) {
535        AUDIO_FUNC_LOGE("PlayingAudioInitFile Fail");
536        return HDF_FAILURE;
537    }
538
539    int32_t palyModeFlag = 0;
540    if (SelectPlayMode(&palyModeFlag) < 0) {
541        AUDIO_FUNC_LOGE("SelectPlayMode Fail");
542        FileClose(&g_file);
543        return HDF_FAILURE;
544    }
545
546    struct IAudioRender *render = NULL;
547    if (PlayingAudioInitRender(&render) < 0) {
548        AUDIO_FUNC_LOGE("PlayingAudioInitRender fail");
549        FileClose(&g_file);
550        return HDF_FAILURE;
551    }
552
553    if (StartPlayThread(palyModeFlag) < 0) {
554        FileClose(&g_file);
555        if (g_adapter != NULL && g_adapter->DestroyRender != NULL) {
556            g_adapter->DestroyRender(g_adapter, g_renderId);
557        }
558        IAudioRenderRelease(render, g_isDirect);
559        return HDF_FAILURE;
560    }
561
562    *renderS = render;
563    printf("Start Successful,Music is playing\n");
564    return HDF_SUCCESS;
565}
566
567static int32_t SelectLoadingMode(void)
568{
569    int choice = 0;
570
571    system("clear");
572
573    PrintLoadModeMenu();
574
575    printf("Please enter your choice:");
576
577    int32_t ret = CheckInputName(INPUT_INT, (void *)&choice);
578    if (ret < 0) {
579        return HDF_FAILURE;
580    }
581
582    switch (choice) {
583        case 1: // 1 is Passthrough Loading
584            g_isDirect = true;
585            break;
586        case 2: // 2 is IPC Loading
587            g_isDirect = false;
588            break;
589        default:
590            printf("Input error,Switched to direct loading in for you.\n");
591            SystemInputFail();
592            g_isDirect = true;
593            break;
594    }
595
596    return HDF_SUCCESS;
597}
598
599void AudioAdapterDescriptorFree(struct AudioAdapterDescriptor *dataBlock, bool freeSelf)
600{
601    if (dataBlock == NULL) {
602        return;
603    }
604
605    if (dataBlock->adapterName != NULL) {
606        OsalMemFree(dataBlock->adapterName);
607        dataBlock->adapterName = NULL;
608    }
609
610    if (dataBlock->ports != NULL) {
611        OsalMemFree(dataBlock->ports);
612    }
613
614    if (freeSelf) {
615        OsalMemFree(dataBlock);
616    }
617}
618
619static void ReleaseAdapterDescs(struct AudioAdapterDescriptor **descs, uint32_t descsLen)
620{
621    if (descsLen > 0 && descs != NULL && (*descs) != NULL) {
622        for (uint32_t i = 0; i < descsLen; i++) {
623            AudioAdapterDescriptorFree(&(*descs)[i], false);
624        }
625        OsalMemFree(*descs);
626        *descs = NULL;
627    }
628}
629
630static int32_t GetManagerAndLoadAdapter(struct AudioPort *renderPort)
631{
632    int32_t adapterIndex = 0;
633
634    if (renderPort == NULL) {
635        AUDIO_FUNC_LOGE("The Parameter is NULL");
636        return HDF_FAILURE;
637    }
638
639    struct IAudioManager *audioManagerIns = IAudioManagerGet(g_isDirect);
640    if (audioManagerIns == NULL) {
641        AUDIO_FUNC_LOGE("Get audio Manager Fail");
642        return HDF_FAILURE;
643    }
644
645    g_audioManager = audioManagerIns;
646
647    struct AudioAdapterDescriptor *descs = (struct AudioAdapterDescriptor *)OsalMemCalloc(
648        sizeof(struct AudioAdapterDescriptor) * (MAX_AUDIO_ADAPTER_DESC));
649    if (descs == NULL) {
650        AUDIO_FUNC_LOGE("OsalMemCalloc for descs failed");
651        return HDF_FAILURE;
652    }
653
654    uint32_t adapterNum = MAX_AUDIO_ADAPTER_DESC;
655
656    int32_t ret = audioManagerIns->GetAllAdapters(audioManagerIns, descs, &adapterNum);
657    if (ret < 0 || adapterNum == 0) {
658        AUDIO_FUNC_LOGE("Get All Adapters Fail");
659        ReleaseAdapterDescs(&descs, MAX_AUDIO_ADAPTER_DESC);
660        return HDF_ERR_NOT_SUPPORT;
661    }
662    if (SelectAudioCard(descs, adapterNum, &adapterIndex) != HDF_SUCCESS) {
663        ReleaseAdapterDescs(&descs, MAX_AUDIO_ADAPTER_DESC);
664        return HDF_ERR_NOT_SUPPORT;
665    }
666    if (strcpy_s(g_adapterName, PATH_LEN, descs[adapterIndex - 1].adapterName) < 0) {
667        ReleaseAdapterDescs(&descs, MAX_AUDIO_ADAPTER_DESC);
668        return HDF_ERR_NOT_SUPPORT;
669    }
670    if (SwitchAudioPort(&descs[adapterIndex - 1], PORT_OUT, renderPort) != HDF_SUCCESS) {
671        ReleaseAdapterDescs(&descs, MAX_AUDIO_ADAPTER_DESC);
672        return HDF_ERR_NOT_SUPPORT;
673    }
674    if (audioManagerIns->LoadAdapter(audioManagerIns, &descs[adapterIndex - 1], &g_adapter)) {
675        AUDIO_FUNC_LOGE("Load Adapter Fail");
676        ReleaseAdapterDescs(&descs, MAX_AUDIO_ADAPTER_DESC);
677        return HDF_ERR_NOT_SUPPORT;
678    }
679
680    ReleaseAdapterDescs(&descs, MAX_AUDIO_ADAPTER_DESC);
681
682    return HDF_SUCCESS;
683}
684
685static int32_t InitRenderParam(uint32_t portId)
686{
687    if (g_adapter == NULL || g_adapter->InitAllPorts == NULL) {
688        return HDF_FAILURE;
689    }
690    // Initialization port information, can fill through mode and other parameters
691    (void)g_adapter->InitAllPorts(g_adapter);
692
693    // User needs to set
694    if (InitAttrs(&g_attrs) < 0) {
695        AUDIO_FUNC_LOGE("InitAttrs failed");
696        return HDF_FAILURE;
697    }
698
699    // Specify a hardware device
700    if (InitDevDesc(&g_devDesc, portId) < 0) {
701        AUDIO_FUNC_LOGE("InitDevDesc failed");
702        return HDF_FAILURE;
703    }
704    return HDF_SUCCESS;
705}
706
707static int32_t RenderGetAdapterAndInitEnvParams(void)
708{
709    struct AudioPort renderPort;
710
711    int32_t ret = GetManagerAndLoadAdapter(&renderPort);
712    if (ret < 0) {
713        return ret;
714    }
715
716    if (InitRenderParam(renderPort.portId) < 0) {
717        g_audioManager->UnloadAdapter(g_audioManager, g_adapterName);
718        IAudioAdapterRelease(g_adapter, g_isDirect);
719        g_adapter = NULL;
720        return HDF_FAILURE;
721    }
722    return HDF_SUCCESS;
723}
724
725static int32_t InitParam(void)
726{
727    if (SelectLoadingMode() < 0) {
728        return HDF_FAILURE;
729    }
730
731    /* Select loading mode,end */
732    g_audioPort.dir = PORT_OUT;
733    g_audioPort.portId = 0;
734    g_audioPort.portName = "AOP";
735
736    if (RenderGetAdapterAndInitEnvParams() < 0) {
737        AUDIO_FUNC_LOGE("GetProxyManagerFunc Fail");
738        if (g_audioManager != NULL) {
739            IAudioManagerRelease(g_audioManager, g_isDirect);
740            g_audioManager = NULL;
741        }
742        return HDF_FAILURE;
743    }
744    return HDF_SUCCESS;
745}
746
747static int32_t SetRenderMute(struct IAudioRender **render)
748{
749    (void)render;
750    if (g_render == NULL || g_render->GetMute == NULL) {
751        return HDF_FAILURE;
752    }
753
754    int32_t val;
755    bool isMute = false;
756
757    int32_t ret = g_render->GetMute((void *)g_render, &isMute);
758    if (ret < 0) {
759        AUDIO_FUNC_LOGE("The current mute state was not obtained!");
760    }
761
762    printf("Now %s ,Do you need to set mute status(1/0):", isMute ? "mute" : "not mute");
763
764    ret = CheckInputName(INPUT_INT, (void *)&val);
765    if (ret < 0) {
766        return HDF_FAILURE;
767    }
768
769    if (g_render == NULL || g_render->SetMute == NULL) {
770        AUDIO_FUNC_LOGE("Music already stop!");
771        SystemInputFail();
772        return HDF_FAILURE;
773    }
774    if (val == 1) {
775        ret = g_render->SetMute((void *)g_render, !isMute);
776    }
777    return ret;
778}
779
780static int32_t SetRenderVolume(struct IAudioRender **render)
781{
782    (void)render;
783    if (g_render == NULL || g_render->GetVolume == NULL) {
784        return HDF_FAILURE;
785    }
786
787    int32_t ret;
788    float val = 0.0;
789
790    ret = g_render->GetVolume((void *)g_render, &val);
791    if (ret < 0) {
792        AUDIO_FUNC_LOGE("Get current volume failed!");
793        SystemInputFail();
794        return ret;
795    }
796
797    printf("Now the volume is %f ,Please enter the volume value you want to set (0.0-1.0):", val);
798
799    ret = CheckInputName(INPUT_FLOAT, (void *)&val);
800    if (ret < 0) {
801        return HDF_FAILURE;
802    }
803
804    if (val < 0.0 || val > 1.0) {
805        AUDIO_FUNC_LOGE("Invalid volume value!");
806        SystemInputFail();
807        return HDF_FAILURE;
808    }
809
810    if (g_render == NULL || g_render->SetVolume == NULL) {
811        AUDIO_FUNC_LOGE("Music already stop!");
812        SystemInputFail();
813        return HDF_FAILURE;
814    }
815
816    ret = g_render->SetVolume((void *)g_render, val);
817    if (ret < 0) {
818        AUDIO_FUNC_LOGE("set volume fail!");
819        SystemInputFail();
820    }
821    return ret;
822}
823
824static int32_t GetRenderGain(struct IAudioRender **render)
825{
826    (void)render;
827    if (g_render == NULL || g_render->GetGain == NULL) {
828        return HDF_FAILURE;
829    }
830
831    float val = 1.0;
832
833    int32_t ret = g_render->GetGain((void *)g_render, &val);
834    if (ret < 0) {
835        AUDIO_FUNC_LOGE("Get current gain failed!");
836        SystemInputFail();
837        return HDF_FAILURE;
838    }
839    printf("Now the gain is %f,", val);
840    SystemInputFail();
841    return HDF_SUCCESS;
842}
843
844static int32_t SetRenderPause(struct IAudioRender **render)
845{
846    (void)render;
847
848    if (g_waitSleep) {
849        AUDIO_FUNC_LOGE("Already pause,not need pause again!");
850        SystemInputFail();
851        return HDF_FAILURE;
852    }
853
854    if (g_render == NULL || g_render->Pause == NULL) {
855        return HDF_FAILURE;
856    }
857
858    int32_t ret = g_render->Pause((void *)g_render);
859    if (ret != 0) {
860        return HDF_FAILURE;
861    }
862
863    printf("Pause success!\n");
864    g_waitSleep = true;
865    return HDF_SUCCESS;
866}
867
868static int32_t SetRenderResume(struct IAudioRender **render)
869{
870    (void)render;
871
872    if (!g_waitSleep) {
873        AUDIO_FUNC_LOGE("Now is Playing,not need resume!");
874        SystemInputFail();
875        return HDF_FAILURE;
876    }
877
878    if (g_render == NULL || g_render->Resume == NULL) {
879        return HDF_FAILURE;
880    }
881
882    int32_t ret = g_render->Resume((void *)g_render);
883    if (ret != 0) {
884        return HDF_FAILURE;
885    }
886    printf("resume success!\n");
887
888    pthread_mutex_lock(&g_mutex);
889    g_waitSleep = false;
890    pthread_cond_signal(&g_functionCond);
891    pthread_mutex_unlock(&g_mutex);
892    return HDF_SUCCESS;
893}
894static void PrintAttributesFromat(void)
895{
896    printf(" ============= Render Sample Attributes Fromat =============== \n");
897    printf("| 1. Render AUDIO_FORMAT_TYPE_PCM_8_BIT                            |\n");
898    printf("| 2. Render AUDIO_FORMAT_TYPE_PCM_16_BIT                           |\n");
899    printf("| 3. Render AUDIO_FORMAT_TYPE_PCM_24_BIT                           |\n");
900    printf("| 4. Render AUDIO_FORMAT_TYPE_PCM_32_BIT                           |\n");
901    printf(" ============================================================= \n");
902}
903static int32_t SelectAttributesFomat(uint32_t *pcmFomat)
904{
905    if (pcmFomat == NULL) {
906        AUDIO_FUNC_LOGE("fomat is null!");
907        return HDF_FAILURE;
908    }
909
910    int val = 0;
911
912    PrintAttributesFromat();
913
914    printf("Please select audio format,If not selected, the default is 16bit:");
915
916    int32_t ret = CheckInputName(INPUT_INT, (void *)&val);
917    if (ret < 0) {
918        AUDIO_FUNC_LOGE("CheckInputName failed.");
919        return HDF_FAILURE;
920    }
921
922    switch (val) {
923        case AUDIO_FORMAT_TYPE_PCM_8_BIT:
924            *pcmFomat = AUDIO_FORMAT_TYPE_PCM_8_BIT;
925            break;
926        case AUDIO_FORMAT_TYPE_PCM_16_BIT:
927            *pcmFomat = AUDIO_FORMAT_TYPE_PCM_16_BIT;
928            break;
929        case AUDIO_FORMAT_TYPE_PCM_24_BIT:
930            *pcmFomat = AUDIO_FORMAT_TYPE_PCM_24_BIT;
931            break;
932        case AUDIO_FORMAT_TYPE_PCM_32_BIT:
933            *pcmFomat = AUDIO_FORMAT_TYPE_PCM_32_BIT;
934            break;
935        default:
936            *pcmFomat = AUDIO_FORMAT_TYPE_PCM_16_BIT;
937            break;
938    }
939    return HDF_SUCCESS;
940}
941
942static int32_t SetRenderAttributes(struct IAudioRender **render)
943{
944    (void)render;
945
946    struct AudioSampleAttributes attrs;
947
948    if (g_render == NULL || g_render->GetSampleAttributes == NULL) {
949        AUDIO_FUNC_LOGE("The pointer is null!");
950        return HDF_FAILURE;
951    }
952
953    int32_t ret = g_render->GetSampleAttributes((void *)g_render, &attrs);
954    if (ret < 0) {
955        AUDIO_FUNC_LOGE("GetRenderAttributes failed!");
956    } else {
957        printf("Current sample attributes:\n");
958        printf("audioType is %u\nfomat is %u\nsampleRate is %u\nchannalCount is"
959               "%u\nperiod is %u\nframesize is %u\nbigEndian is %u\nSignedData is %u\n",
960            attrs.type, attrs.format, attrs.sampleRate, attrs.channelCount, attrs.period, attrs.frameSize,
961            attrs.isBigEndian, attrs.isSignedData);
962    }
963    printf("Set Sample Attributes,");
964    SystemInputFail();
965    system("clear");
966    printf("The sample attributes you want to set,Step by step, please.\n");
967
968    ret = SelectAttributesFomat((uint32_t *)(&attrs.format));
969    if (ret < 0) {
970        AUDIO_FUNC_LOGE("SetRenderAttributes format failed!");
971        return HDF_FAILURE;
972    }
973
974    printf("\nPlease input sample rate(48000,44100,32000...):");
975
976    ret = CheckInputName(INPUT_UINT32, (void *)(&attrs.sampleRate));
977    if (ret < 0) {
978        return HDF_FAILURE;
979    }
980
981    printf("\nPlease input bigEndian(false=0/true=1):");
982
983    ret = CheckInputName(INPUT_UINT32, (void *)(&attrs.isBigEndian));
984    if (ret < 0) {
985        return HDF_FAILURE;
986    }
987    if (g_render == NULL || g_render->SetSampleAttributes == NULL) {
988        AUDIO_FUNC_LOGE("Music already complete,Please replay and set the attrbutes!");
989        SystemInputFail();
990        return HDF_FAILURE;
991    }
992
993    ret = g_render->SetSampleAttributes((void *)g_render, &attrs);
994    if (ret < 0) {
995        AUDIO_FUNC_LOGE("Set render attributes failed!");
996        SystemInputFail();
997    }
998    return ret;
999}
1000
1001static int32_t PrintRenderSelectPinFirst(struct AudioSceneDescriptor *scene)
1002{
1003    system("clear");
1004    printf(" ==================== Select Pin =====================  \n");
1005    printf("| 0. Speaker                                           |\n");
1006    printf("| 1. HeadPhones                                        |\n");
1007    printf(" =====================================================  \n");
1008
1009    printf("Please input your choice:\n");
1010    int32_t val = 0;
1011    int32_t ret = CheckInputName(INPUT_INT, (void *)&val);
1012    if (ret < 0) {
1013        AUDIO_FUNC_LOGE("Invalid value!");
1014        SystemInputFail();
1015        return HDF_FAILURE;
1016    }
1017
1018    if (val == 1) {
1019        scene->desc.pins = PIN_OUT_HEADSET;
1020    } else {
1021        scene->desc.pins = PIN_OUT_SPEAKER;
1022    }
1023
1024    return HDF_SUCCESS;
1025}
1026
1027static int32_t PrintRenderSelectPinSecond(struct AudioSceneDescriptor *scene)
1028{
1029    system("clear");
1030    printf(" ==================== Select Pin =====================  \n");
1031    printf("| 0. Speaker                                           |\n");
1032    printf("| 1. HeadPhones                                        |\n");
1033    printf("| 2. Speaker and HeadPhones                            |\n");
1034    printf(" =====================================================  \n");
1035
1036    printf("Please input your choice:\n");
1037    int32_t val = 0;
1038    int32_t ret = CheckInputName(INPUT_INT, (void *)&val);
1039    if (ret < 0) {
1040        AUDIO_FUNC_LOGE("Invalid value!");
1041        SystemInputFail();
1042        return HDF_FAILURE;
1043    }
1044
1045    if (val == 1) {
1046        scene->desc.pins = PIN_OUT_HEADSET;
1047    } else if (val == 0) {
1048        scene->desc.pins = PIN_OUT_SPEAKER;
1049    } else {
1050        scene->desc.pins = PIN_OUT_SPEAKER | PIN_OUT_HEADSET;
1051    }
1052
1053    return HDF_SUCCESS;
1054}
1055
1056static int32_t PrintRenderSelectPinThird(struct AudioSceneDescriptor *scene)
1057{
1058    system("clear");
1059    printf(" ==================== Select Pin =====================  \n");
1060    printf("| 0. Speaker                                           |\n");
1061    printf("| 1. HeadPhones                                        |\n");
1062    printf(" =====================================================  \n");
1063
1064    printf("Please input your choice:\n");
1065    int32_t val = 0;
1066    int32_t ret = CheckInputName(INPUT_INT, (void *)&val);
1067    if (ret < 0) {
1068        AUDIO_FUNC_LOGE("Invalid value!");
1069        SystemInputFail();
1070        return HDF_FAILURE;
1071    }
1072
1073    if (val == 1) {
1074        scene->desc.pins = PIN_OUT_HEADSET;
1075    } else {
1076        scene->desc.pins = PIN_OUT_SPEAKER;
1077    }
1078
1079    return HDF_SUCCESS;
1080}
1081
1082static void SelectSceneMenu(void)
1083{
1084    printf(" =================== Select Scene ======================== \n");
1085    printf("0 is Midea.                                               |\n");
1086    printf("1 is Communication.                                       |\n");
1087    printf("2 is Ring-Tone.                                           |\n");
1088    printf("3 is Voice-Call.                                          |\n");
1089    printf("4 is Mmap.                                                |\n");
1090    printf(" ========================================================= \n");
1091}
1092
1093static int32_t SelectRenderScene(struct IAudioRender **render)
1094{
1095    (void)render;
1096
1097    int32_t val = 0;
1098    struct AudioSceneDescriptor scene;
1099    system("clear");
1100    SelectSceneMenu();
1101    printf("Please input your choice:\n");
1102
1103    int32_t ret = CheckInputName(INPUT_INT, (void *)&val);
1104    if (ret < 0) {
1105        AUDIO_FUNC_LOGE("Invalid value!");
1106        SystemInputFail();
1107        return HDF_FAILURE;
1108    }
1109
1110    switch (val) {
1111        case AUDIO_IN_MEDIA:
1112            scene.scene.id = AUDIO_IN_MEDIA;
1113            PrintRenderSelectPinFirst(&scene);
1114            break;
1115        case AUDIO_IN_COMMUNICATION:
1116            scene.scene.id = AUDIO_IN_COMMUNICATION;
1117            PrintRenderSelectPinSecond(&scene);
1118            break;
1119        case AUDIO_IN_RINGTONE:
1120            scene.scene.id = AUDIO_IN_RINGTONE;
1121            scene.desc.pins = PIN_OUT_SPEAKER | PIN_OUT_HEADSET;
1122            break;
1123        case AUDIO_IN_CALL:
1124            scene.scene.id = AUDIO_IN_CALL;
1125            PrintRenderSelectPinThird(&scene);
1126            break;
1127        case AUDIO_MMAP_NOIRQ:
1128            scene.scene.id = AUDIO_MMAP_NOIRQ;
1129            PrintRenderSelectPinFirst(&scene);
1130            break;
1131        default:
1132            break;
1133    }
1134
1135    scene.desc.desc = "mic";
1136
1137    if (g_render == NULL || g_render->SelectScene == NULL) {
1138        AUDIO_FUNC_LOGE("Music already stop,");
1139        SystemInputFail();
1140        return HDF_FAILURE;
1141    }
1142
1143    ret = g_render->SelectScene((void *)g_render, &scene);
1144    if (ret < 0) {
1145        AUDIO_FUNC_LOGE("Select scene fail\n");
1146    }
1147    return ret;
1148}
1149
1150static int32_t GetExtParams(struct IAudioRender **render)
1151{
1152    (void)render;
1153    if (g_render == NULL || g_render->GetExtraParams == NULL) {
1154        return HDF_FAILURE;
1155    }
1156
1157    char keyValueList[BUFFER_LEN] = {0};
1158
1159    int32_t ret = g_render->GetExtraParams((void *)g_render, keyValueList, EXT_PARAMS_MAXLEN);
1160    if (ret < 0) {
1161        AUDIO_FUNC_LOGE("Get EXT params failed!");
1162        SystemInputFail();
1163        return HDF_FAILURE;
1164    }
1165    printf("keyValueList = %s\n", keyValueList);
1166    return HDF_SUCCESS;
1167}
1168
1169static int32_t GetRenderMmapPosition(struct IAudioRender **render)
1170{
1171    (void)render;
1172
1173    if (g_render == NULL || g_render->GetMmapPosition == NULL) {
1174        return HDF_FAILURE;
1175    }
1176
1177    uint64_t frames = 0;
1178    struct AudioTimeStamp time;
1179    time.tvNSec = 0;
1180    time.tvSec = 0;
1181
1182    int32_t ret = g_render->GetMmapPosition((void *)g_render, &frames, &time);
1183    if (ret < 0) {
1184        AUDIO_FUNC_LOGE("Get current Mmap frames Position failed!");
1185        SystemInputFail();
1186        return HDF_FAILURE;
1187    }
1188    printf("Now the Position is %" PRIu64 "\n", frames);
1189    return HDF_SUCCESS;
1190}
1191
1192static void PrintMenu2(void)
1193{
1194    printf(" ================== Play Render Menu ================== \n");
1195    printf("| 1. Render Start                                      |\n");
1196    printf("| 2. Render Stop                                       |\n");
1197    printf("| 3. Render Resume                                     |\n");
1198    printf("| 4. Render Pause                                      |\n");
1199    printf("| 5. Render SetVolume                                  |\n");
1200    printf("| 6. Render GetGain                                    |\n");
1201    printf("| 7. Render SetMute                                    |\n");
1202    printf("| 8. Render SetAttributes                              |\n");
1203    printf("| 9. Render SelectScene                                |\n");
1204    printf("| 10. Render getEXtParams                              |\n");
1205    printf("| 11. Render getMmapPosition                           |\n");
1206    printf("| 12.Exit                                              |\n");
1207    printf(" ====================================================== \n");
1208}
1209
1210static struct ProcessRenderMenuSwitchList g_processRenderMenuSwitchList[] = {
1211    {RENDER_START,            PlayingAudioFiles    },
1212    {RENDER_STOP,             StopAudioFiles       },
1213    {RENDER_RESUME,           SetRenderResume      },
1214    {RENDER_PAUSE,            SetRenderPause       },
1215    {SET_RENDER_VOLUME,       SetRenderVolume      },
1216    {SET_RENDER_GAIN,         GetRenderGain        },
1217    {SET_RENDER_MUTE,         SetRenderMute        },
1218    {SET_RENDER_ATTRIBUTES,   SetRenderAttributes  },
1219    {SET_RENDER_SLECET_SCENE, SelectRenderScene    },
1220    {GET_RENDER_EXT_PARAMS,   GetExtParams         },
1221    {GET_RENDER_POSITION,     GetRenderMmapPosition},
1222};
1223
1224static void ProcessMenu(int32_t choice)
1225{
1226    if (choice == GET_RENDER_POSITION + 1) {
1227        return;
1228    }
1229
1230    if (g_render == NULL && choice != 1) {
1231        AUDIO_FUNC_LOGE("This render already release!");
1232        SystemInputFail();
1233        return;
1234    }
1235
1236    for (int32_t i = RENDER_START; i <= GET_RENDER_POSITION; ++i) {
1237        if ((choice == (int32_t)g_processRenderMenuSwitchList[i - 1].cmd) &&
1238            (g_processRenderMenuSwitchList[i - 1].operation != NULL)) {
1239            g_processRenderMenuSwitchList[i - 1].operation(&g_render);
1240        }
1241    }
1242}
1243
1244static void Choice(void)
1245{
1246    int32_t choice = 0;
1247
1248    while (choice < GET_RENDER_POSITION + 1 && choice >= 0) {
1249        system("clear");
1250        PrintMenu2();
1251        printf("your choice is:\n");
1252
1253        int32_t ret = CheckInputName(INPUT_INT, (void *)&choice);
1254        if (ret < 0) {
1255            continue;
1256        }
1257
1258        if (choice < RENDER_START || choice > GET_RENDER_POSITION + 1) {
1259            AUDIO_FUNC_LOGE("You input is wrong!");
1260            choice = 0;
1261            SystemInputFail();
1262            continue;
1263        }
1264        ProcessMenu(choice);
1265    }
1266}
1267
1268int32_t main(int32_t argc, char const *argv[])
1269{
1270    if (argc < 2 || argv == NULL || argv[0] == NULL) { // The parameter number is not greater than 2
1271        printf("usage:[1]sample [2]/data/test.wav\n");
1272        return 0;
1273    }
1274
1275    if (argv[1] == NULL || strlen(argv[1]) == 0) {
1276        return HDF_FAILURE;
1277    }
1278
1279    int32_t ret = strncpy_s(g_path, PATH_LEN - 1, argv[1], strlen(argv[1]) + 1);
1280    if (ret != 0) {
1281        AUDIO_FUNC_LOGE("strncpy_s Fail!");
1282        return HDF_FAILURE;
1283    }
1284
1285    char pathBuf[PATH_MAX] = {'\0'};
1286    if (realpath(g_path, pathBuf) == NULL) {
1287        AUDIO_FUNC_LOGE("realpath Fail!");
1288        return HDF_FAILURE;
1289    }
1290
1291    if (InitParam() != HDF_SUCCESS) { // init
1292        AUDIO_FUNC_LOGE("InitParam Fail!");
1293        return HDF_FAILURE;
1294    }
1295
1296    Choice();
1297
1298    if (g_render != NULL && g_adapter != NULL) {
1299        StopAudioFiles(&g_render);
1300    }
1301
1302    if (g_audioManager != NULL && g_audioManager->UnloadAdapter != NULL) {
1303        g_audioManager->UnloadAdapter(g_audioManager, g_adapterName);
1304        IAudioAdapterRelease(g_adapter, g_isDirect);
1305        g_adapter = NULL;
1306        IAudioManagerRelease(g_audioManager, g_isDirect);
1307        g_audioManager = NULL;
1308    }
1309    return 0;
1310}
1311