SHA256
1
0
forked from pool/alsa-utils
alsa-utils/0009-alsaucm-add-json-dump-command.patch
Takashi Iwai 7200ea9d85 Accepting request 766332 from home:tiwai:branches:multimedia:libs
- Backport upstream patches:
  A few portability fixes, alsaucm fixes and extensions, alsatplg
  minor fixes, alsa-info.sh extensions:
  0001-treewide-sys-poll-to-poll.patch
  0002-treewide-Fix-wrong-formats-on-32-bit.patch
  0003-treewide-Fix-printf-formats.patch
  0004-aplay-Adjust-buffer-sizes-to-fix-snprintf-warnings.patch
  0005-aplay-Limit-VUMeter-progress-bar-to-100-for-negative.patch
  0006-alsactl-sysfs-add-sys-kernel-uevent_seqnum-check-to-.patch
  0007-alsaucm-use-the-first-sound-card-use-case-name-hw-CA.patch
  0008-alsaucm-add-text-dump-command.patch
  0009-alsaucm-add-json-dump-command.patch
  0010-alsaucm-dump-fix-the-prefixed.patch
  0011-alsactl-fix-sched-idle-set-it-really-to-SCHED_IDLE.patch
  0012-configure-Fix-linking-of-alsatplg-with-the-older-lib.patch
  0013-alsatplg-add-n-normalize-option.patch
  0014-alsatplg-add-s-sort-and-fix-memory-leaks.patch
  0015-alsatplg-fix-another-small-leak-in-normalize_config.patch
  0016-alsa-info.sh-Consolidate-PCI-device-output.patch
  0017-alsa-info.sh-Read-from-proc-modules-and-sort-the-res.patch
  0018-alsa-info.sh-Simplify-iteration-over-cards-when-call.patch
  0019-alsa-info.sh-Use-existing-function-to-print-ALSA-con.patch
  0020-alsa-info.sh-Exit-script-after-writing-information-t.patch
  0021-alsa-info.sh-Replace-gauge-with-infobox-for-upload-d.patch
  0022-alsa-info.sh-Remove-progress-spinner-during-upload-w.patch
  0023-alsa-info.sh-Condense-nested-commands-for-file-uploa.patch
  0024-alsa-info.sh-Condense-nested-commands-for-formatting.patch
  0025-alsa-info.sh-Perform-test-for-wget-earlier.patch
  0026-alsa-info.sh-Warn-after-actual-upload-failure-do-not.patch

OBS-URL: https://build.opensuse.org/request/show/766332
OBS-URL: https://build.opensuse.org/package/show/multimedia:libs/alsa-utils?expand=0&rev=165
2020-01-22 14:28:06 +00:00

359 lines
8.9 KiB
Diff

From 49716fa61e9ddc67476d40f9ea84f07fe0017748 Mon Sep 17 00:00:00 2001
From: Jaroslav Kysela <perex@perex.cz>
Date: Sat, 30 Nov 2019 20:30:33 +0100
Subject: [PATCH 09/26] alsaucm: add json dump command
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
---
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 ae0af2f1f108..bc638f1588e9 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 44fc92bebfcd..1ed91ea56863 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.16.4