Blame alsaucm/dump.c

Packit Service a9274b
/*
Packit Service a9274b
 *  This library is free software; you can redistribute it and/or
Packit Service a9274b
 *  modify it under the terms of the GNU Lesser General Public
Packit Service a9274b
 *  License as published by the Free Software Foundation; either
Packit Service a9274b
 *  version 2 of the License, or (at your option) any later version.
Packit Service a9274b
 *
Packit Service a9274b
 *  This library is distributed in the hope that it will be useful,
Packit Service a9274b
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service a9274b
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit Service a9274b
 *  Lesser General Public License for more details.
Packit Service a9274b
 *
Packit Service a9274b
 *  You should have received a copy of the GNU General Public License
Packit Service a9274b
 *  along with this program; if not, write to the Free Software
Packit Service a9274b
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
Packit Service a9274b
 *
Packit Service a9274b
 *  Copyright (C) 2019 Red Hat Inc.
Packit Service a9274b
 *  Authors: Jaroslav Kysela <perex@perex.cz>
Packit Service a9274b
 */
Packit Service a9274b
Packit Service a9274b
#include <stdio.h>
Packit Service a9274b
#include <string.h>
Packit Service a9274b
#include <alsa/asoundlib.h>
Packit Service a9274b
#include <alsa/use-case.h>
Packit Service a9274b
#include "usecase.h"
Packit Service a9274b
#include "aconfig.h"
Packit Service a9274b
#include "version.h"
Packit Service a9274b
Packit Service a9274b
struct renderer {
Packit Service a9274b
	int (*init)(struct renderer *r);
Packit Service a9274b
	void (*done)(struct renderer *r);
Packit Service a9274b
	int (*verb_begin)(struct renderer *r,
Packit Service a9274b
			  const char *verb,
Packit Service a9274b
			  const char *comment);
Packit Service a9274b
	int (*verb_end)(struct renderer *r);
Packit Service a9274b
	int (*device_block_begin)(struct renderer *r);
Packit Service a9274b
	int (*device_block_end)(struct renderer *r);
Packit Service a9274b
	int (*device_begin)(struct renderer *r,
Packit Service a9274b
			    const char *device,
Packit Service a9274b
			    const char *comment);
Packit Service a9274b
	int (*device_end)(struct renderer *r);
Packit Service a9274b
	int (*modifier_block_begin)(struct renderer *r);
Packit Service a9274b
	int (*modifier_block_end)(struct renderer *r);
Packit Service a9274b
	int (*modifier_begin)(struct renderer *r,
Packit Service a9274b
			      const char *device,
Packit Service a9274b
			      const char *comment);
Packit Service a9274b
	int (*modifier_end)(struct renderer *r);
Packit Service a9274b
	int (*supported_begin)(struct renderer *r);
Packit Service a9274b
	int (*supported_value)(struct renderer *r, const char *value, int last);
Packit Service a9274b
	int (*supported_end)(struct renderer *r);
Packit Service a9274b
	int (*conflict_begin)(struct renderer *r);
Packit Service a9274b
	int (*conflict_value)(struct renderer *r, const char *value, int last);
Packit Service a9274b
	int (*conflict_end)(struct renderer *r);
Packit Service a9274b
	int (*value_begin)(struct renderer *r);
Packit Service a9274b
	int (*value_end)(struct renderer *r);
Packit Service a9274b
	int (*value)(struct renderer *r, const char *ident, const char *value);
Packit Service a9274b
	void *opaque;
Packit Service a9274b
};
Packit Service a9274b
Packit Service a9274b
/*
Packit Service a9274b
 * Text renderer
Packit Service a9274b
 */
