1c72fcc34Sopenharmony_ci/* 2c72fcc34Sopenharmony_ci Copyright(c) 2019 Red Hat Inc. 3c72fcc34Sopenharmony_ci Copyright(c) 2014-2015 Intel Corporation 4c72fcc34Sopenharmony_ci Copyright(c) 2010-2011 Texas Instruments Incorporated, 5c72fcc34Sopenharmony_ci All rights reserved. 6c72fcc34Sopenharmony_ci 7c72fcc34Sopenharmony_ci This program is free software; you can redistribute it and/or modify 8c72fcc34Sopenharmony_ci it under the terms of version 2 of the GNU General Public License as 9c72fcc34Sopenharmony_ci published by the Free Software Foundation. 10c72fcc34Sopenharmony_ci 11c72fcc34Sopenharmony_ci This program is distributed in the hope that it will be useful, but 12c72fcc34Sopenharmony_ci WITHOUT ANY WARRANTY; without even the implied warranty of 13c72fcc34Sopenharmony_ci MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14c72fcc34Sopenharmony_ci General Public License for more details. 15c72fcc34Sopenharmony_ci 16c72fcc34Sopenharmony_ci You should have received a copy of the GNU General Public License 17c72fcc34Sopenharmony_ci along with this program; if not, write to the Free Software 18c72fcc34Sopenharmony_ci Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. 19c72fcc34Sopenharmony_ci The full GNU General Public License is included in this distribution 20c72fcc34Sopenharmony_ci in the file called LICENSE.GPL. 21c72fcc34Sopenharmony_ci*/ 22c72fcc34Sopenharmony_ci 23c72fcc34Sopenharmony_ci#include "aconfig.h" 24c72fcc34Sopenharmony_ci#include <stdbool.h> 25c72fcc34Sopenharmony_ci#include <stdlib.h> 26c72fcc34Sopenharmony_ci#include <stdio.h> 27c72fcc34Sopenharmony_ci#include <stdint.h> 28c72fcc34Sopenharmony_ci#include <fcntl.h> 29c72fcc34Sopenharmony_ci#include <unistd.h> 30c72fcc34Sopenharmony_ci#include <errno.h> 31c72fcc34Sopenharmony_ci#include <string.h> 32c72fcc34Sopenharmony_ci#include <sys/stat.h> 33c72fcc34Sopenharmony_ci#include <getopt.h> 34c72fcc34Sopenharmony_ci#include <assert.h> 35c72fcc34Sopenharmony_ci 36c72fcc34Sopenharmony_ci#include <alsa/asoundlib.h> 37c72fcc34Sopenharmony_ci#include <alsa/topology.h> 38c72fcc34Sopenharmony_ci#include "gettext.h" 39c72fcc34Sopenharmony_ci#ifdef ENABLE_NLS 40c72fcc34Sopenharmony_ci#include <locale.h> 41c72fcc34Sopenharmony_ci#endif 42c72fcc34Sopenharmony_ci#include "version.h" 43c72fcc34Sopenharmony_ci#include "topology.h" 44c72fcc34Sopenharmony_ci 45c72fcc34Sopenharmony_cibool pre_process_config = false; 46c72fcc34Sopenharmony_ci 47c72fcc34Sopenharmony_cistatic snd_output_t *log; 48c72fcc34Sopenharmony_ci 49c72fcc34Sopenharmony_cistatic void usage(const char *name) 50c72fcc34Sopenharmony_ci{ 51c72fcc34Sopenharmony_ci printf( 52c72fcc34Sopenharmony_ci_("Usage: %s [OPTIONS]...\n" 53c72fcc34Sopenharmony_ci"\n" 54c72fcc34Sopenharmony_ci"-h, --help help\n" 55c72fcc34Sopenharmony_ci"-c, --compile=FILE compile configuration file\n" 56c72fcc34Sopenharmony_ci"-p, --pre-process pre-process Topology2.0 configuration file before compilation\n" 57c72fcc34Sopenharmony_ci"-P, --pre-process=FILE pre-process Topology2.0 configuration file\n" 58c72fcc34Sopenharmony_ci"-d, --decode=FILE decode binary topology file\n" 59c72fcc34Sopenharmony_ci"-n, --normalize=FILE normalize configuration file\n" 60c72fcc34Sopenharmony_ci"-u, --dump=FILE dump (reparse) configuration file\n" 61c72fcc34Sopenharmony_ci"-v, --verbose=LEVEL set verbosity level (0...1)\n" 62c72fcc34Sopenharmony_ci"-o, --output=FILE set output file\n" 63c72fcc34Sopenharmony_ci#if SND_LIB_VER(1, 2, 5) < SND_LIB_VERSION 64c72fcc34Sopenharmony_ci"-D, --define=ARGS define variables (VAR1=VAL1[,VAR2=VAL2] ...)\n" 65c72fcc34Sopenharmony_ci" (may be used multiple times)\n" 66c72fcc34Sopenharmony_ci"-I, --inc-dir=DIR set include path\n" 67c72fcc34Sopenharmony_ci#endif 68c72fcc34Sopenharmony_ci"-s, --sort sort the identifiers in the normalized output\n" 69c72fcc34Sopenharmony_ci"-g, --group save configuration by group indexes\n" 70c72fcc34Sopenharmony_ci"-x, --nocheck save configuration without additional integrity checks\n" 71c72fcc34Sopenharmony_ci"-z, --dapm-nosort do not sort the DAPM widgets\n" 72c72fcc34Sopenharmony_ci"-V, --version print version\n" 73c72fcc34Sopenharmony_ci), name); 74c72fcc34Sopenharmony_ci} 75c72fcc34Sopenharmony_ci 76c72fcc34Sopenharmony_cistatic void version(const char *name) 77c72fcc34Sopenharmony_ci{ 78c72fcc34Sopenharmony_ci printf( 79c72fcc34Sopenharmony_ci_("%s version %s\n" 80c72fcc34Sopenharmony_ci"libasound version %s\n" 81c72fcc34Sopenharmony_ci"libatopology version %s\n" 82c72fcc34Sopenharmony_ci), name, SND_UTIL_VERSION_STR, 83c72fcc34Sopenharmony_ci snd_asoundlib_version(), snd_tplg_version()); 84c72fcc34Sopenharmony_ci} 85c72fcc34Sopenharmony_ci 86c72fcc34Sopenharmony_cistatic int load(const char *source_file, void **dst, size_t *dst_size) 87c72fcc34Sopenharmony_ci{ 88c72fcc34Sopenharmony_ci int fd; 89c72fcc34Sopenharmony_ci void *buf, *buf2; 90c72fcc34Sopenharmony_ci size_t size, pos; 91c72fcc34Sopenharmony_ci ssize_t r; 92c72fcc34Sopenharmony_ci 93c72fcc34Sopenharmony_ci if (strcmp(source_file, "-") == 0) { 94c72fcc34Sopenharmony_ci fd = fileno(stdin); 95c72fcc34Sopenharmony_ci } else { 96c72fcc34Sopenharmony_ci fd = open(source_file, O_RDONLY); 97c72fcc34Sopenharmony_ci if (fd < 0) { 98c72fcc34Sopenharmony_ci fprintf(stderr, _("Unable to open input file '%s': %s\n"), 99c72fcc34Sopenharmony_ci source_file, strerror(errno)); 100c72fcc34Sopenharmony_ci return 1; 101c72fcc34Sopenharmony_ci } 102c72fcc34Sopenharmony_ci } 103c72fcc34Sopenharmony_ci 104c72fcc34Sopenharmony_ci size = 16*1024; 105c72fcc34Sopenharmony_ci pos = 0; 106c72fcc34Sopenharmony_ci buf = malloc(size); 107c72fcc34Sopenharmony_ci if (buf == NULL) 108c72fcc34Sopenharmony_ci goto _nomem; 109c72fcc34Sopenharmony_ci while (1) { 110c72fcc34Sopenharmony_ci r = read(fd, buf + pos, size - pos); 111c72fcc34Sopenharmony_ci if (r < 0 && (errno == EAGAIN || errno == EINTR)) 112c72fcc34Sopenharmony_ci continue; 113c72fcc34Sopenharmony_ci if (r <= 0) 114c72fcc34Sopenharmony_ci break; 115c72fcc34Sopenharmony_ci pos += r; 116c72fcc34Sopenharmony_ci size += 8*1024; 117c72fcc34Sopenharmony_ci buf2 = realloc(buf, size); 118c72fcc34Sopenharmony_ci if (buf2 == NULL) 119c72fcc34Sopenharmony_ci goto _nomem; 120c72fcc34Sopenharmony_ci buf = buf2; 121c72fcc34Sopenharmony_ci } 122c72fcc34Sopenharmony_ci if (r < 0) { 123c72fcc34Sopenharmony_ci fprintf(stderr, _("Read error: %s\n"), strerror(errno)); 124c72fcc34Sopenharmony_ci goto _err; 125c72fcc34Sopenharmony_ci } 126c72fcc34Sopenharmony_ci 127c72fcc34Sopenharmony_ci if (fd != fileno(stdin)) 128c72fcc34Sopenharmony_ci close(fd); 129c72fcc34Sopenharmony_ci 130c72fcc34Sopenharmony_ci *dst = buf; 131c72fcc34Sopenharmony_ci *dst_size = pos; 132c72fcc34Sopenharmony_ci return 0; 133c72fcc34Sopenharmony_ci 134c72fcc34Sopenharmony_ci_nomem: 135c72fcc34Sopenharmony_ci fprintf(stderr, _("No enough memory\n")); 136c72fcc34Sopenharmony_ci_err: 137c72fcc34Sopenharmony_ci if (fd != fileno(stdin)) 138c72fcc34Sopenharmony_ci close(fd); 139c72fcc34Sopenharmony_ci free(buf); 140c72fcc34Sopenharmony_ci return 1; 141c72fcc34Sopenharmony_ci} 142c72fcc34Sopenharmony_ci 143c72fcc34Sopenharmony_cistatic int load_topology(snd_tplg_t **tplg, char *config, 144c72fcc34Sopenharmony_ci size_t config_size, int cflags) 145c72fcc34Sopenharmony_ci{ 146c72fcc34Sopenharmony_ci int err; 147c72fcc34Sopenharmony_ci 148c72fcc34Sopenharmony_ci *tplg = snd_tplg_create(cflags); 149c72fcc34Sopenharmony_ci if (*tplg == NULL) { 150c72fcc34Sopenharmony_ci fprintf(stderr, _("failed to create new topology context\n")); 151c72fcc34Sopenharmony_ci return 1; 152c72fcc34Sopenharmony_ci } 153c72fcc34Sopenharmony_ci 154c72fcc34Sopenharmony_ci err = snd_tplg_load(*tplg, config, config_size); 155c72fcc34Sopenharmony_ci if (err < 0) { 156c72fcc34Sopenharmony_ci fprintf(stderr, _("Unable to load configuration: %s\n"), 157c72fcc34Sopenharmony_ci snd_strerror(-err)); 158c72fcc34Sopenharmony_ci snd_tplg_free(*tplg); 159c72fcc34Sopenharmony_ci return 1; 160c72fcc34Sopenharmony_ci } 161c72fcc34Sopenharmony_ci 162c72fcc34Sopenharmony_ci return 0; 163c72fcc34Sopenharmony_ci} 164c72fcc34Sopenharmony_ci 165c72fcc34Sopenharmony_cistatic int save(const char *output_file, void *buf, size_t size) 166c72fcc34Sopenharmony_ci{ 167c72fcc34Sopenharmony_ci char *fname = NULL; 168c72fcc34Sopenharmony_ci int fd; 169c72fcc34Sopenharmony_ci ssize_t r; 170c72fcc34Sopenharmony_ci 171c72fcc34Sopenharmony_ci if (strcmp(output_file, "-") == 0) { 172c72fcc34Sopenharmony_ci fd = fileno(stdout); 173c72fcc34Sopenharmony_ci } else { 174c72fcc34Sopenharmony_ci fname = alloca(strlen(output_file) + 5); 175c72fcc34Sopenharmony_ci strcpy(fname, output_file); 176c72fcc34Sopenharmony_ci strcat(fname, ".new"); 177c72fcc34Sopenharmony_ci fd = open(fname, O_RDWR | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH); 178c72fcc34Sopenharmony_ci if (fd < 0) { 179c72fcc34Sopenharmony_ci fprintf(stderr, _("Unable to open output file '%s': %s\n"), 180c72fcc34Sopenharmony_ci fname, strerror(errno)); 181c72fcc34Sopenharmony_ci return 1; 182c72fcc34Sopenharmony_ci } 183c72fcc34Sopenharmony_ci } 184c72fcc34Sopenharmony_ci 185c72fcc34Sopenharmony_ci r = 0; 186c72fcc34Sopenharmony_ci while (size > 0) { 187c72fcc34Sopenharmony_ci r = write(fd, buf, size); 188c72fcc34Sopenharmony_ci if (r < 0 && (errno == EAGAIN || errno == EINTR)) 189c72fcc34Sopenharmony_ci continue; 190c72fcc34Sopenharmony_ci if (r < 0) 191c72fcc34Sopenharmony_ci break; 192c72fcc34Sopenharmony_ci size -= r; 193c72fcc34Sopenharmony_ci buf += r; 194c72fcc34Sopenharmony_ci } 195c72fcc34Sopenharmony_ci 196c72fcc34Sopenharmony_ci if (r < 0) { 197c72fcc34Sopenharmony_ci fprintf(stderr, _("Write error: %s\n"), strerror(errno)); 198c72fcc34Sopenharmony_ci if (fd != fileno(stdout)) { 199c72fcc34Sopenharmony_ci if (fname && remove(fname)) 200c72fcc34Sopenharmony_ci fprintf(stderr, _("Unable to remove file %s: %s\n"), 201c72fcc34Sopenharmony_ci fname, strerror(errno)); 202c72fcc34Sopenharmony_ci close(fd); 203c72fcc34Sopenharmony_ci } 204c72fcc34Sopenharmony_ci return 1; 205c72fcc34Sopenharmony_ci } 206c72fcc34Sopenharmony_ci 207c72fcc34Sopenharmony_ci if (fd != fileno(stdout)) 208c72fcc34Sopenharmony_ci close(fd); 209c72fcc34Sopenharmony_ci 210c72fcc34Sopenharmony_ci if (fname && rename(fname, output_file)) { 211c72fcc34Sopenharmony_ci fprintf(stderr, _("Unable to rename file '%s' to '%s': %s\n"), 212c72fcc34Sopenharmony_ci fname, output_file, strerror(errno)); 213c72fcc34Sopenharmony_ci return 1; 214c72fcc34Sopenharmony_ci } 215c72fcc34Sopenharmony_ci 216c72fcc34Sopenharmony_ci return 0; 217c72fcc34Sopenharmony_ci} 218c72fcc34Sopenharmony_ci 219c72fcc34Sopenharmony_cistatic int dump(const char *source_file, const char *output_file, int cflags, int sflags) 220c72fcc34Sopenharmony_ci{ 221c72fcc34Sopenharmony_ci snd_tplg_t *tplg; 222c72fcc34Sopenharmony_ci char *config, *text; 223c72fcc34Sopenharmony_ci size_t size; 224c72fcc34Sopenharmony_ci int err; 225c72fcc34Sopenharmony_ci 226c72fcc34Sopenharmony_ci err = load(source_file, (void **)&config, &size); 227c72fcc34Sopenharmony_ci if (err) 228c72fcc34Sopenharmony_ci return err; 229c72fcc34Sopenharmony_ci err = load_topology(&tplg, config, size, cflags); 230c72fcc34Sopenharmony_ci free(config); 231c72fcc34Sopenharmony_ci if (err) 232c72fcc34Sopenharmony_ci return err; 233c72fcc34Sopenharmony_ci err = snd_tplg_save(tplg, &text, sflags); 234c72fcc34Sopenharmony_ci snd_tplg_free(tplg); 235c72fcc34Sopenharmony_ci if (err < 0) { 236c72fcc34Sopenharmony_ci fprintf(stderr, _("Unable to save parsed configuration: %s\n"), 237c72fcc34Sopenharmony_ci snd_strerror(-err)); 238c72fcc34Sopenharmony_ci return 1; 239c72fcc34Sopenharmony_ci } 240c72fcc34Sopenharmony_ci err = save(output_file, text, strlen(text)); 241c72fcc34Sopenharmony_ci free(text); 242c72fcc34Sopenharmony_ci return err; 243c72fcc34Sopenharmony_ci} 244c72fcc34Sopenharmony_ci 245c72fcc34Sopenharmony_cistatic char *get_inc_path(const char *filename) 246c72fcc34Sopenharmony_ci{ 247c72fcc34Sopenharmony_ci const char *s = strrchr(filename, '/'); 248c72fcc34Sopenharmony_ci char *r = strdup(filename); 249c72fcc34Sopenharmony_ci if (r) { 250c72fcc34Sopenharmony_ci if (s) 251c72fcc34Sopenharmony_ci r[s - filename] = '\0'; 252c72fcc34Sopenharmony_ci else if (r[0]) 253c72fcc34Sopenharmony_ci strcpy(r, "."); 254c72fcc34Sopenharmony_ci } 255c72fcc34Sopenharmony_ci return r; 256c72fcc34Sopenharmony_ci} 257c72fcc34Sopenharmony_ci 258c72fcc34Sopenharmony_cistatic int pre_process_run(struct tplg_pre_processor **tplg_pp, 259c72fcc34Sopenharmony_ci const char *source_file, const char *output_file, 260c72fcc34Sopenharmony_ci const char *pre_processor_defs, const char *include_path) 261c72fcc34Sopenharmony_ci{ 262c72fcc34Sopenharmony_ci size_t config_size; 263c72fcc34Sopenharmony_ci char *config, *inc_path; 264c72fcc34Sopenharmony_ci snd_output_type_t output_type; 265c72fcc34Sopenharmony_ci int err; 266c72fcc34Sopenharmony_ci 267c72fcc34Sopenharmony_ci err = load(source_file, (void **)&config, &config_size); 268c72fcc34Sopenharmony_ci if (err) 269c72fcc34Sopenharmony_ci return err; 270c72fcc34Sopenharmony_ci 271c72fcc34Sopenharmony_ci /* init pre-processor */ 272c72fcc34Sopenharmony_ci output_type = output_file == NULL ? SND_OUTPUT_BUFFER : SND_OUTPUT_STDIO; 273c72fcc34Sopenharmony_ci err = init_pre_processor(tplg_pp, output_type, output_file); 274c72fcc34Sopenharmony_ci if (err < 0) { 275c72fcc34Sopenharmony_ci fprintf(stderr, _("failed to init pre-processor for Topology2.0\n")); 276c72fcc34Sopenharmony_ci free(config); 277c72fcc34Sopenharmony_ci return err; 278c72fcc34Sopenharmony_ci } 279c72fcc34Sopenharmony_ci 280c72fcc34Sopenharmony_ci /* pre-process conf file */ 281c72fcc34Sopenharmony_ci if (!include_path) 282c72fcc34Sopenharmony_ci inc_path = get_inc_path(source_file); 283c72fcc34Sopenharmony_ci else 284c72fcc34Sopenharmony_ci inc_path = strdup(include_path); 285c72fcc34Sopenharmony_ci err = pre_process(*tplg_pp, config, config_size, pre_processor_defs, inc_path); 286c72fcc34Sopenharmony_ci free(inc_path); 287c72fcc34Sopenharmony_ci 288c72fcc34Sopenharmony_ci if (err < 0) 289c72fcc34Sopenharmony_ci free_pre_processor(*tplg_pp); 290c72fcc34Sopenharmony_ci free(config); 291c72fcc34Sopenharmony_ci return err; 292c72fcc34Sopenharmony_ci} 293c72fcc34Sopenharmony_ci 294c72fcc34Sopenharmony_ci/* Convert Topology2.0 conf to the existing conf syntax */ 295c72fcc34Sopenharmony_cistatic int pre_process_conf(const char *source_file, const char *output_file, 296c72fcc34Sopenharmony_ci const char *pre_processor_defs, const char *include_path) 297c72fcc34Sopenharmony_ci{ 298c72fcc34Sopenharmony_ci struct tplg_pre_processor *tplg_pp; 299c72fcc34Sopenharmony_ci int err; 300c72fcc34Sopenharmony_ci 301c72fcc34Sopenharmony_ci err = pre_process_run(&tplg_pp, source_file, output_file, 302c72fcc34Sopenharmony_ci pre_processor_defs, include_path); 303c72fcc34Sopenharmony_ci if (err < 0) 304c72fcc34Sopenharmony_ci return err; 305c72fcc34Sopenharmony_ci 306c72fcc34Sopenharmony_ci /* free pre-processor */ 307c72fcc34Sopenharmony_ci free_pre_processor(tplg_pp); 308c72fcc34Sopenharmony_ci return err; 309c72fcc34Sopenharmony_ci} 310c72fcc34Sopenharmony_ci 311c72fcc34Sopenharmony_cistatic int compile(const char *source_file, const char *output_file, int cflags, 312c72fcc34Sopenharmony_ci const char *pre_processor_defs, const char *include_path) 313c72fcc34Sopenharmony_ci{ 314c72fcc34Sopenharmony_ci struct tplg_pre_processor *tplg_pp = NULL; 315c72fcc34Sopenharmony_ci snd_tplg_t *tplg; 316c72fcc34Sopenharmony_ci char *config; 317c72fcc34Sopenharmony_ci void *bin; 318c72fcc34Sopenharmony_ci size_t config_size, size; 319c72fcc34Sopenharmony_ci int err; 320c72fcc34Sopenharmony_ci 321c72fcc34Sopenharmony_ci err = load(source_file, (void **)&config, &config_size); 322c72fcc34Sopenharmony_ci if (err) 323c72fcc34Sopenharmony_ci return err; 324c72fcc34Sopenharmony_ci 325c72fcc34Sopenharmony_ci /* pre-process before compiling */ 326c72fcc34Sopenharmony_ci if (pre_process_config) { 327c72fcc34Sopenharmony_ci char *pconfig; 328c72fcc34Sopenharmony_ci size_t size; 329c72fcc34Sopenharmony_ci 330c72fcc34Sopenharmony_ci err = pre_process_run(&tplg_pp, source_file, NULL, 331c72fcc34Sopenharmony_ci pre_processor_defs, include_path); 332c72fcc34Sopenharmony_ci if (err < 0) 333c72fcc34Sopenharmony_ci return err; 334c72fcc34Sopenharmony_ci 335c72fcc34Sopenharmony_ci /* load topology */ 336c72fcc34Sopenharmony_ci size = snd_output_buffer_string(tplg_pp->output, &pconfig); 337c72fcc34Sopenharmony_ci err = load_topology(&tplg, pconfig, size, cflags); 338c72fcc34Sopenharmony_ci 339c72fcc34Sopenharmony_ci /* free pre-processor */ 340c72fcc34Sopenharmony_ci free_pre_processor(tplg_pp); 341c72fcc34Sopenharmony_ci } else { 342c72fcc34Sopenharmony_ci err = load_topology(&tplg, config, config_size, cflags); 343c72fcc34Sopenharmony_ci } 344c72fcc34Sopenharmony_ci free(config); 345c72fcc34Sopenharmony_ci if (err) 346c72fcc34Sopenharmony_ci return err; 347c72fcc34Sopenharmony_ci err = snd_tplg_build_bin(tplg, &bin, &size); 348c72fcc34Sopenharmony_ci snd_tplg_free(tplg); 349c72fcc34Sopenharmony_ci if (err < 0 || size == 0) { 350c72fcc34Sopenharmony_ci fprintf(stderr, _("failed to compile context %s: %s\n"), 351c72fcc34Sopenharmony_ci source_file, snd_strerror(-err)); 352c72fcc34Sopenharmony_ci return 1; 353c72fcc34Sopenharmony_ci } 354c72fcc34Sopenharmony_ci err = save(output_file, bin, size); 355c72fcc34Sopenharmony_ci free(bin); 356c72fcc34Sopenharmony_ci return err; 357c72fcc34Sopenharmony_ci} 358c72fcc34Sopenharmony_ci 359c72fcc34Sopenharmony_cistatic int decode(const char *source_file, const char *output_file, 360c72fcc34Sopenharmony_ci int cflags, int dflags, int sflags) 361c72fcc34Sopenharmony_ci{ 362c72fcc34Sopenharmony_ci snd_tplg_t *tplg; 363c72fcc34Sopenharmony_ci void *bin; 364c72fcc34Sopenharmony_ci char *text; 365c72fcc34Sopenharmony_ci size_t size; 366c72fcc34Sopenharmony_ci int err; 367c72fcc34Sopenharmony_ci 368c72fcc34Sopenharmony_ci if (load(source_file, &bin, &size)) 369c72fcc34Sopenharmony_ci return 1; 370c72fcc34Sopenharmony_ci tplg = snd_tplg_create(cflags); 371c72fcc34Sopenharmony_ci if (tplg == NULL) { 372c72fcc34Sopenharmony_ci fprintf(stderr, _("failed to create new topology context\n")); 373c72fcc34Sopenharmony_ci return 1; 374c72fcc34Sopenharmony_ci } 375c72fcc34Sopenharmony_ci err = snd_tplg_decode(tplg, bin, size, dflags); 376c72fcc34Sopenharmony_ci free(bin); 377c72fcc34Sopenharmony_ci if (err < 0) { 378c72fcc34Sopenharmony_ci snd_tplg_free(tplg); 379c72fcc34Sopenharmony_ci fprintf(stderr, _("failed to decode context %s: %s\n"), 380c72fcc34Sopenharmony_ci source_file, snd_strerror(-err)); 381c72fcc34Sopenharmony_ci return 1; 382c72fcc34Sopenharmony_ci } 383c72fcc34Sopenharmony_ci err = snd_tplg_save(tplg, &text, sflags); 384c72fcc34Sopenharmony_ci snd_tplg_free(tplg); 385c72fcc34Sopenharmony_ci if (err < 0) { 386c72fcc34Sopenharmony_ci fprintf(stderr, _("Unable to save parsed configuration: %s\n"), 387c72fcc34Sopenharmony_ci snd_strerror(-err)); 388c72fcc34Sopenharmony_ci return 1; 389c72fcc34Sopenharmony_ci } 390c72fcc34Sopenharmony_ci err = save(output_file, text, strlen(text)); 391c72fcc34Sopenharmony_ci free(text); 392c72fcc34Sopenharmony_ci return err; 393c72fcc34Sopenharmony_ci} 394c72fcc34Sopenharmony_ci 395c72fcc34Sopenharmony_ci#if SND_LIB_VER(1, 2, 5) < SND_LIB_VERSION 396c72fcc34Sopenharmony_cistatic int add_define(char **defs, char *d) 397c72fcc34Sopenharmony_ci{ 398c72fcc34Sopenharmony_ci size_t len = (*defs ? strlen(*defs) : 0) + strlen(d) + 2; 399c72fcc34Sopenharmony_ci char *m = realloc(*defs, len); 400c72fcc34Sopenharmony_ci if (m) { 401c72fcc34Sopenharmony_ci if (*defs) 402c72fcc34Sopenharmony_ci strcat(m, ","); 403c72fcc34Sopenharmony_ci strcat(m, d); 404c72fcc34Sopenharmony_ci *defs = m; 405c72fcc34Sopenharmony_ci return 0; 406c72fcc34Sopenharmony_ci } 407c72fcc34Sopenharmony_ci return 1; 408c72fcc34Sopenharmony_ci} 409c72fcc34Sopenharmony_ci#endif 410c72fcc34Sopenharmony_ci 411c72fcc34Sopenharmony_ciint main(int argc, char *argv[]) 412c72fcc34Sopenharmony_ci{ 413c72fcc34Sopenharmony_ci static const char short_options[] = "hc:d:n:u:v:o:pP:sgxzV" 414c72fcc34Sopenharmony_ci#if SND_LIB_VER(1, 2, 5) < SND_LIB_VERSION 415c72fcc34Sopenharmony_ci "D:I:" 416c72fcc34Sopenharmony_ci#endif 417c72fcc34Sopenharmony_ci ; 418c72fcc34Sopenharmony_ci static const struct option long_options[] = { 419c72fcc34Sopenharmony_ci {"help", 0, NULL, 'h'}, 420c72fcc34Sopenharmony_ci {"verbose", 1, NULL, 'v'}, 421c72fcc34Sopenharmony_ci {"compile", 1, NULL, 'c'}, 422c72fcc34Sopenharmony_ci {"pre-process", 1, NULL, 'p'}, 423c72fcc34Sopenharmony_ci {"decode", 1, NULL, 'd'}, 424c72fcc34Sopenharmony_ci {"normalize", 1, NULL, 'n'}, 425c72fcc34Sopenharmony_ci {"dump", 1, NULL, 'u'}, 426c72fcc34Sopenharmony_ci {"output", 1, NULL, 'o'}, 427c72fcc34Sopenharmony_ci#if SND_LIB_VER(1, 2, 5) < SND_LIB_VERSION 428c72fcc34Sopenharmony_ci {"define", 1, NULL, 'D'}, 429c72fcc34Sopenharmony_ci {"inc-dir", 1, NULL, 'I'}, 430c72fcc34Sopenharmony_ci#endif 431c72fcc34Sopenharmony_ci {"sort", 0, NULL, 's'}, 432c72fcc34Sopenharmony_ci {"group", 0, NULL, 'g'}, 433c72fcc34Sopenharmony_ci {"nocheck", 0, NULL, 'x'}, 434c72fcc34Sopenharmony_ci {"dapm-nosort", 0, NULL, 'z'}, 435c72fcc34Sopenharmony_ci {"version", 0, NULL, 'V'}, 436c72fcc34Sopenharmony_ci {0, 0, 0, 0}, 437c72fcc34Sopenharmony_ci }; 438c72fcc34Sopenharmony_ci char *source_file = NULL; 439c72fcc34Sopenharmony_ci char *output_file = NULL; 440c72fcc34Sopenharmony_ci const char *inc_path = NULL; 441c72fcc34Sopenharmony_ci char *pre_processor_defs = NULL; 442c72fcc34Sopenharmony_ci int c, err, op = 'c', cflags = 0, dflags = 0, sflags = 0, option_index; 443c72fcc34Sopenharmony_ci 444c72fcc34Sopenharmony_ci#ifdef ENABLE_NLS 445c72fcc34Sopenharmony_ci setlocale(LC_ALL, ""); 446c72fcc34Sopenharmony_ci textdomain(PACKAGE); 447c72fcc34Sopenharmony_ci#endif 448c72fcc34Sopenharmony_ci 449c72fcc34Sopenharmony_ci err = snd_output_stdio_attach(&log, stderr, 0); 450c72fcc34Sopenharmony_ci assert(err >= 0); 451c72fcc34Sopenharmony_ci 452c72fcc34Sopenharmony_ci while ((c = getopt_long(argc, argv, short_options, long_options, &option_index)) != -1) { 453c72fcc34Sopenharmony_ci switch (c) { 454c72fcc34Sopenharmony_ci case 'h': 455c72fcc34Sopenharmony_ci usage(argv[0]); 456c72fcc34Sopenharmony_ci return 0; 457c72fcc34Sopenharmony_ci case 'v': 458c72fcc34Sopenharmony_ci cflags |= SND_TPLG_CREATE_VERBOSE; 459c72fcc34Sopenharmony_ci break; 460c72fcc34Sopenharmony_ci case 'z': 461c72fcc34Sopenharmony_ci cflags |= SND_TPLG_CREATE_DAPM_NOSORT; 462c72fcc34Sopenharmony_ci break; 463c72fcc34Sopenharmony_ci case 'c': 464c72fcc34Sopenharmony_ci case 'd': 465c72fcc34Sopenharmony_ci case 'n': 466c72fcc34Sopenharmony_ci case 'u': 467c72fcc34Sopenharmony_ci if (source_file) { 468c72fcc34Sopenharmony_ci fprintf(stderr, _("Cannot combine operations (compile, normalize, pre-process, dump)\n")); 469c72fcc34Sopenharmony_ci return 1; 470c72fcc34Sopenharmony_ci } 471c72fcc34Sopenharmony_ci source_file = optarg; 472c72fcc34Sopenharmony_ci op = c; 473c72fcc34Sopenharmony_ci break; 474c72fcc34Sopenharmony_ci case 'o': 475c72fcc34Sopenharmony_ci output_file = optarg; 476c72fcc34Sopenharmony_ci break; 477c72fcc34Sopenharmony_ci case 's': 478c72fcc34Sopenharmony_ci sflags |= SND_TPLG_SAVE_SORT; 479c72fcc34Sopenharmony_ci break; 480c72fcc34Sopenharmony_ci case 'P': 481c72fcc34Sopenharmony_ci op = 'P'; 482c72fcc34Sopenharmony_ci source_file = optarg; 483c72fcc34Sopenharmony_ci break; 484c72fcc34Sopenharmony_ci#if SND_LIB_VER(1, 2, 5) < SND_LIB_VERSION 485c72fcc34Sopenharmony_ci case 'I': 486c72fcc34Sopenharmony_ci inc_path = optarg; 487c72fcc34Sopenharmony_ci break; 488c72fcc34Sopenharmony_ci#endif 489c72fcc34Sopenharmony_ci case 'p': 490c72fcc34Sopenharmony_ci pre_process_config = true; 491c72fcc34Sopenharmony_ci break; 492c72fcc34Sopenharmony_ci case 'g': 493c72fcc34Sopenharmony_ci sflags |= SND_TPLG_SAVE_GROUPS; 494c72fcc34Sopenharmony_ci break; 495c72fcc34Sopenharmony_ci case 'x': 496c72fcc34Sopenharmony_ci sflags |= SND_TPLG_SAVE_NOCHECK; 497c72fcc34Sopenharmony_ci break; 498c72fcc34Sopenharmony_ci#if SND_LIB_VER(1, 2, 5) < SND_LIB_VERSION 499c72fcc34Sopenharmony_ci case 'D': 500c72fcc34Sopenharmony_ci if (add_define(&pre_processor_defs, optarg)) { 501c72fcc34Sopenharmony_ci fprintf(stderr, _("No enough memory")); 502c72fcc34Sopenharmony_ci return 1; 503c72fcc34Sopenharmony_ci } 504c72fcc34Sopenharmony_ci break; 505c72fcc34Sopenharmony_ci#endif 506c72fcc34Sopenharmony_ci case 'V': 507c72fcc34Sopenharmony_ci version(argv[0]); 508c72fcc34Sopenharmony_ci return 0; 509c72fcc34Sopenharmony_ci default: 510c72fcc34Sopenharmony_ci fprintf(stderr, _("Try `%s --help' for more information.\n"), argv[0]); 511c72fcc34Sopenharmony_ci return 1; 512c72fcc34Sopenharmony_ci } 513c72fcc34Sopenharmony_ci } 514c72fcc34Sopenharmony_ci 515c72fcc34Sopenharmony_ci if (source_file == NULL || output_file == NULL) { 516c72fcc34Sopenharmony_ci usage(argv[0]); 517c72fcc34Sopenharmony_ci return 1; 518c72fcc34Sopenharmony_ci } 519c72fcc34Sopenharmony_ci 520c72fcc34Sopenharmony_ci if ((cflags & SND_TPLG_CREATE_VERBOSE) != 0 && 521c72fcc34Sopenharmony_ci output_file && strcmp(output_file, "-") == 0) { 522c72fcc34Sopenharmony_ci fprintf(stderr, _("Invalid mix of verbose level and output to stdout.\n")); 523c72fcc34Sopenharmony_ci return 1; 524c72fcc34Sopenharmony_ci } 525c72fcc34Sopenharmony_ci 526c72fcc34Sopenharmony_ci if (op == 'n') { 527c72fcc34Sopenharmony_ci if (sflags != 0 && sflags != SND_TPLG_SAVE_SORT) { 528c72fcc34Sopenharmony_ci fprintf(stderr, _("Wrong parameters for the normalize operation!\n")); 529c72fcc34Sopenharmony_ci return 1; 530c72fcc34Sopenharmony_ci } 531c72fcc34Sopenharmony_ci /* normalize has predefined output */ 532c72fcc34Sopenharmony_ci sflags = SND_TPLG_SAVE_SORT; 533c72fcc34Sopenharmony_ci } 534c72fcc34Sopenharmony_ci 535c72fcc34Sopenharmony_ci switch (op) { 536c72fcc34Sopenharmony_ci case 'c': 537c72fcc34Sopenharmony_ci err = compile(source_file, output_file, cflags, pre_processor_defs, inc_path); 538c72fcc34Sopenharmony_ci break; 539c72fcc34Sopenharmony_ci case 'd': 540c72fcc34Sopenharmony_ci err = decode(source_file, output_file, cflags, dflags, sflags); 541c72fcc34Sopenharmony_ci break; 542c72fcc34Sopenharmony_ci case 'P': 543c72fcc34Sopenharmony_ci err = pre_process_conf(source_file, output_file, pre_processor_defs, inc_path); 544c72fcc34Sopenharmony_ci break; 545c72fcc34Sopenharmony_ci default: 546c72fcc34Sopenharmony_ci err = dump(source_file, output_file, cflags, sflags); 547c72fcc34Sopenharmony_ci break; 548c72fcc34Sopenharmony_ci } 549c72fcc34Sopenharmony_ci 550c72fcc34Sopenharmony_ci snd_output_close(log); 551c72fcc34Sopenharmony_ci free(pre_processor_defs); 552c72fcc34Sopenharmony_ci return err ? 1 : 0; 553c72fcc34Sopenharmony_ci} 554