diff options
author | David Li <dvdli@google.com> | 2023-09-18 20:32:11 +0000 |
---|---|---|
committer | Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com> | 2023-09-18 20:32:11 +0000 |
commit | 4937852134ba29131b4dcf53314c21d6cfaec30b (patch) | |
tree | ce094436772521d150e24b67d56d5cb9d01a27b2 | |
parent | e334bb0baf0dfabfb34d1ca990b6cc52cc369304 (diff) | |
parent | 80277c15735fb17f0684f08d505a064a52564f9e (diff) | |
download | tinyalsa_new-4937852134ba29131b4dcf53314c21d6cfaec30b.tar.gz |
Merge remote-tracking branch 'aosp/upstream-master' into audio am: 152d9ce1fd am: 88bf0f3e6e am: adb8f11a10 am: 9c4d4dbf6a am: 80277c1573
Original change: https://android-review.googlesource.com/c/platform/external/tinyalsa_new/+/2752232
Change-Id: I294c5bfe293879002f23b6d4f86b8aff7cdb3801
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
-rw-r--r-- | include/tinyalsa/mixer.h | 6 | ||||
-rw-r--r-- | include/tinyalsa/pcm.h | 2 | ||||
-rw-r--r-- | include/tinyalsa/plugin.h | 5 | ||||
-rw-r--r-- | src/mixer.c | 57 | ||||
-rw-r--r-- | src/pcm.c | 20 | ||||
-rw-r--r-- | src/pcm_plugin.c | 13 | ||||
-rw-r--r-- | utils/tinycap.1 | 5 | ||||
-rw-r--r-- | utils/tinycap.c | 26 | ||||
-rw-r--r-- | utils/tinymix.c | 9 | ||||
-rw-r--r-- | utils/tinyplay.c | 2 |
10 files changed, 130 insertions, 15 deletions
diff --git a/include/tinyalsa/mixer.h b/include/tinyalsa/mixer.h index 7d0580f..149b395 100644 --- a/include/tinyalsa/mixer.h +++ b/include/tinyalsa/mixer.h @@ -103,6 +103,10 @@ struct mixer_ctl *mixer_get_ctl(struct mixer *mixer, unsigned int id); struct mixer_ctl *mixer_get_ctl_by_name(struct mixer *mixer, const char *name); +struct mixer_ctl *mixer_get_ctl_by_name_and_device(struct mixer *mixer, + const char *name, + unsigned int device); + struct mixer_ctl *mixer_get_ctl_by_name_and_index(struct mixer *mixer, const char *name, unsigned int index); @@ -153,6 +157,8 @@ int mixer_ctl_get_range_min(const struct mixer_ctl *ctl); int mixer_ctl_get_range_max(const struct mixer_ctl *ctl); +unsigned int mixer_ctl_get_device(const struct mixer_ctl *ctl); + int mixer_read_event(struct mixer *mixer, struct mixer_ctl_event *event); int mixer_consume_event(struct mixer *mixer); diff --git a/include/tinyalsa/pcm.h b/include/tinyalsa/pcm.h index 9fca92d..35318a5 100644 --- a/include/tinyalsa/pcm.h +++ b/include/tinyalsa/pcm.h @@ -361,6 +361,8 @@ int pcm_prepare(struct pcm *pcm); int pcm_start(struct pcm *pcm); +int pcm_drain(struct pcm *pcm); + int pcm_stop(struct pcm *pcm); int pcm_wait(struct pcm *pcm, int timeout); diff --git a/include/tinyalsa/plugin.h b/include/tinyalsa/plugin.h index b2f97b9..055734c 100644 --- a/include/tinyalsa/plugin.h +++ b/include/tinyalsa/plugin.h @@ -124,7 +124,10 @@ struct pcm_plugin_ops { int (*prepare) (struct pcm_plugin *plugin); /** Start data transfer from/to the plugin */ int (*start) (struct pcm_plugin *plugin); - /** Drop pcm frames */ + /** Signal the plugin to drain PCM */ + int (*drain) (struct pcm_plugin *plugin); + /** Stop a PCM dropping pending frames if drain() is NOT called. + * Stop a PCM preserving pending frames if drain() is called. */ int (*drop) (struct pcm_plugin *plugin); /** Any custom or alsa specific ioctl implementation */ int (*ioctl) (struct pcm_plugin *plugin, diff --git a/src/mixer.c b/src/mixer.c index 029fc84..f2c21c3 100644 --- a/src/mixer.c +++ b/src/mixer.c @@ -760,6 +760,55 @@ struct mixer_ctl *mixer_get_ctl_by_name_and_index(struct mixer *mixer, return NULL; } +/** Gets an instance of mixer control handle, by the mixer control's name and device. + * For instance, if two controls have same name, + * e.g. 'Playback Channel map', then PCM device returns the specific control. + * @param mixer An initialized mixer handle. + * @param name The control's name in the given mixer. + * @param device The PCM device + * @returns A handle to the mixer control. + * @ingroup libtinyalsa-mixer + */ +struct mixer_ctl *mixer_get_ctl_by_name_and_device(struct mixer *mixer, + const char *name, + unsigned int device) +{ + struct mixer_ctl_group *grp; + unsigned int n; + struct mixer_ctl *ctl; + + if (!mixer || !name) { + return NULL; + } + + if (mixer->h_grp) { + grp = mixer->h_grp; + ctl = grp->ctl; + + for (n = 0; n < grp->count; n++) { + if (!strcmp(name, (char*) ctl[n].info.id.name) && + device == ctl[n].info.id.device) { + return ctl + n; + } + } + } + +#ifdef TINYALSA_USES_PLUGINS + if (mixer->v_grp) { + grp = mixer->v_grp; + ctl = grp->ctl; + + for (n = 0; n < grp->count; n++) { + if (!strcmp(name, (char*) ctl[n].info.id.name) && + device == ctl[n].info.id.device) { + return ctl + n; + } + } + } +#endif + return NULL; +} + /** Updates the control's info. * This is useful for a program that may be idle for a period of time. * @param ctl An initialized control handle. @@ -822,6 +871,14 @@ const char *mixer_ctl_get_name(const struct mixer_ctl *ctl) return (const char *)ctl->info.id.name; } +unsigned int mixer_ctl_get_device(const struct mixer_ctl *ctl) +{ + if (!ctl) + return UINT_MAX; + + return ctl->info.id.device; +} + /** Gets the value type of the control. * @param ctl An initialized control handle * @returns On success, the type of mixer control. @@ -1092,8 +1092,10 @@ struct pcm *pcm_open(unsigned int card, unsigned int device, } pcm->subdevice = info.subdevice; - if (pcm_set_config(pcm, config) != 0) + if (pcm_set_config(pcm, config) != 0) { + memcpy(bad_pcm.error, pcm->error, sizeof(pcm->error)); goto fail_close; + } rc = pcm_hw_mmap_status(pcm); if (rc < 0) { @@ -1216,6 +1218,22 @@ int pcm_start(struct pcm *pcm) return 0; } +/** Drains a PCM. + * @param pcm A PCM handle. + * @return On success, zero; on failure, a negative number. + * @ingroup libtinyalsa-pcm + */ +int pcm_drain(struct pcm *pcm) +{ + if (!pcm_is_ready(pcm)) + return -1; + + if (pcm->ops->ioctl(pcm->data, SNDRV_PCM_IOCTL_DRAIN) < 0) + return oops(pcm, errno, "cannot drain channel"); + + return 0; +} + /** Stops a PCM. * @param pcm A PCM handle. * @return On success, zero; on failure, a negative number. diff --git a/src/pcm_plugin.c b/src/pcm_plugin.c index b6b69aa..4d2651c 100644 --- a/src/pcm_plugin.c +++ b/src/pcm_plugin.c @@ -622,6 +622,16 @@ static int pcm_plug_drop(struct pcm_plug_data *plug_data) return rc; } +static int pcm_plug_drain(struct pcm_plug_data *plug_data) +{ + struct pcm_plugin *plugin = plug_data->plugin; + + if (plugin->state != PCM_PLUG_STATE_RUNNING) + return -EBADFD; + + return plug_data->ops->drain(plugin); +} + static int pcm_plug_ioctl(void *data, unsigned int cmd, ...) { struct pcm_plug_data *plug_data = data; @@ -659,6 +669,9 @@ static int pcm_plug_ioctl(void *data, unsigned int cmd, ...) case SNDRV_PCM_IOCTL_START: ret = pcm_plug_start(plug_data); break; + case SNDRV_PCM_IOCTL_DRAIN: + ret = pcm_plug_drain(plug_data); + break; case SNDRV_PCM_IOCTL_DROP: ret = pcm_plug_drop(plug_data); break; diff --git a/utils/tinycap.1 b/utils/tinycap.1 index ad60a2e..d18dd12 100644 --- a/utils/tinycap.1 +++ b/utils/tinycap.1 @@ -24,6 +24,11 @@ Device number of the PCM. The default is 0. .TP +\fB\-M\fR +Use memory-mapped I/O method. +If this option is not specified, then read and write I/O method will be used. + +.TP \fB\-c\fR \fIchannels\fR Number of channels the PCM will have. The default is 2. diff --git a/utils/tinycap.c b/utils/tinycap.c index 7d4b8a4..617d16a 100644 --- a/utils/tinycap.c +++ b/utils/tinycap.c @@ -30,6 +30,7 @@ #include <stdio.h> #include <stdlib.h> #include <stdint.h> +#include <stdbool.h> #include <signal.h> #include <string.h> #include <limits.h> @@ -64,7 +65,7 @@ int capturing = 1; int prinfo = 1; unsigned int capture_sample(FILE *file, unsigned int card, unsigned int device, - unsigned int channels, unsigned int rate, + bool use_mmap, unsigned int channels, unsigned int rate, enum pcm_format format, unsigned int period_size, unsigned int period_count, unsigned int capture_time); @@ -88,12 +89,13 @@ int main(int argc, char **argv) unsigned int period_size = 1024; unsigned int period_count = 4; unsigned int capture_time = UINT_MAX; + bool use_mmap = false; enum pcm_format format; int no_header = 0, c; struct optparse opts; if (argc < 2) { - fprintf(stderr, "Usage: %s {file.wav | --} [-D card] [-d device] [-c channels] " + fprintf(stderr, "Usage: %s {file.wav | --} [-D card] [-d device] [-M] [-c channels] " "[-r rate] [-b bits] [-p period_size] [-n n_periods] [-t time_in_seconds]\n\n" "Use -- for filename to send raw PCM to stdout\n", argv[0]); return 1; @@ -113,7 +115,7 @@ int main(int argc, char **argv) /* parse command line arguments */ optparse_init(&opts, argv + 1); - while ((c = optparse(&opts, "D:d:c:r:b:p:n:t:")) != -1) { + while ((c = optparse(&opts, "D:d:c:r:b:p:n:t:M")) != -1) { switch (c) { case 'd': device = atoi(opts.optarg); @@ -139,6 +141,9 @@ int main(int argc, char **argv) case 't': capture_time = atoi(opts.optarg); break; + case 'M': + use_mmap = true; + break; case '?': fprintf(stderr, "%s\n", opts.errmsg); return EXIT_FAILURE; @@ -182,9 +187,9 @@ int main(int argc, char **argv) /* install signal handler and begin capturing */ signal(SIGINT, sigint_handler); - frames = capture_sample(file, card, device, header.num_channels, - header.sample_rate, format, - period_size, period_count, capture_time); + frames = capture_sample(file, card, device, use_mmap, + header.num_channels, header.sample_rate, + format, period_size, period_count, capture_time); if (prinfo) { printf("Captured %u frames\n", frames); } @@ -203,11 +208,12 @@ int main(int argc, char **argv) } unsigned int capture_sample(FILE *file, unsigned int card, unsigned int device, - unsigned int channels, unsigned int rate, + bool use_mmap, unsigned int channels, unsigned int rate, enum pcm_format format, unsigned int period_size, unsigned int period_count, unsigned int capture_time) { struct pcm_config config; + unsigned int pcm_open_flags; struct pcm *pcm; char *buffer; unsigned int size; @@ -225,7 +231,11 @@ unsigned int capture_sample(FILE *file, unsigned int card, unsigned int device, config.stop_threshold = 0; config.silence_threshold = 0; - pcm = pcm_open(card, device, PCM_IN, &config); + pcm_open_flags = PCM_IN; + if (use_mmap) + pcm_open_flags |= PCM_MMAP; + + pcm = pcm_open(card, device, pcm_open_flags, &config); if (!pcm || !pcm_is_ready(pcm)) { fprintf(stderr, "Unable to open PCM device (%s)\n", pcm_get_error(pcm)); diff --git a/utils/tinymix.c b/utils/tinymix.c index e272ade..edeb6ad 100644 --- a/utils/tinymix.c +++ b/utils/tinymix.c @@ -201,7 +201,7 @@ static void list_controls(struct mixer *mixer, int print_all) { struct mixer_ctl *ctl; const char *name, *type; - unsigned int num_ctls, num_values; + unsigned int num_ctls, num_values, device; unsigned int i; num_ctls = mixer_get_num_ctls(mixer); @@ -209,9 +209,9 @@ static void list_controls(struct mixer *mixer, int print_all) printf("Number of controls: %u\n", num_ctls); if (print_all) - printf("ctl\ttype\tnum\t%-40svalue\n", "name"); + printf("ctl\ttype\tnum\t%-40s\tdevice\tvalue\n", "name"); else - printf("ctl\ttype\tnum\t%-40s\n", "name"); + printf("ctl\ttype\tnum\t%-40s\tdevice\n", "name"); for (i = 0; i < num_ctls; i++) { ctl = mixer_get_ctl(mixer, i); @@ -219,7 +219,8 @@ static void list_controls(struct mixer *mixer, int print_all) name = mixer_ctl_get_name(ctl); type = mixer_ctl_get_type_string(ctl); num_values = mixer_ctl_get_num_values(ctl); - printf("%u\t%s\t%u\t%-40s", i, type, num_values, name); + device = mixer_ctl_get_device(ctl); + printf("%u\t%s\t%u\t%-40s\t%u", i, type, num_values, name, device); if (print_all) print_control_values(ctl); printf("\n"); diff --git a/utils/tinyplay.c b/utils/tinyplay.c index 9f72bbb..d617074 100644 --- a/utils/tinyplay.c +++ b/utils/tinyplay.c @@ -112,7 +112,7 @@ static bool is_wave_file(const char *filetype) return filetype != NULL && strcmp(filetype, "wav") == 0; } -static bool signed_pcm_bits_to_format(int bits) +static enum pcm_format signed_pcm_bits_to_format(int bits) { switch (bits) { case 8: |