Packit Service a9274b
Packit Service a9274b
struct text {
Packit Service a9274b
	char a[1];
Packit Service a9274b
};
Packit Service a9274b
Packit Service a9274b
static char *tesc(const char *s, char *buf, size_t buf_len)
Packit Service a9274b
{
Packit Service a9274b
	char *dst = buf;
Packit Service a9274b
	char c = '\0';
Packit Service a9274b
	if (strchr(s, '"') || strchr(s, ' ') || strchr(s, '.')) {
Packit Service a9274b
		*dst++ = c = '"';
Packit Service a9274b
		buf_len--;
Packit Service a9274b
	}
Packit Service a9274b
	while (*s && buf_len > 2) {
Packit Service a9274b
		if (*s == '"') {
Packit Service a9274b
			if (buf_len > 3) {
Packit Service a9274b
				*dst++ = '\\';
Packit Service a9274b
				*dst++ = *s++;
Packit Service a9274b
				buf_len -= 2;
Packit Service a9274b
				continue;
Packit Service a9274b
			} else {
Packit Service a9274b
				break;
Packit Service a9274b
			}
Packit Service a9274b
		}
Packit Service a9274b
		*dst++ = *s++;
Packit Service a9274b
	}
Packit Service a9274b
	if (c)
Packit Service a9274b
		*dst++ = c;
Packit Service a9274b
	*dst = '\0';
Packit Service a9274b
	return buf;
Packit Service a9274b
}
Packit Service a9274b
Packit Service a9274b
#define ESC(s, esc) tesc((s), (esc), sizeof(esc))
Packit Service a9274b
Packit Service a9274b
static int text_verb_start(struct renderer *r, const char *verb, const char *comment)
Packit Service a9274b
{
Packit Service a9274b
	char buf1[128], buf2[128];
Packit Service a9274b
	printf("Verb.%s {\n", ESC(verb, buf1));
Packit Service a9274b
	if (comment && comment[0])
Packit Service a9274b
		printf("\tComment %s\n", ESC(comment, buf2));
Packit Service a9274b
	return 0;
Packit Service a9274b
}
Packit Service a9274b
Packit Service a9274b
static int text_verb_end(struct renderer *r)
Packit Service a9274b
{
Packit Service a9274b
	printf("}\n");
Packit Service a9274b
	return 0;
Packit Service a9274b
}
Packit Service a9274b
Packit Service a9274b
static int text_2nd_level_begin(struct renderer *r,
Packit Service a9274b
				const char *key,
Packit Service a9274b
				const char *val,
Packit Service a9274b
				const char *comment)
