diff options
author | Simon Wilson <simonwilson@google.com> | 2012-11-09 15:16:47 -0800 |
---|---|---|
committer | Simon Wilson <simonwilson@google.com> | 2012-11-09 15:22:36 -0800 |
commit | da39e0b09eb0a1b559a96e2108160d1d8dccf314 (patch) | |
tree | 81e2afcb7d8abcbe0829366d5c46b9d7fdeb2300 | |
parent | ff2e54293f32b5bb5ff75b4cb25babb00f429ca4 (diff) | |
download | android_external_tinyalsa-da39e0b09eb0a1b559a96e2108160d1d8dccf314.tar.gz android_external_tinyalsa-da39e0b09eb0a1b559a96e2108160d1d8dccf314.tar.bz2 android_external_tinyalsa-da39e0b09eb0a1b559a96e2108160d1d8dccf314.zip |
Update to latest tinyalsa
2c3a8e2 Add -Wall to Makefile and fix warnings
4ef9a57 tinyplay: add clean shutdown handler for ctrl-c
9bb8066 Merge pull request #15 from quantumdream/master
bad2b79 tinymix: Add support for passing control name
f51c05b mixer: Add mixer_ctl_{set,get}_bytes()
fcf66ab Merge pull request #16 from PeterMalkin/master
3d62222 Add pcm_wait() to the tinyalsa API.
f9678dd tinyplay: Add missing header file <string.h>
cde1f6f Fix several 'symbol defined but not used' warnings.
2a274a1 pcm: Add support for S8 and S24LE formats.
a5baefd tinymix: support setting of multiple control values
Change-Id: I3d5fe076753ce7d1f74dd3ebedc59202d29f4efd
-rw-r--r-- | include/tinyalsa/asoundlib.h | 8 | ||||
-rw-r--r-- | mixer.c | 43 | ||||
-rw-r--r-- | pcm.c | 14 | ||||
-rw-r--r-- | tinycap.c | 2 | ||||
-rw-r--r-- | tinymix.c | 80 | ||||
-rw-r--r-- | tinyplay.c | 16 |
6 files changed, 123 insertions, 40 deletions
diff --git a/include/tinyalsa/asoundlib.h b/include/tinyalsa/asoundlib.h index a796a66..6148361 100644 --- a/include/tinyalsa/asoundlib.h +++ b/include/tinyalsa/asoundlib.h @@ -30,6 +30,7 @@ #define ASOUNDLIB_H #include <sys/time.h> +#include <stddef.h> #if defined(__cplusplus) extern "C" { @@ -70,6 +71,8 @@ struct pcm; enum pcm_format { PCM_FORMAT_S16_LE = 0, PCM_FORMAT_S32_LE, + PCM_FORMAT_S8, + PCM_FORMAT_S24_LE, PCM_FORMAT_MAX, }; @@ -163,6 +166,9 @@ int pcm_mmap_commit(struct pcm *pcm, unsigned int offset, unsigned int frames); int pcm_start(struct pcm *pcm); int pcm_stop(struct pcm *pcm); +/* Interrupt driven API */ +int pcm_wait(struct pcm *pcm, int timeout); + /* Change avail_min after the stream has been opened with no need to stop the stream. * Only accepted if opened with PCM_MMAP and PCM_NOIRQ flags */ @@ -198,7 +204,9 @@ int mixer_ctl_get_percent(struct mixer_ctl *ctl, unsigned int id); int mixer_ctl_set_percent(struct mixer_ctl *ctl, unsigned int id, int percent); int mixer_ctl_get_value(struct mixer_ctl *ctl, unsigned int id); +int mixer_ctl_get_bytes(struct mixer_ctl *ctl, void *data, size_t len); int mixer_ctl_set_value(struct mixer_ctl *ctl, unsigned int id, int value); +int mixer_ctl_set_bytes(struct mixer_ctl *ctl, const void *data, size_t len); int mixer_ctl_set_enum_by_string(struct mixer_ctl *ctl, const char *string); /* Determe range of integer mixer controls */ @@ -317,6 +317,27 @@ int mixer_ctl_get_value(struct mixer_ctl *ctl, unsigned int id) return 0; } +int mixer_ctl_get_bytes(struct mixer_ctl *ctl, void *data, size_t len) +{ + struct snd_ctl_elem_value ev; + int ret; + + if (!ctl || (len > ctl->info->count) || !len || !data || + (ctl->info->type != SNDRV_CTL_ELEM_TYPE_BYTES)) + return -EINVAL; + + memset(&ev, 0, sizeof(ev)); + ev.id.numid = ctl->info->id.numid; + + ret = ioctl(ctl->mixer->fd, SNDRV_CTL_IOCTL_ELEM_READ, &ev); + if (ret < 0) + return ret; + + memcpy(data, ev.value.bytes.data, len); + + return 0; +} + int mixer_ctl_set_value(struct mixer_ctl *ctl, unsigned int id, int value) { struct snd_ctl_elem_value ev; @@ -351,10 +372,24 @@ int mixer_ctl_set_value(struct mixer_ctl *ctl, unsigned int id, int value) return ioctl(ctl->mixer->fd, SNDRV_CTL_IOCTL_ELEM_WRITE, &ev); } -int mixer_ctl_get_range_min(struct mixer_ctl *ctl) +int mixer_ctl_set_bytes(struct mixer_ctl *ctl, const void *data, size_t len) { - int ret; + struct snd_ctl_elem_value ev; + if (!ctl || (len > ctl->info->count) || !len || !data || + (ctl->info->type != SNDRV_CTL_ELEM_TYPE_BYTES)) + return -EINVAL; + + memset(&ev, 0, sizeof(ev)); + ev.id.numid = ctl->info->id.numid; + + memcpy(ev.value.bytes.data, data, len); + + return ioctl(ctl->mixer->fd, SNDRV_CTL_IOCTL_ELEM_WRITE, &ev); +} + +int mixer_ctl_get_range_min(struct mixer_ctl *ctl) +{ if (!ctl || (ctl->info->type != SNDRV_CTL_ELEM_TYPE_INTEGER)) return -EINVAL; @@ -363,8 +398,6 @@ int mixer_ctl_get_range_min(struct mixer_ctl *ctl) int mixer_ctl_get_range_max(struct mixer_ctl *ctl) { - int ret; - if (!ctl || (ctl->info->type != SNDRV_CTL_ELEM_TYPE_INTEGER)) return -EINVAL; @@ -382,8 +415,6 @@ unsigned int mixer_ctl_get_num_enums(struct mixer_ctl *ctl) const char *mixer_ctl_get_enum_string(struct mixer_ctl *ctl, unsigned int enum_id) { - int ret; - if (!ctl || (ctl->info->type != SNDRV_CTL_ELEM_TYPE_ENUMERATED) || (enum_id >= ctl->info->value.enumerated.items)) return NULL; @@ -93,14 +93,6 @@ static void param_set_min(struct snd_pcm_hw_params *p, int n, unsigned int val) } } -static void param_set_max(struct snd_pcm_hw_params *p, int n, unsigned int val) -{ - if (param_is_interval(n)) { - struct snd_interval *i = param_to_interval(p, n); - i->max = val; - } -} - static void param_set_int(struct snd_pcm_hw_params *p, int n, unsigned int val) { if (param_is_interval(n)) { @@ -190,6 +182,10 @@ static unsigned int pcm_format_to_alsa(enum pcm_format format) switch (format) { case PCM_FORMAT_S32_LE: return SNDRV_PCM_FORMAT_S32_LE; + case PCM_FORMAT_S8: + return SNDRV_PCM_FORMAT_S8; + case PCM_FORMAT_S24_LE: + return SNDRV_PCM_FORMAT_S24_LE; default: case PCM_FORMAT_S16_LE: return SNDRV_PCM_FORMAT_S16_LE; @@ -741,7 +737,6 @@ int pcm_set_avail_min(struct pcm *pcm, int avail_min) int pcm_wait(struct pcm *pcm, int timeout) { struct pollfd pfd; - unsigned short revents = 0; int err; pfd.fd = pcm->fd; @@ -864,6 +859,5 @@ int pcm_mmap_write(struct pcm *pcm, const void *buffer, unsigned int bytes) count -= frames; } -_end: return 0; } @@ -31,6 +31,7 @@ #include <stdlib.h> #include <stdint.h> #include <signal.h> +#include <string.h> #define ID_RIFF 0x46464952 #define ID_WAVE 0x45564157 @@ -153,6 +154,7 @@ int main(int argc, char **argv) /* write header now all information is known */ header.data_sz = frames * header.block_align; + header.riff_sz = header.data_sz + sizeof(header) - 8; fseek(file, 0, SEEK_SET); fwrite(&header, sizeof(struct wav_header), 1, file); @@ -30,12 +30,13 @@ #include <stdio.h> #include <stdlib.h> #include <ctype.h> +#include <string.h> static void tinymix_list_controls(struct mixer *mixer); -static void tinymix_detail_control(struct mixer *mixer, unsigned int id, +static void tinymix_detail_control(struct mixer *mixer, const char *control, int print_all); -static void tinymix_set_value(struct mixer *mixer, unsigned int id, - char *value); +static void tinymix_set_value(struct mixer *mixer, const char *control, + char **values, unsigned int num_values); static void tinymix_print_enum(struct mixer_ctl *ctl, int print_all); int main(int argc, char **argv) @@ -63,9 +64,9 @@ int main(int argc, char **argv) if (argc == 1) tinymix_list_controls(mixer); else if (argc == 2) - tinymix_detail_control(mixer, atoi(argv[1]), 1); - else if (argc == 3) - tinymix_set_value(mixer, atoi(argv[1]), argv[2]); + tinymix_detail_control(mixer, argv[1], 1); + else if (argc >= 3) + tinymix_set_value(mixer, argv[1], &argv[2], argc - 2); else printf("Usage: tinymix [-D card] [control id] [value to set]\n"); @@ -93,7 +94,7 @@ static void tinymix_list_controls(struct mixer *mixer) type = mixer_ctl_get_type_string(ctl); num_values = mixer_ctl_get_num_values(ctl); printf("%d\t%s\t%d\t%-40s", i, type, num_values, name); - tinymix_detail_control(mixer, i, 0); + tinymix_detail_control(mixer, name, 0); } } @@ -115,7 +116,7 @@ static void tinymix_print_enum(struct mixer_ctl *ctl, int print_all) } } -static void tinymix_detail_control(struct mixer *mixer, unsigned int id, +static void tinymix_detail_control(struct mixer *mixer, const char *control, int print_all) { struct mixer_ctl *ctl; @@ -124,13 +125,16 @@ static void tinymix_detail_control(struct mixer *mixer, unsigned int id, unsigned int i; int min, max; - if (id >= mixer_get_num_ctls(mixer)) { + if (isdigit(control[0])) + ctl = mixer_get_ctl(mixer, atoi(control)); + else + ctl = mixer_get_ctl_by_name(mixer, control); + + if (!ctl) { fprintf(stderr, "Invalid mixer control\n"); return; } - ctl = mixer_get_ctl(mixer, id); - type = mixer_ctl_get_type(ctl); num_values = mixer_ctl_get_num_values(ctl); @@ -168,30 +172,60 @@ static void tinymix_detail_control(struct mixer *mixer, unsigned int id, printf("\n"); } -static void tinymix_set_value(struct mixer *mixer, unsigned int id, - char *string) +static void tinymix_set_value(struct mixer *mixer, const char *control, + char **values, unsigned int num_values) { struct mixer_ctl *ctl; enum mixer_ctl_type type; - unsigned int num_values; + unsigned int num_ctl_values; unsigned int i; - ctl = mixer_get_ctl(mixer, id); - type = mixer_ctl_get_type(ctl); - num_values = mixer_ctl_get_num_values(ctl); + if (isdigit(control[0])) + ctl = mixer_get_ctl(mixer, atoi(control)); + else + ctl = mixer_get_ctl_by_name(mixer, control); - if (isdigit(string[0])) { - int value = atoi(string); + if (!ctl) { + fprintf(stderr, "Invalid mixer control\n"); + return; + } - for (i = 0; i < num_values; i++) { - if (mixer_ctl_set_value(ctl, i, value)) { - fprintf(stderr, "Error: invalid value\n"); + type = mixer_ctl_get_type(ctl); + num_ctl_values = mixer_ctl_get_num_values(ctl); + + if (isdigit(values[0][0])) { + if (num_values == 1) { + /* Set all values the same */ + int value = atoi(values[0]); + + for (i = 0; i < num_ctl_values; i++) { + if (mixer_ctl_set_value(ctl, i, value)) { + fprintf(stderr, "Error: invalid value\n"); + return; + } + } + } else { + /* Set multiple values */ + if (num_values > num_ctl_values) { + fprintf(stderr, + "Error: %d values given, but control only takes %d\n", + num_values, num_ctl_values); return; } + for (i = 0; i < num_values; i++) { + if (mixer_ctl_set_value(ctl, i, atoi(values[i]))) { + fprintf(stderr, "Error: invalid value for index %d\n", i); + return; + } + } } } else { if (type == MIXER_CTL_TYPE_ENUM) { - if (mixer_ctl_set_enum_by_string(ctl, string)) + if (num_values != 1) { + fprintf(stderr, "Enclose strings in quotes and try again\n"); + return; + } + if (mixer_ctl_set_enum_by_string(ctl, values[0])) fprintf(stderr, "Error: invalid enum value\n"); } else { fprintf(stderr, "Error: only enum types can be set with strings\n"); @@ -30,6 +30,8 @@ #include <stdio.h> #include <stdlib.h> #include <stdint.h> +#include <string.h> +#include <signal.h> #define ID_RIFF 0x46464952 #define ID_WAVE 0x45564157 @@ -56,10 +58,19 @@ struct chunk_fmt { uint16_t bits_per_sample; }; +static int close = 0; + void play_sample(FILE *file, unsigned int card, unsigned int device, unsigned int channels, unsigned int rate, unsigned int bits, unsigned int period_size, unsigned int period_count); +void stream_close(int sig) +{ + /* allow the stream to be closed gracefully */ + signal(sig, SIG_IGN); + close = 1; +} + int main(int argc, char **argv) { FILE *file; @@ -189,6 +200,9 @@ void play_sample(FILE *file, unsigned int card, unsigned int device, unsigned in printf("Playing sample: %u ch, %u hz, %u bit\n", channels, rate, bits); + /* catch ctrl-c to shutdown cleanly */ + signal(SIGINT, stream_close); + do { num_read = fread(buffer, 1, size, file); if (num_read > 0) { @@ -197,7 +211,7 @@ void play_sample(FILE *file, unsigned int card, unsigned int device, unsigned in break; } } - } while (num_read > 0); + } while (!close && num_read > 0); free(buffer); pcm_close(pcm); |