* Copyright (c) 2022-2023 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <dlfcn.h>
#include <limits.h>
#include <pthread.h>
#include <securec.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <unistd.h>
#include "framework_common.h"
#include "hdf_base.h"
#include "inttypes.h"
#include "osal_mem.h"
#include "v6_1/audio_types.h"
#include "v6_1/iaudio_manager.h"
#define MAX_AUDIO_ADAPTER_DESC 5
#define BUFFER_LEN 256
#define AUDIO_CHANNELCOUNT 2
#define AUDIO_SAMPLE_RATE_48K 48000
#define PATH_LEN 256
#define DEEP_BUFFER_RENDER_PERIOD_SIZE 4096
#define INT_32_MAX 0x7fffffff
#define EXT_PARAMS_MAXLEN 107
#define BITS_TO_FROMAT 3
struct StrPara {
struct IAudioRender *render;
FILE *file;
struct AudioSampleAttributes attrs;
uint64_t *replyBytes;
char *frame;
int32_t bufferSize;
};
struct IAudioRender *g_render = NULL;
struct IAudioAdapter *g_adapter = NULL;
static struct IAudioManager *g_audioManager = NULL;
struct AudioDeviceDescriptor g_devDesc;
struct AudioSampleAttributes g_attrs;
struct AudioPort g_audioPort;
struct AudioHeadInfo g_wavHeadInfo;
static struct StrPara g_str;
uint32_t g_renderId = 0;
pthread_t g_tids;
char *g_frame = NULL;
FILE *g_file;
char g_path[256];
char g_adapterName[PATH_LEN] = {0};
static int32_t g_closeEnd = 0;
pthread_mutex_t g_mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t g_functionCond = PTHREAD_COND_INITIALIZER;
bool g_waitSleep = false;
bool g_isDirect = true;
enum RenderMenuId {
RENDER_START = 1,
RENDER_STOP,
RENDER_RESUME,
RENDER_PAUSE,
SET_RENDER_VOLUME,
SET_RENDER_GAIN,
SET_RENDER_MUTE,
SET_RENDER_ATTRIBUTES,
SET_RENDER_SLECET_SCENE,
GET_RENDER_EXT_PARAMS,
GET_RENDER_POSITION,
};
enum RenderInputType {
INPUT_INT = 0,
INPUT_FLOAT,
INPUT_UINT32,
};
typedef int32_t (*AudioRenderOperation)(struct IAudioRender **);
struct ProcessRenderMenuSwitchList {
enum RenderMenuId cmd;
AudioRenderOperation operation;
};
static int32_t CheckInputName(int type, void *val)
{
if (val == NULL) {
return HDF_FAILURE;
}
int ret;
int inputInt = 0;
float inputFloat = 0.0;
uint32_t inputUint = 0;
printf("\n");
switch (type) {
case INPUT_INT:
ret = scanf_s("%d", &inputInt);
if (inputInt < 0 || inputInt > GET_RENDER_POSITION + 1) {
if (g_frame != NULL) {
OsalMemFree(g_frame);
g_frame = NULL;
}
AUDIO_FUNC_LOGE("Input failure");
return HDF_FAILURE;
}
*(int *)val = inputInt;
break;
case INPUT_FLOAT:
ret = scanf_s("%f", &inputFloat);
*(float *)val = inputFloat;
break;
case INPUT_UINT32:
ret = scanf_s("%u", &inputUint);
if (inputUint > 0xFFFFFFFF) {
return HDF_FAILURE;
}
*(uint32_t *)val = inputUint;
break;
default:
ret = EOF;
break;
}
if (ret == 0) {
CleanStdin();
} else if (ret == EOF) {
AUDIO_FUNC_LOGE("Input failure occurs!");
return HDF_FAILURE;
}
return HDF_SUCCESS;
}
static int32_t InitAttrs(struct AudioSampleAttributes *attrs)
{
if (attrs == NULL) {
return HDF_FAILURE;
}
attrs->format = AUDIO_FORMAT_TYPE_PCM_16_BIT;
attrs->channelCount = AUDIO_CHANNELCOUNT;
attrs->sampleRate = AUDIO_SAMPLE_RATE_48K;
attrs->interleaved = 0;
attrs->type = AUDIO_IN_MEDIA;
attrs->period = DEEP_BUFFER_RENDER_PERIOD_SIZE;
attrs->frameSize = PCM_16_BIT * attrs->channelCount / PCM_8_BIT;
attrs->isBigEndian = false;
attrs->isSignedData = true;
attrs->startThreshold = DEEP_BUFFER_RENDER_PERIOD_SIZE / (attrs->frameSize);
attrs->stopThreshold = INT_32_MAX;
attrs->silenceThreshold = 0;
return HDF_SUCCESS;
}
static int32_t InitDevDesc(struct AudioDeviceDescriptor *devDesc, uint32_t portId)
{
if (devDesc == NULL) {
return HDF_FAILURE;
}
devDesc->portId = portId;
devDesc->pins = PIN_OUT_SPEAKER;
devDesc->desc = strdup("cardname");
return HDF_SUCCESS;
}
static void StreamClose(int32_t sig)
{
(void)signal(sig, SIG_IGN);
g_closeEnd = 1;
}
static uint32_t PcmFramesToBytes(const struct AudioSampleAttributes attrs)
{
return DEEP_BUFFER_RENDER_PERIOD_SIZE * attrs.channelCount * (PcmFormatToBits(attrs.format) >> BITS_TO_FROMAT);
}
static int32_t StopAudioFiles(struct IAudioRender **renderS)
{
if (renderS == NULL) {
return HDF_FAILURE;
}
if (g_waitSleep) {
pthread_mutex_lock(&g_mutex);
g_waitSleep = false;
pthread_cond_signal(&g_functionCond);
pthread_mutex_unlock(&g_mutex);
}
if (!g_closeEnd) {
g_closeEnd = true;
usleep(100000);
}
struct IAudioRender *render = *renderS;
if (render == NULL) {
AUDIO_FUNC_LOGE("render is null");
return HDF_FAILURE;
}
int32_t ret = render->Stop((void *)render);
if (ret < 0) {
AUDIO_FUNC_LOGE("Stop Render!");
}
if (g_adapter == NULL || g_adapter->DestroyRender == NULL) {
return HDF_FAILURE;
}
ret = g_adapter->DestroyRender(g_adapter, g_renderId);
if (ret < 0) {
AUDIO_FUNC_LOGE("Destroy Render!");
}
IAudioRenderRelease(render, g_isDirect);
*renderS = NULL;
g_render = NULL;
if (g_frame != NULL) {
OsalMemFree(g_frame);
g_frame = NULL;
}
if (g_file != NULL) {
fclose(g_file);
g_file = NULL;
}
printf("Stop Successful\n");
return ret;
}
static int32_t FrameStartMmap(const struct StrPara *param)
{
if (param == NULL) {
return HDF_FAILURE;
}
const struct StrPara *strParam = param;
struct IAudioRender *render = strParam->render;
struct AudioMmapBufferDescriptor mmapDesc;
(void)signal(SIGINT, StreamClose);
char pathBuf[PATH_MAX] = {'\0'};
if (realpath(g_path, pathBuf) == NULL) {
return HDF_FAILURE;
}
FILE *fp = fopen(pathBuf, "rb+");
if (fp == NULL) {
printf("Open file failed!\n");
return HDF_FAILURE;
}
int32_t ret = fseek(fp, 0, SEEK_END);
if (ret != 0) {
fclose(fp);
return HDF_FAILURE;
}
int32_t reqSize = (int32_t)ftell(fp);
if (reqSize < 0) {
fclose(fp);
return HDF_FAILURE;
}
(void)fclose(fp);
mmapDesc.memoryFd = 0;
mmapDesc.filePath = strdup(pathBuf);
mmapDesc.isShareable = 1;
mmapDesc.transferFrameSize = DEEP_BUFFER_RENDER_PERIOD_SIZE / 4;
mmapDesc.offset = sizeof(g_wavHeadInfo);
if (render == NULL || render->ReqMmapBuffer == NULL) {
free(mmapDesc.filePath);
return HDF_FAILURE;
}
ret = render->ReqMmapBuffer(render, reqSize, &mmapDesc);
if (ret < 0 || reqSize <= 0) {
free(mmapDesc.filePath);
printf("Request map fail,please check.\n");
return HDF_FAILURE;
}
if (g_render != NULL) {
ret = StopAudioFiles(&render);
if (ret < 0) {
free(mmapDesc.filePath);
AUDIO_FUNC_LOGE("StopAudioFiles File!");
}
}
free(mmapDesc.filePath);
return HDF_SUCCESS;
}
static int32_t FrameStart(const struct StrPara *param)
{
if (param == NULL) {
return HDF_FAILURE;
}
size_t numRead;
char *frame = param->frame;
int32_t bufferSize = param->bufferSize;
struct IAudioRender *render = param->render;
size_t remainingDataSize = g_wavHeadInfo.riffSize;
(void)signal(SIGINT, StreamClose);
if (g_file == NULL) {
return HDF_FAILURE;
}
if (render == NULL || render->RenderFrame == NULL || frame == NULL) {
return HDF_FAILURE;
}
do {
uint64_t replyBytes = 0;
size_t readSize = (remainingDataSize > bufferSize) ? (size_t)bufferSize : remainingDataSize;
numRead = fread(frame, 1, readSize, g_file);
if (numRead > 0) {
int32_t ret = render->RenderFrame(render, (int8_t *)frame, numRead, &replyBytes);
if (ret == HDF_ERR_INVALID_OBJECT) {
AUDIO_FUNC_LOGE("Render already stop!");
break;
}
remainingDataSize -= numRead;
}
while (g_waitSleep) {
printf("music pause now.\n");
pthread_cond_wait(&g_functionCond, &g_mutex);
printf("music resume now.\n");
}
} while (!g_closeEnd && numRead > 0 && remainingDataSize > 0);
if (!g_closeEnd) {
printf("\nPlay complete, please select input again\n");
(void)StopAudioFiles(&render);
}
return HDF_SUCCESS;
}
static int32_t InitPlayingAudioParam(struct IAudioRender *render)
{
if (render == NULL) {
return HDF_FAILURE;
}
uint64_t frameSize = 0;
uint64_t frameCount = 0;
uint64_t bufferSize = 0;
if (render->GetFrameSize(render, &frameSize) != HDF_SUCCESS) {
AUDIO_FUNC_LOGE("get frame size failed");
}
if (render->GetFrameCount(render, &frameCount) != HDF_SUCCESS) {
AUDIO_FUNC_LOGE("get frame count failed");
}
bufferSize = frameCount * frameSize;
if (bufferSize == 0) {
bufferSize = PcmFramesToBytes(g_attrs);
AUDIO_FUNC_LOGE("buffer size by calc is %" PRIu64 "", bufferSize);
}
g_frame = (char *)OsalMemCalloc(bufferSize);
if (g_frame == NULL) {
return HDF_FAILURE;
}
(void)memset_s(&g_str, sizeof(struct StrPara), 0, sizeof(struct StrPara));
g_str.render = render;
g_str.bufferSize = (int32_t)bufferSize;
g_str.frame = g_frame;
return HDF_SUCCESS;
}
static void PrintPlayMode(void)
{
printf(" ============= Play Render Mode ==========\n");
printf("| 1. Render non-mmap |\n");
printf("| 2. Render mmap |\n");
printf(" ======================================== \n");
}
static int32_t SelectPlayMode(int32_t *palyModeFlag)
{
if (palyModeFlag == NULL) {
AUDIO_FUNC_LOGE("palyModeFlag is null");
return HDF_FAILURE;
}
int choice = 0;
system("clear");
PrintPlayMode();
printf("Please enter your choice:");
int32_t ret = CheckInputName(INPUT_INT, (void *)&choice);
if (ret < 0) {
AUDIO_FUNC_LOGE("CheckInputName Fail");
return HDF_FAILURE;
} else {
*palyModeFlag = choice;
}
return HDF_SUCCESS;
}
static int32_t StartPlayThread(int32_t palyModeFlag)
{
pthread_attr_t tidsAttr;
pthread_attr_init(&tidsAttr);
pthread_attr_setdetachstate(&tidsAttr, PTHREAD_CREATE_DETACHED);
switch (palyModeFlag) {
case 1:
if (pthread_create(&g_tids, &tidsAttr, (void *)(&FrameStart), &g_str) != 0) {
AUDIO_FUNC_LOGE("Create Thread Fail");
return HDF_FAILURE;
}
break;
case 2:
if (pthread_create(&g_tids, &tidsAttr, (void *)(&FrameStartMmap), &g_str) != 0) {
AUDIO_FUNC_LOGE("Create Thread Fail");
return HDF_FAILURE;
}
break;
default:
printf("Input error,Switched to non-mmap Mode for you.\n");
SystemInputFail();
if (pthread_create(&g_tids, &tidsAttr, (void *)(&FrameStart), &g_str) != 0) {
AUDIO_FUNC_LOGE("Create Thread Fail");
return HDF_FAILURE;
}
break;
}
return HDF_SUCCESS;
}
static int32_t PlayingAudioInitFile(void)
{
if (g_file != NULL) {
AUDIO_FUNC_LOGE("the music is playing,please stop first");
return HDF_FAILURE;
}
g_closeEnd = false;
char pathBuf[PATH_MAX] = {'\0'};
if (realpath(g_path, pathBuf) == NULL) {
return HDF_FAILURE;
}
g_file = fopen(pathBuf, "rb");
if (g_file == NULL) {
printf("failed to open '%s'\n", g_path);
return HDF_FAILURE;
}
if (CheckWavFileHeader(g_file, &g_wavHeadInfo, &g_attrs) < 0) {
FileClose(&g_file);
return HDF_FAILURE;
}
(void)chmod(g_path, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
return HDF_SUCCESS;
}
static int32_t PlayingAudioInitRender(struct IAudioRender **renderTemp)
{
if (renderTemp == NULL) {
AUDIO_FUNC_LOGE("render is null");
return HDF_FAILURE;
}
struct IAudioRender *render = NULL;
if (g_adapter == NULL || g_adapter->CreateRender == NULL) {
return HDF_FAILURE;
}
int32_t ret = g_adapter->CreateRender(g_adapter, &g_devDesc, &g_attrs, &render, &g_renderId);
if (render == NULL || ret < 0 || render->RenderFrame == NULL) {
AUDIO_FUNC_LOGE("AudioDeviceCreateRender failed or RenderFrame is null");
return HDF_FAILURE;
}
if (render->Start((void *)render)) {
AUDIO_FUNC_LOGE("Start Bind Fail!");
g_adapter->DestroyRender(g_adapter, g_renderId);
IAudioRenderRelease(render, g_isDirect);
return HDF_FAILURE;
}
if (InitPlayingAudioParam(render) < 0) {
g_adapter->DestroyRender(g_adapter, g_renderId);
IAudioRenderRelease(render, g_isDirect);
return HDF_FAILURE;
}
*renderTemp = render;
return HDF_SUCCESS;
}
static int32_t PlayingAudioFiles(struct IAudioRender **renderS)
{
if (renderS == NULL || g_adapter == NULL) {
return HDF_FAILURE;
}
if (PlayingAudioInitFile() < 0) {
AUDIO_FUNC_LOGE("PlayingAudioInitFile Fail");
return HDF_FAILURE;
}
int32_t palyModeFlag = 0;
if (SelectPlayMode(&palyModeFlag) < 0) {
AUDIO_FUNC_LOGE("SelectPlayMode Fail");
FileClose(&g_file);
return HDF_FAILURE;
}
struct IAudioRender *render = NULL;
if (PlayingAudioInitRender(&render) < 0) {
AUDIO_FUNC_LOGE("PlayingAudioInitRender fail");
FileClose(&g_file);
return HDF_FAILURE;
}
if (StartPlayThread(palyModeFlag) < 0) {
FileClose(&g_file);
if (g_adapter != NULL && g_adapter->DestroyRender != NULL) {
g_adapter->DestroyRender(g_adapter, g_renderId);
}
IAudioRenderRelease(render, g_isDirect);
return HDF_FAILURE;
}
*renderS = render;
printf("Start Successful,Music is playing\n");
return HDF_SUCCESS;
}
static int32_t SelectLoadingMode(void)
{
int choice = 0;
system("clear");
PrintLoadModeMenu();
printf("Please enter your choice:");
int32_t ret = CheckInputName(INPUT_INT, (void *)&choice);
if (ret < 0) {
return HDF_FAILURE;
}
switch (choice) {
case 1:
g_isDirect = true;
break;
case 2:
g_isDirect = false;
break;
default:
printf("Input error,Switched to direct loading in for you.\n");
SystemInputFail();
g_isDirect = true;
break;
}
return HDF_SUCCESS;
}
void AudioAdapterDescriptorFree(struct AudioAdapterDescriptor *dataBlock, bool freeSelf)
{
if (dataBlock == NULL) {
return;
}
if (dataBlock->adapterName != NULL) {
OsalMemFree(dataBlock->adapterName);
dataBlock->adapterName = NULL;
}
if (dataBlock->ports != NULL) {
OsalMemFree(dataBlock->ports);
}
if (freeSelf) {
OsalMemFree(dataBlock);
}
}
static void ReleaseAdapterDescs(struct AudioAdapterDescriptor **descs, uint32_t descsLen)
{
if (descsLen > 0 && descs != NULL && (*descs) != NULL) {
for (uint32_t i = 0; i < descsLen; i++) {
AudioAdapterDescriptorFree(&(*descs)[i], false);
}
OsalMemFree(*descs);
*descs = NULL;
}
}
static int32_t GetManagerAndLoadAdapter(struct AudioPort *renderPort)
{
int32_t adapterIndex = 0;
if (renderPort == NULL) {
AUDIO_FUNC_LOGE("The Parameter is NULL");
return HDF_FAILURE;
}
struct IAudioManager *audioManagerIns = IAudioManagerGet(g_isDirect);
if (audioManagerIns == NULL) {
AUDIO_FUNC_LOGE("Get audio Manager Fail");
return HDF_FAILURE;
}
g_audioManager = audioManagerIns;
struct AudioAdapterDescriptor *descs = (struct AudioAdapterDescriptor *)OsalMemCalloc(
sizeof(struct AudioAdapterDescriptor) * (MAX_AUDIO_ADAPTER_DESC));
if (descs == NULL) {
AUDIO_FUNC_LOGE("OsalMemCalloc for descs failed");
return HDF_FAILURE;
}
uint32_t adapterNum = MAX_AUDIO_ADAPTER_DESC;
int32_t ret = audioManagerIns->GetAllAdapters(audioManagerIns, descs, &adapterNum);
if (ret < 0 || adapterNum == 0) {
AUDIO_FUNC_LOGE("Get All Adapters Fail");
ReleaseAdapterDescs(&descs, MAX_AUDIO_ADAPTER_DESC);
return HDF_ERR_NOT_SUPPORT;
}
if (SelectAudioCard(descs, adapterNum, &adapterIndex) != HDF_SUCCESS) {
ReleaseAdapterDescs(&descs, MAX_AUDIO_ADAPTER_DESC);
return HDF_ERR_NOT_SUPPORT;
}
if (strcpy_s(g_adapterName, PATH_LEN, descs[adapterIndex - 1].adapterName) < 0) {
ReleaseAdapterDescs(&descs, MAX_AUDIO_ADAPTER_DESC);
return HDF_ERR_NOT_SUPPORT;
}
if (SwitchAudioPort(&descs[adapterIndex - 1], PORT_OUT, renderPort) != HDF_SUCCESS) {
ReleaseAdapterDescs(&descs, MAX_AUDIO_ADAPTER_DESC);
return HDF_ERR_NOT_SUPPORT;
}
if (audioManagerIns->LoadAdapter(audioManagerIns, &descs[adapterIndex - 1], &g_adapter)) {
AUDIO_FUNC_LOGE("Load Adapter Fail");
ReleaseAdapterDescs(&descs, MAX_AUDIO_ADAPTER_DESC);
return HDF_ERR_NOT_SUPPORT;
}
ReleaseAdapterDescs(&descs, MAX_AUDIO_ADAPTER_DESC);
return HDF_SUCCESS;
}
static int32_t InitRenderParam(uint32_t portId)
{
if (g_adapter == NULL || g_adapter->InitAllPorts == NULL) {
return HDF_FAILURE;
}
(void)g_adapter->InitAllPorts(g_adapter);
if (InitAttrs(&g_attrs) < 0) {
AUDIO_FUNC_LOGE("InitAttrs failed");
return HDF_FAILURE;
}
if (InitDevDesc(&g_devDesc, portId) < 0) {
AUDIO_FUNC_LOGE("InitDevDesc failed");
return HDF_FAILURE;
}
return HDF_SUCCESS;
}
static int32_t RenderGetAdapterAndInitEnvParams(void)
{
struct AudioPort renderPort;
int32_t ret = GetManagerAndLoadAdapter(&renderPort);
if (ret < 0) {
return ret;
}
if (InitRenderParam(renderPort.portId) < 0) {
g_audioManager->UnloadAdapter(g_audioManager, g_adapterName);
IAudioAdapterRelease(g_adapter, g_isDirect);
g_adapter = NULL;
return HDF_FAILURE;
}
return HDF_SUCCESS;
}
static int32_t InitParam(void)
{
if (SelectLoadingMode() < 0) {
return HDF_FAILURE;
}
g_audioPort.dir = PORT_OUT;
g_audioPort.portId = 0;
g_audioPort.portName = "AOP";
if (RenderGetAdapterAndInitEnvParams() < 0) {
AUDIO_FUNC_LOGE("GetProxyManagerFunc Fail");
if (g_audioManager != NULL) {
IAudioManagerRelease(g_audioManager, g_isDirect);
g_audioManager = NULL;
}
return HDF_FAILURE;
}
return HDF_SUCCESS;
}
static int32_t SetRenderMute(struct IAudioRender **render)
{
(void)render;
if (g_render == NULL || g_render->GetMute == NULL) {
return HDF_FAILURE;
}
int32_t val;
bool isMute = false;
int32_t ret = g_render->GetMute((void *)g_render, &isMute);
if (ret < 0) {
AUDIO_FUNC_LOGE("The current mute state was not obtained!");
}
printf("Now %s ,Do you need to set mute status(1/0):", isMute ? "mute" : "not mute");
ret = CheckInputName(INPUT_INT, (void *)&val);
if (ret < 0) {
return HDF_FAILURE;
}
if (g_render == NULL || g_render->SetMute == NULL) {
AUDIO_FUNC_LOGE("Music already stop!");
SystemInputFail();
return HDF_FAILURE;
}
if (val == 1) {
ret = g_render->SetMute((void *)g_render, !isMute);
}
return ret;
}
static int32_t SetRenderVolume(struct IAudioRender **render)
{
(void)render;
if (g_render == NULL || g_render->GetVolume == NULL) {
return HDF_FAILURE;
}
int32_t ret;
float val = 0.0;
ret = g_render->GetVolume((void *)g_render, &val);
if (ret < 0) {
AUDIO_FUNC_LOGE("Get current volume failed!");
SystemInputFail();
return ret;
}
printf("Now the volume is %f ,Please enter the volume value you want to set (0.0-1.0):", val);
ret = CheckInputName(INPUT_FLOAT, (void *)&val);
if (ret < 0) {
return HDF_FAILURE;
}
if (val < 0.0 || val > 1.0) {
AUDIO_FUNC_LOGE("Invalid volume value!");
SystemInputFail();
return HDF_FAILURE;
}
if (g_render == NULL || g_render->SetVolume == NULL) {
AUDIO_FUNC_LOGE("Music already stop!");
SystemInputFail();
return HDF_FAILURE;
}
ret = g_render->SetVolume((void *)g_render, val);
if (ret < 0) {
AUDIO_FUNC_LOGE("set volume fail!");
SystemInputFail();
}
return ret;
}
static int32_t GetRenderGain(struct IAudioRender **render)
{
(void)render;
if (g_render == NULL || g_render->GetGain == NULL) {
return HDF_FAILURE;
}
float val = 1.0;
int32_t ret = g_render->GetGain((void *)g_render, &val);
if (ret < 0) {
AUDIO_FUNC_LOGE("Get current gain failed!");
SystemInputFail();
return HDF_FAILURE;
}
printf("Now the gain is %f,", val);
SystemInputFail();
return HDF_SUCCESS;
}
static int32_t SetRenderPause(struct IAudioRender **render)
{
(void)render;
if (g_waitSleep) {
AUDIO_FUNC_LOGE("Already pause,not need pause again!");
SystemInputFail();
return HDF_FAILURE;
}
if (g_render == NULL || g_render->Pause == NULL) {
return HDF_FAILURE;
}
int32_t ret = g_render->Pause((void *)g_render);
if (ret != 0) {
return HDF_FAILURE;
}
printf("Pause success!\n");
g_waitSleep = true;
return HDF_SUCCESS;
}
static int32_t SetRenderResume(struct IAudioRender **render)
{
(void)render;
if (!g_waitSleep) {
AUDIO_FUNC_LOGE("Now is Playing,not need resume!");
SystemInputFail();
return HDF_FAILURE;
}
if (g_render == NULL || g_render->Resume == NULL) {
return HDF_FAILURE;
}
int32_t ret = g_render->Resume((void *)g_render);
if (ret != 0) {
return HDF_FAILURE;
}
printf("resume success!\n");
pthread_mutex_lock(&g_mutex);
g_waitSleep = false;
pthread_cond_signal(&g_functionCond);
pthread_mutex_unlock(&g_mutex);
return HDF_SUCCESS;
}
static void PrintAttributesFromat(void)
{
printf(" ============= Render Sample Attributes Fromat =============== \n");
printf("| 1. Render AUDIO_FORMAT_TYPE_PCM_8_BIT |\n");
printf("| 2. Render AUDIO_FORMAT_TYPE_PCM_16_BIT |\n");
printf("| 3. Render AUDIO_FORMAT_TYPE_PCM_24_BIT |\n");
printf("| 4. Render AUDIO_FORMAT_TYPE_PCM_32_BIT |\n");
printf(" ============================================================= \n");
}
static int32_t SelectAttributesFomat(uint32_t *pcmFomat)
{
if (pcmFomat == NULL) {
AUDIO_FUNC_LOGE("fomat is null!");
return HDF_FAILURE;
}
int val = 0;
PrintAttributesFromat();
printf("Please select audio format,If not selected, the default is 16bit:");
int32_t ret = CheckInputName(INPUT_INT, (void *)&val);
if (ret < 0) {
AUDIO_FUNC_LOGE("CheckInputName failed.");
return HDF_FAILURE;
}
switch (val) {
case AUDIO_FORMAT_TYPE_PCM_8_BIT:
*pcmFomat = AUDIO_FORMAT_TYPE_PCM_8_BIT;
break;
case AUDIO_FORMAT_TYPE_PCM_16_BIT:
*pcmFomat = AUDIO_FORMAT_TYPE_PCM_16_BIT;
break;
case AUDIO_FORMAT_TYPE_PCM_24_BIT:
*pcmFomat = AUDIO_FORMAT_TYPE_PCM_24_BIT;
break;
case AUDIO_FORMAT_TYPE_PCM_32_BIT:
*pcmFomat = AUDIO_FORMAT_TYPE_PCM_32_BIT;
break;
default:
*pcmFomat = AUDIO_FORMAT_TYPE_PCM_16_BIT;
break;
}
return HDF_SUCCESS;
}
static int32_t SetRenderAttributes(struct IAudioRender **render)
{
(void)render;
struct AudioSampleAttributes attrs;
if (g_render == NULL || g_render->GetSampleAttributes == NULL) {
AUDIO_FUNC_LOGE("The pointer is null!");
return HDF_FAILURE;
}
int32_t ret = g_render->GetSampleAttributes((void *)g_render, &attrs);
if (ret < 0) {
AUDIO_FUNC_LOGE("GetRenderAttributes failed!");
} else {
printf("Current sample attributes:\n");
printf("audioType is %u\nfomat is %u\nsampleRate is %u\nchannalCount is"
"%u\nperiod is %u\nframesize is %u\nbigEndian is %u\nSignedData is %u\n",
attrs.type, attrs.format, attrs.sampleRate, attrs.channelCount, attrs.period, attrs.frameSize,
attrs.isBigEndian, attrs.isSignedData);
}
printf("Set Sample Attributes,");
SystemInputFail();
system("clear");
printf("The sample attributes you want to set,Step by step, please.\n");
ret = SelectAttributesFomat((uint32_t *)(&attrs.format));
if (ret < 0) {
AUDIO_FUNC_LOGE("SetRenderAttributes format failed!");
return HDF_FAILURE;
}
printf("\nPlease input sample rate(48000,44100,32000...):");
ret = CheckInputName(INPUT_UINT32, (void *)(&attrs.sampleRate));
if (ret < 0) {
return HDF_FAILURE;
}
printf("\nPlease input bigEndian(false=0/true=1):");
ret = CheckInputName(INPUT_UINT32, (void *)(&attrs.isBigEndian));
if (ret < 0) {
return HDF_FAILURE;
}
if (g_render == NULL || g_render->SetSampleAttributes == NULL) {
AUDIO_FUNC_LOGE("Music already complete,Please replay and set the attrbutes!");
SystemInputFail();
return HDF_FAILURE;
}
ret = g_render->SetSampleAttributes((void *)g_render, &attrs);
if (ret < 0) {
AUDIO_FUNC_LOGE("Set render attributes failed!");
SystemInputFail();
}
return ret;
}
static int32_t PrintRenderSelectPinFirst(struct AudioSceneDescriptor *scene)
{
system("clear");
printf(" ==================== Select Pin ===================== \n");
printf("| 0. Speaker |\n");
printf("| 1. HeadPhones |\n");
printf(" ===================================================== \n");
printf("Please input your choice:\n");
int32_t val = 0;
int32_t ret = CheckInputName(INPUT_INT, (void *)&val);
if (ret < 0) {
AUDIO_FUNC_LOGE("Invalid value!");
SystemInputFail();
return HDF_FAILURE;
}
if (val == 1) {
scene->desc.pins = PIN_OUT_HEADSET;
} else {
scene->desc.pins = PIN_OUT_SPEAKER;
}
return HDF_SUCCESS;
}
static int32_t PrintRenderSelectPinSecond(struct AudioSceneDescriptor *scene)
{
system("clear");
printf(" ==================== Select Pin ===================== \n");
printf("| 0. Speaker |\n");
printf("| 1. HeadPhones |\n");
printf("| 2. Speaker and HeadPhones |\n");
printf(" ===================================================== \n");
printf("Please input your choice:\n");
int32_t val = 0;
int32_t ret = CheckInputName(INPUT_INT, (void *)&val);
if (ret < 0) {
AUDIO_FUNC_LOGE("Invalid value!");
SystemInputFail();
return HDF_FAILURE;
}
if (val == 1) {
scene->desc.pins = PIN_OUT_HEADSET;
} else if (val == 0) {
scene->desc.pins = PIN_OUT_SPEAKER;
} else {
scene->desc.pins = PIN_OUT_SPEAKER | PIN_OUT_HEADSET;
}
return HDF_SUCCESS;
}
static int32_t PrintRenderSelectPinThird(struct AudioSceneDescriptor *scene)
{
system("clear");
printf(" ==================== Select Pin ===================== \n");
printf("| 0. Speaker |\n");
printf("| 1. HeadPhones |\n");
printf(" ===================================================== \n");
printf("Please input your choice:\n");
int32_t val = 0;
int32_t ret = CheckInputName(INPUT_INT, (void *)&val);
if (ret < 0) {
AUDIO_FUNC_LOGE("Invalid value!");
SystemInputFail();
return HDF_FAILURE;
}
if (val == 1) {
scene->desc.pins = PIN_OUT_HEADSET;
} else {
scene->desc.pins = PIN_OUT_SPEAKER;
}
return HDF_SUCCESS;
}
static void SelectSceneMenu(void)
{
printf(" =================== Select Scene ======================== \n");
printf("0 is Midea. |\n");
printf("1 is Communication. |\n");
printf("2 is Ring-Tone. |\n");
printf("3 is Voice-Call. |\n");
printf("4 is Mmap. |\n");
printf(" ========================================================= \n");
}
static int32_t SelectRenderScene(struct IAudioRender **render)
{
(void)render;
int32_t val = 0;
struct AudioSceneDescriptor scene;
system("clear");
SelectSceneMenu();
printf("Please input your choice:\n");
int32_t ret = CheckInputName(INPUT_INT, (void *)&val);
if (ret < 0) {
AUDIO_FUNC_LOGE("Invalid value!");
SystemInputFail();
return HDF_FAILURE;
}
switch (val) {
case AUDIO_IN_MEDIA:
scene.scene.id = AUDIO_IN_MEDIA;
PrintRenderSelectPinFirst(&scene);
break;
case AUDIO_IN_COMMUNICATION:
scene.scene.id = AUDIO_IN_COMMUNICATION;
PrintRenderSelectPinSecond(&scene);
break;
case AUDIO_IN_RINGTONE:
scene.scene.id = AUDIO_IN_RINGTONE;
scene.desc.pins = PIN_OUT_SPEAKER | PIN_OUT_HEADSET;
break;
case AUDIO_IN_CALL:
scene.scene.id = AUDIO_IN_CALL;
PrintRenderSelectPinThird(&scene);
break;
case AUDIO_MMAP_NOIRQ:
scene.scene.id = AUDIO_MMAP_NOIRQ;
PrintRenderSelectPinFirst(&scene);
break;
default:
break;
}
scene.desc.desc = "mic";
if (g_render == NULL || g_render->SelectScene == NULL) {
AUDIO_FUNC_LOGE("Music already stop,");
SystemInputFail();
return HDF_FAILURE;
}
ret = g_render->SelectScene((void *)g_render, &scene);
if (ret < 0) {
AUDIO_FUNC_LOGE("Select scene fail\n");
}
return ret;
}
static int32_t GetExtParams(struct IAudioRender **render)
{
(void)render;
if (g_render == NULL || g_render->GetExtraParams == NULL) {
return HDF_FAILURE;
}
char keyValueList[BUFFER_LEN] = {0};
int32_t ret = g_render->GetExtraParams((void *)g_render, keyValueList, EXT_PARAMS_MAXLEN);
if (ret < 0) {
AUDIO_FUNC_LOGE("Get EXT params failed!");
SystemInputFail();
return HDF_FAILURE;
}
printf("keyValueList = %s\n", keyValueList);
return HDF_SUCCESS;
}
static int32_t GetRenderMmapPosition(struct IAudioRender **render)
{
(void)render;
if (g_render == NULL || g_render->GetMmapPosition == NULL) {
return HDF_FAILURE;
}
uint64_t frames = 0;
struct AudioTimeStamp time;
time.tvNSec = 0;
time.tvSec = 0;
int32_t ret = g_render->GetMmapPosition((void *)g_render, &frames, &time);
if (ret < 0) {
AUDIO_FUNC_LOGE("Get current Mmap frames Position failed!");
SystemInputFail();
return HDF_FAILURE;
}
printf("Now the Position is %" PRIu64 "\n", frames);
return HDF_SUCCESS;
}
static void PrintMenu2(void)
{
printf(" ================== Play Render Menu ================== \n");
printf("| 1. Render Start |\n");
printf("| 2. Render Stop |\n");
printf("| 3. Render Resume |\n");
printf("| 4. Render Pause |\n");
printf("| 5. Render SetVolume |\n");
printf("| 6. Render GetGain |\n");
printf("| 7. Render SetMute |\n");
printf("| 8. Render SetAttributes |\n");
printf("| 9. Render SelectScene |\n");
printf("| 10. Render getEXtParams |\n");
printf("| 11. Render getMmapPosition |\n");
printf("| 12.Exit |\n");
printf(" ====================================================== \n");
}
static struct ProcessRenderMenuSwitchList g_processRenderMenuSwitchList[] = {
{RENDER_START, PlayingAudioFiles },
{RENDER_STOP, StopAudioFiles },
{RENDER_RESUME, SetRenderResume },
{RENDER_PAUSE, SetRenderPause },
{SET_RENDER_VOLUME, SetRenderVolume },
{SET_RENDER_GAIN, GetRenderGain },
{SET_RENDER_MUTE, SetRenderMute },
{SET_RENDER_ATTRIBUTES, SetRenderAttributes },
{SET_RENDER_SLECET_SCENE, SelectRenderScene },
{GET_RENDER_EXT_PARAMS, GetExtParams },
{GET_RENDER_POSITION, GetRenderMmapPosition},
};
static void ProcessMenu(int32_t choice)
{
if (choice == GET_RENDER_POSITION + 1) {
return;
}
if (g_render == NULL && choice != 1) {
AUDIO_FUNC_LOGE("This render already release!");
SystemInputFail();
return;
}
for (int32_t i = RENDER_START; i <= GET_RENDER_POSITION; ++i) {
if ((choice == (int32_t)g_processRenderMenuSwitchList[i - 1].cmd) &&
(g_processRenderMenuSwitchList[i - 1].operation != NULL)) {
g_processRenderMenuSwitchList[i - 1].operation(&g_render);
}
}
}
static void Choice(void)
{
int32_t choice = 0;
while (choice < GET_RENDER_POSITION + 1 && choice >= 0) {
system("clear");
PrintMenu2();
printf("your choice is:\n");
int32_t ret = CheckInputName(INPUT_INT, (void *)&choice);
if (ret < 0) {
continue;
}
if (choice < RENDER_START || choice > GET_RENDER_POSITION + 1) {
AUDIO_FUNC_LOGE("You input is wrong!");
choice = 0;
SystemInputFail();
continue;
}
ProcessMenu(choice);
}
}
int32_t main(int32_t argc, char const *argv[])
{
if (argc < 2 || argv == NULL || argv[0] == NULL) {
printf("usage:[1]sample [2]/data/test.wav\n");
return 0;
}
if (argv[1] == NULL || strlen(argv[1]) == 0) {
return HDF_FAILURE;
}
int32_t ret = strncpy_s(g_path, PATH_LEN - 1, argv[1], strlen(argv[1]) + 1);
if (ret != 0) {
AUDIO_FUNC_LOGE("strncpy_s Fail!");
return HDF_FAILURE;
}
char pathBuf[PATH_MAX] = {'\0'};
if (realpath(g_path, pathBuf) == NULL) {
AUDIO_FUNC_LOGE("realpath Fail!");
return HDF_FAILURE;
}
if (InitParam() != HDF_SUCCESS) {
AUDIO_FUNC_LOGE("InitParam Fail!");
return HDF_FAILURE;
}
Choice();
if (g_render != NULL && g_adapter != NULL) {
StopAudioFiles(&g_render);
}
if (g_audioManager != NULL && g_audioManager->UnloadAdapter != NULL) {
g_audioManager->UnloadAdapter(g_audioManager, g_adapterName);
IAudioAdapterRelease(g_adapter, g_isDirect);
g_adapter = NULL;
IAudioManagerRelease(g_audioManager, g_isDirect);
g_audioManager = NULL;
}
return 0;
}