Packit Service a9274b
{
Packit Service a9274b
	char buf1[128], buf2[128];
Packit Service a9274b
	printf("\t%s.%s {\n", key, ESC(val, buf1));
Packit Service a9274b
	if (comment && comment[0])
Packit Service a9274b
		printf("\t\tComment %s\n", ESC(comment, buf2));
Packit Service a9274b
	return 0;
Packit Service a9274b
}
Packit Service a9274b
Packit Service a9274b
static int text_2nd_level_end(struct renderer *r)
Packit Service a9274b
{
Packit Service a9274b
	printf("\t}\n");
Packit Service a9274b
	return 0;
Packit Service a9274b
}
Packit Service a9274b
Packit Service a9274b
static int text_2nd_level(struct renderer *r, const char *txt)
Packit Service a9274b
{
Packit Service a9274b
	printf("\t\t%s", txt);
Packit Service a9274b
	return 0;
Packit Service a9274b
}
Packit Service a9274b
Packit Service a9274b
static int text_3rd_level(struct renderer *r, const char *txt)
Packit Service a9274b
{
Packit Service a9274b
	printf("\t\t\t%s", txt);
Packit Service a9274b
	return 0;
Packit Service a9274b
}
Packit Service a9274b
Packit Service a9274b
static int text_dev_start(struct renderer *r, const char *dev, const char *comment)
Packit Service a9274b
{
Packit Service a9274b
	return text_2nd_level_begin(r, "Device", dev, comment);
Packit Service a9274b
}
Packit Service a9274b
Packit Service a9274b
static int text_mod_start(struct renderer *r, const char *dev, const char *comment)
Packit Service a9274b
{
Packit Service a9274b
	return text_2nd_level_begin(r, "Modifier", dev, comment);
Packit Service a9274b
}
Packit Service a9274b
Packit Service a9274b
static int text_supcon_start(struct renderer *r, const char *key)
Packit Service a9274b
{
Packit Service a9274b
	if (text_2nd_level(r, key))
Packit Service a9274b
		return 1;
Packit Service a9274b
	printf(" [\n");
Packit Service a9274b
	return 0;
Packit Service a9274b
}
Packit Service a9274b
Packit Service a9274b
static int text_supcon_value(struct renderer *r, const char *value, int last)
Packit Service a9274b
{
Packit Service a9274b
	char buf[256];
Packit Service a9274b
	ESC(value, buf);
Packit Service a9274b
	if (!last && strlen(buf) < sizeof(buf) - 2)
Packit Service a9274b
		strcat(buf, ",");
Packit Service a9274b
	if (text_3rd_level(r, buf))
Packit Service a9274b
		return 1;
Packit Service a9274b
	printf("\n");
Packit Service a9274b
	return 0;
Packit Service a9274b
}
Packit Service a9274b
Packit Service a9274b
static int text_supcon_end(struct renderer *r)
Packit Service a9274b
{
Packit Service a9274b
	return text_2nd_level(r, "]\n");
Packit Service a9274b
}
Packit Service a9274b
Packit Service a9274b
static int text_sup_start(struct renderer *r)
Packit Service a9274b
{
Packit Service a9274b
	return text_supcon_start(r, "SupportedDevices");
Packit Service a9274b
}
Packit Service a9274b
Packit Service a9274b
static int text_con_start(struct renderer *r)
Packit Service a9274b
{
Packit Service a9274b
	return text_supcon_start(r, "ConflictingDevices");
Packit Service a9274b
}
Packit Service a9274b
Packit Service a9274b
static int text_value_begin(struct renderer *r)
Packit Service a9274b
{
Packit Service a9274b
	return text_2nd_level(r, "Values {\n");
Packit Service a9274b
}
Packit Service a9274b
Packit Service a9274b
static int text_value_end(struct renderer *r)
Packit Service a9274b
{
Packit Service a9274b
	return text_2nd_level(r, "}\n");
Packit Service a9274b
}
Packit Service a9274b
Packit Service a9274b
static int text_value(struct renderer *r, const char *ident, const char *value)
Packit Service a9274b
{
Packit Service a9274b
	char buf1[256], buf2[256];
Packit Service a9274b
	int err;
Packit Service a9274b
Packit Service a9274b
	ESC(ident, buf1);
Packit Service a9274b
	err = text_3rd_level(r, buf1);
Packit Service a9274b
	if (err < 0)
Packit Service a9274b
		return err;
Packit Service a9274b
	ESC(value, buf2);
Packit Service a9274b
	printf(" %s\n", buf2);
Packit Service a9274b
	return 0;
Packit Service a9274b
}
Packit Service a9274b
Packit Service a9274b
static struct renderer text_renderer = {
Packit Service a9274b
	.verb_begin = text_verb_start,
Packit Service a9274b
	.verb_end = text_verb_end,
Packit Service a9274b
	.device_begin = text_dev_start,
Packit Service a9274b
	.device_end = text_2nd_level_end,
Packit Service a9274b
	.modifier_begin = text_mod_start,
Packit Service a9274b
	.modifier_end = text_2nd_level_end,
Packit Service a9274b
	.supported_begin = text_sup_start,
Packit Service a9274b
	.supported_value = text_supcon_value,
Packit Service a9274b
	.supported_end = text_supcon_end,
Packit Service a9274b
	.conflict_begin = text_con_start,
Packit Service a9274b
	.conflict_value = text_supcon_value,
Packit Service a9274b
	.conflict_end = text_supcon_end,
Packit Service a9274b
	.value_begin = text_value_begin,
Packit Service a9274b
	.value_end = text_value_end,
Packit Service a9274b
	.value = text_value,
Packit Service a9274b
};
Packit Service a9274b
Packit Service a9274b
/*
Packit Service a9274b
 * JSON renderer
Packit Service a9274b
 */
