Files
drivers_peripheral/audio/sample/framework_render.c
T

1358 lines
41 KiB
C

/*
* Copyright (c) 2021 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 <unistd.h>
#include "hdf_base.h"
#include "inttypes.h"
#include "audio_manager.h"
#include "audio_types.h"
#define AUDIO_FUNC_LOGE(fmt, arg...) do { \
printf("%s: [%s]: [%d]:[ERROR]:" fmt"\n", __FILE__, __func__, __LINE__, ##arg); \
} while (0)
#define BUFFER_LEN 256
#define ID_RIFF 0x46464952
#define ID_WAVE 0x45564157
#define ID_FMT 0x20746d66
#define ID_DATA 0x61746164
#define MOVE_LEFT_NUM 8
#define AUDIO_SAMPLE_RATE_8K 8000
#define AUDIO_CHANNELCOUNT 2
#define AUDIO_SAMPLE_RATE_48K 48000
#define PATH_LEN 256
#define DEEP_BUFFER_RENDER_PERIOD_SIZE 1024
#define DEEP_BUFFER_RENDER_PERIOD_COUNT 8
#define INT_32_MAX 0x7fffffff
#define PERIOD_SIZE 1024
#define ATTR_PERIOD_MIN 2048
#define EXT_PARAMS_MAXLEN 107
enum AudioPCMBit {
PCM_8_BIT = 8, /* 8-bit PCM */
PCM_16_BIT = 16, /* 16-bit PCM */
PCM_24_BIT = 24, /* 24-bit PCM */
PCM_32_BIT = 32, /* 32-bit PCM */
};
enum RenderSoundCardMode {
PRIMARY = 1,
PRIMARY_EXT = 2,
AUDIO_USB = 3,
AUDIO_A2DP = 4,
};
enum RenderLoadingMode {
DIRECT = 1,
SERVICE = 2,
};
struct AudioHeadInfo {
uint32_t testFileRiffId;
uint32_t testFileRiffSize;
uint32_t testFileFmt;
uint32_t audioFileFmtId;
uint32_t audioFileFmtSize;
uint16_t audioFileFormat;
uint16_t audioChannelNum;
uint32_t audioSampleRate;
uint32_t audioByteRate;
uint16_t audioBlockAlign;
uint16_t audioBitsPerSample;
uint32_t dataId;
uint32_t dataSize;
};
struct StrPara {
struct AudioRender *render;
FILE *file;
struct AudioSampleAttributes attrs;
uint64_t *replyBytes;
char *frame;
int32_t bufferSize;
};
struct AudioRender *g_render = NULL;
struct AudioAdapter *g_adapter = NULL;
struct AudioManager *g_manager = NULL;
static struct AudioManager *g_proxyManager = NULL;
struct AudioDeviceDescriptor g_devDesc;
struct AudioSampleAttributes g_attrs;
struct AudioPort g_audioPort;
struct AudioHeadInfo g_wavHeadInfo;
static struct StrPara g_str;
pthread_t g_tids;
char *g_frame = NULL;
void *g_handle;
FILE *g_file;
char g_path[256];
static int32_t g_closeEnd = 0;
pthread_mutex_t g_mutex = PTHREAD_MUTEX_INITIALIZER;
pthread_cond_t g_functionCond = PTHREAD_COND_INITIALIZER;
int g_waitSleep = 0;
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 AudioRender **);
struct ProcessRenderMenuSwitchList {
enum RenderMenuId cmd;
AudioRenderOperation operation;
};
void CleanStdin(void)
{
int c;
do {
c = getchar();
} while (c != '\n' && c != EOF);
}
int32_t CheckInputName(int type, void *val)
{
int ret;
int inputInt = 0;
float inputFloat = 0.0;
uint32_t inputUint = 0;
if (val == NULL) {
return HDF_FAILURE;
}
printf("\n");
switch (type) {
case INPUT_INT:
ret = scanf_s("%d", &inputInt);
if (inputInt < 0 || inputInt > GET_RENDER_POSITION + 1) {
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 || inputUint < 0) {
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;
}
void SystemInputFail(void)
{
printf("please ENTER to go on...");
while (getchar() != '\n') {
continue;
}
printf("%c", getchar());
}
int32_t InitAttrs(struct AudioSampleAttributes *attrs)
{
if (attrs == NULL) {
return HDF_FAILURE;
}
/* Initialization of audio parameters for playback */
attrs->format = AUDIO_FORMAT_PCM_16_BIT;
attrs->channelCount = AUDIO_CHANNELCOUNT;
attrs->sampleRate = AUDIO_SAMPLE_RATE_48K;
attrs->interleaved = 1;
attrs->type = AUDIO_IN_MEDIA;
attrs->period = ATTR_PERIOD_MIN;
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;
}
int32_t InitDevDesc(struct AudioDeviceDescriptor *devDesc, uint32_t portId)
{
if (devDesc == NULL) {
return HDF_FAILURE;
}
/* Initialization of audio parameters for playback */
devDesc->portId = portId;
devDesc->pins = PIN_OUT_SPEAKER;
devDesc->desc = NULL;
return HDF_SUCCESS;
}
uint32_t StringToInt(const char *flag)
{
if (flag == NULL) {
return 0;
}
uint32_t temp = flag[0];
for (int32_t i = strlen(flag) - 1; i >= 0; i--) {
temp <<= MOVE_LEFT_NUM;
temp += flag[i];
}
return temp;
}
int32_t WavHeadAnalysis(FILE *file, struct AudioSampleAttributes *attrs)
{
if (file == NULL || attrs == NULL) {
printf("params is null\n");
return HDF_FAILURE;
}
uint32_t ret;
const char *audioRiffIdParam = "RIFF";
const char *audioFileFmtParam = "WAVE";
const char *aduioDataIdParam = "data";
ret = fread(&g_wavHeadInfo, sizeof(g_wavHeadInfo), 1, file);
if (ret != 1) {
return HDF_FAILURE;
}
uint32_t audioRiffId = StringToInt(audioRiffIdParam);
uint32_t audioFileFmt = StringToInt(audioFileFmtParam);
uint32_t aduioDataId = StringToInt(aduioDataIdParam);
if (g_wavHeadInfo.testFileRiffId != audioRiffId || g_wavHeadInfo.testFileFmt != audioFileFmt ||
g_wavHeadInfo.dataId != aduioDataId) {
printf("audio format error \n");
return HDF_FAILURE;
}
attrs->channelCount = g_wavHeadInfo.audioChannelNum;
attrs->sampleRate = g_wavHeadInfo.audioSampleRate;
switch (g_wavHeadInfo.audioBitsPerSample) {
case PCM_8_BIT: {
attrs->format = AUDIO_FORMAT_PCM_8_BIT;
break;
}
case PCM_16_BIT: {
attrs->format = AUDIO_FORMAT_PCM_16_BIT;
break;
}
case PCM_24_BIT: {
attrs->format = AUDIO_FORMAT_PCM_24_BIT;
break;
}
case PCM_32_BIT: {
attrs->format = AUDIO_FORMAT_PCM_32_BIT;
break;
}
default:
printf("nonsupport audio format %d\n", g_wavHeadInfo.audioBitsPerSample);
return HDF_FAILURE;
}
return HDF_SUCCESS;
}
int32_t SwitchAdapter(struct AudioAdapterDescriptor *descs,
const char *adapterNameCase, enum AudioPortDirection portFlag,
struct AudioPort *renderPort, int32_t size)
{
struct AudioAdapterDescriptor *desc = NULL;
if (descs == NULL || adapterNameCase == NULL || renderPort == NULL) {
return HDF_FAILURE;
}
uint32_t port;
for (int32_t index = 0; index < size; index++) {
desc = &descs[index];
if (desc == NULL) {
continue;
}
if (desc->adapterName == NULL) {
return HDF_FAILURE;
}
if (strcmp(desc->adapterName, adapterNameCase)) {
continue;
}
for (port = 0; port < desc->portNum; port++) {
// Only find out the port of out in the sound card
if (desc->ports[port].dir == portFlag) {
*renderPort = desc->ports[port];
return index;
}
}
}
return HDF_ERR_NOT_SUPPORT;
}
uint32_t PcmFormatToBits(enum AudioFormat formatBit)
{
switch (formatBit) {
case AUDIO_FORMAT_PCM_16_BIT:
return PCM_16_BIT;
case AUDIO_FORMAT_PCM_8_BIT:
return PCM_8_BIT;
default:
return PCM_16_BIT;
}
}
uint32_t PcmFramesToBytes(const struct AudioSampleAttributes attrs)
{
return DEEP_BUFFER_RENDER_PERIOD_SIZE * attrs.channelCount * (PcmFormatToBits(attrs.format) >> 3);
}
static inline void FileClose(FILE **file)
{
if ((file != NULL) && ((*file) != NULL)) {
fclose(*file);
*file = NULL;
}
return;
}
int32_t StopAudioFiles(struct AudioRender **renderS)
{
if (renderS == NULL) {
return HDF_FAILURE;
}
if (g_waitSleep) {
pthread_mutex_lock(&g_mutex);
g_waitSleep = 0;
pthread_cond_signal(&g_functionCond);
pthread_mutex_unlock(&g_mutex);
}
if (!g_closeEnd) {
g_closeEnd = true;
usleep(100000); // sleep 100000us
}
struct AudioRender *render = *renderS;
if (render == NULL) {
AUDIO_FUNC_LOGE("render is null");
return HDF_FAILURE;
}
int32_t ret = render->control.Stop((AudioHandle)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, render);
if (ret < 0) {
AUDIO_FUNC_LOGE("Destroy Render!");
}
render = NULL;
g_render = NULL;
if (g_frame != NULL) {
free(g_frame);
g_frame = NULL;
}
FileClose(&g_file);
printf("Stop Successful\n");
return ret;
}
bool PrepareStopAndUloadAdapter(void)
{
bool soMode = false;
if (g_render != NULL && g_adapter != NULL) {
StopAudioFiles(&g_render);
}
if (g_manager != NULL) {
soMode = true;
if (g_manager->UnloadAdapter != NULL) {
g_manager->UnloadAdapter(g_manager, g_adapter);
}
} else {
if (g_proxyManager != NULL && g_proxyManager->UnloadAdapter != NULL) {
g_proxyManager->UnloadAdapter(g_proxyManager, g_adapter);
}
}
return soMode;
}
void StopRenderBySig(int32_t sig)
{
bool soMode = false;
soMode = PrepareStopAndUloadAdapter();
dlclose(g_handle);
g_closeEnd = 1;
(void)signal(sig, SIG_DFL);
return;
}
static inline void ProcessCommonSig(void)
{
(void)signal(SIGKILL, StopRenderBySig);
(void)signal(SIGINT, StopRenderBySig);
(void)signal(SIGTERM, StopRenderBySig);
return;
}
int32_t MmapInitFile(FILE **fp)
{
if (fp == NULL) {
return HDF_FAILURE;
}
char pathBuf[PATH_MAX] = {'\0'};
if (realpath(g_path, pathBuf) == NULL) {
return HDF_FAILURE;
}
*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) {
return HDF_FAILURE;
}
return HDF_SUCCESS;
}
int32_t FrameStartMmap(const AudioHandle param)
{
if (param == NULL) {
return HDF_FAILURE;
}
struct StrPara *strParam = (struct StrPara *)param;
struct AudioRender *render = strParam->render;
struct AudioMmapBufferDescripter desc;
ProcessCommonSig();
// get file length
FILE *fp = NULL;
if (MmapInitFile(&fp) < 0) {
if (fp != NULL) {
fclose(fp);
}
}
int32_t reqSize = ftell(fp);
// Converts a file pointer to a device descriptor
int fd = fileno(fp);
if (fd == -1) {
printf("fileno failed, fd is %d\n", fd);
fclose(fp);
return HDF_FAILURE;
}
// Init param
desc.memoryFd = fd;
desc.isShareable = 1; // 1:Shareable ,0:Don't share
desc.transferFrameSize = DEEP_BUFFER_RENDER_PERIOD_SIZE / 4; // One frame size 4 bit
desc.offset = sizeof(g_wavHeadInfo);
// start
if (render == NULL || render->attr.ReqMmapBuffer == NULL) {
fclose(fp);
return HDF_FAILURE;
}
int32_t ret = render->attr.ReqMmapBuffer(render, reqSize, &desc);
if (ret < 0 || reqSize <= 0) {
printf("Request map fail,please check.\n");
fclose(fp);
return HDF_FAILURE;
}
munmap(desc.memoryAddress, reqSize);
fclose(fp);
if (g_render != NULL) {
ret = StopAudioFiles(&render);
if (ret < 0) {
AUDIO_FUNC_LOGE("StopAudioFiles File!");
}
}
return HDF_SUCCESS;
}
int32_t FrameStart(const AudioHandle param)
{
if (param == NULL) {
return HDF_FAILURE;
}
struct StrPara *strParam = (struct StrPara *)param;
struct AudioRender *render = strParam->render;
char *frame = strParam->frame;
int32_t bufferSize = strParam->bufferSize;
int32_t ret;
int32_t readSize;
int32_t remainingDataSize = g_wavHeadInfo.testFileRiffSize;
uint32_t numRead;
ProcessCommonSig();
uint64_t replyBytes;
if (g_file == NULL) {
return HDF_FAILURE;
}
if (render == NULL || render->RenderFrame == NULL || frame == NULL) {
return HDF_FAILURE;
}
do {
readSize = (remainingDataSize > bufferSize) ? bufferSize : remainingDataSize;
numRead = fread(frame, 1, readSize, g_file);
if (numRead > 0) {
ret = render->RenderFrame(render, 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;
}
int32_t InitPlayingAudioParam(struct AudioRender *render)
{
if (render == NULL) {
return HDF_FAILURE;
}
uint32_t bufferSize = PcmFramesToBytes(g_attrs);
g_frame = (char *)calloc(1, 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 = bufferSize;
g_str.frame = g_frame;
return HDF_SUCCESS;
}
void PrintPlayMode(void)
{
printf(" ============= Play Render Mode ==========\n");
printf("| 1. Render non-mmap |\n");
printf("| 2. Render mmap |\n");
printf(" ======================================== \n");
}
int32_t SelectPlayMode(int32_t *palyModeFlag)
{
if (palyModeFlag == NULL) {
AUDIO_FUNC_LOGE("palyModeFlag is null");
return HDF_FAILURE;
}
system("clear");
int choice = 0;
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;
}
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: // 1. Stander Loading
if (pthread_create(&g_tids, &tidsAttr, (void *)(&FrameStart), &g_str) != 0) {
AUDIO_FUNC_LOGE("Create Thread Fail");
return HDF_FAILURE;
}
break;
case 2: // 2. Low latency Loading
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,");
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;
}
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 (WavHeadAnalysis(g_file, &g_attrs) < 0) {
AUDIO_FUNC_LOGE("Frame test is Fail");
FileClose(&g_file);
return HDF_FAILURE;
}
return HDF_SUCCESS;
}
int32_t PlayingAudioFiles(struct AudioRender **renderS)
{
if (renderS == NULL || g_adapter == NULL || g_adapter->CreateRender == 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 AudioRender *render = NULL;
int32_t ret = g_adapter->CreateRender(g_adapter, &g_devDesc, &g_attrs, &render);
if (render == NULL || ret < 0 || render->RenderFrame == NULL) {
AUDIO_FUNC_LOGE("AudioDeviceCreateRender failed or RenderFrame is null");
FileClose(&g_file);
return HDF_FAILURE;
}
// Playing audio files
if (render->control.Start((AudioHandle)render)) {
AUDIO_FUNC_LOGE("Start Bind Fail!");
FileClose(&g_file);
return HDF_FAILURE;
}
if (InitPlayingAudioParam(render) < 0) {
AUDIO_FUNC_LOGE("InitPlayingAudioParam Fail");
FileClose(&g_file);
return HDF_FAILURE;
}
if (StartPlayThread(palyModeFlag) < 0) {
AUDIO_FUNC_LOGE("Create Thread Fail");
FileClose(&g_file);
return HDF_FAILURE;
}
*renderS = render;
printf("Start Successful,Music is playing\n");
return HDF_SUCCESS;
}
void PrintMenu0(void)
{
printf(" ============= Play Render Sound Card Mode ==========\n");
printf("| 1. Render Primary |\n");
printf("| 2. Render Primary_Ext |\n");
printf("| 3. Render Usb |\n");
printf("| 4. Render A2dp |\n");
printf(" =================================================== \n");
}
void PrintMenu1(void)
{
printf(" ============== Play Render Loading Mode ===========\n");
printf("| 1. Render Direct Loading |\n");
printf("| 2. Render Service Loading |\n");
printf("| Note: switching is not supported in the MPI's |\n");
printf("| version. |\n");
printf(" ================================================== \n");
}
int32_t SwitchInternalOrExternal(char *adapterNameCase, int32_t nameLen)
{
system("clear");
int choice = 0;
PrintMenu0();
printf("Please enter your choice:");
int32_t ret = CheckInputName(INPUT_INT, (void *)&choice);
if (ret < 0) return HDF_FAILURE;
switch (choice) {
case PRIMARY:
snprintf_s(adapterNameCase, nameLen, nameLen - 1, "%s", "primary");
break;
case PRIMARY_EXT:
snprintf_s(adapterNameCase, nameLen, nameLen - 1, "%s", "primary_ext");
break;
case AUDIO_USB:
snprintf_s(adapterNameCase, nameLen, nameLen - 1, "%s", "usb");
break;
case AUDIO_A2DP:
snprintf_s(adapterNameCase, nameLen, nameLen - 1, "%s", "a2dp");
break;
default:
printf("Input error,Switched to Acodec in for you,");
SystemInputFail();
snprintf_s(adapterNameCase, nameLen, nameLen - 1, "%s", "primary");
break;
}
return HDF_SUCCESS;
}
int32_t SelectLoadingMode(char *resolvedPath, int32_t pathLen, char *func, int32_t funcpathLen)
{
system("clear");
int choice = 0;
char *soPathHdi = NULL;
char *soPathProxy = NULL;
soPathHdi = HDF_LIBRARY_FULL_PATH("libhdi_audio");
soPathProxy = HDF_LIBRARY_FULL_PATH("libhdi_audio_client");
PrintMenu1();
printf("Please enter your choice:");
int32_t ret = CheckInputName(INPUT_INT, (void *)&choice);
if (ret < 0) {
return HDF_FAILURE;
}
switch (choice) {
case DIRECT:
if (snprintf_s(resolvedPath, pathLen, pathLen - 1, "%s", soPathHdi) < 0) {
return HDF_FAILURE;
}
if (snprintf_s(func, funcpathLen, funcpathLen - 1, "%s", "GetAudioManagerFuncs") < 0) {
return HDF_FAILURE;
}
break;
case SERVICE:
if (snprintf_s(resolvedPath, pathLen, pathLen - 1, "%s", soPathProxy) < 0) {
return HDF_FAILURE;
}
if (snprintf_s(func, funcpathLen, funcpathLen - 1, "%s", "GetAudioManagerFuncs") < 0) {
return HDF_FAILURE;
}
break;
default:
printf("Input error,Switched to direct loading in for you,");
SystemInputFail();
if (snprintf_s(resolvedPath, pathLen, pathLen - 1, "%s", soPathHdi) < 0) {
return HDF_FAILURE;
}
if (snprintf_s(func, funcpathLen, funcpathLen - 1, "%s", "GetAudioManagerFuncs") < 0) {
return HDF_FAILURE;
}
break;
}
return HDF_SUCCESS;
}
struct AudioManager *GetAudioManagerInsForRender(const char *funcString)
{
struct AudioManager *(*getAudioManager)(void) = NULL;
if (funcString == NULL) {
AUDIO_FUNC_LOGE("funcString is null!");
return NULL;
}
if (g_handle == NULL) {
AUDIO_FUNC_LOGE("g_captureHandle is null!");
return NULL;
}
getAudioManager = (struct AudioManager *(*)())(dlsym(g_handle, funcString));
if (getAudioManager == NULL) {
AUDIO_FUNC_LOGE("Get Audio Manager Funcs Fail");
return NULL;
}
return getAudioManager();
}
int32_t GetRenderPassthroughManagerFunc(const char *adapterNameCase)
{
struct AudioAdapterDescriptor *descs = NULL;
enum AudioPortDirection port = PORT_OUT; // Set port information
struct AudioPort renderPort;
int32_t size = 0;
if (adapterNameCase == NULL) {
AUDIO_FUNC_LOGE("The Parameter is NULL");
return HDF_FAILURE;
}
struct AudioManager *manager = GetAudioManagerInsForRender("GetAudioManagerFuncs");
if (manager == NULL) {
AUDIO_FUNC_LOGE("GetAudioManagerInsForRender Fail");
return HDF_FAILURE;
}
int32_t ret = manager->GetAllAdapters(manager, &descs, &size);
int32_t check = size == 0 || descs == NULL || ret < 0;
if (check) {
AUDIO_FUNC_LOGE("Get All Adapters Fail");
return HDF_ERR_NOT_SUPPORT;
}
int32_t index = SwitchAdapter(descs, adapterNameCase, port, &renderPort, size);
if (index < 0) {
AUDIO_FUNC_LOGE("Not Switch Adapter Invalid");
return HDF_ERR_NOT_SUPPORT;
}
struct AudioAdapterDescriptor *desc = &descs[index];
if (manager->LoadAdapter(manager, desc, &g_adapter) != 0) {
AUDIO_FUNC_LOGE("Load Adapter Fail");
return HDF_ERR_NOT_SUPPORT;
}
g_manager = manager;
if (g_adapter == NULL) {
AUDIO_FUNC_LOGE("load audio device Invalid");
return HDF_FAILURE;
}
(void)g_adapter->InitAllPorts(g_adapter);
if (InitAttrs(&g_attrs) < 0) {
g_manager->UnloadAdapter(g_manager, g_adapter);
return HDF_FAILURE;
}
// Specify a hardware device
if (InitDevDesc(&g_devDesc, renderPort.portId) < 0) {
g_manager->UnloadAdapter(g_manager, g_adapter);
return HDF_FAILURE;
}
return HDF_SUCCESS;
}
int32_t GetRenderProxyManagerFunc(const char *adapterNameCase)
{
struct AudioAdapterDescriptor *descs = NULL;
enum AudioPortDirection port = PORT_OUT; // Set port information
struct AudioPort renderPort;
int32_t size = 0;
if (adapterNameCase == NULL) {
AUDIO_FUNC_LOGE("The Parameter is NULL");
return HDF_FAILURE;
}
struct AudioManager *proxyManager = GetAudioManagerInsForRender("GetAudioManagerFuncs");
if (proxyManager == NULL) {
AUDIO_FUNC_LOGE("GetAudioManagerInsForRender Fail");
return HDF_FAILURE;
}
int32_t ret = proxyManager->GetAllAdapters(proxyManager, &descs, &size);
int32_t temp = size == 0 || descs == NULL || ret < 0;
if (temp) {
AUDIO_FUNC_LOGE("Get All Adapters Fail");
return HDF_ERR_NOT_SUPPORT;
}
// Get qualified sound card and port
int32_t index = SwitchAdapter(descs, adapterNameCase, port, &renderPort, size);
if (index < 0) {
AUDIO_FUNC_LOGE("Not Switch Adapter Fail");
return HDF_ERR_NOT_SUPPORT;
}
struct AudioAdapterDescriptor *desc = &descs[index];
if (proxyManager->LoadAdapter(proxyManager, desc, &g_adapter)) {
AUDIO_FUNC_LOGE("Load Adapter Fail");
return HDF_ERR_NOT_SUPPORT;
}
g_proxyManager = proxyManager;
if (g_adapter == NULL) {
AUDIO_FUNC_LOGE("load audio device failed");
return HDF_FAILURE;
}
// Initialization port information, can fill through mode and other parameters
(void)g_adapter->InitAllPorts(g_adapter);
// User needs to set
if (InitAttrs(&g_attrs) < 0) {
g_proxyManager->UnloadAdapter(g_proxyManager, g_adapter);
return HDF_FAILURE;
}
// Specify a hardware device
if (InitDevDesc(&g_devDesc, renderPort.portId) < 0) {
g_proxyManager->UnloadAdapter(g_proxyManager, g_adapter);
return HDF_FAILURE;
}
return HDF_SUCCESS;
}
int32_t InitParam(void)
{
/* Internal and external switch,begin */
char adapterNameCase[PATH_LEN] = {0};
if (SwitchInternalOrExternal(adapterNameCase, PATH_LEN) < 0) {
return HDF_FAILURE;
}
char resolvedPath[PATH_LEN] = {0}; // Select loading mode,begin
char func[PATH_LEN] = {0};
if (SelectLoadingMode(resolvedPath, PATH_LEN, func, PATH_LEN) < 0) {
return HDF_FAILURE;
}
/* Select loading mode,end */
g_audioPort.dir = PORT_OUT;
g_audioPort.portId = 0;
g_audioPort.portName = "AOP";
g_handle = dlopen(resolvedPath, 1);
if (g_handle == NULL) {
AUDIO_FUNC_LOGE("Open so Fail, reason:%s", dlerror());
return HDF_FAILURE;
}
if (strcmp(func, "GetAudioManagerFuncs") == 0) {
if (GetRenderPassthroughManagerFunc(adapterNameCase) < 0) {
AUDIO_FUNC_LOGE("GetPassthroughManagerFunc Fail");
return HDF_FAILURE;
}
} else {
if (GetRenderProxyManagerFunc(adapterNameCase) < 0) {
AUDIO_FUNC_LOGE("GetProxyManagerFunc Fail");
return HDF_FAILURE;
}
}
return HDF_SUCCESS;
}
int32_t SetRenderMute(struct AudioRender **render)
{
(void)render;
int32_t val;
bool isMute = false;
int32_t ret;
if (g_render == NULL || g_render->volume.GetMute == NULL) {
return HDF_FAILURE;
}
ret = g_render->volume.GetMute((AudioHandle)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 (isMute != 0 && isMute != 1) {
AUDIO_FUNC_LOGE("Invalid value!");
SystemInputFail();
return HDF_FAILURE;
}
if (g_render == NULL || g_render->volume.SetMute == NULL) {
AUDIO_FUNC_LOGE("Music already stop!");
SystemInputFail();
return HDF_FAILURE;
}
if (val == 1) {
ret = g_render->volume.SetMute((AudioHandle)g_render, !isMute);
}
return ret;
}
int32_t SetRenderVolume(struct AudioRender **render)
{
(void)render;
int32_t ret;
float val = 0.0;
if (g_render == NULL || g_render->volume.GetVolume == NULL) {
return HDF_FAILURE;
}
ret = g_render->volume.GetVolume((AudioHandle)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->volume.SetVolume == NULL) {
AUDIO_FUNC_LOGE("Music already stop!");
SystemInputFail();
return HDF_FAILURE;
}
ret = g_render->volume.SetVolume((AudioHandle)g_render, val);
if (ret < 0) {
AUDIO_FUNC_LOGE("set volume fail!");
SystemInputFail();
}
return ret;
}
int32_t GetRenderGain(struct AudioRender **render)
{
(void)render;
int32_t ret;
float val = 1.0;
if (g_render == NULL || g_render->volume.GetGain == NULL) {
return HDF_FAILURE;
}
ret = g_render->volume.GetGain((AudioHandle)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;
}
int32_t SetRenderPause(struct AudioRender **render)
{
(void)render;
if (g_waitSleep) {
AUDIO_FUNC_LOGE("Already pause,not need pause again!");
SystemInputFail();
return HDF_FAILURE;
}
int32_t ret;
if (g_render == NULL || g_render->control.Pause == NULL) {
return HDF_FAILURE;
}
ret = g_render->control.Pause((AudioHandle)g_render);
if (ret != 0) {
return HDF_FAILURE;
}
printf("Pause success!\n");
g_waitSleep = 1;
return HDF_SUCCESS;
}
int32_t SetRenderResume(struct AudioRender **render)
{
(void)render;
if (!g_waitSleep) {
AUDIO_FUNC_LOGE("Now is Playing,not need resume!");
SystemInputFail();
return HDF_FAILURE;
}
int32_t ret;
if (g_render == NULL || g_render->control.Resume == NULL) {
return HDF_FAILURE;
}
ret = g_render->control.Resume((AudioHandle)g_render);
if (ret != 0) {
return HDF_FAILURE;
}
printf("resume success!\n");
pthread_mutex_lock(&g_mutex);
g_waitSleep = 0;
pthread_cond_signal(&g_functionCond);
pthread_mutex_unlock(&g_mutex);
return HDF_SUCCESS;
}
void PrintAttributesFromat(void)
{
printf(" ============= Render Sample Attributes Format =============== \n");
printf("| 1. Render AUDIO_FORMAT_PCM_8_BIT |\n");
printf("| 2. Render AUDIO_FORMAT_PCM_16_BIT |\n");
printf("| 3. Render AUDIO_FORMAT_PCM_24_BIT |\n");
printf("| 4. Render AUDIO_FORMAT_PCM_32_BIT |\n");
printf(" ============================================================= \n");
}
int32_t SelectAttributesFomat(uint32_t *fomat)
{
if (fomat == NULL) {
AUDIO_FUNC_LOGE("fomat is null!");
return HDF_FAILURE;
}
PrintAttributesFromat();
printf("Please select audio format,If not selected, the default is 16bit:");
int32_t ret;
int val = 0;
ret = CheckInputName(INPUT_INT, (void *)&val);
if (ret < 0) return HDF_FAILURE;
switch (val) {
case AUDIO_FORMAT_PCM_8_BIT:
*fomat = AUDIO_FORMAT_PCM_8_BIT;
break;
case AUDIO_FORMAT_PCM_16_BIT:
*fomat = AUDIO_FORMAT_PCM_16_BIT;
break;
case AUDIO_FORMAT_PCM_24_BIT:
*fomat = AUDIO_FORMAT_PCM_24_BIT;
break;
case AUDIO_FORMAT_PCM_32_BIT:
*fomat = AUDIO_FORMAT_PCM_32_BIT;
break;
default:
*fomat = AUDIO_FORMAT_PCM_16_BIT;
break;
}
return HDF_SUCCESS;
}
int32_t SetRenderAttributes(struct AudioRender **render)
{
(void)render;
int32_t ret;
struct AudioSampleAttributes attrs;
if (g_render == NULL || g_render->attr.GetSampleAttributes == NULL) {
AUDIO_FUNC_LOGE("The pointer is null!");
return HDF_FAILURE;
}
ret = g_render->attr.GetSampleAttributes((AudioHandle)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->attr.SetSampleAttributes == NULL) {
AUDIO_FUNC_LOGE("Music already complete,Please replay and set the attrbutes!");
SystemInputFail();
return HDF_FAILURE;
}
ret = g_render->attr.SetSampleAttributes((AudioHandle)g_render, &attrs);
if (ret < 0) {
AUDIO_FUNC_LOGE("Set render attributes failed!");
SystemInputFail();
}
return ret;
}
int32_t SelectRenderScene(struct AudioRender **render)
{
(void)render;
system("clear");
int32_t ret;
int val = 0;
struct AudioSceneDescriptor scene;
printf(" =================== Select Scene ===================== \n");
printf("0 is Speaker. |\n");
printf("1 is HeadPhones. |\n");
printf(" ====================================================== \n");
printf("Please input your choice:\n");
ret = CheckInputName(INPUT_INT, (void *)&val);
if (ret < 0 || (val != 0 && val != 1)) {
AUDIO_FUNC_LOGE("Invalid value!");
SystemInputFail();
return HDF_FAILURE;
}
if (val == 1) {
scene.scene.id = 0;
scene.desc.pins = PIN_OUT_HEADSET;
} else {
scene.scene.id = 0;
scene.desc.pins = PIN_OUT_SPEAKER;
}
if (g_render == NULL) {
AUDIO_FUNC_LOGE("Music already stop,");
SystemInputFail();
return HDF_FAILURE;
}
if (g_render->scene.SelectScene == NULL) {
return HDF_FAILURE;
}
ret = g_render->scene.SelectScene((AudioHandle)g_render, &scene);
if (ret < 0) {
AUDIO_FUNC_LOGE("Select scene fail\n");
}
return ret;
}
int32_t GetExtParams(struct AudioRender **render)
{
(void)render;
char keyValueList[BUFFER_LEN] = {0};
int32_t ret;
if (g_render == NULL || g_render->attr.GetExtraParams == NULL) {
return HDF_FAILURE;
}
ret = g_render->attr.GetExtraParams((AudioHandle)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;
}
int32_t GetRenderMmapPosition(struct AudioRender **render)
{
(void)render;
int32_t ret;
if (g_render == NULL || g_render->attr.GetMmapPosition == NULL) {
return HDF_FAILURE;
}
uint64_t frames = 0;
struct AudioTimeStamp time;
time.tvNSec = 0;
time.tvSec = 0;
ret = g_render->attr.GetMmapPosition((AudioHandle)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;
}
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},
};
void ProcessMenu(int32_t choice)
{
int32_t i;
if (choice == GET_RENDER_POSITION + 1) {
return;
}
if (g_render == NULL && choice != 1) {
AUDIO_FUNC_LOGE("This render already release!");
SystemInputFail();
return;
}
for (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);
}
}
}
void Choice(void)
{
int32_t choice = 0;
int ret;
while (choice < GET_RENDER_POSITION + 1 && choice >= 0) {
system("clear");
PrintMenu2();
printf("your choice is:\n");
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[])
{
int32_t ret = 0;
if (argc < 2 || argv == NULL || argv[0] == NULL) { // The parameter number is not greater than 2
printf("usage:[1]sample [2]/data/test.wav\n");
return 0;
}
if (argv[1] == NULL || strlen(argv[1]) == 0) {
return HDF_FAILURE;
}
ret = strncpy_s(g_path, PATH_LEN, argv[1], strlen(argv[1]) + 1);
if (ret != 0) {
AUDIO_FUNC_LOGE("strncpy_s failed!");
return HDF_FAILURE;
}
char pathBuf[PATH_MAX] = {'\0'};
if (realpath(g_path, pathBuf) == NULL) {
return HDF_FAILURE;
}
FILE *file = fopen(pathBuf, "rb");
if (file == NULL) {
printf("Failed to open '%s',Please enter the correct file name \n", g_path);
return HDF_FAILURE;
}
fclose(file);
bool soMode = false;
if (InitParam()) { // init
AUDIO_FUNC_LOGE("InitParam Fail!");
return HDF_FAILURE;
}
Choice();
soMode = PrepareStopAndUloadAdapter();
dlclose(g_handle);
return 0;
}