diff --git a/alsa-git.patch b/alsa-git.patch index 8b13789..ddfa20e 100644 --- a/alsa-git.patch +++ b/alsa-git.patch @@ -1 +1,3553 @@ +From 5e6df5ae4ba587ba324dd97b7bd8af9f8159f59a Mon Sep 17 00:00:00 2001 +From: Rosen Penev +Date: Tue, 19 Nov 2019 20:28:53 -0800 +Subject: [PATCH 01/31] treewide: sys/poll to poll + +Fixes warning on musl: + +warning redirecting incorrect #include to + +Signed-off-by: Rosen Penev +Signed-off-by: Takashi Iwai +--- + amidi/amidi.c | 2 +- + amixer/amixer.c | 2 +- + aplay/aplay.c | 2 +- + seq/aplaymidi/arecordmidi.c | 2 +- + seq/aseqdump/aseqdump.c | 2 +- + 5 files changed, 5 insertions(+), 5 deletions(-) + +diff --git a/amidi/amidi.c b/amidi/amidi.c +index b6e05e1..c6268e4 100644 +--- a/amidi/amidi.c ++++ b/amidi/amidi.c +@@ -31,7 +31,7 @@ + #include + #include + #include +-#include ++#include + #include + #include + #include +diff --git a/amixer/amixer.c b/amixer/amixer.c +index ad9c482..f7f31f0 100644 +--- a/amixer/amixer.c ++++ b/amixer/amixer.c +@@ -28,7 +28,7 @@ + #include + #include + #include +-#include ++#include + #include + #include "amixer.h" + #include "../alsamixer/volume_mapping.h" +diff --git a/aplay/aplay.c b/aplay/aplay.c +index 274bbce..5241068 100644 +--- a/aplay/aplay.c ++++ b/aplay/aplay.c +@@ -44,7 +44,7 @@ + #include + #include + #include +-#include ++#include + #include + #include + #include +diff --git a/seq/aplaymidi/arecordmidi.c b/seq/aplaymidi/arecordmidi.c +index f3db65e..604cd0d 100644 +--- a/seq/aplaymidi/arecordmidi.c ++++ b/seq/aplaymidi/arecordmidi.c +@@ -27,7 +27,7 @@ + #include + #include + #include +-#include ++#include + #include + #include "aconfig.h" + #include "version.h" +diff --git a/seq/aseqdump/aseqdump.c b/seq/aseqdump/aseqdump.c +index 7904540..578e06f 100644 +--- a/seq/aseqdump/aseqdump.c ++++ b/seq/aseqdump/aseqdump.c +@@ -25,7 +25,7 @@ + #include + #include + #include +-#include ++#include + #include + #include "aconfig.h" + #include "version.h" +-- +2.24.1 + + +From 66e9a816093c7d8fbdfbc407062daabe89825b35 Mon Sep 17 00:00:00 2001 +From: Rosen Penev +Date: Tue, 19 Nov 2019 20:28:54 -0800 +Subject: [PATCH 02/31] treewide: Fix wrong formats on 32-bit + +uint64_t evaluates to unsigned long long on 32-bit, not unsigned long. +Use the proper formats. + +Signed-off-by: Rosen Penev +Signed-off-by: Takashi Iwai +--- + axfer/container.c | 7 ++++--- + axfer/subcmd-transfer.c | 4 +++- + 2 files changed, 7 insertions(+), 4 deletions(-) + +diff --git a/axfer/container.c b/axfer/container.c +index 7da97c6..566acd0 100644 +--- a/axfer/container.c ++++ b/axfer/container.c +@@ -13,6 +13,7 @@ + #include + #include + #include ++#include + + static const char *const cntr_type_labels[] = { + [CONTAINER_TYPE_PARSER] = "parser", +@@ -356,10 +357,10 @@ int container_context_pre_process(struct container_context *cntr, + fprintf(stderr, " frames/second: %u\n", + cntr->frames_per_second); + if (cntr->type == CONTAINER_TYPE_PARSER) { +- fprintf(stderr, " frames: %lu\n", ++ fprintf(stderr, " frames: %" PRIu64 "\n", + *frame_count); + } else { +- fprintf(stderr, " max frames: %lu\n", ++ fprintf(stderr, " max frames: %" PRIu64 "\n", + *frame_count); + } + } +@@ -427,7 +428,7 @@ int container_context_post_process(struct container_context *cntr, + assert(frame_count); + + if (cntr->verbose && cntr->handled_byte_count > 0) { +- fprintf(stderr, " Handled bytes: %lu\n", ++ fprintf(stderr, " Handled bytes: %" PRIu64 "\n", + cntr->handled_byte_count); + } + +diff --git a/axfer/subcmd-transfer.c b/axfer/subcmd-transfer.c +index 3ca745a..8746e6f 100644 +--- a/axfer/subcmd-transfer.c ++++ b/axfer/subcmd-transfer.c +@@ -11,6 +11,7 @@ + #include "misc.h" + + #include ++#include + + struct context { + struct xfer_context xfer; +@@ -389,7 +390,8 @@ static int context_process_frames(struct context *ctx, + + if (!ctx->xfer.quiet) { + fprintf(stderr, +- "%s: Expected %lu frames, Actual %lu frames\n", ++ "%s: Expected %" PRIu64 "frames, " ++ "Actual %" PRIu64 "frames\n", + snd_pcm_stream_name(direction), expected_frame_count, + *actual_frame_count); + if (ctx->interrupted) { +-- +2.24.1 + + +From 80fd81f4a8647fe2b62a02db9a497d2a7639d9e3 Mon Sep 17 00:00:00 2001 +From: Rosen Penev +Date: Tue, 19 Nov 2019 20:28:55 -0800 +Subject: [PATCH 03/31] treewide: Fix printf formats + +Found with cppcheck + +Signed-off-by: Rosen Penev +Signed-off-by: Takashi Iwai +--- + alsactl/init_parse.c | 4 ++-- + alsaloop/pcmjob.c | 10 +++++----- + amixer/amixer.c | 6 +++--- + aplay/aplay.c | 2 +- + axfer/subcmd-list.c | 2 +- + axfer/xfer-libffado.c | 2 +- + axfer/xfer-options.c | 2 +- + 7 files changed, 14 insertions(+), 14 deletions(-) + +diff --git a/alsactl/init_parse.c b/alsactl/init_parse.c +index 562e674..c048fd3 100644 +--- a/alsactl/init_parse.c ++++ b/alsactl/init_parse.c +@@ -187,7 +187,7 @@ static int init_space(struct space **space, int card) + return -ENOMEM; + res->ctl_id_changed = ~0; + res->linenum = -1; +- sprintf(device, "hw:%u", card); ++ sprintf(device, "hw:%d", card); + err = snd_hctl_open(&res->ctl_handle, device, 0); + if (err < 0) + goto error; +@@ -734,7 +734,7 @@ dbvalue: + elem = snd_hctl_elem_next(elem); + } + snd_ctl_elem_id_free(id); +- sprintf(res, "%u", index); ++ sprintf(res, "%d", index); + dbg("do_ctl_count found %s controls", res); + return res; + } +diff --git a/alsaloop/pcmjob.c b/alsaloop/pcmjob.c +index 29d1aba..b252486 100644 +--- a/alsaloop/pcmjob.c ++++ b/alsaloop/pcmjob.c +@@ -120,7 +120,7 @@ static int setparams_stream(struct loopback_handle *lhandle, + } + err = snd_pcm_hw_params_set_rate_resample(handle, params, lhandle->resample); + if (err < 0) { +- logit(LOG_CRIT, "Resample setup failed for %s (val %i): %s\n", lhandle->id, lhandle->resample, snd_strerror(err)); ++ logit(LOG_CRIT, "Resample setup failed for %s (val %u): %s\n", lhandle->id, lhandle->resample, snd_strerror(err)); + return err; + } + err = snd_pcm_hw_params_set_access(handle, params, lhandle->access); +@@ -135,13 +135,13 @@ static int setparams_stream(struct loopback_handle *lhandle, + } + err = snd_pcm_hw_params_set_channels(handle, params, lhandle->channels); + if (err < 0) { +- logit(LOG_CRIT, "Channels count (%i) not available for %s: %s\n", lhandle->channels, lhandle->id, snd_strerror(err)); ++ logit(LOG_CRIT, "Channels count (%u) not available for %s: %s\n", lhandle->channels, lhandle->id, snd_strerror(err)); + return err; + } + rrate = lhandle->rate_req; + err = snd_pcm_hw_params_set_rate_near(handle, params, &rrate, 0); + if (err < 0) { +- logit(LOG_CRIT, "Rate %iHz not available for %s: %s\n", lhandle->rate_req, lhandle->id, snd_strerror(err)); ++ logit(LOG_CRIT, "Rate %uHz not available for %s: %s\n", lhandle->rate_req, lhandle->id, snd_strerror(err)); + return err; + } + rrate = 0; +@@ -152,7 +152,7 @@ static int setparams_stream(struct loopback_handle *lhandle, + !lhandle->loopback->src_enable && + #endif + (int)rrate != lhandle->rate) { +- logit(LOG_CRIT, "Rate does not match (requested %iHz, got %iHz, resample %i)\n", lhandle->rate, rrate, lhandle->resample); ++ logit(LOG_CRIT, "Rate does not match (requested %uHz, got %uHz, resample %u)\n", lhandle->rate, rrate, lhandle->resample); + return -EINVAL; + } + lhandle->pitch = (double)lhandle->rate_req / (double)lhandle->rate; +@@ -1613,7 +1613,7 @@ __again: + if (count > loop->play->buffer_size) + count = loop->play->buffer_size; + if (err != count) { +- logit(LOG_CRIT, "%s: initial playback fill error (%i/%i/%i)\n", loop->id, err, (int)count, loop->play->buffer_size); ++ logit(LOG_CRIT, "%s: initial playback fill error (%i/%i/%u)\n", loop->id, err, (int)count, loop->play->buffer_size); + err = -EIO; + goto __error; + } +diff --git a/amixer/amixer.c b/amixer/amixer.c +index f7f31f0..928f7c5 100644 +--- a/amixer/amixer.c ++++ b/amixer/amixer.c +@@ -465,7 +465,7 @@ static void decode_tlv(unsigned int spaces, unsigned int *tlv, unsigned int tlv_ + size = tlv[idx++]; + tlv_size -= 2 * sizeof(unsigned int); + if (size > tlv_size) { +- printf("TLV size error (%i, %i, %i)!\n", type, size, tlv_size); ++ printf("TLV size error (%u, %u, %u)!\n", type, size, tlv_size); + return; + } + switch (type) { +@@ -576,7 +576,7 @@ static void decode_tlv(unsigned int spaces, unsigned int *tlv, unsigned int tlv_ + break; + #endif + default: +- printf("unk-%i-", type); ++ printf("unk-%u-", type); + while (size > 0) { + printf("0x%08x,", tlv[idx++]); + size -= sizeof(unsigned int); +@@ -611,7 +611,7 @@ static int show_control(const char *space, snd_hctl_elem_t *elem, + } + count = snd_ctl_elem_info_get_count(info); + type = snd_ctl_elem_info_get_type(info); +- printf("%s; type=%s,access=%s,values=%i", space, control_type(info), control_access(info), count); ++ printf("%s; type=%s,access=%s,values=%u", space, control_type(info), control_access(info), count); + switch (type) { + case SND_CTL_ELEM_TYPE_INTEGER: + printf(",min=%li,max=%li,step=%li\n", +diff --git a/aplay/aplay.c b/aplay/aplay.c +index 5241068..72fa567 100644 +--- a/aplay/aplay.c ++++ b/aplay/aplay.c +@@ -3346,7 +3346,7 @@ static void playbackv(char **names, unsigned int count) + } + alloced = 1; + } else if (count != channels) { +- error(_("You need to specify %d files"), channels); ++ error(_("You need to specify %u files"), channels); + prg_exit(EXIT_FAILURE); + } + +diff --git a/axfer/subcmd-list.c b/axfer/subcmd-list.c +index e22628c..359f73f 100644 +--- a/axfer/subcmd-list.c ++++ b/axfer/subcmd-list.c +@@ -31,7 +31,7 @@ static int dump_device(snd_ctl_t *handle, const char *id, const char *name, + snd_pcm_info_get_name(info)); + + count = snd_pcm_info_get_subdevices_count(info); +- printf(" Subdevices: %i/%i\n", ++ printf(" Subdevices: %i/%u\n", + snd_pcm_info_get_subdevices_avail(info), count); + + for (i = 0; i < count; ++i) { +diff --git a/axfer/xfer-libffado.c b/axfer/xfer-libffado.c +index a37cce6..6db835d 100644 +--- a/axfer/xfer-libffado.c ++++ b/axfer/xfer-libffado.c +@@ -440,7 +440,7 @@ static int xfer_libffado_pre_process(struct xfer_context *xfer, + } + if (*samples_per_frame != channels) { + fprintf(stderr, +- "The number of samples per frame should be %i.\n", ++ "The number of samples per frame should be %u.\n", + channels); + return -EINVAL; + } +diff --git a/axfer/xfer-options.c b/axfer/xfer-options.c +index 352d126..3740b16 100644 +--- a/axfer/xfer-options.c ++++ b/axfer/xfer-options.c +@@ -238,7 +238,7 @@ static int validate_options(struct xfer_context *xfer) + xfer->frames_per_second *= 1000; + if (xfer->frames_per_second < 2000 || + xfer->frames_per_second > 192000) { +- fprintf(stderr, "bad speed value '%i'\n", val); ++ fprintf(stderr, "bad speed value '%u'\n", val); + return -EINVAL; + } + +-- +2.24.1 + + +From ac82b651676303e0689b1c23ad72aaf7b264ce5f Mon Sep 17 00:00:00 2001 +From: Rosen Penev +Date: Wed, 20 Nov 2019 10:19:20 -0800 +Subject: [PATCH 04/31] aplay: Adjust buffer sizes to fix snprintf warnings + +It also reduces compiled size slightly. + +aplay.c: In function 'capture': +aplay.c:3055:34: error: '-01' directive output may be truncated writing 3 +bytes into a region of size between 1 and 4097 [-Werror=format-truncation= +] + 3055 | snprintf(namebuf, namelen, "%s-01", buf); + | ^~~ +aplay.c:3055:4: note: 'snprintf' output between 4 and 4100 bytes into a +destination of size 4097 + 3055 | snprintf(namebuf, namelen, "%s-01", buf); + | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +aplay.c:3053:34: error: '-01.' directive output may be truncated writing 4 +bytes into a region of size between 1 and 4097 [-Werror=format-truncation= +] + 3053 | snprintf(namebuf, namelen, "%s-01.%s", buf, s); + | ^~~~ +aplay.c:3053:4: note: 'snprintf' output 5 or more bytes (assuming 4101) +into a destination of size 4097 + 3053 | snprintf(namebuf, namelen, "%s-01.%s", buf, s); + | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +aplay.c:3065:34: error: '%02i' directive output may be truncated writing +between 2 and 10 bytes into a region of size between 0 and 4096 [-Werror= +format-truncation=] + 3065 | snprintf(namebuf, namelen, "%s-%02i", buf, filecount); + | ^~~~ +aplay.c:3065:30: note: directive argument in the range [1, 2147483647] + 3065 | snprintf(namebuf, namelen, "%s-%02i", buf, filecount); + | ^~~~~~~~~ +aplay.c:3065:3: note: 'snprintf' output between 4 and 4108 bytes into a +destination of size 4097 + 3065 | snprintf(namebuf, namelen, "%s-%02i", buf, filecount); + | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +aplay.c:3063:34: error: '%02i' directive output may be truncated writing +between 2 and 10 bytes into a region of size between 0 and 4096 [-Werror= +format-truncation=] + 3063 | snprintf(namebuf, namelen, "%s-%02i.%s", buf, filecount, s); + | ^~~~ +aplay.c:3063:30: note: directive argument in the range [1, 2147483647] + 3063 | snprintf(namebuf, namelen, "%s-%02i.%s", buf, filecount, s); + | ^~~~~~~~~~~~ +aplay.c:3063:3: note: 'snprintf' output 5 or more bytes (assuming 4109) +into a destination of size 4097 + 3063 | snprintf(namebuf, namelen, "%s-%02i.%s", buf, filecount, s); + +Signed-off-by: Rosen Penev +Signed-off-by: Takashi Iwai +--- + aplay/aplay.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/aplay/aplay.c b/aplay/aplay.c +index 72fa567..78adee2 100644 +--- a/aplay/aplay.c ++++ b/aplay/aplay.c +@@ -3015,7 +3015,7 @@ static int new_capture_file(char *name, char *namebuf, size_t namelen, + int filecount) + { + char *s; +- char buf[PATH_MAX+1]; ++ char buf[PATH_MAX-10]; + time_t t; + struct tm *tmp; + +@@ -3122,7 +3122,7 @@ static void capture(char *orig_name) + int tostdout=0; /* boolean which describes output stream */ + int filecount=0; /* number of files written */ + char *name = orig_name; /* current filename */ +- char namebuf[PATH_MAX+1]; ++ char namebuf[PATH_MAX+2]; + off64_t count, rest; /* number of bytes to capture */ + struct stat statbuf; + +-- +2.24.1 + + +From c9dc401264ad3c0b621f52e8098e7c1661c50cea Mon Sep 17 00:00:00 2001 +From: Rosen Penev +Date: Wed, 20 Nov 2019 11:13:55 -0800 +Subject: [PATCH 05/31] aplay: Limit VUMeter progress bar to 100 for negative + as well + +While the progress bar cannot be negative, GCC concludes that it can be +and assumes tmp can be written past the end. Fixes this GCC warning: + +aplay.c:1747:18: warning: '%02d' directive writing between 2 and 11 bytes + into a region of size 4 [-Wformat-overflow=] + 1747 | sprintf(tmp, "%02d%%", maxperc[c]); + +Signed-off-by: Rosen Penev +Signed-off-by: Takashi Iwai +--- + aplay/aplay.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/aplay/aplay.c b/aplay/aplay.c +index 78adee2..1a887e4 100644 +--- a/aplay/aplay.c ++++ b/aplay/aplay.c +@@ -54,6 +54,8 @@ + #include "formats.h" + #include "version.h" + ++#define ABS(a) (a) < 0 ? -(a) : (a) ++ + #ifdef SND_CHMAP_API_VERSION + #define CONFIG_SUPPORT_CHMAP 1 + #endif +@@ -1741,7 +1743,7 @@ static void print_vu_meter_stereo(int *perc, int *maxperc) + line[bar_length + 6 + 1 + p] = '+'; + else + line[bar_length - p - 1] = '+'; +- if (maxperc[c] > 99) ++ if (ABS(maxperc[c]) > 99) + sprintf(tmp, "MAX"); + else + sprintf(tmp, "%02d%%", maxperc[c]); +-- +2.24.1 + + +From 3c740d90490abe64c86c667934ba5d990817b873 Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Wed, 20 Nov 2019 13:20:39 +0100 +Subject: [PATCH 06/31] alsactl: sysfs - add /sys/kernel/uevent_seqnum check to + init + +Signed-off-by: Jaroslav Kysela +--- + alsactl/init_sysfs.c | 13 +++++++++---- + 1 file changed, 9 insertions(+), 4 deletions(-) + +diff --git a/alsactl/init_sysfs.c b/alsactl/init_sysfs.c +index 5c789b6..57ef615 100644 +--- a/alsactl/init_sysfs.c ++++ b/alsactl/init_sysfs.c +@@ -34,6 +34,8 @@ static int sysfs_init(void) + const char *env; + char sysfs_test[PATH_SIZE]; + ++ INIT_LIST_HEAD(&attr_list); ++ + env = getenv("SYSFS_PATH"); + if (env) { + strlcpy(sysfs_path, env, sizeof(sysfs_path)); +@@ -43,13 +45,16 @@ static int sysfs_init(void) + dbg("sysfs_path='%s'", sysfs_path); + + strlcpy(sysfs_test, sysfs_path, sizeof(sysfs_test)); +- strlcat(sysfs_test, "/kernel/uevent_helper", sizeof(sysfs_test)); ++ strlcat(sysfs_test, "/kernel/uevent_seqnum", sizeof(sysfs_test)); + if (access(sysfs_test, F_OK)) { +- error("sysfs path '%s' is invalid\n", sysfs_path); +- return -errno; ++ strlcpy(sysfs_test, sysfs_path, sizeof(sysfs_test)); ++ strlcat(sysfs_test, "/kernel/uevent_helper", sizeof(sysfs_test)); ++ if (access(sysfs_test, F_OK)) { ++ error("sysfs path '%s' is invalid", sysfs_path); ++ return -errno; ++ } + } + +- INIT_LIST_HEAD(&attr_list); + return 0; + } + +-- +2.24.1 + + +From 745c5df26066de94622dd38c667da31ac6b88510 Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Mon, 25 Nov 2019 17:58:51 +0100 +Subject: [PATCH 07/31] alsaucm: use the first sound card (use case name + 'hw:CARDNO') as default + +Signed-off-by: Jaroslav Kysela +--- + alsaucm/go.sh | 5 ++++- + alsaucm/usecase.c | 17 +++++++---------- + 2 files changed, 11 insertions(+), 11 deletions(-) + +diff --git a/alsaucm/usecase.c b/alsaucm/usecase.c +index 7677422..8b1c8c7 100644 +--- a/alsaucm/usecase.c ++++ b/alsaucm/usecase.c +@@ -188,22 +188,19 @@ static void my_exit(struct context *context, int exitcode) + + static void do_initial_open(struct context *context) + { +- const char **list; +- int err; ++ int card, err; ++ char name[16]; + + if (!context->no_open && context->card == NULL) { +- err = snd_use_case_card_list(&list); ++ card = -1; ++ err = snd_card_next(&card); + if (err < 0) { +- fprintf(stderr, "%s: unable to obtain card list: %s\n", ++ fprintf(stderr, "%s: no sound card found: %s\n", + context->command, snd_strerror(err)); + my_exit(context, EXIT_FAILURE); + } +- if (err == 0) { +- printf("No card found\n"); +- my_exit(context, EXIT_SUCCESS); +- } +- context->card = strdup(list[0]); +- snd_use_case_free_list(list, err); ++ snprintf(name, sizeof(name), "hw:%d", card); ++ context->card = strdup(name); + } + + /* open library */ +-- +2.24.1 + + +From 860ffda82518dad6018f877f58aed1485d49e3a0 Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Wed, 27 Nov 2019 08:51:29 +0100 +Subject: [PATCH 08/31] alsaucm: add text dump command + +Signed-off-by: Jaroslav Kysela +--- + alsaucm/Makefile.am | 2 +- + alsaucm/dump.c | 403 ++++++++++++++++++++++++++++++++++++++++++++ + alsaucm/usecase.c | 22 +-- + alsaucm/usecase.h | 35 ++++ + 4 files changed, 447 insertions(+), 15 deletions(-) + create mode 100644 alsaucm/dump.c + create mode 100644 alsaucm/usecase.h + +diff --git a/alsaucm/Makefile.am b/alsaucm/Makefile.am +index 4b447dd..03f99e0 100644 +--- a/alsaucm/Makefile.am ++++ b/alsaucm/Makefile.am +@@ -5,7 +5,7 @@ if USE_RST2MAN + man_MANS = alsaucm.1 + endif + +-alsaucm_SOURCES = usecase.c ++alsaucm_SOURCES = usecase.c dump.c + + AM_CPPFLAGS = \ + -Wall -I$(top_srcdir)/include +diff --git a/alsaucm/dump.c b/alsaucm/dump.c +new file mode 100644 +index 0000000..ae0af2f +--- /dev/null ++++ b/alsaucm/dump.c +@@ -0,0 +1,403 @@ ++/* ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2 of the License, or (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ++ * ++ * Copyright (C) 2019 Red Hat Inc. ++ * Authors: Jaroslav Kysela ++ */ ++ ++#include ++#include ++#include ++#include ++#include "usecase.h" ++#include "aconfig.h" ++#include "version.h" ++ ++struct renderer { ++ int (*init)(struct renderer *r); ++ void (*done)(struct renderer *r); ++ int (*verb_begin)(struct renderer *r, ++ const char *verb, ++ const char *comment); ++ int (*verb_end)(struct renderer *r); ++ int (*device_begin)(struct renderer *r, ++ const char *device, ++ const char *comment); ++ int (*device_end)(struct renderer *r); ++ int (*modifier_begin)(struct renderer *r, ++ const char *device, ++ const char *comment); ++ int (*modifier_end)(struct renderer *r); ++ int (*supported_begin)(struct renderer *r); ++ int (*supported_value)(struct renderer *r, const char *value, int last); ++ int (*supported_end)(struct renderer *r); ++ int (*conflict_begin)(struct renderer *r); ++ int (*conflict_value)(struct renderer *r, const char *value, int last); ++ int (*conflict_end)(struct renderer *r); ++ int (*value_begin)(struct renderer *r); ++ int (*value_end)(struct renderer *r); ++ int (*value)(struct renderer *r, const char *ident, const char *value); ++ void *opaque; ++}; ++ ++struct text { ++ char a[1]; ++}; ++ ++static char *tesc(const char *s, char *buf, size_t buf_len) ++{ ++ char *dst = buf; ++ char c = '\0'; ++ if (strchr(s, '"') || strchr(s, ' ') || strchr(s, '.')) { ++ *dst++ = c = '"'; ++ buf_len--; ++ } ++ while (*s && buf_len > 2) { ++ if (*s == '\"') { ++ if (buf_len > 3) { ++ *dst++ = '"'; ++ *dst++ = *s++; ++ buf_len -= 2; ++ continue; ++ } else { ++ break; ++ } ++ } ++ *dst++ = *s++; ++ } ++ if (c) ++ *dst++ = c; ++ *dst = '\0'; ++ return buf; ++} ++ ++#define ESC(s, esc) tesc((s), (esc), sizeof(esc)) ++ ++static int text_verb_start(struct renderer *r, const char *verb, const char *comment) ++{ ++ char buf1[128], buf2[128]; ++ printf("Verb.%s {\n", ESC(verb, buf1)); ++ if (comment && comment[0]) ++ printf("\tComment %s\n", ESC(comment, buf2)); ++ return 0; ++} ++ ++static int text_verb_end(struct renderer *r) ++{ ++ printf("}\n"); ++ return 0; ++} ++ ++static int text_2nd_level_begin(struct renderer *r, ++ const char *key, ++ const char *val, ++ const char *comment) ++{ ++ char buf1[128], buf2[128]; ++ printf("\t%s.%s {\n", key, ESC(val, buf1)); ++ if (comment && comment[0]) ++ printf("\t\tComment %s\n", ESC(comment, buf2)); ++ return 0; ++} ++ ++static int text_2nd_level_end(struct renderer *r) ++{ ++ printf("\t}\n"); ++ return 0; ++} ++ ++static int text_2nd_level(struct renderer *r, const char *txt) ++{ ++ printf("\t\t%s", txt); ++ return 0; ++} ++ ++static int text_3rd_level(struct renderer *r, const char *txt) ++{ ++ printf("\t\t\t%s", txt); ++ return 0; ++} ++ ++static int text_dev_start(struct renderer *r, const char *dev, const char *comment) ++{ ++ return text_2nd_level_begin(r, "Device", dev, comment); ++} ++ ++static int text_mod_start(struct renderer *r, const char *dev, const char *comment) ++{ ++ return text_2nd_level_begin(r, "Modifier", dev, comment); ++} ++ ++static int text_supcon_start(struct renderer *r, const char *key) ++{ ++ if (text_2nd_level(r, key)) ++ return 1; ++ printf(" [\n"); ++ return 0; ++} ++ ++static int text_supcon_value(struct renderer *r, const char *value, int last) ++{ ++ char buf[256]; ++ ESC(value, buf); ++ if (!last && strlen(buf) < sizeof(buf) - 2) ++ strcat(buf, ","); ++ if (text_3rd_level(r, buf)) ++ return 1; ++ printf("\n"); ++ return 0; ++} ++ ++static int text_supcon_end(struct renderer *r) ++{ ++ return text_2nd_level(r, "]\n"); ++} ++ ++static int text_sup_start(struct renderer *r) ++{ ++ return text_supcon_start(r, "SupportedDevices"); ++} ++ ++static int text_con_start(struct renderer *r) ++{ ++ return text_supcon_start(r, "ConflictingDevices"); ++} ++ ++static int text_value_begin(struct renderer *r) ++{ ++ return text_2nd_level(r, "Values [\n"); ++} ++ ++static int text_value_end(struct renderer *r) ++{ ++ return text_2nd_level(r, "]\n"); ++} ++ ++static int text_value(struct renderer *r, const char *ident, const char *value) ++{ ++ char buf1[256], buf2[256]; ++ int err; ++ ++ ESC(ident, buf1); ++ err = text_3rd_level(r, buf1); ++ if (err < 0) ++ return err; ++ ESC(value, buf2); ++ printf(" %s\n", buf2); ++ return 0; ++} ++ ++static struct renderer text_renderer = { ++ .verb_begin = text_verb_start, ++ .verb_end = text_verb_end, ++ .device_begin = text_dev_start, ++ .device_end = text_2nd_level_end, ++ .modifier_begin = text_mod_start, ++ .modifier_end = text_2nd_level_end, ++ .supported_begin = text_sup_start, ++ .supported_value = text_supcon_value, ++ .supported_end = text_supcon_end, ++ .conflict_begin = text_con_start, ++ .conflict_value = text_supcon_value, ++ .conflict_end = text_supcon_end, ++ .value_begin = text_value_begin, ++ .value_end = text_value_end, ++ .value = text_value, ++}; ++ ++static int render_devlist(struct context *context, ++ struct renderer *render, ++ const char *verb, ++ const char *device, ++ const char *list, ++ int (*begin)(struct renderer *), ++ int (*value)(struct renderer *, const char *value, int last), ++ int (*end)(struct renderer *)) ++{ ++ snd_use_case_mgr_t *uc_mgr = context->uc_mgr; ++ const char **dev_list; ++ char buf[256]; ++ int err = 0, j, dev_num; ++ ++ snprintf(buf, sizeof(buf), "%s/%s/%s", list, device, verb); ++ dev_num = snd_use_case_get_list(uc_mgr, buf, &dev_list); ++ if (dev_num < 0) { ++ fprintf(stderr, "%s: unable to get %s for verb '%s' for device '%s'\n", ++ context->command, list, verb, device); ++ return dev_num; ++ } ++ if (dev_num > 0) { ++ err = begin(render); ++ if (err < 0) ++ goto __err; ++ for (j = 0; j < dev_num; j++) { ++ err = value(render, dev_list[j], j + 1 == dev_num); ++ if (err < 0) ++ goto __err; ++ } ++ err = end(render); ++ } ++__err: ++ snd_use_case_free_list(dev_list, dev_num); ++ return err; ++} ++ ++static int render_values(struct context *context, ++ struct renderer *render, ++ const char *verb, ++ const char *device) ++{ ++ snd_use_case_mgr_t *uc_mgr = context->uc_mgr; ++ const char **list, *value; ++ char buf[256]; ++ int err = 0, j, num; ++ ++ snprintf(buf, sizeof(buf), "_identifiers/%s/%s", device, verb); ++ num = snd_use_case_get_list(uc_mgr, buf, &list); ++ if (num < 0) { ++ fprintf(stderr, "%s: unable to get _identifiers for verb '%s' for device '%s': %s\n", ++ context->command, verb, device, snd_strerror(num)); ++ return num; ++ } ++ if (num == 0) ++ goto __err; ++ if (render->value_begin) { ++ err = render->value_begin(render); ++ if (err < 0) ++ goto __err; ++ } ++ for (j = 0; j < num; j++) { ++ snprintf(buf, sizeof(buf), "%s/%s/%s", list[j], device, verb); ++ err = snd_use_case_get(uc_mgr, buf, &value); ++ if (err < 0) { ++ fprintf(stderr, "%s: unable to get value '%s' for verb '%s' for device '%s': %s\n", ++ context->command, list[j], verb, device, snd_strerror(err)); ++ goto __err; ++ } ++ err = render->value(render, list[j], value); ++ free((char *)value); ++ if (err < 0) ++ goto __err; ++ } ++ if (render->value_end) ++ err = render->value_end(render); ++__err: ++ snd_use_case_free_list(list, num); ++ return err; ++} ++ ++static int render_device(struct context *context, ++ struct renderer *render, ++ const char *verb, ++ const char *device) ++{ ++ int err; ++ ++ err = render_devlist(context, render, verb, device, ++ "_supporteddevs", ++ render->supported_begin, ++ render->supported_value, ++ render->supported_end); ++ if (err < 0) ++ return err; ++ err = render_devlist(context, render, verb, device, ++ "_conflictingdevs", ++ render->conflict_begin, ++ render->conflict_value, ++ render->conflict_end); ++ if (err < 0) ++ return err; ++ return render_values(context, render, verb, device); ++} ++ ++static void render(struct context *context, struct renderer *render) ++{ ++ snd_use_case_mgr_t *uc_mgr = context->uc_mgr; ++ int i, j, num, dev_num; ++ const char **list, **dev_list, *verb, *comment; ++ char buf[256]; ++ ++ num = snd_use_case_verb_list(uc_mgr, &list); ++ if (num < 0) { ++ fprintf(stderr, "%s: no verbs found\n", context->command); ++ return; ++ } ++ if (render->init && render->init(render)) ++ goto __end; ++ for (i = 0; i < num; i += 2) { ++ /* verb */ ++ verb = list[i + 0]; ++ comment = list[i + 1]; ++ if (render->verb_begin(render, verb, comment)) ++ break; ++ /* devices */ ++ snprintf(buf, sizeof(buf), "_devices/%s", verb); ++ dev_num = snd_use_case_get_list(uc_mgr, buf, &dev_list); ++ if (dev_num < 0) { ++ fprintf(stderr, "%s: unable to get devices for verb '%s'\n", ++ context->command, verb); ++ continue; ++ } ++ for (j = 0; j < dev_num; j += 2) { ++ render->device_begin(render, dev_list[j + 0], dev_list[j + 1]); ++ if (render_device(context, render, verb, dev_list[j + 0])) { ++ snd_use_case_free_list(dev_list, dev_num); ++ goto __end; ++ } ++ render->device_end(render); ++ } ++ snd_use_case_free_list(dev_list, dev_num); ++ /* modifiers */ ++ snprintf(buf, sizeof(buf), "_modifiers/%s", verb); ++ dev_num = snd_use_case_get_list(uc_mgr, buf, &dev_list); ++ if (dev_num < 0) { ++ fprintf(stderr, "%s: unable to get modifiers for verb '%s'\n", ++ context->command, verb); ++ continue; ++ } ++ for (j = 0; j < dev_num; j += 2) { ++ render->modifier_begin(render, dev_list[j + 0], dev_list[j + 1]); ++ render->modifier_end(render); ++ } ++ snd_use_case_free_list(dev_list, dev_num); ++ /* end */ ++ if (render->verb_end(render)) ++ break; ++ } ++ if (render->done) ++ render->done(render); ++__end: ++ snd_use_case_free_list(list, num); ++} ++ ++void dump(struct context *context, const char *format) ++{ ++ struct renderer r; ++ ++ r.opaque = NULL; ++ if (strcasecmp(format, "text") == 0 || ++ strcasecmp(format, "txt") == 0) { ++ struct text t; ++ memset(&t, 0, sizeof(t)); ++ r = text_renderer; ++ r.opaque = &t; ++ } ++ if (r.opaque != NULL) { ++ render(context, &r); ++ return; ++ } ++ fprintf(stderr, "%s: unknown dump format '%s'\n", ++ context->command, format); ++} +diff --git a/alsaucm/usecase.c b/alsaucm/usecase.c +index 8b1c8c7..44fc92b 100644 +--- a/alsaucm/usecase.c ++++ b/alsaucm/usecase.c +@@ -38,24 +38,12 @@ + #include + #include + #include ++#include "usecase.h" + #include "aconfig.h" + #include "version.h" + + #define MAX_BUF 256 + +-struct context { +- snd_use_case_mgr_t *uc_mgr; +- const char *command; +- char *card; +- char **argv; +- int argc; +- int arga; +- char *batch; +- unsigned int interactive:1; +- unsigned int no_open:1; +- unsigned int do_exit:1; +-}; +- + enum uc_cmd { + /* management */ + OM_UNKNOWN = 0, +@@ -63,6 +51,7 @@ enum uc_cmd { + OM_RESET, + OM_RELOAD, + OM_LISTCARDS, ++ OM_DUMP, + OM_LIST2, + OM_LIST1, + +@@ -88,11 +77,13 @@ static struct cmd cmds[] = { + { OM_RESET, 0, 1, "reset" }, + { OM_RELOAD, 0, 1, "reload" }, + { OM_LISTCARDS, 0, 0, "listcards" }, ++ { OM_DUMP, 1, 1, "dump" }, + { OM_LIST1, 1, 1, "list1" }, + { OM_LIST2, 1, 1, "list" }, + { OM_SET, 2, 1, "set" }, + { OM_GET, 1, 1, "get" }, + { OM_GETI, 1, 1, "geti" }, ++ { OM_DUMP, 1, 1, "dump" }, + { OM_HELP, 0, 0, "help" }, + { OM_QUIT, 0, 0, "quit" }, + { OM_HELP, 0, 0, "h" }, +@@ -117,6 +108,7 @@ static void dump_help(struct context *context) + " reset reset sound card to default state\n" + " reload reload configuration\n" + " listcards list available cards\n" ++" dump FORMAT dump all config information (format: text)\n" + " list IDENTIFIER list command, for items with value + comment\n" + " list1 IDENTIFIER list command, for items without comments\n" + " get IDENTIFIER get string value\n" +@@ -185,7 +177,6 @@ static void my_exit(struct context *context, int exitcode) + snd_config_update_free_global(); + exit(exitcode); + } +- + static void do_initial_open(struct context *context) + { + int card, err; +@@ -288,6 +279,9 @@ static int do_one(struct context *context, struct cmd *cmd, char **argv) + } + snd_use_case_free_list(list, err); + break; ++ case OM_DUMP: ++ dump(context, argv[0]); ++ break; + case OM_LIST1: + case OM_LIST2: + switch (cmd->code) { +diff --git a/alsaucm/usecase.h b/alsaucm/usecase.h +new file mode 100644 +index 0000000..a85716a +--- /dev/null ++++ b/alsaucm/usecase.h +@@ -0,0 +1,35 @@ ++/* ++ * This library is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU Lesser General Public ++ * License as published by the Free Software Foundation; either ++ * version 2 of the License, or (at your option) any later version. ++ * ++ * This library is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * Lesser General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ++ */ ++ ++#ifndef __USECASE_H ++#define __USECASE_H ++ ++struct context { ++ snd_use_case_mgr_t *uc_mgr; ++ const char *command; ++ char *card; ++ char **argv; ++ int argc; ++ int arga; ++ char *batch; ++ unsigned int interactive:1; ++ unsigned int no_open:1; ++ unsigned int do_exit:1; ++}; ++ ++void dump(struct context *context, const char *format); ++ ++#endif +-- +2.24.1 + + +From 49716fa61e9ddc67476d40f9ea84f07fe0017748 Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Sat, 30 Nov 2019 20:30:33 +0100 +Subject: [PATCH 09/31] alsaucm: add json dump command + +Signed-off-by: Jaroslav Kysela +--- + alsaucm/dump.c | 251 +++++++++++++++++++++++++++++++++++++++++++++- + alsaucm/usecase.c | 2 +- + 2 files changed, 249 insertions(+), 4 deletions(-) + +diff --git a/alsaucm/dump.c b/alsaucm/dump.c +index ae0af2f..bc638f1 100644 +--- a/alsaucm/dump.c ++++ b/alsaucm/dump.c +@@ -32,10 +32,14 @@ struct renderer { + const char *verb, + const char *comment); + int (*verb_end)(struct renderer *r); ++ int (*device_block_begin)(struct renderer *r); ++ int (*device_block_end)(struct renderer *r); + int (*device_begin)(struct renderer *r, + const char *device, + const char *comment); + int (*device_end)(struct renderer *r); ++ int (*modifier_block_begin)(struct renderer *r); ++ int (*modifier_block_end)(struct renderer *r); + int (*modifier_begin)(struct renderer *r, + const char *device, + const char *comment); +@@ -52,6 +56,10 @@ struct renderer { + void *opaque; + }; + ++/* ++ * Text renderer ++ */ ++ + struct text { + char a[1]; + }; +@@ -177,12 +185,12 @@ static int text_con_start(struct renderer *r) + + static int text_value_begin(struct renderer *r) + { +- return text_2nd_level(r, "Values [\n"); ++ return text_2nd_level(r, "Values {\n"); + } + + static int text_value_end(struct renderer *r) + { +- return text_2nd_level(r, "]\n"); ++ return text_2nd_level(r, "}\n"); + } + + static int text_value(struct renderer *r, const char *ident, const char *value) +@@ -217,6 +225,220 @@ static struct renderer text_renderer = { + .value = text_value, + }; + ++/* ++ * JSON renderer ++ */ ++ ++struct json { ++ int block[5]; ++}; ++ ++static char *jesc(const char *s, char *buf, size_t buf_len) ++{ ++ char *dst = buf; ++ char c = '"'; ++ *dst++ = c; ++ buf_len--; ++ while (*s && buf_len > 2) { ++ if (*s == '\"') { ++ if (buf_len > 3) { ++ *dst++ = '"'; ++ *dst++ = *s++; ++ buf_len -= 2; ++ continue; ++ } else { ++ break; ++ } ++ } ++ *dst++ = *s++; ++ } ++ *dst++ = c; ++ *dst = '\0'; ++ return buf; ++} ++ ++#define JESC(s, esc) jesc((s), (esc), sizeof(esc)) ++ ++static void json_block(struct renderer *r, int level, int last) ++{ ++ struct json *j = r->opaque; ++ printf((j->block[level] && !last) ? ",\n" : "\n"); ++ j->block[level] = last ? 0 : 1; ++} ++ ++static int json_init(struct renderer *r) ++{ ++ printf("{\n \"Verbs\": {"); ++ return 0; ++} ++ ++static void json_done(struct renderer *r) ++{ ++ json_block(r, 0, 1); ++ printf(" }\n}\n"); ++} ++ ++static int json_verb_start(struct renderer *r, const char *verb, const char *comment) ++{ ++ char buf[256]; ++ json_block(r, 0, 0); ++ printf(" %s: {", JESC(verb, buf)); ++ if (comment && comment[0]) { ++ json_block(r, 1, 0); ++ printf(" \"Comment\": %s", JESC(comment, buf)); ++ } ++ return 0; ++} ++ ++static int json_verb_end(struct renderer *r) ++{ ++ json_block(r, 1, 1); ++ printf(" }"); ++ return 0; ++} ++ ++static int json_2nd_level_block_end(struct renderer *r) ++{ ++ json_block(r, 2, 1); ++ printf(" }"); ++ return 0; ++} ++ ++static int json_2nd_level_begin(struct renderer *r, ++ const char *val, ++ const char *comment) ++{ ++ char buf[256]; ++ json_block(r, 2, 0); ++ printf(" %s: {", JESC(val, buf)); ++ if (comment && comment[0]) { ++ json_block(r, 3, 0); ++ printf(" \"Comment\": %s", JESC(comment, buf)); ++ } ++ return 0; ++} ++ ++static int json_2nd_level_end(struct renderer *r) ++{ ++ json_block(r, 3, 1); ++ printf(" }"); ++ return 0; ++} ++ ++static int json_2nd_level(struct renderer *r, const char *txt) ++{ ++ printf(" %s", txt); ++ return 0; ++} ++ ++static int json_3rd_level(struct renderer *r, const char *txt) ++{ ++ printf(" %s", txt); ++ return 0; ++} ++ ++static int json_dev_block_start(struct renderer *r) ++{ ++ json_block(r, 1, 0); ++ printf(" \"Devices\": {"); ++ return 0; ++} ++ ++static int json_mod_block_start(struct renderer *r) ++{ ++ json_block(r, 1, 0); ++ printf(" \"Modifiers\": {"); ++ return 0; ++} ++ ++static int json_supcon_start(struct renderer *r, const char *key) ++{ ++ json_block(r, 3, 0); ++ if (json_2nd_level(r, key)) ++ return 1; ++ printf(": ["); ++ return 0; ++} ++ ++static int json_supcon_value(struct renderer *r, const char *value, int last) ++{ ++ char buf[256]; ++ JESC(value, buf); ++ json_block(r, 4, 0); ++ return json_3rd_level(r, buf); ++} ++ ++static int json_supcon_end(struct renderer *r) ++{ ++ json_block(r, 4, 1); ++ return json_2nd_level(r, "]"); ++} ++ ++static int json_sup_start(struct renderer *r) ++{ ++ return json_supcon_start(r, "\"SupportedDevices\""); ++} ++ ++static int json_con_start(struct renderer *r) ++{ ++ return json_supcon_start(r, "\"ConflictingDevices\""); ++} ++ ++static int json_value_begin(struct renderer *r) ++{ ++ json_block(r, 3, 0); ++ return json_2nd_level(r, "\"Values\": {"); ++} ++ ++static int json_value_end(struct renderer *r) ++{ ++ json_block(r, 4, 1); ++ return json_2nd_level(r, "}"); ++} ++ ++static int json_value(struct renderer *r, const char *ident, const char *value) ++{ ++ char buf[256]; ++ int err; ++ ++ json_block(r, 4, 0); ++ JESC(ident, buf); ++ err = json_3rd_level(r, buf); ++ if (err < 0) ++ return err; ++ JESC(value, buf); ++ printf(": %s", buf); ++ return 0; ++} ++ ++static struct renderer json_renderer = { ++ .init = json_init, ++ .done = json_done, ++ .verb_begin = json_verb_start, ++ .verb_end = json_verb_end, ++ .device_block_begin = json_dev_block_start, ++ .device_block_end = json_2nd_level_block_end, ++ .device_begin = json_2nd_level_begin, ++ .device_end = json_2nd_level_end, ++ .modifier_block_begin = json_mod_block_start, ++ .modifier_block_end = json_2nd_level_block_end, ++ .modifier_begin = json_2nd_level_begin, ++ .modifier_end = json_2nd_level_end, ++ .supported_begin = json_sup_start, ++ .supported_value = json_supcon_value, ++ .supported_end = json_supcon_end, ++ .conflict_begin = json_con_start, ++ .conflict_value = json_supcon_value, ++ .conflict_end = json_supcon_end, ++ .value_begin = json_value_begin, ++ .value_end = json_value_end, ++ .value = json_value, ++}; ++ ++/* ++ * universal dump functions ++ */ ++ + static int render_devlist(struct context *context, + struct renderer *render, + const char *verb, +@@ -350,6 +572,12 @@ static void render(struct context *context, struct renderer *render) + context->command, verb); + continue; + } ++ if (dev_num == 0) ++ goto __mods; ++ if (render->device_block_begin && render->device_block_begin(render)) { ++ snd_use_case_free_list(dev_list, dev_num); ++ goto __end; ++ } + for (j = 0; j < dev_num; j += 2) { + render->device_begin(render, dev_list[j + 0], dev_list[j + 1]); + if (render_device(context, render, verb, dev_list[j + 0])) { +@@ -359,6 +587,9 @@ static void render(struct context *context, struct renderer *render) + render->device_end(render); + } + snd_use_case_free_list(dev_list, dev_num); ++ if (render->device_block_end && render->device_block_end(render)) ++ goto __end; ++__mods: + /* modifiers */ + snprintf(buf, sizeof(buf), "_modifiers/%s", verb); + dev_num = snd_use_case_get_list(uc_mgr, buf, &dev_list); +@@ -367,11 +598,20 @@ static void render(struct context *context, struct renderer *render) + context->command, verb); + continue; + } ++ if (dev_num == 0) ++ goto __verb_end; ++ if (render->modifier_block_begin && render->modifier_block_begin(render)) { ++ snd_use_case_free_list(dev_list, dev_num); ++ goto __end; ++ } + for (j = 0; j < dev_num; j += 2) { + render->modifier_begin(render, dev_list[j + 0], dev_list[j + 1]); + render->modifier_end(render); + } + snd_use_case_free_list(dev_list, dev_num); ++ if (render->modifier_block_end && render->modifier_block_end(render)) ++ goto __end; ++__verb_end: + /* end */ + if (render->verb_end(render)) + break; +@@ -385,14 +625,19 @@ __end: + void dump(struct context *context, const char *format) + { + struct renderer r; ++ struct text t; ++ struct json j; + + r.opaque = NULL; + if (strcasecmp(format, "text") == 0 || + strcasecmp(format, "txt") == 0) { +- struct text t; + memset(&t, 0, sizeof(t)); + r = text_renderer; + r.opaque = &t; ++ } else if (strcasecmp(format, "json") == 0) { ++ memset(&j, 0, sizeof(j)); ++ r = json_renderer; ++ r.opaque = &j; + } + if (r.opaque != NULL) { + render(context, &r); +diff --git a/alsaucm/usecase.c b/alsaucm/usecase.c +index 44fc92b..1ed91ea 100644 +--- a/alsaucm/usecase.c ++++ b/alsaucm/usecase.c +@@ -108,7 +108,7 @@ static void dump_help(struct context *context) + " reset reset sound card to default state\n" + " reload reload configuration\n" + " listcards list available cards\n" +-" dump FORMAT dump all config information (format: text)\n" ++" dump FORMAT dump all config information (format: text,json)\n" + " list IDENTIFIER list command, for items with value + comment\n" + " list1 IDENTIFIER list command, for items without comments\n" + " get IDENTIFIER get string value\n" +-- +2.24.1 + + +From 160b47e27c787880f1581a0f2e70138f6b24c41b Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Sat, 30 Nov 2019 20:38:17 +0100 +Subject: [PATCH 10/31] alsaucm: dump - fix the prefixed " + +Signed-off-by: Jaroslav Kysela +--- + alsaucm/dump.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/alsaucm/dump.c b/alsaucm/dump.c +index bc638f1..7a90c82 100644 +--- a/alsaucm/dump.c ++++ b/alsaucm/dump.c +@@ -73,9 +73,9 @@ static char *tesc(const char *s, char *buf, size_t buf_len) + buf_len--; + } + while (*s && buf_len > 2) { +- if (*s == '\"') { ++ if (*s == '"') { + if (buf_len > 3) { +- *dst++ = '"'; ++ *dst++ = '\\'; + *dst++ = *s++; + buf_len -= 2; + continue; +@@ -240,9 +240,9 @@ static char *jesc(const char *s, char *buf, size_t buf_len) + *dst++ = c; + buf_len--; + while (*s && buf_len > 2) { +- if (*s == '\"') { ++ if (*s == '"') { + if (buf_len > 3) { +- *dst++ = '"'; ++ *dst++ = '\\'; + *dst++ = *s++; + buf_len -= 2; + continue; +-- +2.24.1 + + +From 34e373d0b12d96353c49c3dcd73ec52eee11484a Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Tue, 3 Dec 2019 13:53:25 +0100 +Subject: [PATCH 11/31] alsactl: fix --sched-idle (set it really to SCHED_IDLE) + +Reported-by: tommy +Signed-off-by: Jaroslav Kysela +--- + alsactl/Makefile.am | 2 ++ + alsactl/alsactl.c | 2 +- + 2 files changed, 3 insertions(+), 1 deletion(-) + +diff --git a/alsactl/Makefile.am b/alsactl/Makefile.am +index aaaf74e..e9ab2eb 100644 +--- a/alsactl/Makefile.am ++++ b/alsactl/Makefile.am +@@ -7,6 +7,8 @@ man_MANS += alsactl_init.7 + endif + EXTRA_DIST=alsactl.1 alsactl_init.xml + ++AM_CFLAGS = -D_GNU_SOURCE ++ + alsactl_SOURCES=alsactl.c state.c lock.c utils.c init_parse.c daemon.c \ + monitor.c + +diff --git a/alsactl/alsactl.c b/alsactl/alsactl.c +index 94cae23..dfb1db7 100644 +--- a/alsactl/alsactl.c ++++ b/alsactl/alsactl.c +@@ -161,7 +161,7 @@ static void do_nice(int use_nice, int sched_idle) + if (sched_idle) { + if (sched_getparam(0, &sched_param) >= 0) { + sched_param.sched_priority = 0; +- if (!sched_setscheduler(0, SCHED_RR, &sched_param)) ++ if (!sched_setscheduler(0, SCHED_IDLE, &sched_param)) + error("sched_setparam failed: %s", strerror(errno)); + } else { + error("sched_getparam failed: %s", strerror(errno)); +-- +2.24.1 + + +From f77a269370af917585df59d8c21c89bca07b5b73 Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Tue, 3 Dec 2019 20:51:56 +0100 +Subject: [PATCH 12/31] configure: Fix linking of alsatplg with the older libs + +BugLink: https://github.com/alsa-project/alsa-utils/issues/33 +Signed-off-by: Jaroslav Kysela +--- + configure.ac | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/configure.ac b/configure.ac +index a4a2dd4..4bee49b 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -70,6 +70,11 @@ AM_CONDITIONAL(HAVE_TOPOLOGY, test "$have_topology" = "yes") + AM_CONDITIONAL(HAVE_SAMPLERATE, test "$have_samplerate" = "yes") + AM_CONDITIONAL(HAVE_FFADO, test "$have_ffado" = "yes") + ++# old libasound with the topology routines in the main library ++if test "x$have_topology" = "xyes" -a "x$ALSA_TOPOLOGY_LIBS" = "x"; then ++ ALSA_TOPOLOGY_LIBS="$ALSA_LIBS" ++fi ++ + dnl Use tinyalsa + alsabat_backend_tiny= + AC_ARG_ENABLE(alsabat_backend_tiny, +-- +2.24.1 + + +From 08d2341a176248a346efbdaa6d8878f3ebd627da Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Thu, 12 Dec 2019 19:00:42 +0100 +Subject: [PATCH 13/31] alsatplg: add -n,--normalize option + +This function loads and parses the topology file and +saves back the structured output in the alsa-lib's format +without comments. + +Signed-off-by: Jaroslav Kysela +--- + topology/topology.c | 165 ++++++++++++++++++++++++++++++++++++++------ + 1 file changed, 145 insertions(+), 20 deletions(-) + +diff --git a/topology/topology.c b/topology/topology.c +index b72e341..a6ebafa 100644 +--- a/topology/topology.c ++++ b/topology/topology.c +@@ -43,23 +43,154 @@ _("Usage: %s [OPTIONS]...\n" + "\n" + "-h, --help help\n" + "-c, --compile=FILE compile file\n" ++"-n, --normalize=FILE normalize file\n" + "-v, --verbose=LEVEL set verbosity level (0...1)\n" + "-o, --output=FILE set output file\n" + ), name); + } + +-int main(int argc, char *argv[]) ++static int _compar(const void *a, const void *b) ++{ ++ const snd_config_t *c1 = *(snd_config_t **)a; ++ const snd_config_t *c2 = *(snd_config_t **)b; ++ const char *id1, *id2; ++ if (snd_config_get_id(c1, &id1)) return 0; ++ if (snd_config_get_id(c2, &id2)) return 0; ++ return strcmp(id1, id2); ++} ++ ++static snd_config_t *normalize_config(const char *id, snd_config_t *src) ++{ ++ snd_config_t *dst, **a; ++ snd_config_iterator_t i, next; ++ int index, count; ++ ++ if (snd_config_get_type(src) != SND_CONFIG_TYPE_COMPOUND) { ++ if (snd_config_copy(&dst, src) >= 0) ++ return dst; ++ return NULL; ++ } ++ if (snd_config_make_compound(&dst, id, 0)) ++ return NULL; ++ count = 0; ++ snd_config_for_each(i, next, src) ++ count++; ++ a = malloc(sizeof(dst) * count); ++ if (a == NULL) ++ return NULL; ++ index = 0; ++ snd_config_for_each(i, next, src) { ++ snd_config_t *s = snd_config_iterator_entry(i); ++ a[index++] = s; ++ } ++ qsort(a, count, sizeof(a[0]), _compar); ++ for (index = 0; index < count; index++) { ++ snd_config_t *s = a[index]; ++ const char *id2; ++ if (snd_config_get_id(s, &id2)) { ++ snd_config_delete(dst); ++ return NULL; ++ } ++ s = normalize_config(id2, s); ++ if (s == NULL || snd_config_add(dst, s)) { ++ snd_config_delete(dst); ++ return NULL; ++ } ++ } ++ return dst; ++} ++ ++static int compile(const char *source_file, const char *output_file, int verbose) + { + snd_tplg_t *snd_tplg; +- static const char short_options[] = "hc:v:o:"; ++ int err; ++ ++ snd_tplg = snd_tplg_new(); ++ if (snd_tplg == NULL) { ++ fprintf(stderr, _("failed to create new topology context\n")); ++ return 1; ++ } ++ ++ snd_tplg_verbose(snd_tplg, verbose); ++ ++ err = snd_tplg_build_file(snd_tplg, source_file, output_file); ++ if (err < 0) { ++ fprintf(stderr, _("failed to compile context %s\n"), source_file); ++ snd_tplg_free(snd_tplg); ++ unlink(output_file); ++ return 1; ++ } ++ ++ snd_tplg_free(snd_tplg); ++ return 1; ++} ++ ++static int normalize(const char *source_file, const char *output_file) ++{ ++ snd_input_t *input; ++ snd_output_t *output; ++ snd_config_t *top, *norm; ++ int err; ++ ++ err = snd_input_stdio_open(&input, source_file, "r"); ++ if (err < 0) { ++ fprintf(stderr, "Unable to open source file '%s': %s\n", source_file, snd_strerror(-err)); ++ return 0; ++ } ++ ++ err = snd_config_top(&top); ++ if (err < 0) { ++ snd_input_close(input); ++ return 1; ++ } ++ ++ err = snd_config_load(top, input); ++ snd_input_close(input); ++ if (err < 0) { ++ snd_config_delete(top); ++ fprintf(stderr, "Unable to parse source file '%s': %s\n", source_file, snd_strerror(-err)); ++ snd_config_delete(top); ++ return 1; ++ } ++ ++ err = snd_output_stdio_open(&output, output_file, "w+"); ++ if (err < 0) { ++ fprintf(stderr, "Unable to open output file '%s': %s\n", output_file, snd_strerror(-err)); ++ snd_config_delete(top); ++ return 1; ++ } ++ ++ norm = normalize_config(NULL, top); ++ if (norm == NULL) { ++ fprintf(stderr, "Unable to normalize configuration (out of memory?)\n"); ++ snd_output_close(output); ++ snd_config_delete(top); ++ return 1; ++ } ++ ++ err = snd_config_save(norm, output); ++ snd_output_close(output); ++ snd_config_delete(top); ++ if (err < 0) { ++ fprintf(stderr, "Unable to save normalized contents: %s\n", snd_strerror(-err)); ++ return 1; ++ } ++ ++ return 0; ++} ++ ++int main(int argc, char *argv[]) ++{ ++ static const char short_options[] = "hc:n:v:o:"; + static const struct option long_options[] = { + {"help", 0, NULL, 'h'}, + {"verbose", 1, NULL, 'v'}, + {"compile", 1, NULL, 'c'}, ++ {"normalize", 1, NULL, 'n'}, + {"output", 1, NULL, 'o'}, + {0, 0, 0, 0}, + }; +- char *source_file = NULL, *output_file = NULL; ++ char *source_file = NULL, *normalize_file = NULL, *output_file = NULL; + int c, err, verbose = 0, option_index; + + #ifdef ENABLE_NLS +@@ -81,6 +212,9 @@ int main(int argc, char *argv[]) + case 'c': + source_file = optarg; + break; ++ case 'n': ++ normalize_file = optarg; ++ break; + case 'o': + output_file = optarg; + break; +@@ -90,28 +224,19 @@ int main(int argc, char *argv[]) + } + } + +- if (source_file == NULL || output_file == NULL) { +- usage(argv[0]); +- return 1; +- } +- +- snd_tplg = snd_tplg_new(); +- if (snd_tplg == NULL) { +- fprintf(stderr, _("failed to create new topology context\n")); ++ if (source_file && normalize_file) { ++ fprintf(stderr, "Cannot normalize and compile at a time!\n"); + return 1; + } + +- snd_tplg_verbose(snd_tplg, verbose); +- +- err = snd_tplg_build_file(snd_tplg, source_file, output_file); +- if (err < 0) { +- fprintf(stderr, _("failed to compile context %s\n"), source_file); +- snd_tplg_free(snd_tplg); +- unlink(output_file); ++ if ((source_file == NULL && normalize_file == NULL) || output_file == NULL) { ++ usage(argv[0]); + return 1; + } + +- snd_tplg_free(snd_tplg); ++ if (source_file) ++ err = compile(source_file, output_file, verbose); ++ else ++ err = normalize(normalize_file, output_file); + return 0; + } +- +-- +2.24.1 + + +From 2656d4bec8fab8b4b9046d3b8c9c255dc2166014 Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Thu, 12 Dec 2019 19:18:28 +0100 +Subject: [PATCH 14/31] alsatplg: add -s,--sort and fix memory leaks + +Signed-off-by: Jaroslav Kysela +--- + topology/topology.c | 34 ++++++++++++++++++++++++---------- + 1 file changed, 24 insertions(+), 10 deletions(-) + +diff --git a/topology/topology.c b/topology/topology.c +index a6ebafa..c12be78 100644 +--- a/topology/topology.c ++++ b/topology/topology.c +@@ -46,6 +46,7 @@ _("Usage: %s [OPTIONS]...\n" + "-n, --normalize=FILE normalize file\n" + "-v, --verbose=LEVEL set verbosity level (0...1)\n" + "-o, --output=FILE set output file\n" ++"-s, --sort sort the identifiers in the normalized output\n" + ), name); + } + +@@ -59,7 +60,7 @@ static int _compar(const void *a, const void *b) + return strcmp(id1, id2); + } + +-static snd_config_t *normalize_config(const char *id, snd_config_t *src) ++static snd_config_t *normalize_config(const char *id, snd_config_t *src, int sort) + { + snd_config_t *dst, **a; + snd_config_iterator_t i, next; +@@ -70,8 +71,6 @@ static snd_config_t *normalize_config(const char *id, snd_config_t *src) + return dst; + return NULL; + } +- if (snd_config_make_compound(&dst, id, 0)) +- return NULL; + count = 0; + snd_config_for_each(i, next, src) + count++; +@@ -83,20 +82,28 @@ static snd_config_t *normalize_config(const char *id, snd_config_t *src) + snd_config_t *s = snd_config_iterator_entry(i); + a[index++] = s; + } +- qsort(a, count, sizeof(a[0]), _compar); ++ if (sort) ++ qsort(a, count, sizeof(a[0]), _compar); ++ if (snd_config_make_compound(&dst, id, count == 1)) { ++ free(a); ++ return NULL; ++ } + for (index = 0; index < count; index++) { + snd_config_t *s = a[index]; + const char *id2; + if (snd_config_get_id(s, &id2)) { + snd_config_delete(dst); ++ free(a); + return NULL; + } +- s = normalize_config(id2, s); ++ s = normalize_config(id2, s, sort); + if (s == NULL || snd_config_add(dst, s)) { + snd_config_delete(dst); ++ free(a); + return NULL; + } + } ++ free(a); + return dst; + } + +@@ -125,7 +132,7 @@ static int compile(const char *source_file, const char *output_file, int verbose + return 1; + } + +-static int normalize(const char *source_file, const char *output_file) ++static int normalize(const char *source_file, const char *output_file, int sort) + { + snd_input_t *input; + snd_output_t *output; +@@ -160,7 +167,7 @@ static int normalize(const char *source_file, const char *output_file) + return 1; + } + +- norm = normalize_config(NULL, top); ++ norm = normalize_config(NULL, top, sort); + if (norm == NULL) { + fprintf(stderr, "Unable to normalize configuration (out of memory?)\n"); + snd_output_close(output); +@@ -170,6 +177,7 @@ static int normalize(const char *source_file, const char *output_file) + + err = snd_config_save(norm, output); + snd_output_close(output); ++ snd_config_delete(norm); + snd_config_delete(top); + if (err < 0) { + fprintf(stderr, "Unable to save normalized contents: %s\n", snd_strerror(-err)); +@@ -181,17 +189,18 @@ static int normalize(const char *source_file, const char *output_file) + + int main(int argc, char *argv[]) + { +- static const char short_options[] = "hc:n:v:o:"; ++ static const char short_options[] = "hc:n:v:o:s"; + static const struct option long_options[] = { + {"help", 0, NULL, 'h'}, + {"verbose", 1, NULL, 'v'}, + {"compile", 1, NULL, 'c'}, + {"normalize", 1, NULL, 'n'}, + {"output", 1, NULL, 'o'}, ++ {"sort", 0, NULL, 's'}, + {0, 0, 0, 0}, + }; + char *source_file = NULL, *normalize_file = NULL, *output_file = NULL; +- int c, err, verbose = 0, option_index; ++ int c, err, verbose = 0, sort = 0, option_index; + + #ifdef ENABLE_NLS + setlocale(LC_ALL, ""); +@@ -218,6 +227,9 @@ int main(int argc, char *argv[]) + case 'o': + output_file = optarg; + break; ++ case 's': ++ sort = 1; ++ break; + default: + fprintf(stderr, _("Try `%s --help' for more information.\n"), argv[0]); + return 1; +@@ -237,6 +249,8 @@ int main(int argc, char *argv[]) + if (source_file) + err = compile(source_file, output_file, verbose); + else +- err = normalize(normalize_file, output_file); ++ err = normalize(normalize_file, output_file, sort); ++ ++ snd_output_close(log); + return 0; + } +-- +2.24.1 + + +From 10db898d9b97f0a8d3093405ad5b4aa4ed53801d Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Fri, 13 Dec 2019 10:44:36 +0100 +Subject: [PATCH 15/31] alsatplg: fix another small leak in normalize_config() + +Signed-off-by: Jaroslav Kysela +--- + topology/topology.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/topology/topology.c b/topology/topology.c +index c12be78..bc5797c 100644 +--- a/topology/topology.c ++++ b/topology/topology.c +@@ -98,6 +98,8 @@ static snd_config_t *normalize_config(const char *id, snd_config_t *src, int sor + } + s = normalize_config(id2, s, sort); + if (s == NULL || snd_config_add(dst, s)) { ++ if (s) ++ snd_config_delete(s); + snd_config_delete(dst); + free(a); + return NULL; +-- +2.24.1 + + +From 11e083d81c330539f0f170bb238a17b1c2e0cb4d Mon Sep 17 00:00:00 2001 +From: David Ward +Date: Sat, 21 Dec 2019 00:32:01 -0500 +Subject: [PATCH 16/31] alsa-info.sh: Consolidate PCI device output + +Include numeric IDs and subsystem info in the PCI device output, +without placing them in a separate section. + +Signed-off-by: David Ward +Signed-off-by: Takashi Iwai +--- + alsa-info/alsa-info.sh | 10 +++------- + 1 file changed, 3 insertions(+), 7 deletions(-) + +diff --git a/alsa-info/alsa-info.sh b/alsa-info/alsa-info.sh +index cf7ad89..8fc6997 100755 +--- a/alsa-info/alsa-info.sh ++++ b/alsa-info/alsa-info.sh +@@ -455,7 +455,9 @@ fi + cat /proc/asound/modules 2>/dev/null | awk '{ print $2 }' > $TEMPDIR/alsamodules.tmp + cat /proc/asound/cards > $TEMPDIR/alsacards.tmp + if [[ ! -z "$LSPCI" ]]; then +- lspci | grep -i "multi\|audio">$TEMPDIR/lspci.tmp ++ for class in 0401 0402 0403; do ++ lspci -vvnn -d "::$class" | sed -n '/^[^\t]/,+1p' ++ done > $TEMPDIR/lspci.tmp + fi + + #Check for HDA-Intel cards codec#* +@@ -585,12 +587,6 @@ echo "" >> $FILE + cat $TEMPDIR/lspci.tmp >> $FILE + echo "" >> $FILE + echo "" >> $FILE +-echo "!!Advanced information - PCI Vendor/Device/Subsystem ID's" >> $FILE +-echo "!!-------------------------------------------------------" >> $FILE +-echo "" >> $FILE +-lspci -vvn |grep -A1 040[1-3] >> $FILE +-echo "" >> $FILE +-echo "" >> $FILE + fi + + if [ "$SNDOPTIONS" ] +-- +2.24.1 + + +From 86b1f80e24b68ce8153874e6ac851fa2b90c43b5 Mon Sep 17 00:00:00 2001 +From: David Ward +Date: Sat, 21 Dec 2019 00:32:02 -0500 +Subject: [PATCH 17/31] alsa-info.sh: Read from /proc/modules and sort the + result + +Sorting the list of loaded modules makes it much easier to compare +two alsa-info.txt files, even if they are both from the same system +(since the order actually changes after each reboot). + +lsmod just formats the contents of /proc/modules. After this script +calls lsmod, it strips everything but module names from the output. +This same result can be obtained just as easily by reading directly +from /proc/modules; then there is no need to remove the header line +printed by lsmod before sorting the output. + +Signed-off-by: David Ward +Signed-off-by: Takashi Iwai +--- + alsa-info/alsa-info.sh | 9 ++++----- + 1 file changed, 4 insertions(+), 5 deletions(-) + +diff --git a/alsa-info/alsa-info.sh b/alsa-info/alsa-info.sh +index 8fc6997..ed1d9e2 100755 +--- a/alsa-info/alsa-info.sh ++++ b/alsa-info/alsa-info.sh +@@ -35,7 +35,7 @@ BGTITLE="ALSA-Info v $SCRIPT_VERSION" + PASTEBINKEY="C9cRIO8m/9y8Cs0nVs0FraRx7U0pHsuc" + + WGET=$(which wget 2>/dev/null | sed 's|^[^/]*||' 2>/dev/null) +-REQUIRES="mktemp grep pgrep whereis ping awk date uname cat dmesg amixer alsactl" ++REQUIRES="mktemp grep pgrep whereis ping awk date uname cat sort dmesg amixer alsactl" + + # + # Define some simple functions +@@ -131,11 +131,11 @@ withaplay() { + echo "" >> $FILE + } + +-withlsmod() { ++withmodules() { + echo "!!All Loaded Modules" >> $FILE + echo "!!------------------" >> $FILE + echo "" >> $FILE +- lsmod | awk '{print $1}' >> $FILE ++ awk '{print $1}' < /proc/modules | sort >> $FILE + echo "" >> $FILE + echo "" >> $FILE + } +@@ -254,7 +254,7 @@ withall() { + withaplay + withamixer + withalsactl +- withlsmod ++ withmodules + withsysfs + withdmesg + WITHALL="no" +@@ -366,7 +366,6 @@ information about your ALSA installation and sound related hardware. + + dmesg + lspci +- lsmod + aplay + amixer + alsactl +-- +2.24.1 + + +From 068dd55717d4e020849e4dd12610d16968cf49be Mon Sep 17 00:00:00 2001 +From: David Ward +Date: Sat, 21 Dec 2019 00:32:03 -0500 +Subject: [PATCH 18/31] alsa-info.sh: Simplify iteration over cards when + calling amixer + +Read card names directly from individual procfs files, and pass them +to amixer using the '-c' option. + +Signed-off-by: David Ward +Signed-off-by: Takashi Iwai +--- + alsa-info/alsa-info.sh | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +diff --git a/alsa-info/alsa-info.sh b/alsa-info/alsa-info.sh +index ed1d9e2..e1067d4 100755 +--- a/alsa-info/alsa-info.sh ++++ b/alsa-info/alsa-info.sh +@@ -144,12 +144,12 @@ withamixer() { + echo "!!Amixer output" >> $FILE + echo "!!-------------" >> $FILE + echo "" >> $FILE +- for i in $(grep "]: " /proc/asound/cards | awk -F ' ' '{ print $1 }') ; do +- CARD_NAME=$(grep "^ *$i " $TEMPDIR/alsacards.tmp | awk '{ print $2 }') +- echo "!!-------Mixer controls for card $i $CARD_NAME]" >> $FILE ++ for f in /proc/asound/card*/id; do ++ [ -f "$f" ] && read -r CARD_NAME < "$f" || continue ++ echo "!!-------Mixer controls for card $CARD_NAME" >> $FILE + echo "" >>$FILE +- amixer -c$i info >> $FILE 2>&1 +- amixer -c$i >> $FILE 2>&1 ++ amixer -c "$CARD_NAME" info >> $FILE 2>&1 ++ amixer -c "$CARD_NAME" >> $FILE 2>&1 + echo "" >> $FILE + done + echo "" >> $FILE +-- +2.24.1 + + +From de5ce14163dbc1337075de1f5d632fd49865a338 Mon Sep 17 00:00:00 2001 +From: David Ward +Date: Sat, 21 Dec 2019 00:32:04 -0500 +Subject: [PATCH 19/31] alsa-info.sh: Use existing function to print ALSA + configuration files + +Signed-off-by: David Ward +Signed-off-by: Takashi Iwai +--- + alsa-info/alsa-info.sh | 27 +-------------------------- + 1 file changed, 1 insertion(+), 26 deletions(-) + +diff --git a/alsa-info/alsa-info.sh b/alsa-info/alsa-info.sh +index e1067d4..bf353de 100755 +--- a/alsa-info/alsa-info.sh ++++ b/alsa-info/alsa-info.sh +@@ -710,33 +710,8 @@ if [ -n "$1" ]; then + WITHALL="no" + ;; + --with-configs) ++ withconfigs + WITHALL="no" +- if [[ -e $HOME/.asoundrc ]] || [[ -e /etc/asound.conf ]] +- then +- echo "!!ALSA configuration files" >> $FILE +- echo "!!------------------------" >> $FILE +- echo "" >> $FILE +- +- #Check for ~/.asoundrc +- if [[ -e $HOME/.asoundrc ]] +- then +- echo "!!User specific config file ($HOME/.asoundrc)" >> $FILE +- echo "" >> $FILE +- cat $HOME/.asoundrc >> $FILE +- echo "" >> $FILE +- echo "" >> $FILE +- fi +- +- #Check for /etc/asound.conf +- if [[ -e /etc/asound.conf ]] +- then +- echo "!!System wide config file (/etc/asound.conf)" >> $FILE +- echo "" >> $FILE +- cat /etc/asound.conf >> $FILE +- echo "" >> $FILE +- echo "" >> $FILE +- fi +- fi + ;; + --stdout) + UPLOAD="no" +-- +2.24.1 + + +From e9e3c3a27d4faad0000a10386da471227b0644d8 Mon Sep 17 00:00:00 2001 +From: David Ward +Date: Sat, 21 Dec 2019 00:32:05 -0500 +Subject: [PATCH 20/31] alsa-info.sh: Exit script after writing information to + stdout + +The '--stdout' option is mutually exclusive with uploading the file. + +Signed-off-by: David Ward +Signed-off-by: Takashi Iwai +--- + alsa-info/alsa-info.sh | 17 ++++++----------- + 1 file changed, 6 insertions(+), 11 deletions(-) + +diff --git a/alsa-info/alsa-info.sh b/alsa-info/alsa-info.sh +index bf353de..372d7ae 100755 +--- a/alsa-info/alsa-info.sh ++++ b/alsa-info/alsa-info.sh +@@ -349,9 +349,7 @@ case "$1" in + ;; + --stdout) + DIALOG="" +- UPLOAD="no" + WELCOME="no" +- TOSTDOUT="yes" + ;; + esac + done +@@ -720,6 +718,7 @@ if [ -n "$1" ]; then + fi + cat $FILE + rm $FILE ++ exit + ;; + --about) + echo "Written/Tested by the following users of #alsa on irc.freenode.net:" +@@ -793,10 +792,8 @@ fi + + if [ "$UPLOAD" = "no" ]; then + +- if [ -z "$TOSTDOUT" ]; then +- mv -f $FILE $NFILE || exit 1 +- KEEP_OUTPUT="yes" +- fi ++ mv -f $FILE $NFILE || exit 1 ++ KEEP_OUTPUT="yes" + + if [[ -n $DIALOG ]] + then +@@ -815,11 +812,9 @@ if [ "$UPLOAD" = "no" ]; then + echo "Your ALSA information is in $NFILE" + echo "" + else +- if [ -z "$TOSTDOUT" ]; then +- echo "" +- echo "Your ALSA information is in $NFILE" +- echo "" +- fi ++ echo "" ++ echo "Your ALSA information is in $NFILE" ++ echo "" + fi + fi + +-- +2.24.1 + + +From d928f7667cfead36b33f38ad7668ca96c6045d4e Mon Sep 17 00:00:00 2001 +From: David Ward +Date: Sat, 21 Dec 2019 00:32:06 -0500 +Subject: [PATCH 21/31] alsa-info.sh: Replace gauge with infobox for upload + dialog + +The gauge did not actually show the upload progress; in fact, the +dialog did not even appear until after the upload was completed. + +Use an infobox instead, which will be displayed while wget runs. + +Signed-off-by: David Ward +Signed-off-by: Takashi Iwai +--- + alsa-info/alsa-info.sh | 12 ++---------- + 1 file changed, 2 insertions(+), 10 deletions(-) + +diff --git a/alsa-info/alsa-info.sh b/alsa-info/alsa-info.sh +index 372d7ae..a02864d 100755 +--- a/alsa-info/alsa-info.sh ++++ b/alsa-info/alsa-info.sh +@@ -830,19 +830,11 @@ if [[ -n $DIALOG ]] + then + + if [[ -z $PASTEBIN ]]; then ++ dialog --backtitle "$BGTITLE" --infobox "Uploading information to www.alsa-project.org ..." 6 70 + wget -O - --tries=5 --timeout=60 --post-file=$FILE "http://www.alsa-project.org/cardinfo-db/" &>$TEMPDIR/wget.tmp || echo "Upload failed; exit" +- { for i in 10 20 30 40 50 60 70 80 90; do +- echo $i +- sleep 0.2 +- done +- echo; } |dialog --backtitle "$BGTITLE" --guage "Uploading information to www.alsa-project.org ..." 6 70 0 + else ++ dialog --backtitle "$BGTITLE" --infobox "Uploading information to www.pastebin.ca ..." 6 70 + wget -O - --tries=5 --timeout=60 --post-file=$FILE "http://pastebin.ca/quiet-paste.php?api=$PASTEBINKEY&encrypt=t&encryptpw=blahblah" &>$TEMPDIR/wget.tmp || echo "Upload failed; exit" +- { for i in 10 20 30 40 50 60 70 80 90; do +- echo $i +- sleep 0.2 +- done +- echo; } |dialog --backtitle "$BGTITLE" --guage "Uploading information to www.pastebin.ca ..." 6 70 0 + fi + + dialog --backtitle "$BGTITLE" --title "Information uploaded" --yesno "Would you like to see the uploaded information?" 5 100 +-- +2.24.1 + + +From 1ebe877b8d89c74e76efd47f2a4dba6cfccf86af Mon Sep 17 00:00:00 2001 +From: David Ward +Date: Sat, 21 Dec 2019 00:32:07 -0500 +Subject: [PATCH 22/31] alsa-info.sh: Remove progress spinner during upload + without dialog + +The spinner did not actually provide information about the status +of the file upload, and caused other problems: it would repeatedly +spawn new pgrep processes (without a delay between them), and it +blocked the script if any wget process was running on the system. + +Signed-off-by: David Ward +Signed-off-by: Takashi Iwai +--- + alsa-info/alsa-info.sh | 11 +---------- + 1 file changed, 1 insertion(+), 10 deletions(-) + +diff --git a/alsa-info/alsa-info.sh b/alsa-info/alsa-info.sh +index a02864d..9bc8c38 100755 +--- a/alsa-info/alsa-info.sh ++++ b/alsa-info/alsa-info.sh +@@ -857,16 +857,7 @@ else + wget -O - --tries=5 --timeout=60 --post-file=$FILE http://pastebin.ca/quiet-paste.php?api=$PASTEBINKEY &>$TEMPDIR/wget.tmp & + fi + +-#Progess spinner for wget transfer. +-i=1 +-sp="/-\|" +-echo -n ' ' +-while pgrep wget &>/dev/null +-do +- echo -en "\b${sp:i++%${#sp}:1}" +-done +- +-echo -e "\b Done!" ++echo -e " Done!" + echo "" + + fi # dialog +-- +2.24.1 + + +From ad49ee756bbc355aa2cf7e9931c81fde17a50913 Mon Sep 17 00:00:00 2001 +From: David Ward +Date: Sat, 21 Dec 2019 00:32:08 -0500 +Subject: [PATCH 23/31] alsa-info.sh: Condense nested commands for file upload + +Signed-off-by: David Ward +Signed-off-by: Takashi Iwai +--- + alsa-info/alsa-info.sh | 16 ++++++---------- + 1 file changed, 6 insertions(+), 10 deletions(-) + +diff --git a/alsa-info/alsa-info.sh b/alsa-info/alsa-info.sh +index 9bc8c38..7560b0d 100755 +--- a/alsa-info/alsa-info.sh ++++ b/alsa-info/alsa-info.sh +@@ -828,15 +828,19 @@ then + + if [[ -n $DIALOG ]] + then ++ dialog --backtitle "$BGTITLE" --infobox "Uploading information to $WWWSERVICE ..." 6 70 ++else ++ echo -n "Uploading information to $WWWSERVICE ..." ++fi + + if [[ -z $PASTEBIN ]]; then +- dialog --backtitle "$BGTITLE" --infobox "Uploading information to www.alsa-project.org ..." 6 70 + wget -O - --tries=5 --timeout=60 --post-file=$FILE "http://www.alsa-project.org/cardinfo-db/" &>$TEMPDIR/wget.tmp || echo "Upload failed; exit" + else +- dialog --backtitle "$BGTITLE" --infobox "Uploading information to www.pastebin.ca ..." 6 70 + wget -O - --tries=5 --timeout=60 --post-file=$FILE "http://pastebin.ca/quiet-paste.php?api=$PASTEBINKEY&encrypt=t&encryptpw=blahblah" &>$TEMPDIR/wget.tmp || echo "Upload failed; exit" + fi + ++if [ -n "$DIALOG" ]; then ++ + dialog --backtitle "$BGTITLE" --title "Information uploaded" --yesno "Would you like to see the uploaded information?" 5 100 + DIALOG_EXIT_CODE=$? + if [ $DIALOG_EXIT_CODE = 0 ]; then +@@ -849,14 +853,6 @@ clear + # no dialog + else + +-if [[ -z $PASTEBIN ]]; then +- echo -n "Uploading information to www.alsa-project.org ... " +- wget -O - --tries=5 --timeout=60 --post-file=$FILE http://www.alsa-project.org/cardinfo-db/ &>$TEMPDIR/wget.tmp & +-else +- echo -n "Uploading information to www.pastebin.ca ... " +- wget -O - --tries=5 --timeout=60 --post-file=$FILE http://pastebin.ca/quiet-paste.php?api=$PASTEBINKEY &>$TEMPDIR/wget.tmp & +-fi +- + echo -e " Done!" + echo "" + +-- +2.24.1 + + +From f93d491a08c7a5c34642aac166d0329c27eaa502 Mon Sep 17 00:00:00 2001 +From: David Ward +Date: Sat, 21 Dec 2019 00:32:09 -0500 +Subject: [PATCH 24/31] alsa-info.sh: Condense nested commands for formatting + upload result + +Signed-off-by: David Ward +Signed-off-by: Takashi Iwai +--- + alsa-info/alsa-info.sh | 20 ++++++++------------ + 1 file changed, 8 insertions(+), 12 deletions(-) + +diff --git a/alsa-info/alsa-info.sh b/alsa-info/alsa-info.sh +index 7560b0d..8b4745b 100755 +--- a/alsa-info/alsa-info.sh ++++ b/alsa-info/alsa-info.sh +@@ -858,19 +858,15 @@ echo "" + + fi # dialog + +-# See if tput is available, and use it if it is. +-if [ -n "$TPUT" ]; then +- if [[ -z $PASTEBIN ]]; then +- FINAL_URL=$(tput setaf 1; grep "SUCCESS:" $TEMPDIR/wget.tmp | cut -d ' ' -f 2 ; tput sgr0) +- else +- FINAL_URL=$(tput setaf 1; grep "SUCCESS:" $TEMPDIR/wget.tmp | sed -n 's/.*\:\([0-9]\+\).*/http:\/\/pastebin.ca\/\1/p'; tput sgr0) +- fi ++if [ -z "$PASTEBIN" ]; then ++ FINAL_URL=$(grep "SUCCESS:" $TEMPDIR/wget.tmp | cut -d ' ' -f 2) + else +- if [[ -z $PASTEBIN ]]; then +- FINAL_URL=$(grep "SUCCESS:" $TEMPDIR/wget.tmp | cut -d ' ' -f 2) +- else +- FINAL_URL=$(grep "SUCCESS:" $TEMPDIR/wget.tmp | sed -n 's/.*\:\([0-9]\+\).*/http:\/\/pastebin.ca\/\1/p') +- fi ++ FINAL_URL=$(grep "SUCCESS:" $TEMPDIR/wget.tmp | sed -n 's/.*\:\([0-9]\+\).*/http:\/\/pastebin.ca\/\1/p') ++fi ++ ++# See if tput is available, and use it if it is. ++if [ -x "$TPUT" ]; then ++ FINAL_URL=$(tput setaf 1; printf '%s' "$FINAL_URL"; tput sgr0) + fi + + # Output the URL of the uploaded file. +-- +2.24.1 + + +From fe322c46e6c2ae6ce130eed70f33a42fc4f6295a Mon Sep 17 00:00:00 2001 +From: David Ward +Date: Sat, 21 Dec 2019 00:32:10 -0500 +Subject: [PATCH 25/31] alsa-info.sh: Perform test for wget earlier + +If wget is not present, do not ask about uploading the information. + +Signed-off-by: David Ward +Signed-off-by: Takashi Iwai +--- + alsa-info/alsa-info.sh | 73 ++++++++++++++++++++---------------------- + 1 file changed, 35 insertions(+), 38 deletions(-) + +diff --git a/alsa-info/alsa-info.sh b/alsa-info/alsa-info.sh +index 8b4745b..399d662 100755 +--- a/alsa-info/alsa-info.sh ++++ b/alsa-info/alsa-info.sh +@@ -769,6 +769,41 @@ if [ -z "$WITHALL" ]; then + withall + fi + ++# Check if wget is installed, and supports --post-file. ++if ! wget --help 2>/dev/null | grep -q post-file; then ++ # We couldn't find a suitable wget. If --upload was passed, tell the user to upload manually. ++ if [ "$UPLOAD" != "yes" ]; then ++ : ++ elif [ -n "$DIALOG" ]; then ++ if [ -z "$PASTEBIN" ]; then ++ dialog --backtitle "$BGTITLE" --msgbox "Could not automatically upload output to http://www.alsa-project.org.\nPossible reasons are:\n\n 1. Couldn't find 'wget' in your PATH\n 2. Your version of wget is less than 1.8.2\n\nPlease manually upload $NFILE to http://www.alsa-project.org/cardinfo-db/ and submit your post." 25 100 ++ else ++ dialog --backtitle "$BGTITLE" --msgbox "Could not automatically upload output to http://www.pastebin.ca.\nPossible reasons are:\n\n 1. Couldn't find 'wget' in your PATH\n 2. Your version of wget is less than 1.8.2\n\nPlease manually upload $NFILE to http://www.pastebin.ca/upload.php and submit your post." 25 100 ++ fi ++ else ++ if [ -z "$PASTEBIN" ]; then ++ echo "" ++ echo "Could not automatically upload output to http://www.alsa-project.org" ++ echo "Possible reasons are:" ++ echo " 1. Couldn't find 'wget' in your PATH" ++ echo " 2. Your version of wget is less than 1.8.2" ++ echo "" ++ echo "Please manually upload $NFILE to http://www.alsa-project.org/cardinfo-db/ and submit your post." ++ echo "" ++ else ++ echo "" ++ echo "Could not automatically upload output to http://www.pastebin.ca" ++ echo "Possible reasons are:" ++ echo " 1. Couldn't find 'wget' in your PATH" ++ echo " 2. Your version of wget is less than 1.8.2" ++ echo "" ++ echo "Please manually upload $NFILE to http://www.pastebin.ca/upload.php and submit your post." ++ echo "" ++ fi ++ fi ++ UPLOAD="no" ++fi ++ + if [ "$UPLOAD" = "ask" ]; then + if [ -n "$DIALOG" ]; then + dialog --backtitle "$BGTITLE" --title "Information collected" --yes-label " UPLOAD / SHARE " --no-label " SAVE LOCALLY " --defaultno --yesno "\n\nAutomatically upload ALSA information to $WWWSERVICE?" 10 80 +@@ -822,10 +857,6 @@ if [ "$UPLOAD" = "no" ]; then + + fi # UPLOAD + +-# Test that wget is installed, and supports --post-file. Upload $FILE if it does, and prompt user to upload file if it does not. +-if [[ -n "${WGET}" ]] && [[ -x "${WGET}" ]] && [[ $(wget --help | grep post-file) ]] +-then +- + if [[ -n $DIALOG ]] + then + dialog --backtitle "$BGTITLE" --infobox "Uploading information to $WWWSERVICE ..." 6 70 +@@ -873,37 +904,3 @@ fi + echo "Your ALSA information is located at $FINAL_URL" + echo "Please inform the person helping you." + echo "" +- +-# We couldnt find a suitable wget, so tell the user to upload manually. +-else +- mv -f $FILE $NFILE || exit 1 +- KEEP_OUTPUT="yes" +- if [[ -z $DIALOG ]] +- then +- if [[ -z $PASTEBIN ]]; then +- echo "" +- echo "Could not automatically upload output to http://www.alsa-project.org" +- echo "Possible reasons are:" +- echo " 1. Couldnt find 'wget' in your PATH" +- echo " 2. Your version of wget is less than 1.8.2" +- echo "" +- echo "Please manually upload $NFILE to http://www.alsa-project.org/cardinfo-db/ and submit your post." +- echo "" +- else +- echo "" +- echo "Could not automatically upload output to http://www.pastebin.ca" +- echo "Possible reasons are:" +- echo " 1. Couldnt find 'wget' in your PATH" +- echo " 2. Your version of wget is less than 1.8.2" +- echo "" +- echo "Please manually upload $NFILE to http://www.pastebin.ca/upload.php and submit your post." +- echo "" +- fi +- else +- if [[ -z $PASTEBIN ]]; then +- dialog --backtitle "$BGTITLE" --msgbox "Could not automatically upload output to http://www.alsa-project.org.\nPossible reasons are:\n\n 1. Couldn't find 'wget' in your PATH\n 2. Your version of wget is less than 1.8.2\n\nPlease manually upload $NFILE to http://www.alsa-project,org/cardinfo-db/ and submit your post." 25 100 +- else +- dialog --backtitle "$BGTITLE" --msgbox "Could not automatically upload output to http://www.pastebin.ca.\nPossible reasons are:\n\n 1. Couldn't find 'wget' in your PATH\n 2. Your version of wget is less than 1.8.2\n\nPlease manually upload $NFILE to http://www.pastebin.ca/upload.php and submit your post." 25 100 +- fi +- fi +-fi +-- +2.24.1 + + +From 27b5c6c19c8d3b4e994f258dc5e51571726ff924 Mon Sep 17 00:00:00 2001 +From: David Ward +Date: Sat, 21 Dec 2019 00:32:11 -0500 +Subject: [PATCH 26/31] alsa-info.sh: Warn after actual upload failure; do not + ping server + +Check the return value of wget to determine if the upload actually +failed. If so, display the message about upload failure, then exit. + +Do not ping the web server; the result does not indicate whether a +file upload will succeed or not. + +Signed-off-by: David Ward +Signed-off-by: Takashi Iwai +--- + alsa-info/alsa-info.sh | 58 ++++++++++++++++++------------------------ + 1 file changed, 25 insertions(+), 33 deletions(-) + +diff --git a/alsa-info/alsa-info.sh b/alsa-info/alsa-info.sh +index 399d662..7bae30a 100755 +--- a/alsa-info/alsa-info.sh ++++ b/alsa-info/alsa-info.sh +@@ -35,22 +35,12 @@ BGTITLE="ALSA-Info v $SCRIPT_VERSION" + PASTEBINKEY="C9cRIO8m/9y8Cs0nVs0FraRx7U0pHsuc" + + WGET=$(which wget 2>/dev/null | sed 's|^[^/]*||' 2>/dev/null) +-REQUIRES="mktemp grep pgrep whereis ping awk date uname cat sort dmesg amixer alsactl" ++REQUIRES="mktemp grep pgrep whereis awk date uname cat sort dmesg amixer alsactl" + + # + # Define some simple functions + # + +-pbcheck() { +- [[ $UPLOAD = "no" ]] && return +- +- if [[ -z $PASTEBIN ]]; then +- [[ $(ping -c1 www.alsa-project.org) ]] || KEEP_FILES="yes" UPLOAD="no" PBERROR="yes" +- else +- [[ $(ping -c1 www.pastebin.ca) ]] || KEEP_FILES="yes" UPLOAD="no" PBERROR="yes" +- fi +-} +- + update() { + test -z "$WGET" -o ! -x "$WGET" && return + +@@ -650,7 +640,6 @@ fi + #If no command line options are specified, then run as though --with-all was specified + if [ -z "$1" ]; then + update +- pbcheck + fi + + fi # proceed +@@ -662,7 +651,6 @@ if [ -n "$1" ]; then + case "$1" in + --pastebin) + update +- pbcheck + ;; + --update) + update +@@ -832,25 +820,11 @@ if [ "$UPLOAD" = "no" ]; then + + if [[ -n $DIALOG ]] + then +- if [[ -n $PBERROR ]]; then +- dialog --backtitle "$BGTITLE" --title "Information collected" --msgbox "An error occurred while contacting the $WWWSERVICE.\n Your information was NOT automatically uploaded.\n\nYour ALSA information is in $NFILE" 10 100 +- else +- dialog --backtitle "$BGTITLE" --title "Information collected" --msgbox "\n\nYour ALSA information is in $NFILE" 10 60 +- fi ++ dialog --backtitle "$BGTITLE" --title "Information collected" --msgbox "\n\nYour ALSA information is in $NFILE" 10 60 + else +- echo +- +- if [[ -n $PBERROR ]]; then +- echo "An error occurred while contacting the $WWWSERVICE." +- echo "Your information was NOT automatically uploaded." +- echo "" +- echo "Your ALSA information is in $NFILE" +- echo "" +- else +- echo "" +- echo "Your ALSA information is in $NFILE" +- echo "" +- fi ++ echo "" ++ echo "Your ALSA information is in $NFILE" ++ echo "" + fi + + exit +@@ -865,9 +839,27 @@ else + fi + + if [[ -z $PASTEBIN ]]; then +- wget -O - --tries=5 --timeout=60 --post-file=$FILE "http://www.alsa-project.org/cardinfo-db/" &>$TEMPDIR/wget.tmp || echo "Upload failed; exit" ++ wget -O - --tries=5 --timeout=60 --post-file=$FILE "http://www.alsa-project.org/cardinfo-db/" &>$TEMPDIR/wget.tmp + else +- wget -O - --tries=5 --timeout=60 --post-file=$FILE "http://pastebin.ca/quiet-paste.php?api=$PASTEBINKEY&encrypt=t&encryptpw=blahblah" &>$TEMPDIR/wget.tmp || echo "Upload failed; exit" ++ wget -O - --tries=5 --timeout=60 --post-file=$FILE "http://pastebin.ca/quiet-paste.php?api=$PASTEBINKEY&encrypt=t&encryptpw=blahblah" &>$TEMPDIR/wget.tmp ++fi ++ ++if [ $? -ne 0 ]; then ++ mv -f $FILE $NFILE || exit 1 ++ KEEP_OUTPUT="yes" ++ ++ if [ -n "$DIALOG" ]; then ++ dialog --backtitle "$BGTITLE" --title "Information not uploaded" --msgbox "An error occurred while contacting $WWWSERVICE.\n Your information was NOT automatically uploaded.\n\nYour ALSA information is in $NFILE" 10 100 ++ else ++ echo "" ++ echo "An error occurred while contacting $WWWSERVICE." ++ echo "Your information was NOT automatically uploaded." ++ echo "" ++ echo "Your ALSA information is in $NFILE" ++ echo "" ++ fi ++ ++ exit + fi + + if [ -n "$DIALOG" ]; then +-- +2.24.1 + + +From cbabe7a3f0cc84ecd352d4cbf85148946fa6c0d5 Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Thu, 19 Dec 2019 15:36:05 +0100 +Subject: [PATCH 27/31] alsatplg: rewrite to use the new libatopology functions + +Add '-u,--dump' operation. +Add '-g,--group' and '-x,--nocheck' modifiers. +Add '-z,--dapm-nosort' modifier. +Allow to operate with stdin/stdout for the file input/output. + +Signed-off-by: Jaroslav Kysela +--- + topology/alsatplg.rst | 17 ++- + topology/topology.c | 304 +++++++++++++++++++++++++----------------- + 2 files changed, 199 insertions(+), 122 deletions(-) + +diff --git a/topology/alsatplg.rst b/topology/alsatplg.rst +index 855edff..e09c865 100644 +--- a/topology/alsatplg.rst ++++ b/topology/alsatplg.rst +@@ -50,12 +50,27 @@ Available options: + **-c**, **--compile** `FILE` + source configuration file for the compilation + ++ **-n**, **--normalize** `FILE` ++ parse and save the configuration file in the normalized format ++ ++ **-u**, **--dump** `FILE` ++ parse and save the configuration file in the specified format ++ + **-o**, **--output** `FILE` +- output binary file ++ output file + + **-v**, **--verbose** `LEVEL` + set verbose level + ++ **-s**, **--sort** ++ sort the configuration identifiers (set for normalization) ++ ++ **-x**, **--nocheck** ++ save the configuration without additional integrity check ++ ++ **-z**, **--dapm-nosort** ++ do not sort DAPM graph items (like in version 1.2.1-) ++ + + FILES + ===== +diff --git a/topology/topology.c b/topology/topology.c +index bc5797c..a94941a 100644 +--- a/topology/topology.c ++++ b/topology/topology.c +@@ -1,4 +1,5 @@ + /* ++ Copyright(c) 2019 Red Hat Inc. + Copyright(c) 2014-2015 Intel Corporation + Copyright(c) 2010-2011 Texas Instruments Incorporated, + All rights reserved. +@@ -44,165 +45,205 @@ _("Usage: %s [OPTIONS]...\n" + "-h, --help help\n" + "-c, --compile=FILE compile file\n" + "-n, --normalize=FILE normalize file\n" ++"-u, --dump=FILE dump (reparse) file\n" + "-v, --verbose=LEVEL set verbosity level (0...1)\n" + "-o, --output=FILE set output file\n" + "-s, --sort sort the identifiers in the normalized output\n" ++"-g, --group save configuration by group indexes\n" ++"-x, --nocheck save configuration without additional integrity checks\n" + ), name); + } + +-static int _compar(const void *a, const void *b) ++static int load(snd_tplg_t **tplg, const char *source_file, int cflags) + { +- const snd_config_t *c1 = *(snd_config_t **)a; +- const snd_config_t *c2 = *(snd_config_t **)b; +- const char *id1, *id2; +- if (snd_config_get_id(c1, &id1)) return 0; +- if (snd_config_get_id(c2, &id2)) return 0; +- return strcmp(id1, id2); +-} ++ int fd, err; ++ char *buf, *buf2; ++ size_t size, pos; ++ ssize_t r; + +-static snd_config_t *normalize_config(const char *id, snd_config_t *src, int sort) +-{ +- snd_config_t *dst, **a; +- snd_config_iterator_t i, next; +- int index, count; +- +- if (snd_config_get_type(src) != SND_CONFIG_TYPE_COMPOUND) { +- if (snd_config_copy(&dst, src) >= 0) +- return dst; +- return NULL; +- } +- count = 0; +- snd_config_for_each(i, next, src) +- count++; +- a = malloc(sizeof(dst) * count); +- if (a == NULL) +- return NULL; +- index = 0; +- snd_config_for_each(i, next, src) { +- snd_config_t *s = snd_config_iterator_entry(i); +- a[index++] = s; +- } +- if (sort) +- qsort(a, count, sizeof(a[0]), _compar); +- if (snd_config_make_compound(&dst, id, count == 1)) { +- free(a); +- return NULL; +- } +- for (index = 0; index < count; index++) { +- snd_config_t *s = a[index]; +- const char *id2; +- if (snd_config_get_id(s, &id2)) { +- snd_config_delete(dst); +- free(a); +- return NULL; +- } +- s = normalize_config(id2, s, sort); +- if (s == NULL || snd_config_add(dst, s)) { +- if (s) +- snd_config_delete(s); +- snd_config_delete(dst); +- free(a); +- return NULL; ++ if (strcmp(source_file, "-") == 0) { ++ fd = fileno(stdin); ++ } else { ++ fd = open(source_file, O_RDONLY); ++ if (fd < 0) { ++ fprintf(stderr, _("Unable to open input file '%s': %s\n"), ++ source_file, strerror(-errno)); ++ return 1; + } + } +- free(a); +- return dst; +-} + +-static int compile(const char *source_file, const char *output_file, int verbose) +-{ +- snd_tplg_t *snd_tplg; +- int err; ++ size = 16*1024; ++ pos = 0; ++ buf = malloc(size); ++ if (buf == NULL) ++ goto _nomem; ++ while (1) { ++ r = read(fd, buf + pos, size - pos); ++ if (r < 0 && (errno == EAGAIN || errno == EINTR)) ++ continue; ++ if (r <= 0) ++ break; ++ pos += r; ++ size += 8*1024; ++ buf2 = realloc(buf, size); ++ if (buf2 == NULL) { ++ free(buf); ++ goto _nomem; ++ } ++ buf = buf2; ++ } ++ if (fd != fileno(stdin)) ++ close(fd); ++ if (r < 0) { ++ fprintf(stderr, _("Read error: %s\n"), strerror(-errno)); ++ free(buf); ++ goto _err; ++ } + +- snd_tplg = snd_tplg_new(); +- if (snd_tplg == NULL) { ++ *tplg = snd_tplg_create(cflags); ++ if (*tplg == NULL) { + fprintf(stderr, _("failed to create new topology context\n")); ++ free(buf); + return 1; + } + +- snd_tplg_verbose(snd_tplg, verbose); +- +- err = snd_tplg_build_file(snd_tplg, source_file, output_file); ++ err = snd_tplg_load(*tplg, buf, pos); ++ free(buf); + if (err < 0) { +- fprintf(stderr, _("failed to compile context %s\n"), source_file); +- snd_tplg_free(snd_tplg); +- unlink(output_file); ++ fprintf(stderr, _("Unable to load configuration: %s\n"), ++ snd_strerror(-err)); ++ snd_tplg_free(*tplg); + return 1; + } + +- snd_tplg_free(snd_tplg); ++ return 0; ++ ++_nomem: ++ fprintf(stderr, _("No enough memory\n")); ++_err: ++ if (fd != fileno(stdin)) ++ close(fd); ++ free(buf); + return 1; + } + +-static int normalize(const char *source_file, const char *output_file, int sort) ++static int save(const char *output_file, void *buf, size_t size) + { +- snd_input_t *input; +- snd_output_t *output; +- snd_config_t *top, *norm; +- int err; ++ char *fname = NULL; ++ int fd; ++ ssize_t r; + +- err = snd_input_stdio_open(&input, source_file, "r"); +- if (err < 0) { +- fprintf(stderr, "Unable to open source file '%s': %s\n", source_file, snd_strerror(-err)); +- return 0; ++ if (strcmp(output_file, "-") == 0) { ++ fd = fileno(stdout); ++ } else { ++ fname = alloca(strlen(output_file) + 5); ++ strcpy(fname, output_file); ++ strcat(fname, ".new"); ++ fd = open(fname, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR); ++ if (fd < 0) { ++ fprintf(stderr, _("Unable to open output file '%s': %s\n"), ++ fname, strerror(-errno)); ++ return 1; ++ } + } + +- err = snd_config_top(&top); +- if (err < 0) { +- snd_input_close(input); +- return 1; ++ r = 0; ++ while (size > 0) { ++ r = write(fd, buf, size); ++ if (r < 0 && (errno == EAGAIN || errno == EINTR)) ++ continue; ++ if (r < 0) ++ break; ++ size -= r; ++ buf += r; + } + +- err = snd_config_load(top, input); +- snd_input_close(input); +- if (err < 0) { +- snd_config_delete(top); +- fprintf(stderr, "Unable to parse source file '%s': %s\n", source_file, snd_strerror(-err)); +- snd_config_delete(top); ++ if (r < 0) { ++ fprintf(stderr, _("Write error: %s\n"), strerror(-errno)); ++ if (fd != fileno(stdout)) { ++ remove(fname); ++ close(fd); ++ } + return 1; + } + +- err = snd_output_stdio_open(&output, output_file, "w+"); +- if (err < 0) { +- fprintf(stderr, "Unable to open output file '%s': %s\n", output_file, snd_strerror(-err)); +- snd_config_delete(top); +- return 1; +- } ++ if (fd != fileno(stdout)) ++ close(fd); + +- norm = normalize_config(NULL, top, sort); +- if (norm == NULL) { +- fprintf(stderr, "Unable to normalize configuration (out of memory?)\n"); +- snd_output_close(output); +- snd_config_delete(top); ++ if (fname && rename(fname, output_file)) { ++ fprintf(stderr, _("Unable to rename file '%s' to '%s': %s\n"), ++ fname, output_file, strerror(-errno)); + return 1; + } + +- err = snd_config_save(norm, output); +- snd_output_close(output); +- snd_config_delete(norm); +- snd_config_delete(top); ++ return 0; ++} ++ ++static int dump(const char *source_file, const char *output_file, int cflags, int sflags) ++{ ++ snd_tplg_t *tplg; ++ char *text; ++ int err; ++ ++ err = load(&tplg, source_file, cflags); ++ if (err) ++ return err; ++ err = snd_tplg_save(tplg, &text, sflags); ++ snd_tplg_free(tplg); + if (err < 0) { +- fprintf(stderr, "Unable to save normalized contents: %s\n", snd_strerror(-err)); ++ fprintf(stderr, _("Unable to save parsed configuration: %s\n"), ++ snd_strerror(-err)); + return 1; + } ++ err = save(output_file, text, strlen(text)); ++ free(text); ++ return err; ++} + +- return 0; ++static int compile(const char *source_file, const char *output_file, int cflags) ++{ ++ snd_tplg_t *tplg; ++ void *bin; ++ size_t size; ++ int err; ++ ++ err = load(&tplg, source_file, cflags); ++ if (err) ++ return err; ++ err = snd_tplg_build_bin(tplg, &bin, &size); ++ snd_tplg_free(tplg); ++ if (err < 0 || size == 0) { ++ fprintf(stderr, _("failed to compile context %s\n"), source_file); ++ return 1; ++ } ++ err = save(output_file, bin, size); ++ free(bin); ++ return err; + } + ++#define OP_COMPILE 1 ++#define OP_NORMALIZE 2 ++#define OP_DUMP 3 ++ + int main(int argc, char *argv[]) + { +- static const char short_options[] = "hc:n:v:o:s"; ++ static const char short_options[] = "hc:n:u:v:o:sgxz"; + static const struct option long_options[] = { + {"help", 0, NULL, 'h'}, + {"verbose", 1, NULL, 'v'}, + {"compile", 1, NULL, 'c'}, + {"normalize", 1, NULL, 'n'}, ++ {"dump", 1, NULL, 'u'}, + {"output", 1, NULL, 'o'}, + {"sort", 0, NULL, 's'}, ++ {"group", 0, NULL, 'g'}, ++ {"nocheck", 0, NULL, 'x'}, ++ {"dapm-nosort", 0, NULL, 'z'}, + {0, 0, 0, 0}, + }; +- char *source_file = NULL, *normalize_file = NULL, *output_file = NULL; +- int c, err, verbose = 0, sort = 0, option_index; ++ char *source_file = NULL; ++ char *output_file = NULL; ++ int c, err, op = 'c', cflags = 0, sflags = 0, option_index; + + #ifdef ENABLE_NLS + setlocale(LC_ALL, ""); +@@ -218,19 +259,32 @@ int main(int argc, char *argv[]) + usage(argv[0]); + return 0; + case 'v': +- verbose = atoi(optarg); ++ cflags |= SND_TPLG_CREATE_VERBOSE; + break; +- case 'c': +- source_file = optarg; ++ case 'z': ++ cflags |= SND_TPLG_CREATE_DAPM_NOSORT; + break; ++ case 'c': + case 'n': +- normalize_file = optarg; ++ case 'u': ++ if (source_file) { ++ fprintf(stderr, _("Cannot combine operations (compile, normalize, dump)\n")); ++ return 1; ++ } ++ source_file = optarg; ++ op = c; + break; + case 'o': + output_file = optarg; + break; + case 's': +- sort = 1; ++ sflags |= SND_TPLG_SAVE_SORT; ++ break; ++ case 'g': ++ sflags |= SND_TPLG_SAVE_GROUPS; ++ break; ++ case 'x': ++ sflags |= SND_TPLG_SAVE_NOCHECK; + break; + default: + fprintf(stderr, _("Try `%s --help' for more information.\n"), argv[0]); +@@ -238,21 +292,29 @@ int main(int argc, char *argv[]) + } + } + +- if (source_file && normalize_file) { +- fprintf(stderr, "Cannot normalize and compile at a time!\n"); ++ if (source_file == NULL || output_file == NULL) { ++ usage(argv[0]); + return 1; + } + +- if ((source_file == NULL && normalize_file == NULL) || output_file == NULL) { +- usage(argv[0]); +- return 1; ++ if (op == 'n') { ++ if (sflags != 0 && sflags != SND_TPLG_SAVE_SORT) { ++ fprintf(stderr, _("Wrong parameters for the normalize operation!\n")); ++ return 1; ++ } ++ /* normalize has predefined output */ ++ sflags = SND_TPLG_SAVE_SORT; + } + +- if (source_file) +- err = compile(source_file, output_file, verbose); +- else +- err = normalize(normalize_file, output_file, sort); ++ switch (op) { ++ case 'c': ++ err = compile(source_file, output_file, cflags); ++ break; ++ default: ++ err = dump(source_file, output_file, cflags, sflags); ++ break; ++ } + + snd_output_close(log); +- return 0; ++ return err ? 1 : 0; + } +-- +2.24.1 + + +From 32e7016fd710f6ed9d514100c7c05453974036d0 Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Fri, 20 Dec 2019 15:23:27 +0100 +Subject: [PATCH 28/31] alsatplg: add -V,--version option + +Signed-off-by: Jaroslav Kysela +--- + topology/alsatplg.rst | 3 +++ + topology/topology.c | 20 ++++++++++++++++++-- + 2 files changed, 21 insertions(+), 2 deletions(-) + +diff --git a/topology/alsatplg.rst b/topology/alsatplg.rst +index e09c865..260454b 100644 +--- a/topology/alsatplg.rst ++++ b/topology/alsatplg.rst +@@ -47,6 +47,9 @@ Available options: + **-h**, **--help** + this help + ++ **-V**, **--version** ++ show the utility version and versions of used libraries ++ + **-c**, **--compile** `FILE` + source configuration file for the compilation + +diff --git a/topology/topology.c b/topology/topology.c +index a94941a..101f8cc 100644 +--- a/topology/topology.c ++++ b/topology/topology.c +@@ -34,10 +34,11 @@ + #include + #include + #include "gettext.h" ++#include "version.h" + + static snd_output_t *log; + +-static void usage(char *name) ++static void usage(const char *name) + { + printf( + _("Usage: %s [OPTIONS]...\n" +@@ -51,9 +52,20 @@ _("Usage: %s [OPTIONS]...\n" + "-s, --sort sort the identifiers in the normalized output\n" + "-g, --group save configuration by group indexes\n" + "-x, --nocheck save configuration without additional integrity checks\n" ++"-V, --version print version\n" + ), name); + } + ++static void version(const char *name) ++{ ++ printf( ++_("%s version %s\n" ++"libasound version %s\n" ++"libatopology version %s\n" ++), name, SND_UTIL_VERSION_STR, ++ snd_asoundlib_version(), snd_tplg_version()); ++} ++ + static int load(snd_tplg_t **tplg, const char *source_file, int cflags) + { + int fd, err; +@@ -227,7 +239,7 @@ static int compile(const char *source_file, const char *output_file, int cflags) + + int main(int argc, char *argv[]) + { +- static const char short_options[] = "hc:n:u:v:o:sgxz"; ++ static const char short_options[] = "hc:n:u:v:o:sgxzV"; + static const struct option long_options[] = { + {"help", 0, NULL, 'h'}, + {"verbose", 1, NULL, 'v'}, +@@ -239,6 +251,7 @@ int main(int argc, char *argv[]) + {"group", 0, NULL, 'g'}, + {"nocheck", 0, NULL, 'x'}, + {"dapm-nosort", 0, NULL, 'z'}, ++ {"version", 0, NULL, 'V'}, + {0, 0, 0, 0}, + }; + char *source_file = NULL; +@@ -286,6 +299,9 @@ int main(int argc, char *argv[]) + case 'x': + sflags |= SND_TPLG_SAVE_NOCHECK; + break; ++ case 'V': ++ version(argv[0]); ++ return 0; + default: + fprintf(stderr, _("Try `%s --help' for more information.\n"), argv[0]); + return 1; +-- +2.24.1 + + +From 786c3ee8144893dfb56b35c46542d3ded78d746c Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Sun, 22 Dec 2019 15:44:56 +0100 +Subject: [PATCH 29/31] alsatplg: add decode command + +Signed-off-by: Jaroslav Kysela +--- + topology/alsatplg.rst | 3 ++ + topology/topology.c | 111 ++++++++++++++++++++++++++++++++---------- + 2 files changed, 87 insertions(+), 27 deletions(-) + +diff --git a/topology/alsatplg.rst b/topology/alsatplg.rst +index 260454b..56324d5 100644 +--- a/topology/alsatplg.rst ++++ b/topology/alsatplg.rst +@@ -53,6 +53,9 @@ Available options: + **-c**, **--compile** `FILE` + source configuration file for the compilation + ++ **-d**, **--decode** `FILE` ++ source binary topology file for the decode ++ + **-n**, **--normalize** `FILE` + parse and save the configuration file in the normalized format + +diff --git a/topology/topology.c b/topology/topology.c +index 101f8cc..91d2fce 100644 +--- a/topology/topology.c ++++ b/topology/topology.c +@@ -44,9 +44,10 @@ static void usage(const char *name) + _("Usage: %s [OPTIONS]...\n" + "\n" + "-h, --help help\n" +-"-c, --compile=FILE compile file\n" +-"-n, --normalize=FILE normalize file\n" +-"-u, --dump=FILE dump (reparse) file\n" ++"-c, --compile=FILE compile configuration file\n" ++"-d, --decode=FILE decode binary topology file\n" ++"-n, --normalize=FILE normalize configuration file\n" ++"-u, --dump=FILE dump (reparse) configuration file\n" + "-v, --verbose=LEVEL set verbosity level (0...1)\n" + "-o, --output=FILE set output file\n" + "-s, --sort sort the identifiers in the normalized output\n" +@@ -66,10 +67,10 @@ _("%s version %s\n" + snd_asoundlib_version(), snd_tplg_version()); + } + +-static int load(snd_tplg_t **tplg, const char *source_file, int cflags) ++static int load(const char *source_file, void **dst, size_t *dst_size) + { +- int fd, err; +- char *buf, *buf2; ++ int fd; ++ void *buf, *buf2; + size_t size, pos; + ssize_t r; + +@@ -112,15 +113,31 @@ static int load(snd_tplg_t **tplg, const char *source_file, int cflags) + goto _err; + } + ++ *dst = buf; ++ *dst_size = pos; ++ return 0; ++ ++_nomem: ++ fprintf(stderr, _("No enough memory\n")); ++_err: ++ if (fd != fileno(stdin)) ++ close(fd); ++ free(buf); ++ return 1; ++} ++ ++static int load_topology(snd_tplg_t **tplg, char *config, ++ size_t config_size, int cflags) ++{ ++ int err; ++ + *tplg = snd_tplg_create(cflags); + if (*tplg == NULL) { + fprintf(stderr, _("failed to create new topology context\n")); +- free(buf); + return 1; + } + +- err = snd_tplg_load(*tplg, buf, pos); +- free(buf); ++ err = snd_tplg_load(*tplg, config, config_size); + if (err < 0) { + fprintf(stderr, _("Unable to load configuration: %s\n"), + snd_strerror(-err)); +@@ -129,14 +146,6 @@ static int load(snd_tplg_t **tplg, const char *source_file, int cflags) + } + + return 0; +- +-_nomem: +- fprintf(stderr, _("No enough memory\n")); +-_err: +- if (fd != fileno(stdin)) +- close(fd); +- free(buf); +- return 1; + } + + static int save(const char *output_file, void *buf, size_t size) +@@ -194,10 +203,15 @@ static int save(const char *output_file, void *buf, size_t size) + static int dump(const char *source_file, const char *output_file, int cflags, int sflags) + { + snd_tplg_t *tplg; +- char *text; ++ char *config, *text; ++ size_t size; + int err; + +- err = load(&tplg, source_file, cflags); ++ err = load(source_file, (void **)&config, &size); ++ if (err) ++ return err; ++ err = load_topology(&tplg, config, size, cflags); ++ free(config); + if (err) + return err; + err = snd_tplg_save(tplg, &text, sflags); +@@ -215,17 +229,23 @@ static int dump(const char *source_file, const char *output_file, int cflags, in + static int compile(const char *source_file, const char *output_file, int cflags) + { + snd_tplg_t *tplg; ++ char *config; + void *bin; +- size_t size; ++ size_t config_size, size; + int err; + +- err = load(&tplg, source_file, cflags); ++ err = load(source_file, (void **)&config, &config_size); ++ if (err) ++ return err; ++ err = load_topology(&tplg, config, config_size, cflags); ++ free(config); + if (err) + return err; + err = snd_tplg_build_bin(tplg, &bin, &size); + snd_tplg_free(tplg); + if (err < 0 || size == 0) { +- fprintf(stderr, _("failed to compile context %s\n"), source_file); ++ fprintf(stderr, _("failed to compile context %s: %s\n"), ++ source_file, snd_strerror(-err)); + return 1; + } + err = save(output_file, bin, size); +@@ -233,17 +253,50 @@ static int compile(const char *source_file, const char *output_file, int cflags) + return err; + } + +-#define OP_COMPILE 1 +-#define OP_NORMALIZE 2 +-#define OP_DUMP 3 ++static int decode(const char *source_file, const char *output_file, ++ int cflags, int dflags, int sflags) ++{ ++ snd_tplg_t *tplg; ++ void *bin; ++ char *text; ++ size_t size; ++ int err; ++ ++ if (load(source_file, &bin, &size)) ++ return 1; ++ tplg = snd_tplg_create(cflags); ++ if (tplg == NULL) { ++ fprintf(stderr, _("failed to create new topology context\n")); ++ return 1; ++ } ++ err = snd_tplg_decode(tplg, bin, size, dflags); ++ free(bin); ++ if (err < 0) { ++ snd_tplg_free(tplg); ++ fprintf(stderr, _("failed to decode context %s: %s\n"), ++ source_file, snd_strerror(-err)); ++ return 1; ++ } ++ err = snd_tplg_save(tplg, &text, sflags); ++ snd_tplg_free(tplg); ++ if (err < 0) { ++ fprintf(stderr, _("Unable to save parsed configuration: %s\n"), ++ snd_strerror(-err)); ++ return 1; ++ } ++ err = save(output_file, text, strlen(text)); ++ free(text); ++ return err; ++} + + int main(int argc, char *argv[]) + { +- static const char short_options[] = "hc:n:u:v:o:sgxzV"; ++ static const char short_options[] = "hc:d:n:u:v:o:sgxzV"; + static const struct option long_options[] = { + {"help", 0, NULL, 'h'}, + {"verbose", 1, NULL, 'v'}, + {"compile", 1, NULL, 'c'}, ++ {"decode", 1, NULL, 'd'}, + {"normalize", 1, NULL, 'n'}, + {"dump", 1, NULL, 'u'}, + {"output", 1, NULL, 'o'}, +@@ -256,7 +309,7 @@ int main(int argc, char *argv[]) + }; + char *source_file = NULL; + char *output_file = NULL; +- int c, err, op = 'c', cflags = 0, sflags = 0, option_index; ++ int c, err, op = 'c', cflags = 0, dflags = 0, sflags = 0, option_index; + + #ifdef ENABLE_NLS + setlocale(LC_ALL, ""); +@@ -278,6 +331,7 @@ int main(int argc, char *argv[]) + cflags |= SND_TPLG_CREATE_DAPM_NOSORT; + break; + case 'c': ++ case 'd': + case 'n': + case 'u': + if (source_file) { +@@ -326,6 +380,9 @@ int main(int argc, char *argv[]) + case 'c': + err = compile(source_file, output_file, cflags); + break; ++ case 'd': ++ err = decode(source_file, output_file, cflags, dflags, sflags); ++ break; + default: + err = dump(source_file, output_file, cflags, sflags); + break; +-- +2.24.1 + + +From 56e1b879d4bccda62e7c0177b0a395d57a37931c Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Wed, 1 Jan 2020 17:45:06 +0100 +Subject: [PATCH 30/31] alsatplg: add documentation for -z,--dapm-nosort (-h) + +Signed-off-by: Jaroslav Kysela +--- + topology/topology.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/topology/topology.c b/topology/topology.c +index 91d2fce..ad0d108 100644 +--- a/topology/topology.c ++++ b/topology/topology.c +@@ -53,6 +53,7 @@ _("Usage: %s [OPTIONS]...\n" + "-s, --sort sort the identifiers in the normalized output\n" + "-g, --group save configuration by group indexes\n" + "-x, --nocheck save configuration without additional integrity checks\n" ++"-z, --dapm-nosort do not sort the DAPM widgets\n" + "-V, --version print version\n" + ), name); + } +-- +2.24.1 + + +From 996a638e04766df43cb8026673f93927b1047639 Mon Sep 17 00:00:00 2001 +From: Jaroslav Kysela +Date: Fri, 3 Jan 2020 23:46:51 +0100 +Subject: [PATCH 31/31] configure: fix new libatopology check + +--- + configure.ac | 6 +----- + 1 file changed, 1 insertion(+), 5 deletions(-) + +diff --git a/configure.ac b/configure.ac +index 4bee49b..b7ed81a 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -49,6 +49,7 @@ AC_CHECK_LIB([asound], [snd_seq_client_info_get_pid], [HAVE_SEQ_CLIENT_INFO_GET_ + if test "$HAVE_SEQ_CLIENT_INFO_GET_PID" = "yes" ; then + AC_DEFINE([HAVE_SEQ_CLIENT_INFO_GET_PID], 1, [alsa-lib supports snd_seq_client_info_get_pid]) + fi ++AC_CHECK_LIB([atopology], [snd_tplg_save], [have_topology="no"]) + + # + # NOTE: The library 'libffado' (at least v2.4.1) executes ctor/dtor of instances +@@ -70,11 +71,6 @@ AM_CONDITIONAL(HAVE_TOPOLOGY, test "$have_topology" = "yes") + AM_CONDITIONAL(HAVE_SAMPLERATE, test "$have_samplerate" = "yes") + AM_CONDITIONAL(HAVE_FFADO, test "$have_ffado" = "yes") + +-# old libasound with the topology routines in the main library +-if test "x$have_topology" = "xyes" -a "x$ALSA_TOPOLOGY_LIBS" = "x"; then +- ALSA_TOPOLOGY_LIBS="$ALSA_LIBS" +-fi +- + dnl Use tinyalsa + alsabat_backend_tiny= + AC_ARG_ENABLE(alsabat_backend_tiny, +-- +2.24.1 diff --git a/alsa-utils.spec b/alsa-utils.spec index 086461d..94dc7dc 100644 --- a/alsa-utils.spec +++ b/alsa-utils.spec @@ -5,7 +5,7 @@ Summary: Advanced Linux Sound Architecture (ALSA) utilities Name: alsa-utils Version: %{baseversion}%{?fixversion} -Release: 5%{?dist} +Release: 6%{?dist} License: GPLv2+ URL: http://www.alsa-project.org/ Source: ftp://ftp.alsa-project.org/pub/utils/alsa-utils-%{version}.tar.bz2 @@ -61,7 +61,7 @@ Architecture (ALSA) framework and Fast Fourier Transform library. %prep %setup -q -n %{name}-%{version} -#%patch1 -p1 +%patch1 -p1 %build %configure CFLAGS="$RPM_OPT_FLAGS -D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64" --disable-alsaconf \ @@ -195,6 +195,9 @@ fi %systemd_postun_with_restart alsa-state.service %changelog +* Sun Feb 9 2020 Jaroslav Kysela - 1.2.1-6 +- UCM and topology fixes + * Tue Jan 28 2020 Fedora Release Engineering - 1.2.1-5 - Rebuilt for https://fedoraproject.org/wiki/Fedora_32_Mass_Rebuild