Packit Service a9274b
Packit Service a9274b
struct json {
Packit Service a9274b
	int block[5];
Packit Service a9274b
};
Packit Service a9274b
Packit Service a9274b
static char *jesc(const char *s, char *buf, size_t buf_len)
Packit Service a9274b
{
Packit Service a9274b
	char *dst = buf;
Packit Service a9274b
	char c = '"';
Packit Service a9274b
	*dst++ = c;
Packit Service a9274b
	buf_len--;
Packit Service a9274b
	while (*s && buf_len > 2) {
Packit Service a9274b
		if (*s == '"') {
Packit Service a9274b
			if (buf_len > 3) {
Packit Service a9274b
				*dst++ = '\\';
Packit Service a9274b
				*dst++ = *s++;
Packit Service a9274b
				buf_len -= 2;
Packit Service a9274b
				continue;
Packit Service a9274b
			} else {
Packit Service a9274b
				break;
Packit Service a9274b
			}
Packit Service a9274b
		}
Packit Service a9274b
		*dst++ = *s++;
Packit Service a9274b
	}
Packit Service a9274b
	*dst++ = c;
Packit Service a9274b
	*dst = '\0';
Packit Service a9274b
	return buf;
Packit Service a9274b
}
Packit Service a9274b
Packit Service a9274b
#define JESC(s, esc) jesc((s), (esc), sizeof(esc))
Packit Service a9274b
Packit Service a9274b
static void json_block(struct renderer *r, int level, int last)
Packit Service a9274b
{
Packit Service a9274b
	struct json *j = r->opaque;
Packit Service a9274b
	printf((j->block[level] && !last) ? ",\n" : "\n");
Packit Service a9274b
	j->block[level] = last ? 0 : 1;
Packit Service a9274b
}
Packit Service a9274b
Packit Service a9274b
static int json_init(struct renderer *r)
Packit Service a9274b
{
Packit Service a9274b
	printf("{\n  \"Verbs\": {");
Packit Service a9274b
	return 0;
Packit Service a9274b
}
Packit Service a9274b
Packit Service a9274b
static void json_done(struct renderer *r)
Packit Service a9274b
{
Packit Service a9274b
	json_block(r, 0, 1);
Packit Service a9274b
	printf("  }\n}\n");
Packit Service a9274b
}
Packit Service a9274b
Packit Service a9274b
static int json_verb_start(struct renderer *r, const char *verb, const char *comment)
Packit Service a9274b
{
Packit Service a9274b
	char buf[256];
Packit Service a9274b
	json_block(r, 0, 0);
Packit Service a9274b
	printf("    %s: {", JESC(verb, buf));
Packit Service a9274b
	if (comment && comment[0]) {
Packit Service a9274b
		json_block(r, 1, 0);
Packit Service a9274b
		printf("      \"Comment\": %s", JESC(comment, buf));
Packit Service a9274b
	}
Packit Service a9274b
	return 0;
Packit Service a9274b
}
Packit Service a9274b
Packit Service a9274b
static int json_verb_end(struct renderer *r)
Packit Service a9274b
{
Packit Service a9274b
	json_block(r, 1, 1);
Packit Service a9274b
	printf("    }");
Packit Service a9274b
	return 0;
Packit Service a9274b
}
Packit Service a9274b
Packit Service a9274b
static int json_2nd_level_block_end(struct renderer *r)
Packit Service a9274b
{
Packit Service a9274b
	json_block(r, 2, 1);
Packit Service a9274b
	printf("      }");
Packit Service a9274b
	return 0;
Packit Service a9274b
}
Packit Service a9274b
Packit Service a9274b
static int json_2nd_level_begin(struct renderer *r,
Packit Service a9274b
				const char *val,
Packit Service a9274b
				const char *comment)
