1c72fcc34Sopenharmony_ci/* 2c72fcc34Sopenharmony_ci * This library is free software; you can redistribute it and/or 3c72fcc34Sopenharmony_ci * modify it under the terms of the GNU Lesser General Public 4c72fcc34Sopenharmony_ci * License as published by the Free Software Foundation; either 5c72fcc34Sopenharmony_ci * version 2 of the License, or (at your option) any later version. 6c72fcc34Sopenharmony_ci * 7c72fcc34Sopenharmony_ci * This library is distributed in the hope that it will be useful, 8c72fcc34Sopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of 9c72fcc34Sopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 10c72fcc34Sopenharmony_ci * Lesser General Public License for more details. 11c72fcc34Sopenharmony_ci * 12c72fcc34Sopenharmony_ci * You should have received a copy of the GNU General Public License 13c72fcc34Sopenharmony_ci * along with this program; if not, write to the Free Software 14c72fcc34Sopenharmony_ci * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 15c72fcc34Sopenharmony_ci * 16c72fcc34Sopenharmony_ci * Copyright (C) 2019 Red Hat Inc. 17c72fcc34Sopenharmony_ci * Authors: Jaroslav Kysela <perex@perex.cz> 18c72fcc34Sopenharmony_ci */ 19c72fcc34Sopenharmony_ci 20c72fcc34Sopenharmony_ci#include <stdio.h> 21c72fcc34Sopenharmony_ci#include <string.h> 22c72fcc34Sopenharmony_ci#include <alsa/asoundlib.h> 23c72fcc34Sopenharmony_ci#include <alsa/use-case.h> 24c72fcc34Sopenharmony_ci#include "usecase.h" 25c72fcc34Sopenharmony_ci#include "aconfig.h" 26c72fcc34Sopenharmony_ci#include "version.h" 27c72fcc34Sopenharmony_ci 28c72fcc34Sopenharmony_cistruct renderer { 29c72fcc34Sopenharmony_ci int (*init)(struct renderer *r); 30c72fcc34Sopenharmony_ci void (*done)(struct renderer *r); 31c72fcc34Sopenharmony_ci int (*verb_begin)(struct renderer *r, 32c72fcc34Sopenharmony_ci const char *verb, 33c72fcc34Sopenharmony_ci const char *comment); 34c72fcc34Sopenharmony_ci int (*verb_end)(struct renderer *r); 35c72fcc34Sopenharmony_ci int (*device_block_begin)(struct renderer *r); 36c72fcc34Sopenharmony_ci int (*device_block_end)(struct renderer *r); 37c72fcc34Sopenharmony_ci int (*device_begin)(struct renderer *r, 38c72fcc34Sopenharmony_ci const char *device, 39c72fcc34Sopenharmony_ci const char *comment); 40c72fcc34Sopenharmony_ci int (*device_end)(struct renderer *r); 41c72fcc34Sopenharmony_ci int (*modifier_block_begin)(struct renderer *r); 42c72fcc34Sopenharmony_ci int (*modifier_block_end)(struct renderer *r); 43c72fcc34Sopenharmony_ci int (*modifier_begin)(struct renderer *r, 44c72fcc34Sopenharmony_ci const char *device, 45c72fcc34Sopenharmony_ci const char *comment); 46c72fcc34Sopenharmony_ci int (*modifier_end)(struct renderer *r); 47c72fcc34Sopenharmony_ci int (*supported_begin)(struct renderer *r); 48c72fcc34Sopenharmony_ci int (*supported_value)(struct renderer *r, const char *value, int last); 49c72fcc34Sopenharmony_ci int (*supported_end)(struct renderer *r); 50c72fcc34Sopenharmony_ci int (*conflict_begin)(struct renderer *r); 51c72fcc34Sopenharmony_ci int (*conflict_value)(struct renderer *r, const char *value, int last); 52c72fcc34Sopenharmony_ci int (*conflict_end)(struct renderer *r); 53c72fcc34Sopenharmony_ci int (*value_begin)(struct renderer *r); 54c72fcc34Sopenharmony_ci int (*value_end)(struct renderer *r); 55c72fcc34Sopenharmony_ci int (*value)(struct renderer *r, const char *ident, const char *value); 56c72fcc34Sopenharmony_ci void *opaque; 57c72fcc34Sopenharmony_ci}; 58c72fcc34Sopenharmony_ci 59c72fcc34Sopenharmony_ci/* 60c72fcc34Sopenharmony_ci * Text renderer 61c72fcc34Sopenharmony_ci */ 62c72fcc34Sopenharmony_ci 63c72fcc34Sopenharmony_cistruct text { 64c72fcc34Sopenharmony_ci char a[1]; 65c72fcc34Sopenharmony_ci}; 66c72fcc34Sopenharmony_ci 67c72fcc34Sopenharmony_cistatic char *tesc(const char *s, char *buf, size_t buf_len) 68c72fcc34Sopenharmony_ci{ 69c72fcc34Sopenharmony_ci char *dst = buf; 70c72fcc34Sopenharmony_ci char c = '\0'; 71c72fcc34Sopenharmony_ci if (strchr(s, '"') || strchr(s, ' ') || strchr(s, '.')) { 72c72fcc34Sopenharmony_ci *dst++ = c = '"'; 73c72fcc34Sopenharmony_ci buf_len--; 74c72fcc34Sopenharmony_ci } 75c72fcc34Sopenharmony_ci while (*s && buf_len > 2) { 76c72fcc34Sopenharmony_ci if (*s == '"') { 77c72fcc34Sopenharmony_ci if (buf_len > 3) { 78c72fcc34Sopenharmony_ci *dst++ = '\\'; 79c72fcc34Sopenharmony_ci *dst++ = *s++; 80c72fcc34Sopenharmony_ci buf_len -= 2; 81c72fcc34Sopenharmony_ci continue; 82c72fcc34Sopenharmony_ci } else { 83c72fcc34Sopenharmony_ci break; 84c72fcc34Sopenharmony_ci } 85c72fcc34Sopenharmony_ci } 86c72fcc34Sopenharmony_ci *dst++ = *s++; 87c72fcc34Sopenharmony_ci } 88c72fcc34Sopenharmony_ci if (c) 89c72fcc34Sopenharmony_ci *dst++ = c; 90c72fcc34Sopenharmony_ci *dst = '\0'; 91c72fcc34Sopenharmony_ci return buf; 92c72fcc34Sopenharmony_ci} 93c72fcc34Sopenharmony_ci 94c72fcc34Sopenharmony_ci#define ESC(s, esc) tesc((s), (esc), sizeof(esc)) 95c72fcc34Sopenharmony_ci 96c72fcc34Sopenharmony_cistatic int text_verb_start(struct renderer *r ATTRIBUTE_UNUSED, 97c72fcc34Sopenharmony_ci const char *verb, const char *comment) 98c72fcc34Sopenharmony_ci{ 99c72fcc34Sopenharmony_ci char buf1[128], buf2[128]; 100c72fcc34Sopenharmony_ci printf("Verb.%s {\n", ESC(verb, buf1)); 101c72fcc34Sopenharmony_ci if (comment && comment[0]) 102c72fcc34Sopenharmony_ci printf("\tComment %s\n", ESC(comment, buf2)); 103c72fcc34Sopenharmony_ci return 0; 104c72fcc34Sopenharmony_ci} 105c72fcc34Sopenharmony_ci 106c72fcc34Sopenharmony_cistatic int text_verb_end(struct renderer *r ATTRIBUTE_UNUSED) 107c72fcc34Sopenharmony_ci{ 108c72fcc34Sopenharmony_ci printf("}\n"); 109c72fcc34Sopenharmony_ci return 0; 110c72fcc34Sopenharmony_ci} 111c72fcc34Sopenharmony_ci 112c72fcc34Sopenharmony_cistatic int text_2nd_level_begin(struct renderer *r ATTRIBUTE_UNUSED, 113c72fcc34Sopenharmony_ci const char *key, 114c72fcc34Sopenharmony_ci const char *val, 115c72fcc34Sopenharmony_ci const char *comment) 116c72fcc34Sopenharmony_ci{ 117c72fcc34Sopenharmony_ci char buf1[128], buf2[128]; 118c72fcc34Sopenharmony_ci printf("\t%s.%s {\n", key, ESC(val, buf1)); 119c72fcc34Sopenharmony_ci if (comment && comment[0]) 120c72fcc34Sopenharmony_ci printf("\t\tComment %s\n", ESC(comment, buf2)); 121c72fcc34Sopenharmony_ci return 0; 122c72fcc34Sopenharmony_ci} 123c72fcc34Sopenharmony_ci 124c72fcc34Sopenharmony_cistatic int text_2nd_level_end(struct renderer *r ATTRIBUTE_UNUSED) 125c72fcc34Sopenharmony_ci{ 126c72fcc34Sopenharmony_ci printf("\t}\n"); 127c72fcc34Sopenharmony_ci return 0; 128c72fcc34Sopenharmony_ci} 129c72fcc34Sopenharmony_ci 130c72fcc34Sopenharmony_cistatic int text_2nd_level(struct renderer *r ATTRIBUTE_UNUSED, const char *txt) 131c72fcc34Sopenharmony_ci{ 132c72fcc34Sopenharmony_ci printf("\t\t%s", txt); 133c72fcc34Sopenharmony_ci return 0; 134c72fcc34Sopenharmony_ci} 135c72fcc34Sopenharmony_ci 136c72fcc34Sopenharmony_cistatic int text_3rd_level(struct renderer *r ATTRIBUTE_UNUSED, const char *txt) 137c72fcc34Sopenharmony_ci{ 138c72fcc34Sopenharmony_ci printf("\t\t\t%s", txt); 139c72fcc34Sopenharmony_ci return 0; 140c72fcc34Sopenharmony_ci} 141c72fcc34Sopenharmony_ci 142c72fcc34Sopenharmony_cistatic int text_dev_start(struct renderer *r, const char *dev, const char *comment) 143c72fcc34Sopenharmony_ci{ 144c72fcc34Sopenharmony_ci return text_2nd_level_begin(r, "Device", dev, comment); 145c72fcc34Sopenharmony_ci} 146c72fcc34Sopenharmony_ci 147c72fcc34Sopenharmony_cistatic int text_mod_start(struct renderer *r, const char *dev, const char *comment) 148c72fcc34Sopenharmony_ci{ 149c72fcc34Sopenharmony_ci return text_2nd_level_begin(r, "Modifier", dev, comment); 150c72fcc34Sopenharmony_ci} 151c72fcc34Sopenharmony_ci 152c72fcc34Sopenharmony_cistatic int text_supcon_start(struct renderer *r, const char *key) 153c72fcc34Sopenharmony_ci{ 154c72fcc34Sopenharmony_ci if (text_2nd_level(r, key)) 155c72fcc34Sopenharmony_ci return 1; 156c72fcc34Sopenharmony_ci printf(" [\n"); 157c72fcc34Sopenharmony_ci return 0; 158c72fcc34Sopenharmony_ci} 159c72fcc34Sopenharmony_ci 160c72fcc34Sopenharmony_cistatic int text_supcon_value(struct renderer *r, const char *value, int last) 161c72fcc34Sopenharmony_ci{ 162c72fcc34Sopenharmony_ci char buf[256]; 163c72fcc34Sopenharmony_ci ESC(value, buf); 164c72fcc34Sopenharmony_ci if (!last && strlen(buf) < sizeof(buf) - 2) 165c72fcc34Sopenharmony_ci strcat(buf, ","); 166c72fcc34Sopenharmony_ci if (text_3rd_level(r, buf)) 167c72fcc34Sopenharmony_ci return 1; 168c72fcc34Sopenharmony_ci printf("\n"); 169c72fcc34Sopenharmony_ci return 0; 170c72fcc34Sopenharmony_ci} 171c72fcc34Sopenharmony_ci 172c72fcc34Sopenharmony_cistatic int text_supcon_end(struct renderer *r) 173c72fcc34Sopenharmony_ci{ 174c72fcc34Sopenharmony_ci return text_2nd_level(r, "]\n"); 175c72fcc34Sopenharmony_ci} 176c72fcc34Sopenharmony_ci 177c72fcc34Sopenharmony_cistatic int text_sup_start(struct renderer *r) 178c72fcc34Sopenharmony_ci{ 179c72fcc34Sopenharmony_ci return text_supcon_start(r, "SupportedDevices"); 180c72fcc34Sopenharmony_ci} 181c72fcc34Sopenharmony_ci 182c72fcc34Sopenharmony_cistatic int text_con_start(struct renderer *r) 183c72fcc34Sopenharmony_ci{ 184c72fcc34Sopenharmony_ci return text_supcon_start(r, "ConflictingDevices"); 185c72fcc34Sopenharmony_ci} 186c72fcc34Sopenharmony_ci 187c72fcc34Sopenharmony_cistatic int text_value_begin(struct renderer *r) 188c72fcc34Sopenharmony_ci{ 189c72fcc34Sopenharmony_ci return text_2nd_level(r, "Values {\n"); 190c72fcc34Sopenharmony_ci} 191c72fcc34Sopenharmony_ci 192c72fcc34Sopenharmony_cistatic int text_value_end(struct renderer *r) 193c72fcc34Sopenharmony_ci{ 194c72fcc34Sopenharmony_ci return text_2nd_level(r, "}\n"); 195c72fcc34Sopenharmony_ci} 196c72fcc34Sopenharmony_ci 197c72fcc34Sopenharmony_cistatic int text_value(struct renderer *r, const char *ident, const char *value) 198c72fcc34Sopenharmony_ci{ 199c72fcc34Sopenharmony_ci char buf1[256], buf2[256]; 200c72fcc34Sopenharmony_ci int err; 201c72fcc34Sopenharmony_ci 202c72fcc34Sopenharmony_ci ESC(ident, buf1); 203c72fcc34Sopenharmony_ci err = text_3rd_level(r, buf1); 204c72fcc34Sopenharmony_ci if (err < 0) 205c72fcc34Sopenharmony_ci return err; 206c72fcc34Sopenharmony_ci ESC(value, buf2); 207c72fcc34Sopenharmony_ci printf(" %s\n", buf2); 208c72fcc34Sopenharmony_ci return 0; 209c72fcc34Sopenharmony_ci} 210c72fcc34Sopenharmony_ci 211c72fcc34Sopenharmony_cistatic struct renderer text_renderer = { 212c72fcc34Sopenharmony_ci .verb_begin = text_verb_start, 213c72fcc34Sopenharmony_ci .verb_end = text_verb_end, 214c72fcc34Sopenharmony_ci .device_begin = text_dev_start, 215c72fcc34Sopenharmony_ci .device_end = text_2nd_level_end, 216c72fcc34Sopenharmony_ci .modifier_begin = text_mod_start, 217c72fcc34Sopenharmony_ci .modifier_end = text_2nd_level_end, 218c72fcc34Sopenharmony_ci .supported_begin = text_sup_start, 219c72fcc34Sopenharmony_ci .supported_value = text_supcon_value, 220c72fcc34Sopenharmony_ci .supported_end = text_supcon_end, 221c72fcc34Sopenharmony_ci .conflict_begin = text_con_start, 222c72fcc34Sopenharmony_ci .conflict_value = text_supcon_value, 223c72fcc34Sopenharmony_ci .conflict_end = text_supcon_end, 224c72fcc34Sopenharmony_ci .value_begin = text_value_begin, 225c72fcc34Sopenharmony_ci .value_end = text_value_end, 226c72fcc34Sopenharmony_ci .value = text_value, 227c72fcc34Sopenharmony_ci}; 228c72fcc34Sopenharmony_ci 229c72fcc34Sopenharmony_ci/* 230c72fcc34Sopenharmony_ci * JSON renderer 231c72fcc34Sopenharmony_ci */ 232c72fcc34Sopenharmony_ci 233c72fcc34Sopenharmony_cistruct json { 234c72fcc34Sopenharmony_ci int block[5]; 235c72fcc34Sopenharmony_ci}; 236c72fcc34Sopenharmony_ci 237c72fcc34Sopenharmony_cistatic char *jesc(const char *s, char *buf, size_t buf_len) 238c72fcc34Sopenharmony_ci{ 239c72fcc34Sopenharmony_ci char *dst = buf; 240c72fcc34Sopenharmony_ci char c = '"'; 241c72fcc34Sopenharmony_ci *dst++ = c; 242c72fcc34Sopenharmony_ci buf_len--; 243c72fcc34Sopenharmony_ci while (*s && buf_len > 2) { 244c72fcc34Sopenharmony_ci if (*s == '"') { 245c72fcc34Sopenharmony_ci if (buf_len > 3) { 246c72fcc34Sopenharmony_ci *dst++ = '\\'; 247c72fcc34Sopenharmony_ci *dst++ = *s++; 248c72fcc34Sopenharmony_ci buf_len -= 2; 249c72fcc34Sopenharmony_ci continue; 250c72fcc34Sopenharmony_ci } else { 251c72fcc34Sopenharmony_ci break; 252c72fcc34Sopenharmony_ci } 253c72fcc34Sopenharmony_ci } 254c72fcc34Sopenharmony_ci *dst++ = *s++; 255c72fcc34Sopenharmony_ci } 256c72fcc34Sopenharmony_ci *dst++ = c; 257c72fcc34Sopenharmony_ci *dst = '\0'; 258c72fcc34Sopenharmony_ci return buf; 259c72fcc34Sopenharmony_ci} 260c72fcc34Sopenharmony_ci 261c72fcc34Sopenharmony_ci#define JESC(s, esc) jesc((s), (esc), sizeof(esc)) 262c72fcc34Sopenharmony_ci 263c72fcc34Sopenharmony_cistatic void json_block(struct renderer *r, int level, int last) 264c72fcc34Sopenharmony_ci{ 265c72fcc34Sopenharmony_ci struct json *j = r->opaque; 266c72fcc34Sopenharmony_ci printf((j->block[level] && !last) ? ",\n" : "\n"); 267c72fcc34Sopenharmony_ci j->block[level] = last ? 0 : 1; 268c72fcc34Sopenharmony_ci} 269c72fcc34Sopenharmony_ci 270c72fcc34Sopenharmony_cistatic int json_init(struct renderer *r ATTRIBUTE_UNUSED) 271c72fcc34Sopenharmony_ci{ 272c72fcc34Sopenharmony_ci printf("{\n \"Verbs\": {"); 273c72fcc34Sopenharmony_ci return 0; 274c72fcc34Sopenharmony_ci} 275c72fcc34Sopenharmony_ci 276c72fcc34Sopenharmony_cistatic void json_done(struct renderer *r) 277c72fcc34Sopenharmony_ci{ 278c72fcc34Sopenharmony_ci json_block(r, 0, 1); 279c72fcc34Sopenharmony_ci printf(" }\n}\n"); 280c72fcc34Sopenharmony_ci} 281c72fcc34Sopenharmony_ci 282c72fcc34Sopenharmony_cistatic int json_verb_start(struct renderer *r, const char *verb, const char *comment) 283c72fcc34Sopenharmony_ci{ 284c72fcc34Sopenharmony_ci char buf[256]; 285c72fcc34Sopenharmony_ci json_block(r, 0, 0); 286c72fcc34Sopenharmony_ci printf(" %s: {", JESC(verb, buf)); 287c72fcc34Sopenharmony_ci if (comment && comment[0]) { 288c72fcc34Sopenharmony_ci json_block(r, 1, 0); 289c72fcc34Sopenharmony_ci printf(" \"Comment\": %s", JESC(comment, buf)); 290c72fcc34Sopenharmony_ci } 291c72fcc34Sopenharmony_ci return 0; 292c72fcc34Sopenharmony_ci} 293c72fcc34Sopenharmony_ci 294c72fcc34Sopenharmony_cistatic int json_verb_end(struct renderer *r) 295c72fcc34Sopenharmony_ci{ 296c72fcc34Sopenharmony_ci json_block(r, 1, 1); 297c72fcc34Sopenharmony_ci printf(" }"); 298c72fcc34Sopenharmony_ci return 0; 299c72fcc34Sopenharmony_ci} 300c72fcc34Sopenharmony_ci 301c72fcc34Sopenharmony_cistatic int json_2nd_level_block_end(struct renderer *r) 302c72fcc34Sopenharmony_ci{ 303c72fcc34Sopenharmony_ci json_block(r, 2, 1); 304c72fcc34Sopenharmony_ci printf(" }"); 305c72fcc34Sopenharmony_ci return 0; 306c72fcc34Sopenharmony_ci} 307c72fcc34Sopenharmony_ci 308c72fcc34Sopenharmony_cistatic int json_2nd_level_begin(struct renderer *r, 309c72fcc34Sopenharmony_ci const char *val, 310c72fcc34Sopenharmony_ci const char *comment) 311c72fcc34Sopenharmony_ci{ 312c72fcc34Sopenharmony_ci char buf[256]; 313c72fcc34Sopenharmony_ci json_block(r, 2, 0); 314c72fcc34Sopenharmony_ci printf(" %s: {", JESC(val, buf)); 315c72fcc34Sopenharmony_ci if (comment && comment[0]) { 316c72fcc34Sopenharmony_ci json_block(r, 3, 0); 317c72fcc34Sopenharmony_ci printf(" \"Comment\": %s", JESC(comment, buf)); 318c72fcc34Sopenharmony_ci } 319c72fcc34Sopenharmony_ci return 0; 320c72fcc34Sopenharmony_ci} 321c72fcc34Sopenharmony_ci 322c72fcc34Sopenharmony_cistatic int json_2nd_level_end(struct renderer *r) 323c72fcc34Sopenharmony_ci{ 324c72fcc34Sopenharmony_ci json_block(r, 3, 1); 325c72fcc34Sopenharmony_ci printf(" }"); 326c72fcc34Sopenharmony_ci return 0; 327c72fcc34Sopenharmony_ci} 328c72fcc34Sopenharmony_ci 329c72fcc34Sopenharmony_cistatic int json_2nd_level(struct renderer *r ATTRIBUTE_UNUSED, const char *txt) 330c72fcc34Sopenharmony_ci{ 331c72fcc34Sopenharmony_ci printf(" %s", txt); 332c72fcc34Sopenharmony_ci return 0; 333c72fcc34Sopenharmony_ci} 334c72fcc34Sopenharmony_ci 335c72fcc34Sopenharmony_cistatic int json_3rd_level(struct renderer *r ATTRIBUTE_UNUSED, const char *txt) 336c72fcc34Sopenharmony_ci{ 337c72fcc34Sopenharmony_ci printf(" %s", txt); 338c72fcc34Sopenharmony_ci return 0; 339c72fcc34Sopenharmony_ci} 340c72fcc34Sopenharmony_ci 341c72fcc34Sopenharmony_cistatic int json_dev_block_start(struct renderer *r) 342c72fcc34Sopenharmony_ci{ 343c72fcc34Sopenharmony_ci json_block(r, 1, 0); 344c72fcc34Sopenharmony_ci printf(" \"Devices\": {"); 345c72fcc34Sopenharmony_ci return 0; 346c72fcc34Sopenharmony_ci} 347c72fcc34Sopenharmony_ci 348c72fcc34Sopenharmony_cistatic int json_mod_block_start(struct renderer *r) 349c72fcc34Sopenharmony_ci{ 350c72fcc34Sopenharmony_ci json_block(r, 1, 0); 351c72fcc34Sopenharmony_ci printf(" \"Modifiers\": {"); 352c72fcc34Sopenharmony_ci return 0; 353c72fcc34Sopenharmony_ci} 354c72fcc34Sopenharmony_ci 355c72fcc34Sopenharmony_cistatic int json_supcon_start(struct renderer *r, const char *key) 356c72fcc34Sopenharmony_ci{ 357c72fcc34Sopenharmony_ci json_block(r, 3, 0); 358c72fcc34Sopenharmony_ci if (json_2nd_level(r, key)) 359c72fcc34Sopenharmony_ci return 1; 360c72fcc34Sopenharmony_ci printf(": ["); 361c72fcc34Sopenharmony_ci return 0; 362c72fcc34Sopenharmony_ci} 363c72fcc34Sopenharmony_ci 364c72fcc34Sopenharmony_cistatic int json_supcon_value(struct renderer *r, const char *value, 365c72fcc34Sopenharmony_ci int last ATTRIBUTE_UNUSED) 366c72fcc34Sopenharmony_ci{ 367c72fcc34Sopenharmony_ci char buf[256]; 368c72fcc34Sopenharmony_ci JESC(value, buf); 369c72fcc34Sopenharmony_ci json_block(r, 4, 0); 370c72fcc34Sopenharmony_ci return json_3rd_level(r, buf); 371c72fcc34Sopenharmony_ci} 372c72fcc34Sopenharmony_ci 373c72fcc34Sopenharmony_cistatic int json_supcon_end(struct renderer *r) 374c72fcc34Sopenharmony_ci{ 375c72fcc34Sopenharmony_ci json_block(r, 4, 1); 376c72fcc34Sopenharmony_ci return json_2nd_level(r, "]"); 377c72fcc34Sopenharmony_ci} 378c72fcc34Sopenharmony_ci 379c72fcc34Sopenharmony_cistatic int json_sup_start(struct renderer *r) 380c72fcc34Sopenharmony_ci{ 381c72fcc34Sopenharmony_ci return json_supcon_start(r, "\"SupportedDevices\""); 382c72fcc34Sopenharmony_ci} 383c72fcc34Sopenharmony_ci 384c72fcc34Sopenharmony_cistatic int json_con_start(struct renderer *r) 385c72fcc34Sopenharmony_ci{ 386c72fcc34Sopenharmony_ci return json_supcon_start(r, "\"ConflictingDevices\""); 387c72fcc34Sopenharmony_ci} 388c72fcc34Sopenharmony_ci 389c72fcc34Sopenharmony_cistatic int json_value_begin(struct renderer *r) 390c72fcc34Sopenharmony_ci{ 391c72fcc34Sopenharmony_ci json_block(r, 3, 0); 392c72fcc34Sopenharmony_ci return json_2nd_level(r, "\"Values\": {"); 393c72fcc34Sopenharmony_ci} 394c72fcc34Sopenharmony_ci 395c72fcc34Sopenharmony_cistatic int json_value_end(struct renderer *r) 396c72fcc34Sopenharmony_ci{ 397c72fcc34Sopenharmony_ci json_block(r, 4, 1); 398c72fcc34Sopenharmony_ci return json_2nd_level(r, "}"); 399c72fcc34Sopenharmony_ci} 400c72fcc34Sopenharmony_ci 401c72fcc34Sopenharmony_cistatic int json_value(struct renderer *r, const char *ident, const char *value) 402c72fcc34Sopenharmony_ci{ 403c72fcc34Sopenharmony_ci char buf[256]; 404c72fcc34Sopenharmony_ci int err; 405c72fcc34Sopenharmony_ci 406c72fcc34Sopenharmony_ci json_block(r, 4, 0); 407c72fcc34Sopenharmony_ci JESC(ident, buf); 408c72fcc34Sopenharmony_ci err = json_3rd_level(r, buf); 409c72fcc34Sopenharmony_ci if (err < 0) 410c72fcc34Sopenharmony_ci return err; 411c72fcc34Sopenharmony_ci JESC(value, buf); 412c72fcc34Sopenharmony_ci printf(": %s", buf); 413c72fcc34Sopenharmony_ci return 0; 414c72fcc34Sopenharmony_ci} 415c72fcc34Sopenharmony_ci 416c72fcc34Sopenharmony_cistatic struct renderer json_renderer = { 417c72fcc34Sopenharmony_ci .init = json_init, 418c72fcc34Sopenharmony_ci .done = json_done, 419c72fcc34Sopenharmony_ci .verb_begin = json_verb_start, 420c72fcc34Sopenharmony_ci .verb_end = json_verb_end, 421c72fcc34Sopenharmony_ci .device_block_begin = json_dev_block_start, 422c72fcc34Sopenharmony_ci .device_block_end = json_2nd_level_block_end, 423c72fcc34Sopenharmony_ci .device_begin = json_2nd_level_begin, 424c72fcc34Sopenharmony_ci .device_end = json_2nd_level_end, 425c72fcc34Sopenharmony_ci .modifier_block_begin = json_mod_block_start, 426c72fcc34Sopenharmony_ci .modifier_block_end = json_2nd_level_block_end, 427c72fcc34Sopenharmony_ci .modifier_begin = json_2nd_level_begin, 428c72fcc34Sopenharmony_ci .modifier_end = json_2nd_level_end, 429c72fcc34Sopenharmony_ci .supported_begin = json_sup_start, 430c72fcc34Sopenharmony_ci .supported_value = json_supcon_value, 431c72fcc34Sopenharmony_ci .supported_end = json_supcon_end, 432c72fcc34Sopenharmony_ci .conflict_begin = json_con_start, 433c72fcc34Sopenharmony_ci .conflict_value = json_supcon_value, 434c72fcc34Sopenharmony_ci .conflict_end = json_supcon_end, 435c72fcc34Sopenharmony_ci .value_begin = json_value_begin, 436c72fcc34Sopenharmony_ci .value_end = json_value_end, 437c72fcc34Sopenharmony_ci .value = json_value, 438c72fcc34Sopenharmony_ci}; 439c72fcc34Sopenharmony_ci 440c72fcc34Sopenharmony_ci/* 441c72fcc34Sopenharmony_ci * universal dump functions 442c72fcc34Sopenharmony_ci */ 443c72fcc34Sopenharmony_ci 444c72fcc34Sopenharmony_cistatic int render_devlist(struct context *context, 445c72fcc34Sopenharmony_ci struct renderer *render, 446c72fcc34Sopenharmony_ci const char *verb, 447c72fcc34Sopenharmony_ci const char *device, 448c72fcc34Sopenharmony_ci const char *list, 449c72fcc34Sopenharmony_ci int (*begin)(struct renderer *), 450c72fcc34Sopenharmony_ci int (*value)(struct renderer *, const char *value, int last), 451c72fcc34Sopenharmony_ci int (*end)(struct renderer *)) 452c72fcc34Sopenharmony_ci{ 453c72fcc34Sopenharmony_ci snd_use_case_mgr_t *uc_mgr = context->uc_mgr; 454c72fcc34Sopenharmony_ci const char **dev_list; 455c72fcc34Sopenharmony_ci char buf[256]; 456c72fcc34Sopenharmony_ci int err = 0, j, dev_num; 457c72fcc34Sopenharmony_ci 458c72fcc34Sopenharmony_ci snprintf(buf, sizeof(buf), "%s/%s/%s", list, device, verb); 459c72fcc34Sopenharmony_ci dev_num = snd_use_case_get_list(uc_mgr, buf, &dev_list); 460c72fcc34Sopenharmony_ci if (dev_num < 0) { 461c72fcc34Sopenharmony_ci fprintf(stderr, "%s: unable to get %s for verb '%s' for device '%s'\n", 462c72fcc34Sopenharmony_ci context->command, list, verb, device); 463c72fcc34Sopenharmony_ci return dev_num; 464c72fcc34Sopenharmony_ci } 465c72fcc34Sopenharmony_ci if (dev_num > 0) { 466c72fcc34Sopenharmony_ci err = begin(render); 467c72fcc34Sopenharmony_ci if (err < 0) 468c72fcc34Sopenharmony_ci goto __err; 469c72fcc34Sopenharmony_ci for (j = 0; j < dev_num; j++) { 470c72fcc34Sopenharmony_ci err = value(render, dev_list[j], j + 1 == dev_num); 471c72fcc34Sopenharmony_ci if (err < 0) 472c72fcc34Sopenharmony_ci goto __err; 473c72fcc34Sopenharmony_ci } 474c72fcc34Sopenharmony_ci err = end(render); 475c72fcc34Sopenharmony_ci } 476c72fcc34Sopenharmony_ci__err: 477c72fcc34Sopenharmony_ci snd_use_case_free_list(dev_list, dev_num); 478c72fcc34Sopenharmony_ci return err; 479c72fcc34Sopenharmony_ci} 480c72fcc34Sopenharmony_ci 481c72fcc34Sopenharmony_cistatic int render_values(struct context *context, 482c72fcc34Sopenharmony_ci struct renderer *render, 483c72fcc34Sopenharmony_ci const char *verb, 484c72fcc34Sopenharmony_ci const char *device) 485c72fcc34Sopenharmony_ci{ 486c72fcc34Sopenharmony_ci snd_use_case_mgr_t *uc_mgr = context->uc_mgr; 487c72fcc34Sopenharmony_ci const char **list, *value; 488c72fcc34Sopenharmony_ci char buf[256]; 489c72fcc34Sopenharmony_ci int err = 0, j, num; 490c72fcc34Sopenharmony_ci 491c72fcc34Sopenharmony_ci snprintf(buf, sizeof(buf), "_identifiers/%s/%s", device, verb); 492c72fcc34Sopenharmony_ci num = snd_use_case_get_list(uc_mgr, buf, &list); 493c72fcc34Sopenharmony_ci if (num < 0) { 494c72fcc34Sopenharmony_ci fprintf(stderr, "%s: unable to get _identifiers for verb '%s' for device '%s': %s\n", 495c72fcc34Sopenharmony_ci context->command, verb, device, snd_strerror(num)); 496c72fcc34Sopenharmony_ci return num; 497c72fcc34Sopenharmony_ci } 498c72fcc34Sopenharmony_ci if (num == 0) 499c72fcc34Sopenharmony_ci goto __err; 500c72fcc34Sopenharmony_ci if (render->value_begin) { 501c72fcc34Sopenharmony_ci err = render->value_begin(render); 502c72fcc34Sopenharmony_ci if (err < 0) 503c72fcc34Sopenharmony_ci goto __err; 504c72fcc34Sopenharmony_ci } 505c72fcc34Sopenharmony_ci for (j = 0; j < num; j++) { 506c72fcc34Sopenharmony_ci snprintf(buf, sizeof(buf), "%s/%s/%s", list[j], device, verb); 507c72fcc34Sopenharmony_ci err = snd_use_case_get(uc_mgr, buf, &value); 508c72fcc34Sopenharmony_ci if (err < 0) { 509c72fcc34Sopenharmony_ci fprintf(stderr, "%s: unable to get value '%s' for verb '%s' for device '%s': %s\n", 510c72fcc34Sopenharmony_ci context->command, list[j], verb, device, snd_strerror(err)); 511c72fcc34Sopenharmony_ci goto __err; 512c72fcc34Sopenharmony_ci } 513c72fcc34Sopenharmony_ci err = render->value(render, list[j], value); 514c72fcc34Sopenharmony_ci free((char *)value); 515c72fcc34Sopenharmony_ci if (err < 0) 516c72fcc34Sopenharmony_ci goto __err; 517c72fcc34Sopenharmony_ci } 518c72fcc34Sopenharmony_ci if (render->value_end) 519c72fcc34Sopenharmony_ci err = render->value_end(render); 520c72fcc34Sopenharmony_ci__err: 521c72fcc34Sopenharmony_ci snd_use_case_free_list(list, num); 522c72fcc34Sopenharmony_ci return err; 523c72fcc34Sopenharmony_ci} 524c72fcc34Sopenharmony_ci 525c72fcc34Sopenharmony_cistatic int render_device(struct context *context, 526c72fcc34Sopenharmony_ci struct renderer *render, 527c72fcc34Sopenharmony_ci const char *verb, 528c72fcc34Sopenharmony_ci const char *device) 529c72fcc34Sopenharmony_ci{ 530c72fcc34Sopenharmony_ci int err; 531c72fcc34Sopenharmony_ci 532c72fcc34Sopenharmony_ci err = render_devlist(context, render, verb, device, 533c72fcc34Sopenharmony_ci "_supporteddevs", 534c72fcc34Sopenharmony_ci render->supported_begin, 535c72fcc34Sopenharmony_ci render->supported_value, 536c72fcc34Sopenharmony_ci render->supported_end); 537c72fcc34Sopenharmony_ci if (err < 0) 538c72fcc34Sopenharmony_ci return err; 539c72fcc34Sopenharmony_ci err = render_devlist(context, render, verb, device, 540c72fcc34Sopenharmony_ci "_conflictingdevs", 541c72fcc34Sopenharmony_ci render->conflict_begin, 542c72fcc34Sopenharmony_ci render->conflict_value, 543c72fcc34Sopenharmony_ci render->conflict_end); 544c72fcc34Sopenharmony_ci if (err < 0) 545c72fcc34Sopenharmony_ci return err; 546c72fcc34Sopenharmony_ci return render_values(context, render, verb, device); 547c72fcc34Sopenharmony_ci} 548c72fcc34Sopenharmony_ci 549c72fcc34Sopenharmony_cistatic void render(struct context *context, struct renderer *render) 550c72fcc34Sopenharmony_ci{ 551c72fcc34Sopenharmony_ci snd_use_case_mgr_t *uc_mgr = context->uc_mgr; 552c72fcc34Sopenharmony_ci int i, j, num, dev_num; 553c72fcc34Sopenharmony_ci const char **list, **dev_list, *verb, *comment; 554c72fcc34Sopenharmony_ci char buf[256]; 555c72fcc34Sopenharmony_ci 556c72fcc34Sopenharmony_ci num = snd_use_case_verb_list(uc_mgr, &list); 557c72fcc34Sopenharmony_ci if (num < 0) { 558c72fcc34Sopenharmony_ci fprintf(stderr, "%s: no verbs found\n", context->command); 559c72fcc34Sopenharmony_ci return; 560c72fcc34Sopenharmony_ci } 561c72fcc34Sopenharmony_ci if (render->init && render->init(render)) 562c72fcc34Sopenharmony_ci goto __end; 563c72fcc34Sopenharmony_ci for (i = 0; i < num; i += 2) { 564c72fcc34Sopenharmony_ci /* verb */ 565c72fcc34Sopenharmony_ci verb = list[i + 0]; 566c72fcc34Sopenharmony_ci comment = list[i + 1]; 567c72fcc34Sopenharmony_ci if (render->verb_begin(render, verb, comment)) 568c72fcc34Sopenharmony_ci break; 569c72fcc34Sopenharmony_ci /* devices */ 570c72fcc34Sopenharmony_ci snprintf(buf, sizeof(buf), "_devices/%s", verb); 571c72fcc34Sopenharmony_ci dev_num = snd_use_case_get_list(uc_mgr, buf, &dev_list); 572c72fcc34Sopenharmony_ci if (dev_num < 0) { 573c72fcc34Sopenharmony_ci fprintf(stderr, "%s: unable to get devices for verb '%s'\n", 574c72fcc34Sopenharmony_ci context->command, verb); 575c72fcc34Sopenharmony_ci continue; 576c72fcc34Sopenharmony_ci } 577c72fcc34Sopenharmony_ci if (dev_num == 0) 578c72fcc34Sopenharmony_ci goto __mods; 579c72fcc34Sopenharmony_ci if (render->device_block_begin && render->device_block_begin(render)) { 580c72fcc34Sopenharmony_ci snd_use_case_free_list(dev_list, dev_num); 581c72fcc34Sopenharmony_ci goto __end; 582c72fcc34Sopenharmony_ci } 583c72fcc34Sopenharmony_ci for (j = 0; j < dev_num; j += 2) { 584c72fcc34Sopenharmony_ci render->device_begin(render, dev_list[j + 0], dev_list[j + 1]); 585c72fcc34Sopenharmony_ci if (render_device(context, render, verb, dev_list[j + 0])) { 586c72fcc34Sopenharmony_ci snd_use_case_free_list(dev_list, dev_num); 587c72fcc34Sopenharmony_ci goto __end; 588c72fcc34Sopenharmony_ci } 589c72fcc34Sopenharmony_ci render->device_end(render); 590c72fcc34Sopenharmony_ci } 591c72fcc34Sopenharmony_ci snd_use_case_free_list(dev_list, dev_num); 592c72fcc34Sopenharmony_ci if (render->device_block_end && render->device_block_end(render)) 593c72fcc34Sopenharmony_ci goto __end; 594c72fcc34Sopenharmony_ci__mods: 595c72fcc34Sopenharmony_ci /* modifiers */ 596c72fcc34Sopenharmony_ci snprintf(buf, sizeof(buf), "_modifiers/%s", verb); 597c72fcc34Sopenharmony_ci dev_num = snd_use_case_get_list(uc_mgr, buf, &dev_list); 598c72fcc34Sopenharmony_ci if (dev_num < 0) { 599c72fcc34Sopenharmony_ci fprintf(stderr, "%s: unable to get modifiers for verb '%s'\n", 600c72fcc34Sopenharmony_ci context->command, verb); 601c72fcc34Sopenharmony_ci continue; 602c72fcc34Sopenharmony_ci } 603c72fcc34Sopenharmony_ci if (dev_num == 0) 604c72fcc34Sopenharmony_ci goto __verb_end; 605c72fcc34Sopenharmony_ci if (render->modifier_block_begin && render->modifier_block_begin(render)) { 606c72fcc34Sopenharmony_ci snd_use_case_free_list(dev_list, dev_num); 607c72fcc34Sopenharmony_ci goto __end; 608c72fcc34Sopenharmony_ci } 609c72fcc34Sopenharmony_ci for (j = 0; j < dev_num; j += 2) { 610c72fcc34Sopenharmony_ci render->modifier_begin(render, dev_list[j + 0], dev_list[j + 1]); 611c72fcc34Sopenharmony_ci render->modifier_end(render); 612c72fcc34Sopenharmony_ci } 613c72fcc34Sopenharmony_ci snd_use_case_free_list(dev_list, dev_num); 614c72fcc34Sopenharmony_ci if (render->modifier_block_end && render->modifier_block_end(render)) 615c72fcc34Sopenharmony_ci goto __end; 616c72fcc34Sopenharmony_ci__verb_end: 617c72fcc34Sopenharmony_ci /* end */ 618c72fcc34Sopenharmony_ci if (render->verb_end(render)) 619c72fcc34Sopenharmony_ci break; 620c72fcc34Sopenharmony_ci } 621c72fcc34Sopenharmony_ci if (render->done) 622c72fcc34Sopenharmony_ci render->done(render); 623c72fcc34Sopenharmony_ci__end: 624c72fcc34Sopenharmony_ci snd_use_case_free_list(list, num); 625c72fcc34Sopenharmony_ci} 626c72fcc34Sopenharmony_ci 627c72fcc34Sopenharmony_civoid dump(struct context *context, const char *format) 628c72fcc34Sopenharmony_ci{ 629c72fcc34Sopenharmony_ci struct renderer r; 630c72fcc34Sopenharmony_ci struct text t; 631c72fcc34Sopenharmony_ci struct json j; 632c72fcc34Sopenharmony_ci 633c72fcc34Sopenharmony_ci r.opaque = NULL; 634c72fcc34Sopenharmony_ci if (strcasecmp(format, "text") == 0 || 635c72fcc34Sopenharmony_ci strcasecmp(format, "txt") == 0) { 636c72fcc34Sopenharmony_ci memset(&t, 0, sizeof(t)); 637c72fcc34Sopenharmony_ci r = text_renderer; 638c72fcc34Sopenharmony_ci r.opaque = &t; 639c72fcc34Sopenharmony_ci } else if (strcasecmp(format, "json") == 0) { 640c72fcc34Sopenharmony_ci memset(&j, 0, sizeof(j)); 641c72fcc34Sopenharmony_ci r = json_renderer; 642c72fcc34Sopenharmony_ci r.opaque = &j; 643c72fcc34Sopenharmony_ci } 644c72fcc34Sopenharmony_ci if (r.opaque != NULL) { 645c72fcc34Sopenharmony_ci render(context, &r); 646c72fcc34Sopenharmony_ci return; 647c72fcc34Sopenharmony_ci } 648c72fcc34Sopenharmony_ci fprintf(stderr, "%s: unknown dump format '%s'\n", 649c72fcc34Sopenharmony_ci context->command, format); 650c72fcc34Sopenharmony_ci} 651