mirror of
https://github.com/openharmony/third_party_tinyalsa.git
synced 2026-07-18 21:34:26 -04:00
Merge pull request #188 from dvdli/android-dev
Synchronize the changes on AOSP repo
This commit is contained in:
@@ -133,7 +133,7 @@ int mixer_ctl_set_array(struct mixer_ctl *ctl, const void *array, size_t count);
|
||||
|
||||
int mixer_ctl_set_enum_by_string(struct mixer_ctl *ctl, const char *string);
|
||||
|
||||
/* Determe range of integer mixer controls */
|
||||
/* Determine range of integer mixer controls */
|
||||
int mixer_ctl_get_range_min(const struct mixer_ctl *ctl);
|
||||
|
||||
int mixer_ctl_get_range_max(const struct mixer_ctl *ctl);
|
||||
|
||||
+29
-3
@@ -202,13 +202,15 @@ struct pcm_config {
|
||||
unsigned int period_count;
|
||||
/** The sample format of a PCM */
|
||||
enum pcm_format format;
|
||||
/* Values to use for the ALSA start, stop and silence thresholds. Setting
|
||||
* any one of these values to 0 will cause the default tinyalsa values to be
|
||||
* used instead. Tinyalsa defaults are as follows.
|
||||
/* Values to use for the ALSA start, stop and silence thresholds, and
|
||||
* silence size. Setting any one of these values to 0 will cause the
|
||||
* default tinyalsa values to be used instead.
|
||||
* Tinyalsa defaults are as follows.
|
||||
*
|
||||
* start_threshold : period_count * period_size
|
||||
* stop_threshold : period_count * period_size
|
||||
* silence_threshold : 0
|
||||
* silence_size : 0
|
||||
*/
|
||||
/** The minimum number of frames required to start the PCM */
|
||||
unsigned int start_threshold;
|
||||
@@ -216,6 +218,9 @@ struct pcm_config {
|
||||
unsigned int stop_threshold;
|
||||
/** The minimum number of frames to silence the PCM */
|
||||
unsigned int silence_threshold;
|
||||
/** The number of frames to overwrite the playback buffer when the playback underrun is greater
|
||||
* than the silence threshold */
|
||||
unsigned int silence_size;
|
||||
};
|
||||
|
||||
/** Enumeration of a PCM's hardware parameters.
|
||||
@@ -264,6 +269,21 @@ unsigned int pcm_params_get_min(const struct pcm_params *pcm_params, enum pcm_pa
|
||||
|
||||
unsigned int pcm_params_get_max(const struct pcm_params *pcm_params, enum pcm_param param);
|
||||
|
||||
/* Converts the pcm parameters to a human readable string.
|
||||
* The string parameter is a caller allocated buffer of size bytes,
|
||||
* which is then filled up to size - 1 and null terminated,
|
||||
* if size is greater than zero.
|
||||
* The return value is the number of bytes copied to string
|
||||
* (not including null termination) if less than size; otherwise,
|
||||
* the number of bytes required for the buffer.
|
||||
*/
|
||||
int pcm_params_to_string(struct pcm_params *params, char *string, unsigned int size);
|
||||
|
||||
/* Returns 1 if the pcm_format is present (format bit set) in
|
||||
* the pcm_params structure; 0 otherwise, or upon unrecognized format.
|
||||
*/
|
||||
int pcm_params_format_test(struct pcm_params *params, enum pcm_format format);
|
||||
|
||||
struct pcm;
|
||||
|
||||
struct pcm *pcm_open(unsigned int card,
|
||||
@@ -321,6 +341,12 @@ int pcm_mmap_begin(struct pcm *pcm, void **areas, unsigned int *offset, unsigned
|
||||
|
||||
int pcm_mmap_commit(struct pcm *pcm, unsigned int offset, unsigned int frames);
|
||||
|
||||
int pcm_mmap_avail(struct pcm *pcm);
|
||||
|
||||
int pcm_mmap_get_hw_ptr(struct pcm* pcm, unsigned int *hw_ptr, struct timespec *tstamp);
|
||||
|
||||
int pcm_get_poll_fd(struct pcm *pcm);
|
||||
|
||||
int pcm_link(struct pcm *pcm1, struct pcm *pcm2);
|
||||
|
||||
int pcm_unlink(struct pcm *pcm);
|
||||
|
||||
+10
@@ -990,6 +990,11 @@ int mixer_ctl_get_array(const struct mixer_ctl *ctl, void *array, size_t count)
|
||||
break;
|
||||
}
|
||||
|
||||
case SNDRV_CTL_ELEM_TYPE_IEC958:
|
||||
size = sizeof(ev.value.iec958);
|
||||
source = &ev.value.iec958;
|
||||
break;
|
||||
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
@@ -1116,6 +1121,11 @@ int mixer_ctl_set_array(struct mixer_ctl *ctl, const void *array, size_t count)
|
||||
}
|
||||
break;
|
||||
|
||||
case SNDRV_CTL_ELEM_TYPE_IEC958:
|
||||
size = sizeof(ev.value.iec958);
|
||||
dest = &ev.value.iec958;
|
||||
break;
|
||||
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@@ -70,6 +70,83 @@
|
||||
#define SNDRV_PCM_HW_PARAMS_NO_PERIOD_WAKEUP (1<<2)
|
||||
#endif /* SNDRV_PCM_HW_PARAMS_NO_PERIOD_WAKEUP */
|
||||
|
||||
/* Logs information into a string; follows snprintf() in that
|
||||
* offset may be greater than size, and though no characters are copied
|
||||
* into string, characters are still counted into offset. */
|
||||
#define STRLOG(string, offset, size, ...) \
|
||||
do { int temp, clipoffset = offset > size ? size : offset; \
|
||||
temp = snprintf(string + clipoffset, size - clipoffset, __VA_ARGS__); \
|
||||
if (temp > 0) offset += temp; } while (0)
|
||||
|
||||
#ifndef ARRAY_SIZE
|
||||
#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
|
||||
#endif
|
||||
|
||||
/* refer to SNDRV_PCM_ACCESS_##index in sound/asound.h. */
|
||||
static const char * const access_lookup[] = {
|
||||
"MMAP_INTERLEAVED",
|
||||
"MMAP_NONINTERLEAVED",
|
||||
"MMAP_COMPLEX",
|
||||
"RW_INTERLEAVED",
|
||||
"RW_NONINTERLEAVED",
|
||||
};
|
||||
|
||||
/* refer to SNDRV_PCM_FORMAT_##index in sound/asound.h. */
|
||||
static const char * const format_lookup[] = {
|
||||
/*[0] =*/ "S8",
|
||||
"U8",
|
||||
"S16_LE",
|
||||
"S16_BE",
|
||||
"U16_LE",
|
||||
"U16_BE",
|
||||
"S24_LE",
|
||||
"S24_BE",
|
||||
"U24_LE",
|
||||
"U24_BE",
|
||||
"S32_LE",
|
||||
"S32_BE",
|
||||
"U32_LE",
|
||||
"U32_BE",
|
||||
"FLOAT_LE",
|
||||
"FLOAT_BE",
|
||||
"FLOAT64_LE",
|
||||
"FLOAT64_BE",
|
||||
"IEC958_SUBFRAME_LE",
|
||||
"IEC958_SUBFRAME_BE",
|
||||
"MU_LAW",
|
||||
"A_LAW",
|
||||
"IMA_ADPCM",
|
||||
"MPEG",
|
||||
/*[24] =*/ "GSM",
|
||||
/* gap */
|
||||
[31] = "SPECIAL",
|
||||
"S24_3LE",
|
||||
"S24_3BE",
|
||||
"U24_3LE",
|
||||
"U24_3BE",
|
||||
"S20_3LE",
|
||||
"S20_3BE",
|
||||
"U20_3LE",
|
||||
"U20_3BE",
|
||||
"S18_3LE",
|
||||
"S18_3BE",
|
||||
"U18_3LE",
|
||||
/*[43] =*/ "U18_3BE",
|
||||
#if 0
|
||||
/* recent additions, may not be present on local asound.h */
|
||||
"G723_24",
|
||||
"G723_24_1B",
|
||||
"G723_40",
|
||||
"G723_40_1B",
|
||||
"DSD_U8",
|
||||
"DSD_U16_LE",
|
||||
#endif
|
||||
};
|
||||
|
||||
/* refer to SNDRV_PCM_SUBFORMAT_##index in sound/asound.h. */
|
||||
static const char * const subformat_lookup[] = {
|
||||
"STD",
|
||||
};
|
||||
|
||||
static inline int param_is_mask(int p)
|
||||
{
|
||||
@@ -255,7 +332,7 @@ static int oops(struct pcm *pcm, int e, const char *fmt, ...)
|
||||
va_end(ap);
|
||||
sz = strlen(pcm->error);
|
||||
|
||||
if (errno)
|
||||
if (e)
|
||||
snprintf(pcm->error + sz, PCM_ERROR_MAX - sz,
|
||||
": %s", strerror(e));
|
||||
return -1;
|
||||
@@ -361,6 +438,7 @@ int pcm_set_config(struct pcm *pcm, const struct pcm_config *config)
|
||||
pcm->config.start_threshold = config->period_count * config->period_size;
|
||||
pcm->config.stop_threshold = config->period_count * config->period_size;
|
||||
pcm->config.silence_threshold = 0;
|
||||
pcm->config.silence_size = 0;
|
||||
} else
|
||||
pcm->config = *config;
|
||||
|
||||
@@ -377,7 +455,7 @@ int pcm_set_config(struct pcm *pcm, const struct pcm_config *config)
|
||||
if (pcm->flags & PCM_NOIRQ) {
|
||||
|
||||
if (!(pcm->flags & PCM_MMAP)) {
|
||||
oops(pcm, -EINVAL, "noirq only currently supported with mmap().");
|
||||
oops(pcm, EINVAL, "noirq only currently supported with mmap().");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
@@ -442,7 +520,7 @@ int pcm_set_config(struct pcm *pcm, const struct pcm_config *config)
|
||||
sparams.stop_threshold = config->stop_threshold;
|
||||
|
||||
sparams.xfer_align = config->period_size / 2; /* needed for old kernels */
|
||||
sparams.silence_size = 0;
|
||||
sparams.silence_size = config->silence_size;
|
||||
sparams.silence_threshold = config->silence_threshold;
|
||||
pcm->boundary = sparams.boundary = pcm->buffer_size;
|
||||
|
||||
@@ -798,6 +876,87 @@ unsigned int pcm_params_get_max(const struct pcm_params *pcm_params,
|
||||
return param_get_max(params, p);
|
||||
}
|
||||
|
||||
static int pcm_mask_test(const struct pcm_mask *m, unsigned int index)
|
||||
{
|
||||
const unsigned int bitshift = 5; /* for 32 bit integer */
|
||||
const unsigned int bitmask = (1 << bitshift) - 1;
|
||||
unsigned int element;
|
||||
|
||||
element = index >> bitshift;
|
||||
if (element >= ARRAY_SIZE(m->bits))
|
||||
return 0; /* for safety, but should never occur */
|
||||
return (m->bits[element] >> (index & bitmask)) & 1;
|
||||
}
|
||||
|
||||
static int pcm_mask_to_string(const struct pcm_mask *m, char *string, unsigned int size,
|
||||
char *mask_name,
|
||||
const char * const *bit_array_name, size_t bit_array_size)
|
||||
{
|
||||
unsigned int i;
|
||||
unsigned int offset = 0;
|
||||
|
||||
if (m == NULL)
|
||||
return 0;
|
||||
if (bit_array_size < 32) {
|
||||
STRLOG(string, offset, size, "%12s:\t%#08x\n", mask_name, m->bits[0]);
|
||||
} else { /* spans two or more bitfields, print with an array index */
|
||||
for (i = 0; i < (bit_array_size + 31) >> 5; ++i) {
|
||||
STRLOG(string, offset, size, "%9s[%d]:\t%#08x\n",
|
||||
mask_name, i, m->bits[i]);
|
||||
}
|
||||
}
|
||||
for (i = 0; i < bit_array_size; ++i) {
|
||||
if (pcm_mask_test(m, i)) {
|
||||
STRLOG(string, offset, size, "%12s \t%s\n", "", bit_array_name[i]);
|
||||
}
|
||||
}
|
||||
return offset;
|
||||
}
|
||||
|
||||
int pcm_params_to_string(struct pcm_params *params, char *string, unsigned int size)
|
||||
{
|
||||
const struct pcm_mask *m;
|
||||
unsigned int min, max;
|
||||
unsigned int clipoffset, offset;
|
||||
|
||||
m = pcm_params_get_mask(params, PCM_PARAM_ACCESS);
|
||||
offset = pcm_mask_to_string(m, string, size,
|
||||
"Access", access_lookup, ARRAY_SIZE(access_lookup));
|
||||
m = pcm_params_get_mask(params, PCM_PARAM_FORMAT);
|
||||
clipoffset = offset > size ? size : offset;
|
||||
offset += pcm_mask_to_string(m, string + clipoffset, size - clipoffset,
|
||||
"Format", format_lookup, ARRAY_SIZE(format_lookup));
|
||||
m = pcm_params_get_mask(params, PCM_PARAM_SUBFORMAT);
|
||||
clipoffset = offset > size ? size : offset;
|
||||
offset += pcm_mask_to_string(m, string + clipoffset, size - clipoffset,
|
||||
"Subformat", subformat_lookup, ARRAY_SIZE(subformat_lookup));
|
||||
min = pcm_params_get_min(params, PCM_PARAM_RATE);
|
||||
max = pcm_params_get_max(params, PCM_PARAM_RATE);
|
||||
STRLOG(string, offset, size, " Rate:\tmin=%uHz\tmax=%uHz\n", min, max);
|
||||
min = pcm_params_get_min(params, PCM_PARAM_CHANNELS);
|
||||
max = pcm_params_get_max(params, PCM_PARAM_CHANNELS);
|
||||
STRLOG(string, offset, size, " Channels:\tmin=%u\t\tmax=%u\n", min, max);
|
||||
min = pcm_params_get_min(params, PCM_PARAM_SAMPLE_BITS);
|
||||
max = pcm_params_get_max(params, PCM_PARAM_SAMPLE_BITS);
|
||||
STRLOG(string, offset, size, " Sample bits:\tmin=%u\t\tmax=%u\n", min, max);
|
||||
min = pcm_params_get_min(params, PCM_PARAM_PERIOD_SIZE);
|
||||
max = pcm_params_get_max(params, PCM_PARAM_PERIOD_SIZE);
|
||||
STRLOG(string, offset, size, " Period size:\tmin=%u\t\tmax=%u\n", min, max);
|
||||
min = pcm_params_get_min(params, PCM_PARAM_PERIODS);
|
||||
max = pcm_params_get_max(params, PCM_PARAM_PERIODS);
|
||||
STRLOG(string, offset, size, "Period count:\tmin=%u\t\tmax=%u\n", min, max);
|
||||
return offset;
|
||||
}
|
||||
|
||||
int pcm_params_format_test(struct pcm_params *params, enum pcm_format format)
|
||||
{
|
||||
unsigned int alsa_format = pcm_format_to_alsa(format);
|
||||
|
||||
if (alsa_format == SNDRV_PCM_FORMAT_S16_LE && format != PCM_FORMAT_S16_LE)
|
||||
return 0; /* caution: format not recognized is equivalent to S16_LE */
|
||||
return pcm_mask_test(pcm_params_get_mask(params, PCM_PARAM_FORMAT), alsa_format);
|
||||
}
|
||||
|
||||
/** Closes a PCM returned by @ref pcm_open.
|
||||
* @param pcm A PCM returned by @ref pcm_open.
|
||||
* May not be NULL.
|
||||
@@ -923,7 +1082,7 @@ struct pcm *pcm_open(unsigned int card, unsigned int device,
|
||||
|
||||
rc = pcm_hw_mmap_status(pcm);
|
||||
if (rc < 0) {
|
||||
oops(pcm, rc, "mmap status failed");
|
||||
oops(pcm, errno, "mmap status failed");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
@@ -932,7 +1091,7 @@ struct pcm *pcm_open(unsigned int card, unsigned int device,
|
||||
int arg = SNDRV_PCM_TSTAMP_TYPE_MONOTONIC;
|
||||
rc = pcm->ops->ioctl(pcm->data, SNDRV_PCM_IOCTL_TTSTAMP, &arg);
|
||||
if (rc < 0) {
|
||||
oops(pcm, rc, "cannot set timestamp type");
|
||||
oops(pcm, errno, "cannot set timestamp type");
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
@@ -1077,7 +1236,7 @@ static inline int pcm_mmap_capture_avail(struct pcm *pcm)
|
||||
return avail;
|
||||
}
|
||||
|
||||
static inline int pcm_mmap_avail(struct pcm *pcm)
|
||||
int pcm_mmap_avail(struct pcm *pcm)
|
||||
{
|
||||
if (pcm->flags & PCM_IN)
|
||||
return pcm_mmap_capture_avail(pcm);
|
||||
@@ -1185,6 +1344,11 @@ static int pcm_mmap_transfer_areas(struct pcm *pcm, char *buf,
|
||||
return count;
|
||||
}
|
||||
|
||||
int pcm_get_poll_fd(struct pcm *pcm)
|
||||
{
|
||||
return pcm->fd;
|
||||
}
|
||||
|
||||
int pcm_avail_update(struct pcm *pcm)
|
||||
{
|
||||
pcm_sync_ptr(pcm, SNDRV_PCM_SYNC_PTR_APPL|SNDRV_PCM_SYNC_PTR_AVAIL_MIN);
|
||||
@@ -1396,6 +1560,37 @@ int pcm_mmap_read(struct pcm *pcm, void *data, unsigned int count)
|
||||
return pcm_mmap_transfer(pcm, data, pcm_bytes_to_frames(pcm, count));
|
||||
}
|
||||
|
||||
/* Returns current read/write position in the mmap buffer with associated time stamp. */
|
||||
int pcm_mmap_get_hw_ptr(struct pcm* pcm, unsigned int *hw_ptr, struct timespec *tstamp)
|
||||
{
|
||||
int rc;
|
||||
|
||||
if (pcm == NULL || hw_ptr == NULL || tstamp == NULL)
|
||||
return oops(pcm, EINVAL, "pcm %p, hw_ptr %p, tstamp %p", pcm, hw_ptr, tstamp);
|
||||
|
||||
if (!pcm_is_ready(pcm))
|
||||
return oops(pcm, errno, "pcm_is_ready failed");
|
||||
|
||||
rc = pcm_sync_ptr(pcm, SNDRV_PCM_SYNC_PTR_HWSYNC);
|
||||
if (rc < 0)
|
||||
return oops(pcm, errno, "pcm_sync_ptr failed");
|
||||
|
||||
if (pcm->mmap_status == NULL)
|
||||
return oops(pcm, EINVAL, "pcm %p, mmap_status is NULL", pcm);
|
||||
|
||||
if ((pcm->mmap_status->state != PCM_STATE_RUNNING) &&
|
||||
(pcm->mmap_status->state != PCM_STATE_DRAINING))
|
||||
return oops(pcm, ENOSYS, "invalid stream state %d", pcm->mmap_status->state);
|
||||
|
||||
*tstamp = pcm->mmap_status->tstamp;
|
||||
if (tstamp->tv_sec == 0 && tstamp->tv_nsec == 0)
|
||||
return oops(pcm, errno, "invalid time stamp");
|
||||
|
||||
*hw_ptr = pcm->mmap_status->hw_ptr;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int pcm_rw_transfer(struct pcm *pcm, void *data, unsigned int frames)
|
||||
{
|
||||
int is_playback;
|
||||
|
||||
+12
-2
@@ -146,6 +146,16 @@ int main(int argc, char **argv)
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
static int isnumber(const char *str) {
|
||||
char *end;
|
||||
|
||||
if (str == NULL || strlen(str) == 0)
|
||||
return 0;
|
||||
|
||||
strtol(str, &end, 0);
|
||||
return strlen(end) == 0;
|
||||
}
|
||||
|
||||
static void tinymix_list_controls(struct mixer *mixer, int print_all)
|
||||
{
|
||||
struct mixer_ctl *ctl;
|
||||
@@ -201,7 +211,7 @@ static void tinymix_detail_control(struct mixer *mixer, const char *control)
|
||||
int ret;
|
||||
char *buf = NULL;
|
||||
|
||||
if (isdigit(control[0]))
|
||||
if (isnumber(control))
|
||||
ctl = mixer_get_ctl(mixer, atoi(control));
|
||||
else
|
||||
ctl = mixer_get_ctl_by_name(mixer, control);
|
||||
@@ -469,7 +479,7 @@ static int tinymix_set_value(struct mixer *mixer, const char *control,
|
||||
struct mixer_ctl *ctl;
|
||||
enum mixer_ctl_type type;
|
||||
|
||||
if (isdigit(control[0]))
|
||||
if (isnumber(control))
|
||||
ctl = mixer_get_ctl(mixer, atoi(control));
|
||||
else
|
||||
ctl = mixer_get_ctl_by_name(mixer, control);
|
||||
|
||||
+15
-9
@@ -59,6 +59,7 @@ void cmd_init(struct cmd *cmd)
|
||||
cmd->config.rate = 48000;
|
||||
cmd->config.format = PCM_FORMAT_S16_LE;
|
||||
cmd->config.silence_threshold = 1024 * 2;
|
||||
cmd->config.silence_size = 0;
|
||||
cmd->config.stop_threshold = 1024 * 2;
|
||||
cmd->config.start_threshold = 1024;
|
||||
cmd->bits = 16;
|
||||
@@ -375,8 +376,10 @@ int sample_is_playable(const struct cmd *cmd)
|
||||
can_play = check_param(params, PCM_PARAM_RATE, cmd->config.rate, "sample rate", "hz");
|
||||
can_play &= check_param(params, PCM_PARAM_CHANNELS, cmd->config.channels, "sample", " channels");
|
||||
can_play &= check_param(params, PCM_PARAM_SAMPLE_BITS, cmd->bits, "bits", " bits");
|
||||
can_play &= check_param(params, PCM_PARAM_PERIOD_SIZE, cmd->config.period_size, "period size", "");
|
||||
can_play &= check_param(params, PCM_PARAM_PERIODS, cmd->config.period_count, "period count", "");
|
||||
can_play &= check_param(params, PCM_PARAM_PERIOD_SIZE, cmd->config.period_size, "period size",
|
||||
" frames");
|
||||
can_play &= check_param(params, PCM_PARAM_PERIODS, cmd->config.period_count, "period count",
|
||||
" frames");
|
||||
|
||||
pcm_params_free(params);
|
||||
|
||||
@@ -386,13 +389,14 @@ int sample_is_playable(const struct cmd *cmd)
|
||||
int play_sample(struct ctx *ctx)
|
||||
{
|
||||
char *buffer;
|
||||
int size;
|
||||
int num_read;
|
||||
size_t buffer_size = pcm_frames_to_bytes(ctx->pcm, pcm_get_buffer_size(ctx->pcm));
|
||||
size_t num_read = 0;
|
||||
size_t remaining_data_size = ctx->chunk_header.sz;
|
||||
size_t read_size = 0;
|
||||
|
||||
size = pcm_frames_to_bytes(ctx->pcm, pcm_get_buffer_size(ctx->pcm));
|
||||
buffer = malloc(size);
|
||||
buffer = malloc(buffer_size);
|
||||
if (!buffer) {
|
||||
fprintf(stderr, "unable to allocate %d bytes\n", size);
|
||||
fprintf(stderr, "unable to allocate %zu bytes\n", buffer_size);
|
||||
return -1;
|
||||
}
|
||||
|
||||
@@ -400,15 +404,17 @@ int play_sample(struct ctx *ctx)
|
||||
signal(SIGINT, stream_close);
|
||||
|
||||
do {
|
||||
num_read = fread(buffer, 1, size, ctx->file);
|
||||
read_size = remaining_data_size > buffer_size ? buffer_size : remaining_data_size;
|
||||
num_read = fread(buffer, 1, read_size, ctx->file);
|
||||
if (num_read > 0) {
|
||||
if (pcm_writei(ctx->pcm, buffer,
|
||||
pcm_bytes_to_frames(ctx->pcm, num_read)) < 0) {
|
||||
fprintf(stderr, "error playing sample\n");
|
||||
break;
|
||||
}
|
||||
remaining_data_size -= num_read;
|
||||
}
|
||||
} while (!close && num_read > 0);
|
||||
} while (!close && num_read > 0 && remaining_data_size > 0);
|
||||
|
||||
pcm_wait(ctx->pcm, -1);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user