Packit Service a9274b
{
Packit Service a9274b
	char buf[256];
Packit Service a9274b
	json_block(r, 2, 0);
Packit Service a9274b
	printf("        %s: {", JESC(val, buf));
Packit Service a9274b
	if (comment && comment[0]) {
Packit Service a9274b
		json_block(r, 3, 0);
Packit Service a9274b
		printf("          \"Comment\": %s", JESC(comment, buf));
Packit Service a9274b
	}
Packit Service a9274b
	return 0;
Packit Service a9274b
}
Packit Service a9274b
Packit Service a9274b
static int json_2nd_level_end(struct renderer *r)
Packit Service a9274b
{
Packit Service a9274b
	json_block(r, 3, 1);
Packit Service a9274b
	printf("        }");
Packit Service a9274b
	return 0;
Packit Service a9274b
}
Packit Service a9274b
Packit Service a9274b
static int json_2nd_level(struct renderer *r, const char *txt)
Packit Service a9274b
{
Packit Service a9274b
	printf("          %s", txt);
Packit Service a9274b
	return 0;
Packit Service a9274b
}
Packit Service a9274b
Packit Service a9274b
static int json_3rd_level(struct renderer *r, const char *txt)
Packit Service a9274b
{
Packit Service a9274b
	printf("            %s", txt);
Packit Service a9274b
	return 0;
Packit Service a9274b
}
Packit Service a9274b
Packit Service a9274b
static int json_dev_block_start(struct renderer *r)
Packit Service a9274b
{
Packit Service a9274b
	json_block(r, 1, 0);
Packit Service a9274b
	printf("      \"Devices\": {");
Packit Service a9274b
	return 0;
Packit Service a9274b
}
Packit Service a9274b
Packit Service a9274b
static int json_mod_block_start(struct renderer *r)
Packit Service a9274b
{
Packit Service a9274b
	json_block(r, 1, 0);
Packit Service a9274b
	printf("      \"Modifiers\": {");
Packit Service a9274b
	return 0;
Packit Service a9274b
}
Packit Service a9274b
Packit Service a9274b
static int json_supcon_start(struct renderer *r, const char *key)
Packit Service a9274b
{
Packit Service a9274b
	json_block(r, 3, 0);
Packit Service a9274b
	if (json_2nd_level(r, key))
Packit Service a9274b
		return 1;
Packit Service a9274b
	printf(": [");
Packit Service a9274b
	return 0;
Packit Service a9274b
}
Packit Service a9274b
Packit Service a9274b
static int json_supcon_value(struct renderer *r, const char *value, int last)
Packit Service a9274b
{
Packit Service a9274b
	char buf[256];
Packit Service a9274b
	JESC(value, buf);
Packit Service a9274b
	json_block(r, 4, 0);
Packit Service a9274b
	return json_3rd_level(r, buf);
Packit Service a9274b
}
Packit Service a9274b
Packit Service a9274b
static int json_supcon_end(struct renderer *r)
Packit Service a9274b
{
Packit Service a9274b
	json_block(r, 4, 1);
Packit Service a9274b
	return json_2nd_level(r, "]");
Packit Service a9274b
}
Packit Service a9274b
Packit Service a9274b
static int json_sup_start(struct renderer *r)
Packit Service a9274b
{
Packit Service a9274b
	return json_supcon_start(r, "\"SupportedDevices\"");
Packit Service a9274b
}
Packit Service a9274b
Packit Service a9274b
static int json_con_start(struct renderer *r)
Packit Service a9274b
{
Packit Service a9274b
	return json_supcon_start(r, "\"ConflictingDevices\"");
Packit Service a9274b
}
Packit Service a9274b
Packit Service a9274b
static int json_value_begin(struct renderer *r)
Packit Service a9274b
{
Packit Service a9274b
	json_block(r, 3, 0);
Packit Service a9274b
	return json_2nd_level(r, "\"Values\": {");
Packit Service a9274b
}
Packit Service a9274b
Packit Service a9274b
static int json_value_end(struct renderer *r)
Packit Service a9274b
{
Packit Service a9274b
	json_block(r, 4, 1);
Packit Service a9274b
	return json_2nd_level(r, "}");
Packit Service a9274b
}
Packit Service a9274b
Packit Service a9274b
static int json_value(struct renderer *r, const char *ident, const char *value)
Packit Service a9274b
{
Packit Service a9274b
	char buf[256];
Packit Service a9274b
	int err;
Packit Service a9274b
Packit Service a9274b
	json_block(r, 4, 0);
Packit Service a9274b
	JESC(ident, buf);
Packit Service a9274b
	err = json_3rd_level(r, buf);
Packit Service a9274b
	if (err < 0)
Packit Service a9274b
		return err;
Packit Service a9274b
	JESC(value, buf);
Packit Service a9274b
	printf(": %s", buf);
Packit Service a9274b
	return 0;
Packit Service a9274b
}
Packit Service a9274b
Packit Service a9274b
static struct renderer json_renderer = {
Packit Service a9274b
	.init = json_init,
Packit Service a9274b
	.done = json_done,
Packit Service a9274b
	.verb_begin = json_verb_start,
Packit Service a9274b
	.verb_end = json_verb_end,
Packit Service a9274b
	.device_block_begin = json_dev_block_start,
Packit Service a9274b
	.device_block_end = json_2nd_level_block_end,
Packit Service a9274b
	.device_begin = json_2nd_level_begin,
Packit Service a9274b
	.device_end = json_2nd_level_end,
Packit Service a9274b
	.modifier_block_begin = json_mod_block_start,
Packit Service a9274b
	.modifier_block_end = json_2nd_level_block_end,
Packit Service a9274b
	.modifier_begin = json_2nd_level_begin,
Packit Service a9274b
	.modifier_end = json_2nd_level_end,
Packit Service a9274b
	.supported_begin = json_sup_start,
Packit Service a9274b
	.supported_value = json_supcon_value,
Packit Service a9274b
	.supported_end = json_supcon_end,
Packit Service a9274b
	.conflict_begin = json_con_start,
Packit Service a9274b
	.conflict_value = json_supcon_value,
Packit Service a9274b
	.conflict_end = json_supcon_end,
Packit Service a9274b
	.value_begin = json_value_begin,
Packit Service a9274b
	.value_end = json_value_end,
Packit Service a9274b
	.value = json_value,
Packit Service a9274b
};
Packit Service a9274b
Packit Service a9274b
/*
Packit Service a9274b
 * universal dump functions
Packit Service a9274b
 */
