add && fix voice capture, add record wave,raw orig data and final data; add adc codec voice capture; format combine dmic and adc;
This commit is contained in:
parent
42986a822f
commit
66a7be5e7b
|
@ -57,10 +57,18 @@ static int voice_major;
|
||||||
static int voice_status;
|
static int voice_status;
|
||||||
static double voice_confidence;
|
static double voice_confidence;
|
||||||
static VoiceSessionStatus vss = VoiceSession_Init;
|
static VoiceSessionStatus vss = VoiceSession_Init;
|
||||||
|
static WorkMode wm = WorkMode_R311_PV1;
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------
|
/* ------------------------------------------------------------------------
|
||||||
** Function Definitions
|
** Function Definitions
|
||||||
** ------------------------------------------------------------------------ */
|
** ------------------------------------------------------------------------ */
|
||||||
|
void setWorkMode(WorkMode mode) {
|
||||||
|
wm = mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
WorkMode getWorkMode() {
|
||||||
|
return wm;
|
||||||
|
}
|
||||||
void setVss(VoiceSessionStatus st) { vss = st; }
|
void setVss(VoiceSessionStatus st) { vss = st; }
|
||||||
VoiceSessionStatus getVss() { return vss; }
|
VoiceSessionStatus getVss() { return vss; }
|
||||||
|
|
||||||
|
|
|
@ -57,6 +57,10 @@ typedef enum {
|
||||||
VoiceSession_Created = 2
|
VoiceSession_Created = 2
|
||||||
} VoiceSessionStatus;
|
} VoiceSessionStatus;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
WorkMode_R311_PV1 = 0
|
||||||
|
} WorkMode;
|
||||||
|
|
||||||
void setVss(VoiceSessionStatus st);
|
void setVss(VoiceSessionStatus st);
|
||||||
VoiceSessionStatus getVss();
|
VoiceSessionStatus getVss();
|
||||||
|
|
||||||
|
@ -92,6 +96,9 @@ void setVoiceConfidence(double voiceConfidence);
|
||||||
double getVoiceConfidence();
|
double getVoiceConfidence();
|
||||||
|
|
||||||
void resetAdc();
|
void resetAdc();
|
||||||
|
void setWorkMode(WorkMode mode);
|
||||||
|
WorkMode getWorkMode();
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
} /* extern "C" */
|
} /* extern "C" */
|
||||||
#endif /* C++ */
|
#endif /* C++ */
|
||||||
|
|
|
@ -47,7 +47,9 @@ typedef struct _RecordData{
|
||||||
pthread_t tid_queue_read;
|
pthread_t tid_queue_read;
|
||||||
int runing;
|
int runing;
|
||||||
int backupfilefd;
|
int backupfilefd;
|
||||||
|
int finalfilefd;
|
||||||
struct pcm_config *pcm_cfg;
|
struct pcm_config *pcm_cfg;
|
||||||
|
struct pcm_config *adc;
|
||||||
size_t significant_bits_per_sample;
|
size_t significant_bits_per_sample;
|
||||||
size_t bits_per_sample;
|
size_t bits_per_sample;
|
||||||
size_t bits_per_frame;
|
size_t bits_per_frame;
|
||||||
|
@ -61,7 +63,6 @@ typedef struct _RecordData{
|
||||||
size_t buffer_frames;
|
size_t buffer_frames;
|
||||||
size_t period_frames;
|
size_t period_frames;
|
||||||
|
|
||||||
snd_output_t *log;
|
|
||||||
}RecordData;
|
}RecordData;
|
||||||
|
|
||||||
struct pcm_config {
|
struct pcm_config {
|
||||||
|
@ -72,14 +73,17 @@ struct pcm_config {
|
||||||
unsigned int period_count;
|
unsigned int period_count;
|
||||||
record_audio_fn audio_cb;
|
record_audio_fn audio_cb;
|
||||||
RecordData *recordata;
|
RecordData *recordata;
|
||||||
|
RecordData *adc;
|
||||||
char *format;
|
char *format;
|
||||||
char *backupfilename;
|
char *backupfilename;
|
||||||
|
char *finalfilename;
|
||||||
int backupfile_waveformat;
|
int backupfile_waveformat;
|
||||||
};
|
};
|
||||||
|
|
||||||
int Neteasae_record_start(struct pcm_config *pcm_cfg);
|
int Neteasae_record_start(struct pcm_config *pcm_cfg);
|
||||||
void Netease_record_stop(struct pcm_config *pcm_cfg);
|
void Netease_record_stop(struct pcm_config *pcm_cfg);
|
||||||
|
void device_list(void);
|
||||||
|
void pcm_list(void);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
} /* extern "C" */
|
} /* extern "C" */
|
||||||
|
|
|
@ -29,10 +29,12 @@ when who why
|
||||||
#include "srcwsapi.h"
|
#include "srcwsapi.h"
|
||||||
#include "uvdbus/smart_sound.h"
|
#include "uvdbus/smart_sound.h"
|
||||||
#include "yunxin.h"
|
#include "yunxin.h"
|
||||||
|
#include <getopt.h>
|
||||||
#include <jansson.h>
|
#include <jansson.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
#include <uvdbus/fifo.h>
|
#include <uvdbus/fifo.h>
|
||||||
#include <uvdbus/log.h>
|
#include <uvdbus/log.h>
|
||||||
|
|
||||||
|
@ -46,21 +48,10 @@ when who why
|
||||||
/* ------------------------------------------------------------------------
|
/* ------------------------------------------------------------------------
|
||||||
** Macros
|
** Macros
|
||||||
** ------------------------------------------------------------------------ */
|
** ------------------------------------------------------------------------ */
|
||||||
//#define BACKUP_ORIG_AUDIO
|
|
||||||
#define BACKUP_FINAL_AUDIO
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------
|
/* ------------------------------------------------------------------------
|
||||||
** Defines
|
** Defines
|
||||||
** ------------------------------------------------------------------------ */
|
** ------------------------------------------------------------------------ */
|
||||||
#ifdef BACKUP_ORIG_AUDIO
|
|
||||||
#define ORIG_AUDIO_FILENAME "/mnt/UDISK/origaudio.pcm"
|
|
||||||
static int fd_audio_orig;
|
|
||||||
char *BACKUP_PATH;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef BACKUP_FINAL_AUDIO
|
|
||||||
static int fd_audio_final;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
//#define ENABLE_OEM_DBUS
|
//#define ENABLE_OEM_DBUS
|
||||||
|
|
||||||
|
@ -75,6 +66,7 @@ static int fd_audio_final;
|
||||||
** ------------------------------------------------------------------------ */
|
** ------------------------------------------------------------------------ */
|
||||||
// unsigned int g_bIsUsedTestServer;
|
// unsigned int g_bIsUsedTestServer;
|
||||||
static int in_aborting = 0;
|
static int in_aborting = 0;
|
||||||
|
static int justrecord = 0;
|
||||||
/* ------------------------------------------------------------------------
|
/* ------------------------------------------------------------------------
|
||||||
** Functions
|
** Functions
|
||||||
** ------------------------------------------------------------------------ */
|
** ------------------------------------------------------------------------ */
|
||||||
|
@ -88,10 +80,26 @@ const char *g_fmaeCfgPath = "/usr/share/fmae_res/config.ini";
|
||||||
CAEDATA *caeconfig = NULL;
|
CAEDATA *caeconfig = NULL;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct pcm_config recordconfig;
|
struct pcm_config recordconfig = {0};
|
||||||
struct audio_bypass *audiobypassconfig = NULL;
|
struct audio_bypass *audiobypassconfig = NULL;
|
||||||
static char been_wakedup = 0;
|
static char been_wakedup = 0;
|
||||||
|
|
||||||
|
static long parse_long(const char *str, int *err)
|
||||||
|
{
|
||||||
|
long val;
|
||||||
|
char *endptr;
|
||||||
|
|
||||||
|
errno = 0;
|
||||||
|
val = strtol(str, &endptr, 0);
|
||||||
|
|
||||||
|
if (errno != 0 || *endptr != '\0')
|
||||||
|
*err = -1;
|
||||||
|
else
|
||||||
|
*err = 0;
|
||||||
|
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
|
||||||
#if USED_NETEASE_DC
|
#if USED_NETEASE_DC
|
||||||
static struct kfifo g_AudioCacheBuf;
|
static struct kfifo g_AudioCacheBuf;
|
||||||
// static DECLARE_KFIFO(g_AudioCacheBuf, unsigned char, WAKE_CACHE_DATA_SIZE);
|
// static DECLARE_KFIFO(g_AudioCacheBuf, unsigned char, WAKE_CACHE_DATA_SIZE);
|
||||||
|
@ -226,17 +234,9 @@ int Duilite_beforming_cb(void *userdata, int type, char *msg, int len) {
|
||||||
size_t hasWritten;
|
size_t hasWritten;
|
||||||
|
|
||||||
if (type == DUILITE_MSG_TYPE_BINARY) {
|
if (type == DUILITE_MSG_TYPE_BINARY) {
|
||||||
#ifdef BACKUP_FINAL_AUDIO
|
if (recordconfig.recordata && recordconfig.recordata->finalfilefd > 0) {
|
||||||
fd = open("/tmp/finalaudio", O_CREAT | O_APPEND | O_RDWR);
|
write(recordconfig.recordata->finalfilefd, msg, len);
|
||||||
if (fd > 0) {
|
|
||||||
hasWritten = write(fd, msg, len);
|
|
||||||
close(fd);
|
|
||||||
|
|
||||||
n_debug("Has written:%d\n", hasWritten);
|
|
||||||
} else {
|
|
||||||
n_error("open file(%s) error: %d", "/tmp/finalaudio", fd);
|
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
if (!!audiobypassconfig) {
|
if (!!audiobypassconfig) {
|
||||||
Netease_audiobypass_write(audiobypassconfig, msg, len);
|
Netease_audiobypass_write(audiobypassconfig, msg, len);
|
||||||
}
|
}
|
||||||
|
@ -283,9 +283,6 @@ static void CAEAudioCb(const void *audioData, unsigned int audioLen, int param1,
|
||||||
static void record_audio_cb(const void *audio, unsigned int audio_len,
|
static void record_audio_cb(const void *audio, unsigned int audio_len,
|
||||||
int err_code) {
|
int err_code) {
|
||||||
unsigned long long cachetime;
|
unsigned long long cachetime;
|
||||||
#ifdef BACKUP_ORIG_AUDIO
|
|
||||||
return;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#ifdef DEBUG_WASTE_TIME
|
#ifdef DEBUG_WASTE_TIME
|
||||||
Netease_caltime(&cachetime, 1);
|
Netease_caltime(&cachetime, 1);
|
||||||
|
@ -509,46 +506,153 @@ void LogFunc(int logLevel, const char *log, void *userData) {
|
||||||
IHW_LogRawString(logLevel, (char *)log);
|
IHW_LogRawString(logLevel, (char *)log);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void signal_handler(int sig)
|
static void signal_handler(int sig) {
|
||||||
{
|
if (in_aborting)
|
||||||
if (in_aborting)
|
return;
|
||||||
return;
|
|
||||||
|
|
||||||
in_aborting = 1;
|
in_aborting = 1;
|
||||||
n_debug("Aborted by signal:%d, %s\n", sig, strsignal(sig));
|
n_debug("Aborted by signal:%d, %s\n", sig, strsignal(sig));
|
||||||
Netease_record_stop(&recordconfig);
|
Netease_record_stop(&recordconfig);
|
||||||
|
|
||||||
signal(sig, SIG_DFL);
|
signal(sig, SIG_DFL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void usage() {
|
||||||
|
printf(
|
||||||
|
"Usage:\n"
|
||||||
|
"-h, --help help\n"
|
||||||
|
"-l, --list-devices list all soundcards and digital audio "
|
||||||
|
"devices\n"
|
||||||
|
"-L, --list-pcms list device names\n"
|
||||||
|
"-w, --work-mode=# work mode: 0: r311_pv1\n"
|
||||||
|
"-f, --list-format list all format in alsa\n"
|
||||||
|
"-r, --just-record Only record voice to file\n"
|
||||||
|
"-t, --type=# sample format (case insensitive): raw,wav\n"
|
||||||
|
"--rawfile=# record raw data to filepath\n"
|
||||||
|
"--finalfile=# record duilite output to filepath\n");
|
||||||
|
}
|
||||||
|
enum {
|
||||||
|
OPT_RAW_FILE = 1,
|
||||||
|
OPT_FINAL_FILE
|
||||||
|
};
|
||||||
|
|
||||||
void main(int argc, char **argv) {
|
void main(int argc, char **argv) {
|
||||||
int ret;
|
int ret, c, option_index, err,tmp;
|
||||||
|
char *rawfile = "/dev/null";
|
||||||
|
char *finalfile = "/dev/null";
|
||||||
|
static const char short_options[] = "hlt:w:Lfr";
|
||||||
|
static const struct option long_options[] = {
|
||||||
|
{"help", 0, 0, 'h'},
|
||||||
|
{"list-devices", 0, 0, 'l'},
|
||||||
|
{"list-pcms", 0, 0, 'L'},
|
||||||
|
{"list-format", 0, 0, 'f'},
|
||||||
|
{"just-record", 0, 0, 'r'},
|
||||||
|
{"rawfile", 1, 0, OPT_RAW_FILE},
|
||||||
|
{"finalfile", 1, 0, OPT_FINAL_FILE},
|
||||||
|
{"type", 1, 0, 't'},
|
||||||
|
{"work-mode", 1, 0, 'w'},
|
||||||
|
{0, 0, 0, 0}};
|
||||||
|
|
||||||
#ifdef BOARD_DMIC
|
recordconfig.backupfile_waveformat = 1;
|
||||||
unsigned int channels = 8;
|
recordconfig.audio_cb = record_audio_cb;
|
||||||
unsigned int rate = 16000;
|
setWorkMode(WorkMode_R311_PV1);
|
||||||
unsigned int card = 1;
|
|
||||||
unsigned int device = 0;
|
|
||||||
#else
|
|
||||||
unsigned int card = 2;
|
|
||||||
unsigned int device = 0;
|
|
||||||
unsigned int channels = 2;
|
|
||||||
unsigned int rate = 96000;
|
|
||||||
#endif
|
|
||||||
// unsigned int frames;
|
|
||||||
unsigned int period_size = 1535;
|
|
||||||
unsigned int period_count = 4;
|
|
||||||
|
|
||||||
char sound_device_name[30];
|
if (argc == 1) {
|
||||||
|
printf("Not enough arg!\n");
|
||||||
|
usage();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
while ((c = getopt_long(argc, argv, short_options, long_options,
|
||||||
|
&option_index)) != -1) {
|
||||||
|
switch (c) {
|
||||||
|
case 'h':
|
||||||
|
usage();
|
||||||
|
return;
|
||||||
|
|
||||||
|
case 'l':
|
||||||
|
device_list();
|
||||||
|
return;
|
||||||
|
|
||||||
|
case 'L':
|
||||||
|
pcm_list();
|
||||||
|
return;
|
||||||
|
|
||||||
|
case 'r':
|
||||||
|
justrecord = 1;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 't':
|
||||||
|
if (strcasecmp(optarg, "wav") == 0) {
|
||||||
|
recordconfig.backupfile_waveformat = 1;
|
||||||
|
} else if (strcasecmp(optarg, "raw") == 0) {
|
||||||
|
recordconfig.backupfile_waveformat = 0;
|
||||||
|
}
|
||||||
|
printf("Wave format:%d\n", recordconfig.backupfile_waveformat);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'w':
|
||||||
|
tmp = parse_long(optarg, &err);
|
||||||
|
if (err < 0) {
|
||||||
|
printf("invalid work mode!%s\n", optarg);
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
setWorkMode((WorkMode)tmp);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case OPT_RAW_FILE:
|
||||||
|
rawfile = optarg;
|
||||||
|
printf("Raw file:%s\n", optarg);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case OPT_FINAL_FILE:
|
||||||
|
finalfile = optarg;
|
||||||
|
printf("Final file:%s\n", optarg);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
printf("Unknow cmd!(%d)\n", c);
|
||||||
|
usage();
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf("parse arg end!\n");
|
||||||
|
|
||||||
signal(SIGINT, signal_handler);
|
signal(SIGINT, signal_handler);
|
||||||
signal(SIGTERM, signal_handler);
|
signal(SIGTERM, signal_handler);
|
||||||
signal(SIGABRT, signal_handler);
|
signal(SIGABRT, signal_handler);
|
||||||
|
// Base module init
|
||||||
|
BaseInit();
|
||||||
|
|
||||||
|
printf("Work mode:%d\n", getWorkMode());
|
||||||
|
|
||||||
|
// resetAdc();
|
||||||
|
|
||||||
|
if (justrecord == 1) {
|
||||||
|
if (rawfile == NULL && finalfile == NULL) {
|
||||||
|
printf("Must input rawfile or finalfile!\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (rawfile != NULL) {
|
||||||
|
recordconfig.backupfilename = rawfile;
|
||||||
|
printf("Will record raw to file:%s\n", rawfile);
|
||||||
|
}
|
||||||
|
if (finalfile != NULL) {
|
||||||
|
recordconfig.finalfilename = finalfile;
|
||||||
|
printf("Will record final data to file:%s\n", finalfile);
|
||||||
|
}
|
||||||
|
|
||||||
|
recordconfig.audio_cb = NULL;
|
||||||
|
Neteasae_record_start(&recordconfig);
|
||||||
|
while (1)
|
||||||
|
usleep(1000000);
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef ENABLE_OEM_DBUS
|
#ifdef ENABLE_OEM_DBUS
|
||||||
ret = Netease_dbus_oem_init(DBusMessageCb);
|
ret = Netease_dbus_oem_init(DBusMessageCb);
|
||||||
#else
|
#else
|
||||||
// ret = Netease_Dbus_Init(DBusMessageCb);
|
ret = Netease_Dbus_Init(DBusMessageCb);
|
||||||
#endif
|
#endif
|
||||||
if (NETEASE_SUCCESS == ret) {
|
if (NETEASE_SUCCESS == ret) {
|
||||||
n_debug("Dbus init success\n");
|
n_debug("Dbus init success\n");
|
||||||
|
@ -579,39 +683,6 @@ void main(int argc, char **argv) {
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
snprintf(sound_device_name, sizeof(sound_device_name), "hw:%u,%u", card,
|
|
||||||
device);
|
|
||||||
|
|
||||||
recordconfig.device_name = sound_device_name;
|
|
||||||
recordconfig.channels = channels;
|
|
||||||
recordconfig.rate = rate;
|
|
||||||
recordconfig.period_size = period_size;
|
|
||||||
recordconfig.period_count = period_count;
|
|
||||||
recordconfig.audio_cb = record_audio_cb;
|
|
||||||
recordconfig.format = "S16_LE";
|
|
||||||
recordconfig.backupfilename = NULL;
|
|
||||||
recordconfig.backupfile_waveformat = 0;
|
|
||||||
// todo write something
|
|
||||||
printf("++++++++++++++++++++++++++\n");
|
|
||||||
printf("device name is %s\n", recordconfig.device_name);
|
|
||||||
printf("Channle is %d\n", recordconfig.channels);
|
|
||||||
printf("rate name is %d\n", recordconfig.rate);
|
|
||||||
printf("period_size name is %d\n", recordconfig.period_size);
|
|
||||||
printf("++++++++++++++++++++++++++\n");
|
|
||||||
n_debug("Begin to init netease_voice modules!\n");
|
|
||||||
|
|
||||||
resetAdc();
|
|
||||||
#ifdef BACKUP_ORIG_AUDIO
|
|
||||||
recordconfig.audio_cb = NULL;
|
|
||||||
recordconfig.backupfilename = argv[1];
|
|
||||||
Neteasae_record_start(&recordconfig);
|
|
||||||
while (1)
|
|
||||||
usleep(1000000);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// Base module init
|
|
||||||
BaseInit();
|
|
||||||
|
|
||||||
#if USED_NETEASE_FMAE
|
#if USED_NETEASE_FMAE
|
||||||
ret = Netease_audiobypass_init(&audiobypassconfig, NULL,
|
ret = Netease_audiobypass_init(&audiobypassconfig, NULL,
|
||||||
AUDIO_BYPASS_CHANNEL_MSC_IAT);
|
AUDIO_BYPASS_CHANNEL_MSC_IAT);
|
||||||
|
@ -696,12 +767,12 @@ void main(int argc, char **argv) {
|
||||||
#ifdef ENABLE_OEM_DBUS
|
#ifdef ENABLE_OEM_DBUS
|
||||||
pthread_create(&tid, NULL, Netease_dbus_oem_start, NULL);
|
pthread_create(&tid, NULL, Netease_dbus_oem_start, NULL);
|
||||||
#else
|
#else
|
||||||
// pthread_create(&tid, NULL, Netease_Dbus_Start_Sync, NULL);
|
pthread_create(&tid, NULL, Netease_Dbus_Start_Sync, NULL);
|
||||||
#endif
|
#endif
|
||||||
// Netease_yunxin_test();
|
// Netease_yunxin_test();
|
||||||
|
|
||||||
#if 1
|
#if 0
|
||||||
while (1) {
|
while (1) {
|
||||||
if (1 == Netease_nduilite_init(Duilite_wakeup_cb, Duilite_doa_cb,
|
if (1 == Netease_nduilite_init(Duilite_wakeup_cb, Duilite_doa_cb,
|
||||||
Duilite_beforming_cb, Duilite_vad_cb)) {
|
Duilite_beforming_cb, Duilite_vad_cb)) {
|
||||||
n_toast("Nduilite init success, exit!\n");
|
n_toast("Nduilite init success, exit!\n");
|
||||||
|
@ -715,7 +786,7 @@ void main(int argc, char **argv) {
|
||||||
while (1)
|
while (1)
|
||||||
usleep(1000000);
|
usleep(1000000);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
if (strlen(getUuid()) == 0 || strlen(getYxToken()) == 0) {
|
if (strlen(getUuid()) == 0 || strlen(getYxToken()) == 0) {
|
||||||
|
|
|
@ -395,11 +395,10 @@ void Netease_nduilite_writeaudio(const void *audioData,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef BOARD_DMIC
|
|
||||||
//n_debug("Write nduilite data, len:%d\n", audio_len);
|
//n_debug("Write nduilite data, len:%d\n", audio_len);
|
||||||
Dmic_data_convert(audioData, audio_len);
|
|
||||||
ret = duilite_fespa_feed(fespa, audioData, audio_len);
|
ret = duilite_fespa_feed(fespa, audioData, audio_len);
|
||||||
#else
|
|
||||||
|
#if 0
|
||||||
newbuf = (char *)malloc(audio_len + 60);
|
newbuf = (char *)malloc(audio_len + 60);
|
||||||
|
|
||||||
if (newbuf == NULL) {
|
if (newbuf == NULL) {
|
||||||
|
|
|
@ -28,6 +28,7 @@ when who why
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "base.h"
|
||||||
#include "formats.h"
|
#include "formats.h"
|
||||||
#include "record.h"
|
#include "record.h"
|
||||||
|
|
||||||
|
@ -44,7 +45,7 @@ when who why
|
||||||
#define ALSA_PCM_NEW_HW_PARAMS_API
|
#define ALSA_PCM_NEW_HW_PARAMS_API
|
||||||
#define AUDIO_QUEUE_BUFF_LEN (1024 * 10)
|
#define AUDIO_QUEUE_BUFF_LEN (1024 * 10)
|
||||||
|
|
||||||
#define QUEUE_BUFF_MULTIPLE 500
|
#define QUEUE_BUFF_MULTIPLE 100
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------
|
/* ------------------------------------------------------------------------
|
||||||
** Types
|
** Types
|
||||||
|
@ -67,6 +68,7 @@ static Proc_CAESetShowLog api_cae_set_show_log;
|
||||||
static Proc_CAEDestroy api_cae_destroy;
|
static Proc_CAEDestroy api_cae_destroy;
|
||||||
|
|
||||||
static off64_t fdcount = 0;
|
static off64_t fdcount = 0;
|
||||||
|
static snd_output_t *sndlog;
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------
|
/* ------------------------------------------------------------------------
|
||||||
** Function Definitions
|
** Function Definitions
|
||||||
|
@ -80,6 +82,7 @@ void _record_stop(void *record_hd);
|
||||||
static void end_wave(int fd);
|
static void end_wave(int fd);
|
||||||
static void begin_wave(RecordData *record, int fd, size_t cnt);
|
static void begin_wave(RecordData *record, int fd, size_t cnt);
|
||||||
void _record_stop(void *record_hd);
|
void _record_stop(void *record_hd);
|
||||||
|
static int init_params(struct pcm_config *pcm_cfg, int init_queue);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* make sure we write all bytes or return an error
|
* make sure we write all bytes or return an error
|
||||||
|
@ -312,33 +315,98 @@ static void begin_wave(RecordData *record, int fd, size_t cnt) {
|
||||||
static void *RecordThread(void *param) {
|
static void *RecordThread(void *param) {
|
||||||
RecordData *record = (RecordData *)param;
|
RecordData *record = (RecordData *)param;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
int i = 0;
|
||||||
long long max_file_size = 2147483648LL;
|
long long max_file_size = 2147483648LL;
|
||||||
|
|
||||||
// cpu_set_t mask;
|
// cpu_set_t mask;
|
||||||
n_toast("RecordThread record:%p, running:%d\n", record, record->runing);
|
n_toast("RecordThread record:%p, running:%d\n", record, record->runing);
|
||||||
|
n_toast("record->pcm_cfg:%p\n", record->pcm_cfg);
|
||||||
|
n_toast("record->pcm_cfg->adc:%p\n", record->pcm_cfg->adc);
|
||||||
// CPU_ZERO(&mask);
|
// CPU_ZERO(&mask);
|
||||||
// CPU_SET(0,&mask);
|
// CPU_SET(0,&mask);
|
||||||
// ret = sched_setaffinity(0, sizeof(mask), &mask);
|
// ret = sched_setaffinity(0, sizeof(mask), &mask);
|
||||||
// printf("sched_setaffinity return = %d\n", ret);
|
// printf("sched_setaffinity return = %d\n", ret);
|
||||||
if (record->backupfilefd > 0 && record->pcm_cfg->backupfile_waveformat > 0) {
|
if (record->backupfilefd > 0 &&
|
||||||
|
record->pcm_cfg->backupfile_waveformat > 0) {
|
||||||
begin_wave(record, record->backupfilefd, (size_t)max_file_size);
|
begin_wave(record, record->backupfilefd, (size_t)max_file_size);
|
||||||
fdcount = 0;
|
fdcount = 0;
|
||||||
}
|
}
|
||||||
|
if (record->finalfilefd > 0 && record->pcm_cfg->backupfile_waveformat > 0) {
|
||||||
|
begin_wave(record, record->backupfilefd, (size_t)max_file_size);
|
||||||
|
}
|
||||||
while (!!record->runing) {
|
while (!!record->runing) {
|
||||||
if (pcm_read(record) == record->chunk_size) {
|
if (getWorkMode() == WorkMode_R311_PV1) {
|
||||||
if (record->backupfilefd > 0) {
|
if (pcm_read(record->pcm_cfg->adc) ==
|
||||||
xwrite(record->backupfilefd, record->buffer,
|
record->pcm_cfg->adc->chunk_size) {
|
||||||
record->chunk_bytes);
|
if (pcm_read(record) == record->chunk_size) {
|
||||||
fdcount += record->chunk_bytes;
|
// Write adc data to dmic data, in first two channel
|
||||||
|
for (i = 0; i < record->chunk_size; i++) {
|
||||||
|
// printf("copy from %p to %p, size:%d, frame:%d\n",
|
||||||
|
// (record->pcm_cfg->adc->buffer +
|
||||||
|
// i *
|
||||||
|
// record->pcm_cfg->adc->bits_per_frame
|
||||||
|
// / 8), (record->buffer + i *
|
||||||
|
// record->bits_per_frame / 8), 2 *
|
||||||
|
// record->significant_bits_per_sample /
|
||||||
|
// 8, i);
|
||||||
|
// ch:1-6 dmic
|
||||||
|
// ch:7-8 adc
|
||||||
|
memmove(
|
||||||
|
(void *)(record->buffer +
|
||||||
|
i * record->bits_per_frame / 8),
|
||||||
|
(void *)(record->buffer +
|
||||||
|
i * record->bits_per_frame / 8 +
|
||||||
|
2 * record->significant_bits_per_sample /
|
||||||
|
8),
|
||||||
|
6 * record->significant_bits_per_sample / 8);
|
||||||
|
|
||||||
|
// printf("copy to 0x%p, size:%d\n", (record->buffer +
|
||||||
|
// i * record->bits_per_frame / 8 +
|
||||||
|
// 6 * record->significant_bits_per_sample /
|
||||||
|
// 8), 2 * record->significant_bits_per_sample / 8);
|
||||||
|
memcpy(
|
||||||
|
(void *)(record->buffer +
|
||||||
|
i * record->bits_per_frame / 8 +
|
||||||
|
6 * record->significant_bits_per_sample /
|
||||||
|
8),
|
||||||
|
(void *)(record->pcm_cfg->adc->buffer +
|
||||||
|
i * record->pcm_cfg->adc->bits_per_frame /
|
||||||
|
8),
|
||||||
|
record->pcm_cfg->adc->bits_per_frame / 8);
|
||||||
|
// memcpy((void *)(record->buffer +
|
||||||
|
// i * record->bits_per_frame / 8),
|
||||||
|
// (void *)(record->pcm_cfg->adc->buffer +
|
||||||
|
// i *
|
||||||
|
// record->pcm_cfg->adc->bits_per_frame
|
||||||
|
// / 8),
|
||||||
|
// 2 * record->significant_bits_per_sample / 8);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (record->backupfilefd > 0) {
|
||||||
|
xwrite(record->backupfilefd, record->buffer,
|
||||||
|
record->chunk_bytes);
|
||||||
|
fdcount += record->chunk_bytes;
|
||||||
|
}
|
||||||
|
queue_write(record->queue, record->buffer,
|
||||||
|
record->chunk_bytes);
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, "short read, read %d frames/n", ret);
|
||||||
|
LOG_EX(LOG_Error, "ALSA Short Read, Read %d Frames: %d\n",
|
||||||
|
ret);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// read dmic data and throw
|
||||||
|
pcm_read(record);
|
||||||
|
printf("Read adc codec error!\n");
|
||||||
}
|
}
|
||||||
queue_write(record->queue, record->buffer, record->chunk_bytes);
|
|
||||||
} else {
|
} else {
|
||||||
fprintf(stderr, "short read, read %d frames/n", ret);
|
printf("Unknow work mode!\n");
|
||||||
LOG_EX(LOG_Error, "ALSA Short Read, Read %d Frames: %d\n", ret);
|
exit(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (record->backupfilefd > 0 && record->pcm_cfg->backupfile_waveformat > 0) {
|
if (record->backupfilefd > 0 &&
|
||||||
|
record->pcm_cfg->backupfile_waveformat > 0) {
|
||||||
end_wave(record->backupfilefd);
|
end_wave(record->backupfilefd);
|
||||||
record->backupfilefd = 0;
|
record->backupfilefd = 0;
|
||||||
n_debug("Write backup file end finish!\n");
|
n_debug("Write backup file end finish!\n");
|
||||||
|
@ -359,11 +427,61 @@ static void show_available_sample_formats(snd_pcm_t *handle,
|
||||||
}
|
}
|
||||||
|
|
||||||
int Neteasae_record_start(struct pcm_config *pcm_cfg) {
|
int Neteasae_record_start(struct pcm_config *pcm_cfg) {
|
||||||
|
pthread_attr_t thread_attr;
|
||||||
|
struct sched_param thread_param;
|
||||||
|
struct pcm_config *tmp;
|
||||||
|
|
||||||
|
printf("Begin to init netease record!\n");
|
||||||
|
snd_output_stdio_attach(&sndlog, stderr, 0);
|
||||||
|
switch (getWorkMode()) {
|
||||||
|
case WorkMode_R311_PV1:
|
||||||
|
// dmic codec
|
||||||
|
pcm_cfg->device_name = "hw:1,0";
|
||||||
|
pcm_cfg->channels = 8;
|
||||||
|
pcm_cfg->rate = 16000;
|
||||||
|
pcm_cfg->period_size = 1535;
|
||||||
|
pcm_cfg->format = "S16_LE";
|
||||||
|
|
||||||
|
printf("Begin to init dmic!\n");
|
||||||
|
init_params(pcm_cfg, 1);
|
||||||
|
tmp = (struct pcm_config *)calloc(1, sizeof(struct pcm_config));
|
||||||
|
if (tmp == NULL) {
|
||||||
|
printf("alloc fail!\n");
|
||||||
|
exit(0);
|
||||||
|
} else {
|
||||||
|
printf("Begin to init adc codec!\n");
|
||||||
|
// adc codec
|
||||||
|
tmp->device_name = "hw:2,0";
|
||||||
|
tmp->channels = 2;
|
||||||
|
tmp->rate = 16000;
|
||||||
|
tmp->period_size = 1535;
|
||||||
|
tmp->format = "S16_LE";
|
||||||
|
init_params(tmp, 0);
|
||||||
|
}
|
||||||
|
pcm_cfg->adc = tmp->recordata;
|
||||||
|
pcm_cfg->recordata->adc = tmp;
|
||||||
|
|
||||||
|
pthread_attr_init(&thread_attr);
|
||||||
|
pthread_attr_setschedpolicy(&thread_attr, SCHED_RR);
|
||||||
|
thread_param.sched_priority = sched_get_priority_max(SCHED_RR);
|
||||||
|
pthread_attr_setschedparam(&thread_attr, &thread_param);
|
||||||
|
|
||||||
|
pthread_create(&pcm_cfg->recordata->tid_pcm_read, &thread_attr,
|
||||||
|
RecordThread, (void *)pcm_cfg->recordata);
|
||||||
|
pthread_create(&pcm_cfg->recordata->tid_queue_read, NULL,
|
||||||
|
QueueReadThread, (void *)pcm_cfg->recordata);
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
printf("Unknow mode!\n");
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
static int init_params(struct pcm_config *pcm_cfg, int init_queue) {
|
||||||
int rc;
|
int rc;
|
||||||
int size;
|
int size;
|
||||||
int ret = NETEASE_SUCCESS;
|
int ret = NETEASE_SUCCESS;
|
||||||
pthread_attr_t thread_attr;
|
|
||||||
struct sched_param thread_param;
|
|
||||||
snd_pcm_hw_params_t *params;
|
snd_pcm_hw_params_t *params;
|
||||||
snd_pcm_sw_params_t *swparams;
|
snd_pcm_sw_params_t *swparams;
|
||||||
unsigned int val, val2;
|
unsigned int val, val2;
|
||||||
|
@ -374,6 +492,7 @@ int Neteasae_record_start(struct pcm_config *pcm_cfg) {
|
||||||
|
|
||||||
RecordData *record = (RecordData *)malloc(sizeof(RecordData));
|
RecordData *record = (RecordData *)malloc(sizeof(RecordData));
|
||||||
if (NULL == record) {
|
if (NULL == record) {
|
||||||
|
printf("Malloc fail for record data!\n");
|
||||||
return NETEASE_ERROR_OUT_OF_MEMORY;
|
return NETEASE_ERROR_OUT_OF_MEMORY;
|
||||||
}
|
}
|
||||||
memset(record, 0, sizeof(RecordData));
|
memset(record, 0, sizeof(RecordData));
|
||||||
|
@ -381,7 +500,6 @@ int Neteasae_record_start(struct pcm_config *pcm_cfg) {
|
||||||
pcm_cfg->recordata = record;
|
pcm_cfg->recordata = record;
|
||||||
record->pcm_cfg = pcm_cfg;
|
record->pcm_cfg = pcm_cfg;
|
||||||
record->cb = pcm_cfg->audio_cb;
|
record->cb = pcm_cfg->audio_cb;
|
||||||
snd_output_stdio_attach(&record->log, stderr, 0);
|
|
||||||
|
|
||||||
//设置录音参数参数
|
//设置录音参数参数
|
||||||
rc = snd_pcm_open(&record->handle, pcm_cfg->device_name,
|
rc = snd_pcm_open(&record->handle, pcm_cfg->device_name,
|
||||||
|
@ -460,12 +578,12 @@ int Neteasae_record_start(struct pcm_config *pcm_cfg) {
|
||||||
rc = snd_pcm_hw_params(record->handle, params);
|
rc = snd_pcm_hw_params(record->handle, params);
|
||||||
if (rc < 0) {
|
if (rc < 0) {
|
||||||
n_error("unable to set hw parameters: %s/n", snd_strerror(rc));
|
n_error("unable to set hw parameters: %s/n", snd_strerror(rc));
|
||||||
// snd_pcm_hw_dump(params, stdout);
|
// snd_pcm_hw_dump(params, sndlog);
|
||||||
ret = NETEASE_ERROR_FAIL;
|
ret = NETEASE_ERROR_FAIL;
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
// snd_pcm_hw_params_dump(params, stdout);
|
// snd_pcm_hw_params_dump(params, stdout);
|
||||||
snd_pcm_dump(record->handle, record->log);
|
snd_pcm_dump(record->handle, sndlog);
|
||||||
/* Use a buffer large enough to hold one period */
|
/* Use a buffer large enough to hold one period */
|
||||||
record->bits_per_sample = snd_pcm_format_physical_width(record->format);
|
record->bits_per_sample = snd_pcm_format_physical_width(record->format);
|
||||||
record->significant_bits_per_sample = snd_pcm_format_width(record->format);
|
record->significant_bits_per_sample = snd_pcm_format_width(record->format);
|
||||||
|
@ -484,14 +602,19 @@ int Neteasae_record_start(struct pcm_config *pcm_cfg) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
record->queue_buff = (char *)malloc(
|
if (init_queue > 0) {
|
||||||
sizeof(audio_queue_t) + record->chunk_bytes * QUEUE_BUFF_MULTIPLE + 1);
|
record->queue_buff = (char *)malloc(
|
||||||
if (NULL == record->queue_buff) {
|
sizeof(audio_queue_t) + record->chunk_bytes * QUEUE_BUFF_MULTIPLE + 1);
|
||||||
ret = NETEASE_ERROR_OUT_OF_MEMORY;
|
if (NULL == record->queue_buff) {
|
||||||
goto error;
|
ret = NETEASE_ERROR_OUT_OF_MEMORY;
|
||||||
|
goto error;
|
||||||
|
}
|
||||||
|
record->queue = queue_init(record->queue_buff,
|
||||||
|
record->chunk_bytes * QUEUE_BUFF_MULTIPLE + 1);
|
||||||
|
} else {
|
||||||
|
record->queue_buff = NULL;
|
||||||
|
record->queue = NULL;
|
||||||
}
|
}
|
||||||
record->queue = queue_init(record->queue_buff,
|
|
||||||
record->chunk_bytes * QUEUE_BUFF_MULTIPLE + 1);
|
|
||||||
|
|
||||||
snd_pcm_sw_params_current(record->handle, swparams);
|
snd_pcm_sw_params_current(record->handle, swparams);
|
||||||
snd_pcm_sw_params_set_avail_min(record->handle, swparams,
|
snd_pcm_sw_params_set_avail_min(record->handle, swparams,
|
||||||
|
@ -505,11 +628,6 @@ int Neteasae_record_start(struct pcm_config *pcm_cfg) {
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
pthread_attr_init(&thread_attr);
|
|
||||||
pthread_attr_setschedpolicy(&thread_attr, SCHED_RR);
|
|
||||||
thread_param.sched_priority = sched_get_priority_max(SCHED_RR);
|
|
||||||
pthread_attr_setschedparam(&thread_attr, &thread_param);
|
|
||||||
|
|
||||||
record->runing = 1;
|
record->runing = 1;
|
||||||
|
|
||||||
if (pcm_cfg->backupfilename != NULL) {
|
if (pcm_cfg->backupfilename != NULL) {
|
||||||
|
@ -523,11 +641,21 @@ int Neteasae_record_start(struct pcm_config *pcm_cfg) {
|
||||||
n_debug("Create backup file:%s, fd:%d\n", pcm_cfg->backupfilename,
|
n_debug("Create backup file:%s, fd:%d\n", pcm_cfg->backupfilename,
|
||||||
record->backupfilefd);
|
record->backupfilefd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (pcm_cfg->finalfilename != NULL) {
|
||||||
|
if (!lstat(pcm_cfg->finalfilename, &statbuf)) {
|
||||||
|
if (S_ISREG(statbuf.st_mode))
|
||||||
|
remove(pcm_cfg->finalfilename);
|
||||||
|
n_debug("Remove file:%s\n", pcm_cfg->finalfilename);
|
||||||
|
}
|
||||||
|
record->finalfilefd =
|
||||||
|
open(pcm_cfg->finalfilename, O_TRUNC | O_WRONLY | O_CREAT, 06444);
|
||||||
|
n_debug("Create final file:%s, fd:%d\n", pcm_cfg->finalfilename,
|
||||||
|
record->finalfilefd);
|
||||||
|
}
|
||||||
|
|
||||||
n_toast("Record_start record :%p\n", record);
|
n_toast("Record_start record :%p\n", record);
|
||||||
pthread_create(&record->tid_pcm_read, &thread_attr, RecordThread,
|
|
||||||
(void *)record);
|
|
||||||
pthread_create(&record->tid_queue_read, NULL, QueueReadThread,
|
|
||||||
(void *)record);
|
|
||||||
goto exit;
|
goto exit;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
|
@ -574,4 +702,117 @@ void Netease_record_stop(struct pcm_config *config) {
|
||||||
if (config != NULL && config->recordata != NULL) {
|
if (config != NULL && config->recordata != NULL) {
|
||||||
config->recordata->runing = 0;
|
config->recordata->runing = 0;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void device_list(void) {
|
||||||
|
snd_ctl_t *handle;
|
||||||
|
int card, err, dev, idx;
|
||||||
|
snd_ctl_card_info_t *info;
|
||||||
|
snd_pcm_info_t *pcminfo;
|
||||||
|
snd_pcm_stream_t stream = SND_PCM_STREAM_CAPTURE;
|
||||||
|
|
||||||
|
snd_ctl_card_info_alloca(&info);
|
||||||
|
snd_pcm_info_alloca(&pcminfo);
|
||||||
|
|
||||||
|
card = -1;
|
||||||
|
if (snd_card_next(&card) < 0 || card < 0) {
|
||||||
|
n_error("no soundcards found...");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
printf("**** List of %s Hardware Devices ****\n",
|
||||||
|
snd_pcm_stream_name(stream));
|
||||||
|
while (card >= 0) {
|
||||||
|
char name[32];
|
||||||
|
sprintf(name, "hw:%d", card);
|
||||||
|
if ((err = snd_ctl_open(&handle, name, 0)) < 0) {
|
||||||
|
n_error("control open (%i): %s", card, snd_strerror(err));
|
||||||
|
goto next_card;
|
||||||
|
}
|
||||||
|
if ((err = snd_ctl_card_info(handle, info)) < 0) {
|
||||||
|
n_error("control hardware info (%i): %s", card, snd_strerror(err));
|
||||||
|
snd_ctl_close(handle);
|
||||||
|
goto next_card;
|
||||||
|
}
|
||||||
|
dev = -1;
|
||||||
|
while (1) {
|
||||||
|
unsigned int count;
|
||||||
|
if (snd_ctl_pcm_next_device(handle, &dev) < 0)
|
||||||
|
n_error("snd_ctl_pcm_next_device");
|
||||||
|
if (dev < 0)
|
||||||
|
break;
|
||||||
|
snd_pcm_info_set_device(pcminfo, dev);
|
||||||
|
snd_pcm_info_set_subdevice(pcminfo, 0);
|
||||||
|
snd_pcm_info_set_stream(pcminfo, stream);
|
||||||
|
if ((err = snd_ctl_pcm_info(handle, pcminfo)) < 0) {
|
||||||
|
if (err != -ENOENT)
|
||||||
|
n_error("control digital audio info (%i): %s", card,
|
||||||
|
snd_strerror(err));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
printf(("card %i: %s [%s], device %i: %s [%s]\n"), card,
|
||||||
|
snd_ctl_card_info_get_id(info),
|
||||||
|
snd_ctl_card_info_get_name(info), dev,
|
||||||
|
snd_pcm_info_get_id(pcminfo),
|
||||||
|
snd_pcm_info_get_name(pcminfo));
|
||||||
|
count = snd_pcm_info_get_subdevices_count(pcminfo);
|
||||||
|
printf((" Subdevices: %i/%i\n"),
|
||||||
|
snd_pcm_info_get_subdevices_avail(pcminfo), count);
|
||||||
|
for (idx = 0; idx < (int)count; idx++) {
|
||||||
|
snd_pcm_info_set_subdevice(pcminfo, idx);
|
||||||
|
if ((err = snd_ctl_pcm_info(handle, pcminfo)) < 0) {
|
||||||
|
n_error("control digital audio playback info (%i): %s",
|
||||||
|
card, snd_strerror(err));
|
||||||
|
} else {
|
||||||
|
printf((" Subdevice #%i: %s\n"), idx,
|
||||||
|
snd_pcm_info_get_subdevice_name(pcminfo));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
snd_ctl_close(handle);
|
||||||
|
next_card:
|
||||||
|
if (snd_card_next(&card) < 0) {
|
||||||
|
n_error("snd_card_next");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void pcm_list(void) {
|
||||||
|
void **hints, **n;
|
||||||
|
char *name, *descr, *descr1, *io;
|
||||||
|
const char *filter;
|
||||||
|
|
||||||
|
if (snd_device_name_hint(-1, "pcm", &hints) < 0)
|
||||||
|
return;
|
||||||
|
n = hints;
|
||||||
|
// filter = stream == SND_PCM_STREAM_CAPTURE ? "Input" : "Output";
|
||||||
|
filter = "Input";
|
||||||
|
while (*n != NULL) {
|
||||||
|
name = snd_device_name_get_hint(*n, "NAME");
|
||||||
|
descr = snd_device_name_get_hint(*n, "DESC");
|
||||||
|
io = snd_device_name_get_hint(*n, "IOID");
|
||||||
|
if (io != NULL && strcmp(io, filter) != 0)
|
||||||
|
goto __end;
|
||||||
|
printf("%s\n", name);
|
||||||
|
if ((descr1 = descr) != NULL) {
|
||||||
|
printf(" ");
|
||||||
|
while (*descr1) {
|
||||||
|
if (*descr1 == '\n')
|
||||||
|
printf("\n ");
|
||||||
|
else
|
||||||
|
putchar(*descr1);
|
||||||
|
descr1++;
|
||||||
|
}
|
||||||
|
putchar('\n');
|
||||||
|
}
|
||||||
|
__end:
|
||||||
|
if (name != NULL)
|
||||||
|
free(name);
|
||||||
|
if (descr != NULL)
|
||||||
|
free(descr);
|
||||||
|
if (io != NULL)
|
||||||
|
free(io);
|
||||||
|
n++;
|
||||||
|
}
|
||||||
|
snd_device_name_free_hint(hints);
|
||||||
}
|
}
|
Loading…
Reference in New Issue