Packit Service a9274b
Packit Service a9274b
static int render_devlist(struct context *context,
Packit Service a9274b
			  struct renderer *render,
Packit Service a9274b
			  const char *verb,
Packit Service a9274b
			  const char *device,
Packit Service a9274b
			  const char *list,
Packit Service a9274b
			  int (*begin)(struct renderer *),
Packit Service a9274b
			  int (*value)(struct renderer *, const char *value, int last),
Packit Service a9274b
			  int (*end)(struct renderer *))
Packit Service a9274b
{
Packit Service a9274b
	snd_use_case_mgr_t *uc_mgr = context->uc_mgr;
Packit Service a9274b
	const char **dev_list;
Packit Service a9274b
	char buf[256];
Packit Service a9274b
	int err = 0, j, dev_num;
Packit Service a9274b
Packit Service a9274b
	snprintf(buf, sizeof(buf), "%s/%s/%s", list, device, verb);
Packit Service a9274b
	dev_num = snd_use_case_get_list(uc_mgr, buf, &dev_list);
Packit Service a9274b
	if (dev_num < 0) {
Packit Service a9274b
		fprintf(stderr, "%s: unable to get %s for verb '%s' for device '%s'\n",
Packit Service a9274b
			context->command, list, verb, device);
Packit Service a9274b
		return dev_num;
Packit Service a9274b
	}
Packit Service a9274b
	if (dev_num > 0) {
Packit Service a9274b
		err = begin(render);
Packit Service a9274b
		if (err < 0)
Packit Service a9274b
			goto __err;
Packit Service a9274b
		for (j = 0; j < dev_num; j++) {
Packit Service a9274b
			err = value(render, dev_list[j], j + 1 == dev_num);
Packit Service a9274b
			if (err < 0)
Packit Service a9274b
				goto __err;
Packit Service a9274b
		}
Packit Service a9274b
		err = end(render);
Packit Service a9274b
	}
Packit Service a9274b
__err:
Packit Service a9274b
	snd_use_case_free_list(dev_list, dev_num);
Packit Service a9274b
	return err;
Packit Service a9274b
}
Packit Service a9274b
Packit Service a9274b
static int render_values(struct context *context,
Packit Service a9274b
			 struct renderer *render,
Packit Service a9274b
			 const char *verb,
Packit Service a9274b
			 const char *device)
Packit Service a9274b
{
Packit Service a9274b
	snd_use_case_mgr_t *uc_mgr = context->uc_mgr;
Packit Service a9274b
	const char **list, *value;
Packit Service a9274b
	char buf[256];
Packit Service a9274b
	int err = 0, j, num;
Packit Service a9274b
Packit Service a9274b
	snprintf(buf, sizeof(buf), "_identifiers/%s/%s", device, verb);
Packit Service a9274b
	num = snd_use_case_get_list(uc_mgr, buf, &list);
Packit Service a9274b
	if (num < 0) {
Packit Service a9274b
		fprintf(stderr, "%s: unable to get _identifiers for verb '%s' for device '%s': %s\n",
Packit Service a9274b
			context->command, verb, device, snd_strerror(num));
Packit Service a9274b
		return num;
Packit Service a9274b
	}
Packit Service a9274b
	if (num == 0)
Packit Service a9274b
		goto __err;
Packit Service a9274b
	if (render->value_begin) {
Packit Service a9274b
		err = render->value_begin(render);
Packit Service a9274b
		if (err < 0)
Packit Service a9274b
			goto __err;
Packit Service a9274b
	}
Packit Service a9274b
	for (j = 0; j < num; j++) {
Packit Service a9274b
		snprintf(buf, sizeof(buf), "%s/%s/%s", list[j], device, verb);
Packit Service a9274b
		err = snd_use_case_get(uc_mgr, buf, &value);
Packit Service a9274b
		if (err < 0) {
Packit Service a9274b
			fprintf(stderr, "%s: unable to get value '%s' for verb '%s' for device '%s': %s\n",
Packit Service a9274b
				context->command, list[j], verb, device, snd_strerror(err));
Packit Service a9274b
			goto __err;
Packit Service a9274b
		}
Packit Service a9274b
		err = render->value(render, list[j], value);
Packit Service a9274b
		free((char *)value);
Packit Service a9274b
		if (err < 0)
Packit Service a9274b
			goto __err;
Packit Service a9274b
	}
Packit Service a9274b
	if (render->value_end)
Packit Service a9274b
		err = render->value_end(render);
Packit Service a9274b
__err:
Packit Service a9274b
	snd_use_case_free_list(list, num);
Packit Service a9274b
	return err;
Packit Service a9274b
}
Packit Service a9274b
Packit Service a9274b
static int render_device(struct context *context,
Packit Service a9274b
			 struct renderer *render,
Packit Service a9274b
			 const char *verb,
Packit Service a9274b
			 const char *device)
Packit Service a9274b
{
Packit Service a9274b
	int err;
Packit Service a9274b
Packit Service a9274b
	err = render_devlist(context, render, verb, device,
Packit Service a9274b
			     "_supporteddevs",
Packit Service a9274b
			     render->supported_begin,
Packit Service a9274b
			     render->supported_value,
Packit Service a9274b
			     render->supported_end);
Packit Service a9274b
	if (err < 0)
Packit Service a9274b
		return err;
Packit Service a9274b
	err = render_devlist(context, render, verb, device,
Packit Service a9274b
			     "_conflictingdevs",
Packit Service a9274b
			     render->conflict_begin,
Packit Service a9274b
			     render->conflict_value,
Packit Service a9274b
			     render->conflict_end);
Packit Service a9274b
	if (err < 0)
Packit Service a9274b
		return err;
Packit Service a9274b
	return render_values(context, render, verb, device);
Packit Service a9274b
}
Packit Service a9274b
Packit Service a9274b
static void render(struct context *context, struct renderer *render)
Packit Service a9274b
{
Packit Service a9274b
	snd_use_case_mgr_t *uc_mgr = context->uc_mgr;
Packit Service a9274b
	int i, j, num, dev_num;
Packit Service a9274b
	const char **list, **dev_list, *verb, *comment;
Packit Service a9274b
	char buf[256];
Packit Service a9274b
Packit Service a9274b
	num = snd_use_case_verb_list(uc_mgr, &list);
Packit Service a9274b
	if (num < 0) {
Packit Service a9274b
		fprintf(stderr, "%s: no verbs found\n", context->command);
Packit Service a9274b
		return;
Packit Service a9274b
	}
Packit Service a9274b
	if (render->init && render->init(render))
Packit Service a9274b
		goto __end;
Packit Service a9274b
	for (i = 0; i < num; i += 2) {
Packit Service a9274b
		/* verb */
Packit Service a9274b
		verb = list[i + 0];
Packit Service a9274b
		comment = list[i + 1];
Packit Service a9274b
		if (render->verb_begin(render, verb, comment))
Packit Service a9274b
			break;
Packit Service a9274b
		/* devices */
Packit Service a9274b
		snprintf(buf, sizeof(buf), "_devices/%s", verb);
Packit Service a9274b
		dev_num = snd_use_case_get_list(uc_mgr, buf, &dev_list);
Packit Service a9274b
		if (dev_num < 0) {
Packit Service a9274b
			fprintf(stderr, "%s: unable to get devices for verb '%s'\n",
Packit Service a9274b
							context->command, verb);
Packit Service a9274b
			continue;
Packit Service a9274b
		}
Packit Service a9274b
		if (dev_num == 0)
Packit Service a9274b
			goto __mods;
Packit Service a9274b
		if (render->device_block_begin && render->device_block_begin(render)) {
Packit Service a9274b
			snd_use_case_free_list(dev_list, dev_num);
Packit Service a9274b
			goto __end;
Packit Service a9274b
		}
Packit Service a9274b
		for (j = 0; j < dev_num; j += 2) {
Packit Service a9274b
			render->device_begin(render, dev_list[j + 0], dev_list[j + 1]);
Packit Service a9274b
			if (render_device(context, render, verb, dev_list[j + 0])) {
Packit Service a9274b
				snd_use_case_free_list(dev_list, dev_num);
Packit Service a9274b
				goto __end;
Packit Service a9274b
			}
Packit Service a9274b
			render->device_end(render);
Packit Service a9274b
		}
Packit Service a9274b
		snd_use_case_free_list(dev_list, dev_num);
Packit Service a9274b
		if (render->device_block_end && render->device_block_end(render))
Packit Service a9274b
			goto __end;
Packit Service a9274b
__mods:
Packit Service a9274b
		/* modifiers */
Packit Service a9274b
		snprintf(buf, sizeof(buf), "_modifiers/%s", verb);
Packit Service a9274b
		dev_num = snd_use_case_get_list(uc_mgr, buf, &dev_list);
Packit Service a9274b
		if (dev_num < 0) {
Packit Service a9274b
			fprintf(stderr, "%s: unable to get modifiers for verb '%s'\n",
Packit Service a9274b
							context->command, verb);
Packit Service a9274b
			continue;
Packit Service a9274b
		}
Packit Service a9274b
		if (dev_num == 0)
Packit Service a9274b
			goto __verb_end;
Packit Service a9274b
		if (render->modifier_block_begin && render->modifier_block_begin(render)) {
Packit Service a9274b
			snd_use_case_free_list(dev_list, dev_num);
Packit Service a9274b
			goto __end;
Packit Service a9274b
		}
Packit Service a9274b
		for (j = 0; j < dev_num; j += 2) {
Packit Service a9274b
			render->modifier_begin(render, dev_list[j + 0], dev_list[j + 1]);
Packit Service a9274b
			render->modifier_end(render);
Packit Service a9274b
		}
Packit Service a9274b
		snd_use_case_free_list(dev_list, dev_num);
Packit Service a9274b
		if (render->modifier_block_end && render->modifier_block_end(render))
Packit Service a9274b
			goto __end;
Packit Service a9274b
__verb_end:
Packit Service a9274b
		/* end */
Packit Service a9274b
		if (render->verb_end(render))
Packit Service a9274b
			break;
Packit Service a9274b
	}
Packit Service a9274b
	if (render->done)
Packit Service a9274b
		render->done(render);
Packit Service a9274b
__end:
Packit Service a9274b
	snd_use_case_free_list(list, num);
Packit Service a9274b
}
Packit Service a9274b
Packit Service a9274b
void dump(struct context *context, const char *format)
Packit Service a9274b
{
Packit Service a9274b
	struct renderer r;
Packit Service a9274b
	struct text t;
Packit Service a9274b
	struct json j;
Packit Service a9274b
Packit Service a9274b
	r.opaque = NULL;
Packit Service a9274b
	if (strcasecmp(format, "text") == 0 ||
Packit Service a9274b
	    strcasecmp(format, "txt") == 0) {
Packit Service a9274b
		memset(&t, 0, sizeof(t));
Packit Service a9274b
		r = text_renderer;
Packit Service a9274b
		r.opaque = &t;
Packit Service a9274b
	} else if (strcasecmp(format, "json") == 0) {
Packit Service a9274b
		memset(&j, 0, sizeof(j));
Packit Service a9274b
		r = json_renderer;
Packit Service a9274b
		r.opaque = &j;
Packit Service a9274b
	}
Packit Service a9274b
	if (r.opaque != NULL) {
Packit Service a9274b
		render(context, &r);
Packit Service a9274b
		return;
Packit Service a9274b
	}
Packit Service a9274b
	fprintf(stderr, "%s: unknown dump format '%s'\n",
Packit Service a9274b
					context->command, format);
Packit Service a9274b
}