alsa-utils/axfer/xfer-options.c

629 lines
16 KiB
C
Raw Normal View History

axfer: add a parser for command-line options In aplay, many command-line options are supported. Some of them have dependency or conflicts. Furthemore, some of them are just for runtime configuration of alsa-lib(libasound), and some options can be used by several xfer backends commonly; e.g. options for file name, sample format and sampling rate. This commit adds a parser for the common options below. * --help (-h) * Just output 'help' string (not written yet). * --verbose (-v) * For verbose output, including information about xfer, mapper and container. * --format (-f): string. format literals or one of ['cd'|'cdr'|'dat'] * For sample format supported by ALSA PCM interface. Special format can be used. For playback, this is auto-detected according to actual file format. * --channels (-c) * For the number of samples included in one data frame. For playback, this is auto-detected according to actual file format, except for 'raw' format. This option can conflict to above format option. * --rate (-r) * For the number of data frames transferred in one second. For playback, this is auto-detected according to actual file format, except for 'raw' format. This option can conflict to format option above. * --file-type (-f): string. one of ['wav'|'au'|'voc'|'raw'] * For format of files of given paths. For playback, this is optional because the format is auto-detected. For capture, this is optional too because the format is decided according to suffix of given path. Anyway, this option is used for cases to fail to detect or decide. * --separate-channels (-I) * When using several files as source or destination for transmission of data frame, this option can be used with several file paths. When '--separate-channels' option is used, users can give several file paths to source/destination of data transmission, else they can give single file path for the purpose. When multiple files are handled by this option, for playback, data frames in first channel is used to construct buffer for data transmission with multi channel. For capture, data frames in each channel of buffer are written to each of given path. Furthermore, when a single path is given for capture, file paths are auto-generated according to available number of channels. For example, 'name.wav' is given for 2 channels capture, 'name-0.wav' and 'name-1.wav' are generated. In a case of no suffix, 'name-0' and 'name-1' are generated. Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp> Signed-off-by: Takashi Iwai <tiwai@suse.de>
2018-11-13 07:41:26 +01:00
// SPDX-License-Identifier: GPL-2.0
//
// xfer-options.c - a parser of commandline options for xfer.
//
// Copyright (c) 2018 Takashi Sakamoto <o-takashi@sakamocchi.jp>
//
// Licensed under the terms of the GNU General Public License, version 2.
#include "xfer.h"
#include "misc.h"
#include <getopt.h>
#include <math.h>
#include <limits.h>
enum no_short_opts {
// 128 or later belong to non us-ascii character set.
OPT_XFER_TYPE = 128,
OPT_DUMP_HW_PARAMS,
OPT_PERIOD_SIZE,
OPT_BUFFER_SIZE,
// Obsoleted.
OPT_MAX_FILE_TIME,
OPT_USE_STRFTIME,
OPT_PROCESS_ID_FILE,
axfer: add a parser for command-line options In aplay, many command-line options are supported. Some of them have dependency or conflicts. Furthemore, some of them are just for runtime configuration of alsa-lib(libasound), and some options can be used by several xfer backends commonly; e.g. options for file name, sample format and sampling rate. This commit adds a parser for the common options below. * --help (-h) * Just output 'help' string (not written yet). * --verbose (-v) * For verbose output, including information about xfer, mapper and container. * --format (-f): string. format literals or one of ['cd'|'cdr'|'dat'] * For sample format supported by ALSA PCM interface. Special format can be used. For playback, this is auto-detected according to actual file format. * --channels (-c) * For the number of samples included in one data frame. For playback, this is auto-detected according to actual file format, except for 'raw' format. This option can conflict to above format option. * --rate (-r) * For the number of data frames transferred in one second. For playback, this is auto-detected according to actual file format, except for 'raw' format. This option can conflict to format option above. * --file-type (-f): string. one of ['wav'|'au'|'voc'|'raw'] * For format of files of given paths. For playback, this is optional because the format is auto-detected. For capture, this is optional too because the format is decided according to suffix of given path. Anyway, this option is used for cases to fail to detect or decide. * --separate-channels (-I) * When using several files as source or destination for transmission of data frame, this option can be used with several file paths. When '--separate-channels' option is used, users can give several file paths to source/destination of data transmission, else they can give single file path for the purpose. When multiple files are handled by this option, for playback, data frames in first channel is used to construct buffer for data transmission with multi channel. For capture, data frames in each channel of buffer are written to each of given path. Furthermore, when a single path is given for capture, file paths are auto-generated according to available number of channels. For example, 'name.wav' is given for 2 channels capture, 'name-0.wav' and 'name-1.wav' are generated. In a case of no suffix, 'name-0' and 'name-1' are generated. Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp> Signed-off-by: Takashi Iwai <tiwai@suse.de>
2018-11-13 07:41:26 +01:00
};
static void print_help()
{
printf(
"Usage:\n"
" axfer transfer DIRECTION [ COMMON-OPTIONS ] [ BACKEND-OPTIONS ]\n"
"\n"
" where:\n"
" DIRECTION = capture | playback\n"
" COMMON-OPTIONS =\n"
" -h, --help help\n"
" -v, --verbose verbose\n"
" -q, --quiet quiet mode\n"
" -d, --duration=# interrupt after # seconds\n"
" -s, --samples=# interrupt after # frames\n"
" -f, --format=FORMAT sample format (case-insensitive)\n"
" -c, --channels=# channels\n"
" -r, --rate=# numeric sample rate in unit of Hz or kHz\n"
" -t, --file-type=TYPE file type (wav, au, sparc, voc or raw, case-insentive)\n"
" -I, --separate-channels one file for each channel\n"
" --dump-hw-params dump hw_params of the device\n"
" --xfer-type=BACKEND backend type (libasound, libffado)\n"
);
}
axfer: add a parser for command-line options In aplay, many command-line options are supported. Some of them have dependency or conflicts. Furthemore, some of them are just for runtime configuration of alsa-lib(libasound), and some options can be used by several xfer backends commonly; e.g. options for file name, sample format and sampling rate. This commit adds a parser for the common options below. * --help (-h) * Just output 'help' string (not written yet). * --verbose (-v) * For verbose output, including information about xfer, mapper and container. * --format (-f): string. format literals or one of ['cd'|'cdr'|'dat'] * For sample format supported by ALSA PCM interface. Special format can be used. For playback, this is auto-detected according to actual file format. * --channels (-c) * For the number of samples included in one data frame. For playback, this is auto-detected according to actual file format, except for 'raw' format. This option can conflict to above format option. * --rate (-r) * For the number of data frames transferred in one second. For playback, this is auto-detected according to actual file format, except for 'raw' format. This option can conflict to format option above. * --file-type (-f): string. one of ['wav'|'au'|'voc'|'raw'] * For format of files of given paths. For playback, this is optional because the format is auto-detected. For capture, this is optional too because the format is decided according to suffix of given path. Anyway, this option is used for cases to fail to detect or decide. * --separate-channels (-I) * When using several files as source or destination for transmission of data frame, this option can be used with several file paths. When '--separate-channels' option is used, users can give several file paths to source/destination of data transmission, else they can give single file path for the purpose. When multiple files are handled by this option, for playback, data frames in first channel is used to construct buffer for data transmission with multi channel. For capture, data frames in each channel of buffer are written to each of given path. Furthermore, when a single path is given for capture, file paths are auto-generated according to available number of channels. For example, 'name.wav' is given for 2 channels capture, 'name-0.wav' and 'name-1.wav' are generated. In a case of no suffix, 'name-0' and 'name-1' are generated. Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp> Signed-off-by: Takashi Iwai <tiwai@suse.de>
2018-11-13 07:41:26 +01:00
static int allocate_paths(struct xfer_context *xfer, char *const *paths,
unsigned int count)
{
bool stdio = false;
unsigned int i;
axfer: add a parser for command-line options In aplay, many command-line options are supported. Some of them have dependency or conflicts. Furthemore, some of them are just for runtime configuration of alsa-lib(libasound), and some options can be used by several xfer backends commonly; e.g. options for file name, sample format and sampling rate. This commit adds a parser for the common options below. * --help (-h) * Just output 'help' string (not written yet). * --verbose (-v) * For verbose output, including information about xfer, mapper and container. * --format (-f): string. format literals or one of ['cd'|'cdr'|'dat'] * For sample format supported by ALSA PCM interface. Special format can be used. For playback, this is auto-detected according to actual file format. * --channels (-c) * For the number of samples included in one data frame. For playback, this is auto-detected according to actual file format, except for 'raw' format. This option can conflict to above format option. * --rate (-r) * For the number of data frames transferred in one second. For playback, this is auto-detected according to actual file format, except for 'raw' format. This option can conflict to format option above. * --file-type (-f): string. one of ['wav'|'au'|'voc'|'raw'] * For format of files of given paths. For playback, this is optional because the format is auto-detected. For capture, this is optional too because the format is decided according to suffix of given path. Anyway, this option is used for cases to fail to detect or decide. * --separate-channels (-I) * When using several files as source or destination for transmission of data frame, this option can be used with several file paths. When '--separate-channels' option is used, users can give several file paths to source/destination of data transmission, else they can give single file path for the purpose. When multiple files are handled by this option, for playback, data frames in first channel is used to construct buffer for data transmission with multi channel. For capture, data frames in each channel of buffer are written to each of given path. Furthermore, when a single path is given for capture, file paths are auto-generated according to available number of channels. For example, 'name.wav' is given for 2 channels capture, 'name-0.wav' and 'name-1.wav' are generated. In a case of no suffix, 'name-0' and 'name-1' are generated. Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp> Signed-off-by: Takashi Iwai <tiwai@suse.de>
2018-11-13 07:41:26 +01:00
if (count == 0) {
stdio = true;
count = 1;
}
xfer->paths = calloc(count, sizeof(xfer->paths[0]));
if (xfer->paths == NULL)
return -ENOMEM;
xfer->path_count = count;
if (stdio) {
xfer->paths[0] = strdup("-");
axfer: add a parser for command-line options In aplay, many command-line options are supported. Some of them have dependency or conflicts. Furthemore, some of them are just for runtime configuration of alsa-lib(libasound), and some options can be used by several xfer backends commonly; e.g. options for file name, sample format and sampling rate. This commit adds a parser for the common options below. * --help (-h) * Just output 'help' string (not written yet). * --verbose (-v) * For verbose output, including information about xfer, mapper and container. * --format (-f): string. format literals or one of ['cd'|'cdr'|'dat'] * For sample format supported by ALSA PCM interface. Special format can be used. For playback, this is auto-detected according to actual file format. * --channels (-c) * For the number of samples included in one data frame. For playback, this is auto-detected according to actual file format, except for 'raw' format. This option can conflict to above format option. * --rate (-r) * For the number of data frames transferred in one second. For playback, this is auto-detected according to actual file format, except for 'raw' format. This option can conflict to format option above. * --file-type (-f): string. one of ['wav'|'au'|'voc'|'raw'] * For format of files of given paths. For playback, this is optional because the format is auto-detected. For capture, this is optional too because the format is decided according to suffix of given path. Anyway, this option is used for cases to fail to detect or decide. * --separate-channels (-I) * When using several files as source or destination for transmission of data frame, this option can be used with several file paths. When '--separate-channels' option is used, users can give several file paths to source/destination of data transmission, else they can give single file path for the purpose. When multiple files are handled by this option, for playback, data frames in first channel is used to construct buffer for data transmission with multi channel. For capture, data frames in each channel of buffer are written to each of given path. Furthermore, when a single path is given for capture, file paths are auto-generated according to available number of channels. For example, 'name.wav' is given for 2 channels capture, 'name-0.wav' and 'name-1.wav' are generated. In a case of no suffix, 'name-0' and 'name-1' are generated. Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp> Signed-off-by: Takashi Iwai <tiwai@suse.de>
2018-11-13 07:41:26 +01:00
if (xfer->paths[0] == NULL)
return -ENOMEM;
} else {
for (i = 0; i < count; ++i) {
xfer->paths[i] = strndup(paths[i], PATH_MAX);
if (xfer->paths[i] == NULL)
return -ENOMEM;
}
}
return 0;
}
static int verify_cntr_format(struct xfer_context *xfer)
{
static const struct {
const char *const literal;
enum container_format cntr_format;
} *entry, entries[] = {
{"raw", CONTAINER_FORMAT_RAW},
{"voc", CONTAINER_FORMAT_VOC},
{"wav", CONTAINER_FORMAT_RIFF_WAVE},
{"au", CONTAINER_FORMAT_AU},
{"sparc", CONTAINER_FORMAT_AU},
};
int i;
for (i = 0; i < (int)ARRAY_SIZE(entries); ++i) {
axfer: add a parser for command-line options In aplay, many command-line options are supported. Some of them have dependency or conflicts. Furthemore, some of them are just for runtime configuration of alsa-lib(libasound), and some options can be used by several xfer backends commonly; e.g. options for file name, sample format and sampling rate. This commit adds a parser for the common options below. * --help (-h) * Just output 'help' string (not written yet). * --verbose (-v) * For verbose output, including information about xfer, mapper and container. * --format (-f): string. format literals or one of ['cd'|'cdr'|'dat'] * For sample format supported by ALSA PCM interface. Special format can be used. For playback, this is auto-detected according to actual file format. * --channels (-c) * For the number of samples included in one data frame. For playback, this is auto-detected according to actual file format, except for 'raw' format. This option can conflict to above format option. * --rate (-r) * For the number of data frames transferred in one second. For playback, this is auto-detected according to actual file format, except for 'raw' format. This option can conflict to format option above. * --file-type (-f): string. one of ['wav'|'au'|'voc'|'raw'] * For format of files of given paths. For playback, this is optional because the format is auto-detected. For capture, this is optional too because the format is decided according to suffix of given path. Anyway, this option is used for cases to fail to detect or decide. * --separate-channels (-I) * When using several files as source or destination for transmission of data frame, this option can be used with several file paths. When '--separate-channels' option is used, users can give several file paths to source/destination of data transmission, else they can give single file path for the purpose. When multiple files are handled by this option, for playback, data frames in first channel is used to construct buffer for data transmission with multi channel. For capture, data frames in each channel of buffer are written to each of given path. Furthermore, when a single path is given for capture, file paths are auto-generated according to available number of channels. For example, 'name.wav' is given for 2 channels capture, 'name-0.wav' and 'name-1.wav' are generated. In a case of no suffix, 'name-0' and 'name-1' are generated. Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp> Signed-off-by: Takashi Iwai <tiwai@suse.de>
2018-11-13 07:41:26 +01:00
entry = &entries[i];
if (strcasecmp(xfer->cntr_format_literal, entry->literal))
continue;
xfer->cntr_format = entry->cntr_format;
return 0;
}
fprintf(stderr, "unrecognized file format '%s'\n",
xfer->cntr_format_literal);
return -EINVAL;
}
// This should be called after 'verify_cntr_format()'.
static int verify_sample_format(struct xfer_context *xfer)
{
static const struct {
const char *const literal;
unsigned int frames_per_second;
unsigned int samples_per_frame;
snd_pcm_format_t le_format;
snd_pcm_format_t be_format;
} *entry, entries[] = {
{"cd", 44100, 2, SND_PCM_FORMAT_S16_LE, SND_PCM_FORMAT_S16_BE},
{"cdr", 44100, 2, SND_PCM_FORMAT_S16_LE, SND_PCM_FORMAT_S16_BE},
{"dat", 48000, 2, SND_PCM_FORMAT_S16_LE, SND_PCM_FORMAT_S16_BE},
};
unsigned int i;
axfer: add a parser for command-line options In aplay, many command-line options are supported. Some of them have dependency or conflicts. Furthemore, some of them are just for runtime configuration of alsa-lib(libasound), and some options can be used by several xfer backends commonly; e.g. options for file name, sample format and sampling rate. This commit adds a parser for the common options below. * --help (-h) * Just output 'help' string (not written yet). * --verbose (-v) * For verbose output, including information about xfer, mapper and container. * --format (-f): string. format literals or one of ['cd'|'cdr'|'dat'] * For sample format supported by ALSA PCM interface. Special format can be used. For playback, this is auto-detected according to actual file format. * --channels (-c) * For the number of samples included in one data frame. For playback, this is auto-detected according to actual file format, except for 'raw' format. This option can conflict to above format option. * --rate (-r) * For the number of data frames transferred in one second. For playback, this is auto-detected according to actual file format, except for 'raw' format. This option can conflict to format option above. * --file-type (-f): string. one of ['wav'|'au'|'voc'|'raw'] * For format of files of given paths. For playback, this is optional because the format is auto-detected. For capture, this is optional too because the format is decided according to suffix of given path. Anyway, this option is used for cases to fail to detect or decide. * --separate-channels (-I) * When using several files as source or destination for transmission of data frame, this option can be used with several file paths. When '--separate-channels' option is used, users can give several file paths to source/destination of data transmission, else they can give single file path for the purpose. When multiple files are handled by this option, for playback, data frames in first channel is used to construct buffer for data transmission with multi channel. For capture, data frames in each channel of buffer are written to each of given path. Furthermore, when a single path is given for capture, file paths are auto-generated according to available number of channels. For example, 'name.wav' is given for 2 channels capture, 'name-0.wav' and 'name-1.wav' are generated. In a case of no suffix, 'name-0' and 'name-1' are generated. Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp> Signed-off-by: Takashi Iwai <tiwai@suse.de>
2018-11-13 07:41:26 +01:00
xfer->sample_format = snd_pcm_format_value(xfer->sample_format_literal);
if (xfer->sample_format != SND_PCM_FORMAT_UNKNOWN)
return 0;
for (i = 0; i < ARRAY_SIZE(entries); ++i) {
entry = &entries[i];
if (strcmp(entry->literal, xfer->sample_format_literal))
continue;
if (xfer->frames_per_second > 0 &&
xfer->frames_per_second != entry->frames_per_second) {
fprintf(stderr,
"'%s' format can't be used with rate except "
"for %u.\n",
entry->literal, entry->frames_per_second);
return -EINVAL;
}
if (xfer->samples_per_frame > 0 &&
xfer->samples_per_frame != entry->samples_per_frame) {
fprintf(stderr,
"'%s' format can't be used with channel except "
"for %u.\n",
entry->literal, entry->samples_per_frame);
return -EINVAL;
}
xfer->frames_per_second = entry->frames_per_second;
xfer->samples_per_frame = entry->samples_per_frame;
if (xfer->cntr_format == CONTAINER_FORMAT_AU)
xfer->sample_format = entry->be_format;
else
xfer->sample_format = entry->le_format;
return 0;
}
fprintf(stderr, "wrong extended format '%s'\n",
xfer->sample_format_literal);
return -EINVAL;
}
static int validate_options(struct xfer_context *xfer)
{
unsigned int val;
int err = 0;
if (xfer->cntr_format_literal == NULL) {
if (xfer->direction == SND_PCM_STREAM_CAPTURE) {
// To stdout.
if (xfer->path_count == 1 &&
!strcmp(xfer->paths[0], "-")) {
xfer->cntr_format = CONTAINER_FORMAT_RAW;
} else {
// Use first path as a representative.
xfer->cntr_format = container_format_from_path(
xfer->paths[0]);
}
}
// For playback, perform auto-detection.
} else {
err = verify_cntr_format(xfer);
}
if (err < 0)
return err;
if (xfer->multiple_cntrs) {
if (!strcmp(xfer->paths[0], "-")) {
fprintf(stderr,
"An option for separated channels is not "
"available with stdin/stdout.\n");
return -EINVAL;
}
// For captured PCM frames, even if one path is given for
// container files, it can be used to generate several paths.
// For this purpose, please see
// 'xfer_options_fixup_paths()'.
if (xfer->direction == SND_PCM_STREAM_PLAYBACK) {
// Require several paths for containers.
if (xfer->path_count == 1) {
fprintf(stderr,
"An option for separated channels "
"requires several files to playback "
"PCM frames.\n");
return -EINVAL;
}
}
} else {
// A single path is available only.
if (xfer->path_count > 1) {
fprintf(stderr,
"When using several files, an option for "
"sepatated channels is used with.\n");
return -EINVAL;
}
}
xfer->sample_format = SND_PCM_FORMAT_UNKNOWN;
if (xfer->sample_format_literal) {
err = verify_sample_format(xfer);
if (err < 0)
return err;
}
val = xfer->frames_per_second;
if (xfer->frames_per_second == 0)
xfer->frames_per_second = 8000;
if (xfer->frames_per_second < 1000)
xfer->frames_per_second *= 1000;
if (xfer->frames_per_second < 2000 ||
xfer->frames_per_second > 192000) {
fprintf(stderr, "bad speed value '%u'\n", val);
axfer: add a parser for command-line options In aplay, many command-line options are supported. Some of them have dependency or conflicts. Furthemore, some of them are just for runtime configuration of alsa-lib(libasound), and some options can be used by several xfer backends commonly; e.g. options for file name, sample format and sampling rate. This commit adds a parser for the common options below. * --help (-h) * Just output 'help' string (not written yet). * --verbose (-v) * For verbose output, including information about xfer, mapper and container. * --format (-f): string. format literals or one of ['cd'|'cdr'|'dat'] * For sample format supported by ALSA PCM interface. Special format can be used. For playback, this is auto-detected according to actual file format. * --channels (-c) * For the number of samples included in one data frame. For playback, this is auto-detected according to actual file format, except for 'raw' format. This option can conflict to above format option. * --rate (-r) * For the number of data frames transferred in one second. For playback, this is auto-detected according to actual file format, except for 'raw' format. This option can conflict to format option above. * --file-type (-f): string. one of ['wav'|'au'|'voc'|'raw'] * For format of files of given paths. For playback, this is optional because the format is auto-detected. For capture, this is optional too because the format is decided according to suffix of given path. Anyway, this option is used for cases to fail to detect or decide. * --separate-channels (-I) * When using several files as source or destination for transmission of data frame, this option can be used with several file paths. When '--separate-channels' option is used, users can give several file paths to source/destination of data transmission, else they can give single file path for the purpose. When multiple files are handled by this option, for playback, data frames in first channel is used to construct buffer for data transmission with multi channel. For capture, data frames in each channel of buffer are written to each of given path. Furthermore, when a single path is given for capture, file paths are auto-generated according to available number of channels. For example, 'name.wav' is given for 2 channels capture, 'name-0.wav' and 'name-1.wav' are generated. In a case of no suffix, 'name-0' and 'name-1' are generated. Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp> Signed-off-by: Takashi Iwai <tiwai@suse.de>
2018-11-13 07:41:26 +01:00
return -EINVAL;
}
if (xfer->samples_per_frame > 0) {
if (xfer->samples_per_frame < 1 ||
xfer->samples_per_frame > 256) {
fprintf(stderr, "invalid channels argument '%u'\n",
xfer->samples_per_frame);
return -EINVAL;
}
}
return err;
}
int xfer_options_parse_args(struct xfer_context *xfer,
const struct xfer_data *data, int argc,
char *const *argv)
{
static const char *short_opts = "CPhvqd:s:f:c:r:t:IV:i";
axfer: add a parser for command-line options In aplay, many command-line options are supported. Some of them have dependency or conflicts. Furthemore, some of them are just for runtime configuration of alsa-lib(libasound), and some options can be used by several xfer backends commonly; e.g. options for file name, sample format and sampling rate. This commit adds a parser for the common options below. * --help (-h) * Just output 'help' string (not written yet). * --verbose (-v) * For verbose output, including information about xfer, mapper and container. * --format (-f): string. format literals or one of ['cd'|'cdr'|'dat'] * For sample format supported by ALSA PCM interface. Special format can be used. For playback, this is auto-detected according to actual file format. * --channels (-c) * For the number of samples included in one data frame. For playback, this is auto-detected according to actual file format, except for 'raw' format. This option can conflict to above format option. * --rate (-r) * For the number of data frames transferred in one second. For playback, this is auto-detected according to actual file format, except for 'raw' format. This option can conflict to format option above. * --file-type (-f): string. one of ['wav'|'au'|'voc'|'raw'] * For format of files of given paths. For playback, this is optional because the format is auto-detected. For capture, this is optional too because the format is decided according to suffix of given path. Anyway, this option is used for cases to fail to detect or decide. * --separate-channels (-I) * When using several files as source or destination for transmission of data frame, this option can be used with several file paths. When '--separate-channels' option is used, users can give several file paths to source/destination of data transmission, else they can give single file path for the purpose. When multiple files are handled by this option, for playback, data frames in first channel is used to construct buffer for data transmission with multi channel. For capture, data frames in each channel of buffer are written to each of given path. Furthermore, when a single path is given for capture, file paths are auto-generated according to available number of channels. For example, 'name.wav' is given for 2 channels capture, 'name-0.wav' and 'name-1.wav' are generated. In a case of no suffix, 'name-0' and 'name-1' are generated. Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp> Signed-off-by: Takashi Iwai <tiwai@suse.de>
2018-11-13 07:41:26 +01:00
static const struct option long_opts[] = {
// For generic purposes.
{"capture", 0, 0, 'C'},
{"playback", 0, 0, 'P'},
{"xfer-type", 1, 0, OPT_XFER_TYPE},
{"help", 0, 0, 'h'},
{"verbose", 0, 0, 'v'},
{"quiet", 0, 0, 'q'},
{"duration", 1, 0, 'd'},
{"samples", 1, 0, 's'},
axfer: add a parser for command-line options In aplay, many command-line options are supported. Some of them have dependency or conflicts. Furthemore, some of them are just for runtime configuration of alsa-lib(libasound), and some options can be used by several xfer backends commonly; e.g. options for file name, sample format and sampling rate. This commit adds a parser for the common options below. * --help (-h) * Just output 'help' string (not written yet). * --verbose (-v) * For verbose output, including information about xfer, mapper and container. * --format (-f): string. format literals or one of ['cd'|'cdr'|'dat'] * For sample format supported by ALSA PCM interface. Special format can be used. For playback, this is auto-detected according to actual file format. * --channels (-c) * For the number of samples included in one data frame. For playback, this is auto-detected according to actual file format, except for 'raw' format. This option can conflict to above format option. * --rate (-r) * For the number of data frames transferred in one second. For playback, this is auto-detected according to actual file format, except for 'raw' format. This option can conflict to format option above. * --file-type (-f): string. one of ['wav'|'au'|'voc'|'raw'] * For format of files of given paths. For playback, this is optional because the format is auto-detected. For capture, this is optional too because the format is decided according to suffix of given path. Anyway, this option is used for cases to fail to detect or decide. * --separate-channels (-I) * When using several files as source or destination for transmission of data frame, this option can be used with several file paths. When '--separate-channels' option is used, users can give several file paths to source/destination of data transmission, else they can give single file path for the purpose. When multiple files are handled by this option, for playback, data frames in first channel is used to construct buffer for data transmission with multi channel. For capture, data frames in each channel of buffer are written to each of given path. Furthermore, when a single path is given for capture, file paths are auto-generated according to available number of channels. For example, 'name.wav' is given for 2 channels capture, 'name-0.wav' and 'name-1.wav' are generated. In a case of no suffix, 'name-0' and 'name-1' are generated. Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp> Signed-off-by: Takashi Iwai <tiwai@suse.de>
2018-11-13 07:41:26 +01:00
// For transfer backend.
{"format", 1, 0, 'f'},
{"channels", 1, 0, 'c'},
{"rate", 1, 0, 'r'},
// For containers.
{"file-type", 1, 0, 't'},
// For mapper.
{"separate-channels", 0, 0, 'I'},
// For debugging.
{"dump-hw-params", 0, 0, OPT_DUMP_HW_PARAMS},
// Obsoleted.
{"max-file-time", 1, 0, OPT_MAX_FILE_TIME},
{"use-strftime", 0, 0, OPT_USE_STRFTIME},
{"process-id-file", 1, 0, OPT_PROCESS_ID_FILE},
{"vumeter", 1, 0, 'V'},
{"interactive", 0, 0, 'i'},
axfer: add a parser for command-line options In aplay, many command-line options are supported. Some of them have dependency or conflicts. Furthemore, some of them are just for runtime configuration of alsa-lib(libasound), and some options can be used by several xfer backends commonly; e.g. options for file name, sample format and sampling rate. This commit adds a parser for the common options below. * --help (-h) * Just output 'help' string (not written yet). * --verbose (-v) * For verbose output, including information about xfer, mapper and container. * --format (-f): string. format literals or one of ['cd'|'cdr'|'dat'] * For sample format supported by ALSA PCM interface. Special format can be used. For playback, this is auto-detected according to actual file format. * --channels (-c) * For the number of samples included in one data frame. For playback, this is auto-detected according to actual file format, except for 'raw' format. This option can conflict to above format option. * --rate (-r) * For the number of data frames transferred in one second. For playback, this is auto-detected according to actual file format, except for 'raw' format. This option can conflict to format option above. * --file-type (-f): string. one of ['wav'|'au'|'voc'|'raw'] * For format of files of given paths. For playback, this is optional because the format is auto-detected. For capture, this is optional too because the format is decided according to suffix of given path. Anyway, this option is used for cases to fail to detect or decide. * --separate-channels (-I) * When using several files as source or destination for transmission of data frame, this option can be used with several file paths. When '--separate-channels' option is used, users can give several file paths to source/destination of data transmission, else they can give single file path for the purpose. When multiple files are handled by this option, for playback, data frames in first channel is used to construct buffer for data transmission with multi channel. For capture, data frames in each channel of buffer are written to each of given path. Furthermore, when a single path is given for capture, file paths are auto-generated according to available number of channels. For example, 'name.wav' is given for 2 channels capture, 'name-0.wav' and 'name-1.wav' are generated. In a case of no suffix, 'name-0' and 'name-1' are generated. Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp> Signed-off-by: Takashi Iwai <tiwai@suse.de>
2018-11-13 07:41:26 +01:00
};
char *s_opts;
struct option *l_opts;
int l_index;
int key;
int err = 0;
// Concatenate short options.
s_opts = malloc(strlen(data->s_opts) + strlen(short_opts) + 1);
if (s_opts == NULL)
return -ENOMEM;
strcpy(s_opts, data->s_opts);
strcpy(s_opts + strlen(s_opts), short_opts);
s_opts[strlen(data->s_opts) + strlen(short_opts)] = '\0';
// Concatenate long options, including a sentinel.
l_opts = calloc(ARRAY_SIZE(long_opts) * data->l_opts_count + 1,
sizeof(*l_opts));
if (l_opts == NULL) {
free(s_opts);
return -ENOMEM;
}
memcpy(l_opts, long_opts, ARRAY_SIZE(long_opts) * sizeof(*l_opts));
memcpy(&l_opts[ARRAY_SIZE(long_opts)], data->l_opts,
data->l_opts_count * sizeof(*l_opts));
// Parse options.
l_index = 0;
optarg = NULL;
optind = 1;
opterr = 1; // use error output.
optopt = 0;
while (1) {
key = getopt_long(argc, argv, s_opts, l_opts, &l_index);
if (key < 0)
break;
else if (key == 'C')
; // already parsed.
else if (key == 'P')
; // already parsed.
else if (key == OPT_XFER_TYPE)
; // already parsed.
else if (key == 'h')
xfer->help = true;
else if (key == 'v')
++xfer->verbose;
else if (key == 'q')
xfer->quiet = true;
else if (key == 'd')
xfer->duration_seconds = arg_parse_decimal_num(optarg, &err);
else if (key == 's')
xfer->duration_frames = arg_parse_decimal_num(optarg, &err);
axfer: add a parser for command-line options In aplay, many command-line options are supported. Some of them have dependency or conflicts. Furthemore, some of them are just for runtime configuration of alsa-lib(libasound), and some options can be used by several xfer backends commonly; e.g. options for file name, sample format and sampling rate. This commit adds a parser for the common options below. * --help (-h) * Just output 'help' string (not written yet). * --verbose (-v) * For verbose output, including information about xfer, mapper and container. * --format (-f): string. format literals or one of ['cd'|'cdr'|'dat'] * For sample format supported by ALSA PCM interface. Special format can be used. For playback, this is auto-detected according to actual file format. * --channels (-c) * For the number of samples included in one data frame. For playback, this is auto-detected according to actual file format, except for 'raw' format. This option can conflict to above format option. * --rate (-r) * For the number of data frames transferred in one second. For playback, this is auto-detected according to actual file format, except for 'raw' format. This option can conflict to format option above. * --file-type (-f): string. one of ['wav'|'au'|'voc'|'raw'] * For format of files of given paths. For playback, this is optional because the format is auto-detected. For capture, this is optional too because the format is decided according to suffix of given path. Anyway, this option is used for cases to fail to detect or decide. * --separate-channels (-I) * When using several files as source or destination for transmission of data frame, this option can be used with several file paths. When '--separate-channels' option is used, users can give several file paths to source/destination of data transmission, else they can give single file path for the purpose. When multiple files are handled by this option, for playback, data frames in first channel is used to construct buffer for data transmission with multi channel. For capture, data frames in each channel of buffer are written to each of given path. Furthermore, when a single path is given for capture, file paths are auto-generated according to available number of channels. For example, 'name.wav' is given for 2 channels capture, 'name-0.wav' and 'name-1.wav' are generated. In a case of no suffix, 'name-0' and 'name-1' are generated. Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp> Signed-off-by: Takashi Iwai <tiwai@suse.de>
2018-11-13 07:41:26 +01:00
else if (key == 'f')
xfer->sample_format_literal = arg_duplicate_string(optarg, &err);
else if (key == 'c')
xfer->samples_per_frame = arg_parse_decimal_num(optarg, &err);
else if (key == 'r')
xfer->frames_per_second = arg_parse_decimal_num(optarg, &err);
else if (key == 't')
xfer->cntr_format_literal = arg_duplicate_string(optarg, &err);
else if (key == 'I')
xfer->multiple_cntrs = true;
else if (key == OPT_DUMP_HW_PARAMS)
xfer->dump_hw_params = true;
else if (key == '?') {
free(l_opts);
free(s_opts);
axfer: add a parser for command-line options In aplay, many command-line options are supported. Some of them have dependency or conflicts. Furthemore, some of them are just for runtime configuration of alsa-lib(libasound), and some options can be used by several xfer backends commonly; e.g. options for file name, sample format and sampling rate. This commit adds a parser for the common options below. * --help (-h) * Just output 'help' string (not written yet). * --verbose (-v) * For verbose output, including information about xfer, mapper and container. * --format (-f): string. format literals or one of ['cd'|'cdr'|'dat'] * For sample format supported by ALSA PCM interface. Special format can be used. For playback, this is auto-detected according to actual file format. * --channels (-c) * For the number of samples included in one data frame. For playback, this is auto-detected according to actual file format, except for 'raw' format. This option can conflict to above format option. * --rate (-r) * For the number of data frames transferred in one second. For playback, this is auto-detected according to actual file format, except for 'raw' format. This option can conflict to format option above. * --file-type (-f): string. one of ['wav'|'au'|'voc'|'raw'] * For format of files of given paths. For playback, this is optional because the format is auto-detected. For capture, this is optional too because the format is decided according to suffix of given path. Anyway, this option is used for cases to fail to detect or decide. * --separate-channels (-I) * When using several files as source or destination for transmission of data frame, this option can be used with several file paths. When '--separate-channels' option is used, users can give several file paths to source/destination of data transmission, else they can give single file path for the purpose. When multiple files are handled by this option, for playback, data frames in first channel is used to construct buffer for data transmission with multi channel. For capture, data frames in each channel of buffer are written to each of given path. Furthermore, when a single path is given for capture, file paths are auto-generated according to available number of channels. For example, 'name.wav' is given for 2 channels capture, 'name-0.wav' and 'name-1.wav' are generated. In a case of no suffix, 'name-0' and 'name-1' are generated. Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp> Signed-off-by: Takashi Iwai <tiwai@suse.de>
2018-11-13 07:41:26 +01:00
return -EINVAL;
}
else if (key == OPT_MAX_FILE_TIME ||
key == OPT_USE_STRFTIME ||
key == OPT_PROCESS_ID_FILE ||
key == 'V' ||
key == 'i') {
fprintf(stderr,
"An option '--%s' is obsoleted and has no "
"effect.\n",
l_opts[l_index].name);
err = -EINVAL;
} else {
axfer: add a parser for command-line options In aplay, many command-line options are supported. Some of them have dependency or conflicts. Furthemore, some of them are just for runtime configuration of alsa-lib(libasound), and some options can be used by several xfer backends commonly; e.g. options for file name, sample format and sampling rate. This commit adds a parser for the common options below. * --help (-h) * Just output 'help' string (not written yet). * --verbose (-v) * For verbose output, including information about xfer, mapper and container. * --format (-f): string. format literals or one of ['cd'|'cdr'|'dat'] * For sample format supported by ALSA PCM interface. Special format can be used. For playback, this is auto-detected according to actual file format. * --channels (-c) * For the number of samples included in one data frame. For playback, this is auto-detected according to actual file format, except for 'raw' format. This option can conflict to above format option. * --rate (-r) * For the number of data frames transferred in one second. For playback, this is auto-detected according to actual file format, except for 'raw' format. This option can conflict to format option above. * --file-type (-f): string. one of ['wav'|'au'|'voc'|'raw'] * For format of files of given paths. For playback, this is optional because the format is auto-detected. For capture, this is optional too because the format is decided according to suffix of given path. Anyway, this option is used for cases to fail to detect or decide. * --separate-channels (-I) * When using several files as source or destination for transmission of data frame, this option can be used with several file paths. When '--separate-channels' option is used, users can give several file paths to source/destination of data transmission, else they can give single file path for the purpose. When multiple files are handled by this option, for playback, data frames in first channel is used to construct buffer for data transmission with multi channel. For capture, data frames in each channel of buffer are written to each of given path. Furthermore, when a single path is given for capture, file paths are auto-generated according to available number of channels. For example, 'name.wav' is given for 2 channels capture, 'name-0.wav' and 'name-1.wav' are generated. In a case of no suffix, 'name-0' and 'name-1' are generated. Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp> Signed-off-by: Takashi Iwai <tiwai@suse.de>
2018-11-13 07:41:26 +01:00
err = xfer->ops->parse_opt(xfer, key, optarg);
if (err < 0 && err != -ENXIO)
break;
}
}
free(l_opts);
free(s_opts);
if (xfer->help) {
print_help();
if (xfer->ops->help) {
printf("\n");
printf(" BACKEND-OPTIONS (%s) =\n",
xfer_label_from_type(xfer->type));
xfer->ops->help(xfer);
}
return 0;
}
axfer: add a parser for command-line options In aplay, many command-line options are supported. Some of them have dependency or conflicts. Furthemore, some of them are just for runtime configuration of alsa-lib(libasound), and some options can be used by several xfer backends commonly; e.g. options for file name, sample format and sampling rate. This commit adds a parser for the common options below. * --help (-h) * Just output 'help' string (not written yet). * --verbose (-v) * For verbose output, including information about xfer, mapper and container. * --format (-f): string. format literals or one of ['cd'|'cdr'|'dat'] * For sample format supported by ALSA PCM interface. Special format can be used. For playback, this is auto-detected according to actual file format. * --channels (-c) * For the number of samples included in one data frame. For playback, this is auto-detected according to actual file format, except for 'raw' format. This option can conflict to above format option. * --rate (-r) * For the number of data frames transferred in one second. For playback, this is auto-detected according to actual file format, except for 'raw' format. This option can conflict to format option above. * --file-type (-f): string. one of ['wav'|'au'|'voc'|'raw'] * For format of files of given paths. For playback, this is optional because the format is auto-detected. For capture, this is optional too because the format is decided according to suffix of given path. Anyway, this option is used for cases to fail to detect or decide. * --separate-channels (-I) * When using several files as source or destination for transmission of data frame, this option can be used with several file paths. When '--separate-channels' option is used, users can give several file paths to source/destination of data transmission, else they can give single file path for the purpose. When multiple files are handled by this option, for playback, data frames in first channel is used to construct buffer for data transmission with multi channel. For capture, data frames in each channel of buffer are written to each of given path. Furthermore, when a single path is given for capture, file paths are auto-generated according to available number of channels. For example, 'name.wav' is given for 2 channels capture, 'name-0.wav' and 'name-1.wav' are generated. In a case of no suffix, 'name-0' and 'name-1' are generated. Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp> Signed-off-by: Takashi Iwai <tiwai@suse.de>
2018-11-13 07:41:26 +01:00
err = allocate_paths(xfer, argv + optind, argc - optind);
if (err < 0)
return err;
return validate_options(xfer);
}
void xfer_options_calculate_duration(struct xfer_context *xfer,
uint64_t *total_frame_count)
{
uint64_t frame_count;
if (xfer->duration_seconds > 0) {
frame_count = (uint64_t)xfer->duration_seconds * (uint64_t)xfer->frames_per_second;
if (frame_count < *total_frame_count)
*total_frame_count = frame_count;
}
if (xfer->duration_frames > 0) {
frame_count = xfer->duration_frames;
if (frame_count < *total_frame_count)
*total_frame_count = frame_count;
}
}
axfer: add a parser for command-line options In aplay, many command-line options are supported. Some of them have dependency or conflicts. Furthemore, some of them are just for runtime configuration of alsa-lib(libasound), and some options can be used by several xfer backends commonly; e.g. options for file name, sample format and sampling rate. This commit adds a parser for the common options below. * --help (-h) * Just output 'help' string (not written yet). * --verbose (-v) * For verbose output, including information about xfer, mapper and container. * --format (-f): string. format literals or one of ['cd'|'cdr'|'dat'] * For sample format supported by ALSA PCM interface. Special format can be used. For playback, this is auto-detected according to actual file format. * --channels (-c) * For the number of samples included in one data frame. For playback, this is auto-detected according to actual file format, except for 'raw' format. This option can conflict to above format option. * --rate (-r) * For the number of data frames transferred in one second. For playback, this is auto-detected according to actual file format, except for 'raw' format. This option can conflict to format option above. * --file-type (-f): string. one of ['wav'|'au'|'voc'|'raw'] * For format of files of given paths. For playback, this is optional because the format is auto-detected. For capture, this is optional too because the format is decided according to suffix of given path. Anyway, this option is used for cases to fail to detect or decide. * --separate-channels (-I) * When using several files as source or destination for transmission of data frame, this option can be used with several file paths. When '--separate-channels' option is used, users can give several file paths to source/destination of data transmission, else they can give single file path for the purpose. When multiple files are handled by this option, for playback, data frames in first channel is used to construct buffer for data transmission with multi channel. For capture, data frames in each channel of buffer are written to each of given path. Furthermore, when a single path is given for capture, file paths are auto-generated according to available number of channels. For example, 'name.wav' is given for 2 channels capture, 'name-0.wav' and 'name-1.wav' are generated. In a case of no suffix, 'name-0' and 'name-1' are generated. Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp> Signed-off-by: Takashi Iwai <tiwai@suse.de>
2018-11-13 07:41:26 +01:00
static const char *const allowed_duplication[] = {
"/dev/null",
"/dev/zero",
"/dev/full",
"/dev/random",
"/dev/urandom",
};
static int generate_path_with_suffix(struct xfer_context *xfer,
const char *template, unsigned int index,
const char *suffix)
{
static const char *const single_format = "%s%s";
static const char *const multiple_format = "%s-%i%s";
unsigned int len;
len = strlen(template) + strlen(suffix) + 1;
if (xfer->path_count > 1)
len += (unsigned int)log10(xfer->path_count) + 2;
xfer->paths[index] = malloc(len);
if (xfer->paths[index] == NULL)
return -ENOMEM;
if (xfer->path_count == 1) {
snprintf(xfer->paths[index], len, single_format, template,
suffix);
} else {
snprintf(xfer->paths[index], len, multiple_format, template,
index, suffix);
}
return 0;
}
static int generate_path_without_suffix(struct xfer_context *xfer,
const char *template,
unsigned int index,
const char *suffix ATTRIBUTE_UNUSED)
axfer: add a parser for command-line options In aplay, many command-line options are supported. Some of them have dependency or conflicts. Furthemore, some of them are just for runtime configuration of alsa-lib(libasound), and some options can be used by several xfer backends commonly; e.g. options for file name, sample format and sampling rate. This commit adds a parser for the common options below. * --help (-h) * Just output 'help' string (not written yet). * --verbose (-v) * For verbose output, including information about xfer, mapper and container. * --format (-f): string. format literals or one of ['cd'|'cdr'|'dat'] * For sample format supported by ALSA PCM interface. Special format can be used. For playback, this is auto-detected according to actual file format. * --channels (-c) * For the number of samples included in one data frame. For playback, this is auto-detected according to actual file format, except for 'raw' format. This option can conflict to above format option. * --rate (-r) * For the number of data frames transferred in one second. For playback, this is auto-detected according to actual file format, except for 'raw' format. This option can conflict to format option above. * --file-type (-f): string. one of ['wav'|'au'|'voc'|'raw'] * For format of files of given paths. For playback, this is optional because the format is auto-detected. For capture, this is optional too because the format is decided according to suffix of given path. Anyway, this option is used for cases to fail to detect or decide. * --separate-channels (-I) * When using several files as source or destination for transmission of data frame, this option can be used with several file paths. When '--separate-channels' option is used, users can give several file paths to source/destination of data transmission, else they can give single file path for the purpose. When multiple files are handled by this option, for playback, data frames in first channel is used to construct buffer for data transmission with multi channel. For capture, data frames in each channel of buffer are written to each of given path. Furthermore, when a single path is given for capture, file paths are auto-generated according to available number of channels. For example, 'name.wav' is given for 2 channels capture, 'name-0.wav' and 'name-1.wav' are generated. In a case of no suffix, 'name-0' and 'name-1' are generated. Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp> Signed-off-by: Takashi Iwai <tiwai@suse.de>
2018-11-13 07:41:26 +01:00
{
static const char *const single_format = "%s";
static const char *const multiple_format = "%s-%i";
unsigned int len;
len = strlen(template) + 1;
if (xfer->path_count > 1)
len += (unsigned int)log10(xfer->path_count) + 2;
xfer->paths[index] = malloc(len);
if (xfer->paths[index] == NULL)
return -ENOMEM;
if (xfer->path_count == 1) {
snprintf(xfer->paths[index], len, single_format, template);
} else {
snprintf(xfer->paths[index], len, multiple_format, template,
index);
}
return 0;
}
static int generate_path(struct xfer_context *xfer, char *template,
unsigned int index, const char *suffix)
{
int (*generator)(struct xfer_context *xfer, const char *template,
unsigned int index, const char *suffix);
char *pos;
if (strlen(suffix) > 0) {
pos = template + strlen(template) - strlen(suffix);
// Separate filename and suffix.
if (!strcmp(pos, suffix))
*pos = '\0';
}
// Select handlers.
if (strlen(suffix) > 0)
generator = generate_path_with_suffix;
else
generator = generate_path_without_suffix;
return generator(xfer, template, index, suffix);
}
static int create_paths(struct xfer_context *xfer, unsigned int path_count)
{
char *template;
const char *suffix;
unsigned int i, j;
axfer: add a parser for command-line options In aplay, many command-line options are supported. Some of them have dependency or conflicts. Furthemore, some of them are just for runtime configuration of alsa-lib(libasound), and some options can be used by several xfer backends commonly; e.g. options for file name, sample format and sampling rate. This commit adds a parser for the common options below. * --help (-h) * Just output 'help' string (not written yet). * --verbose (-v) * For verbose output, including information about xfer, mapper and container. * --format (-f): string. format literals or one of ['cd'|'cdr'|'dat'] * For sample format supported by ALSA PCM interface. Special format can be used. For playback, this is auto-detected according to actual file format. * --channels (-c) * For the number of samples included in one data frame. For playback, this is auto-detected according to actual file format, except for 'raw' format. This option can conflict to above format option. * --rate (-r) * For the number of data frames transferred in one second. For playback, this is auto-detected according to actual file format, except for 'raw' format. This option can conflict to format option above. * --file-type (-f): string. one of ['wav'|'au'|'voc'|'raw'] * For format of files of given paths. For playback, this is optional because the format is auto-detected. For capture, this is optional too because the format is decided according to suffix of given path. Anyway, this option is used for cases to fail to detect or decide. * --separate-channels (-I) * When using several files as source or destination for transmission of data frame, this option can be used with several file paths. When '--separate-channels' option is used, users can give several file paths to source/destination of data transmission, else they can give single file path for the purpose. When multiple files are handled by this option, for playback, data frames in first channel is used to construct buffer for data transmission with multi channel. For capture, data frames in each channel of buffer are written to each of given path. Furthermore, when a single path is given for capture, file paths are auto-generated according to available number of channels. For example, 'name.wav' is given for 2 channels capture, 'name-0.wav' and 'name-1.wav' are generated. In a case of no suffix, 'name-0' and 'name-1' are generated. Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp> Signed-off-by: Takashi Iwai <tiwai@suse.de>
2018-11-13 07:41:26 +01:00
int err = 0;
// Can cause memory leak.
assert(xfer->path_count == 1);
assert(xfer->paths);
assert(xfer->paths[0]);
assert(xfer->paths[0][0] != '\0');
// Release at first.
template = xfer->paths[0];
free(xfer->paths);
xfer->paths = NULL;
// Allocate again.
xfer->paths = calloc(path_count, sizeof(*xfer->paths));
if (xfer->paths == NULL) {
err = -ENOMEM;
goto end;
}
xfer->path_count = path_count;
suffix = container_suffix_from_format(xfer->cntr_format);
for (i = 0; i < xfer->path_count; ++i) {
// Some file names are allowed to be duplicated.
for (j = 0; j < ARRAY_SIZE(allowed_duplication); ++j) {
if (!strcmp(template, allowed_duplication[j]))
break;
}
if (j < ARRAY_SIZE(allowed_duplication))
continue;
err = generate_path(xfer, template, i, suffix);
if (err < 0)
break;
}
end:
free(template);
return err;
}
static int fixup_paths(struct xfer_context *xfer)
{
const char *suffix;
char *template;
unsigned int i, j;
axfer: add a parser for command-line options In aplay, many command-line options are supported. Some of them have dependency or conflicts. Furthemore, some of them are just for runtime configuration of alsa-lib(libasound), and some options can be used by several xfer backends commonly; e.g. options for file name, sample format and sampling rate. This commit adds a parser for the common options below. * --help (-h) * Just output 'help' string (not written yet). * --verbose (-v) * For verbose output, including information about xfer, mapper and container. * --format (-f): string. format literals or one of ['cd'|'cdr'|'dat'] * For sample format supported by ALSA PCM interface. Special format can be used. For playback, this is auto-detected according to actual file format. * --channels (-c) * For the number of samples included in one data frame. For playback, this is auto-detected according to actual file format, except for 'raw' format. This option can conflict to above format option. * --rate (-r) * For the number of data frames transferred in one second. For playback, this is auto-detected according to actual file format, except for 'raw' format. This option can conflict to format option above. * --file-type (-f): string. one of ['wav'|'au'|'voc'|'raw'] * For format of files of given paths. For playback, this is optional because the format is auto-detected. For capture, this is optional too because the format is decided according to suffix of given path. Anyway, this option is used for cases to fail to detect or decide. * --separate-channels (-I) * When using several files as source or destination for transmission of data frame, this option can be used with several file paths. When '--separate-channels' option is used, users can give several file paths to source/destination of data transmission, else they can give single file path for the purpose. When multiple files are handled by this option, for playback, data frames in first channel is used to construct buffer for data transmission with multi channel. For capture, data frames in each channel of buffer are written to each of given path. Furthermore, when a single path is given for capture, file paths are auto-generated according to available number of channels. For example, 'name.wav' is given for 2 channels capture, 'name-0.wav' and 'name-1.wav' are generated. In a case of no suffix, 'name-0' and 'name-1' are generated. Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp> Signed-off-by: Takashi Iwai <tiwai@suse.de>
2018-11-13 07:41:26 +01:00
int err = 0;
suffix = container_suffix_from_format(xfer->cntr_format);
for (i = 0; i < xfer->path_count; ++i) {
// Some file names are allowed to be duplicated.
for (j = 0; j < ARRAY_SIZE(allowed_duplication); ++j) {
if (!strcmp(xfer->paths[i], allowed_duplication[j]))
break;
}
if (j < ARRAY_SIZE(allowed_duplication))
continue;
template = xfer->paths[i];
xfer->paths[i] = NULL;
err = generate_path(xfer, template, i, suffix);
free(template);
if (err < 0)
break;
}
return err;
}
int xfer_options_fixup_paths(struct xfer_context *xfer)
{
unsigned int i, j;
axfer: add a parser for command-line options In aplay, many command-line options are supported. Some of them have dependency or conflicts. Furthemore, some of them are just for runtime configuration of alsa-lib(libasound), and some options can be used by several xfer backends commonly; e.g. options for file name, sample format and sampling rate. This commit adds a parser for the common options below. * --help (-h) * Just output 'help' string (not written yet). * --verbose (-v) * For verbose output, including information about xfer, mapper and container. * --format (-f): string. format literals or one of ['cd'|'cdr'|'dat'] * For sample format supported by ALSA PCM interface. Special format can be used. For playback, this is auto-detected according to actual file format. * --channels (-c) * For the number of samples included in one data frame. For playback, this is auto-detected according to actual file format, except for 'raw' format. This option can conflict to above format option. * --rate (-r) * For the number of data frames transferred in one second. For playback, this is auto-detected according to actual file format, except for 'raw' format. This option can conflict to format option above. * --file-type (-f): string. one of ['wav'|'au'|'voc'|'raw'] * For format of files of given paths. For playback, this is optional because the format is auto-detected. For capture, this is optional too because the format is decided according to suffix of given path. Anyway, this option is used for cases to fail to detect or decide. * --separate-channels (-I) * When using several files as source or destination for transmission of data frame, this option can be used with several file paths. When '--separate-channels' option is used, users can give several file paths to source/destination of data transmission, else they can give single file path for the purpose. When multiple files are handled by this option, for playback, data frames in first channel is used to construct buffer for data transmission with multi channel. For capture, data frames in each channel of buffer are written to each of given path. Furthermore, when a single path is given for capture, file paths are auto-generated according to available number of channels. For example, 'name.wav' is given for 2 channels capture, 'name-0.wav' and 'name-1.wav' are generated. In a case of no suffix, 'name-0' and 'name-1' are generated. Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp> Signed-off-by: Takashi Iwai <tiwai@suse.de>
2018-11-13 07:41:26 +01:00
int err;
if (xfer->path_count == 1) {
// Nothing to do for sign of stdin/stdout.
if (!strcmp(xfer->paths[0], "-"))
return 0;
if (!xfer->multiple_cntrs)
err = fixup_paths(xfer);
else
err = create_paths(xfer, xfer->samples_per_frame);
} else {
if (!xfer->multiple_cntrs)
return -EINVAL;
if (xfer->path_count != xfer->samples_per_frame)
return -EINVAL;
else
err = fixup_paths(xfer);
}
if (err < 0)
return err;
// Check duplication of the paths.
for (i = 0; i < xfer->path_count - 1; ++i) {
// Some file names are allowed to be duplicated.
for (j = 0; j < ARRAY_SIZE(allowed_duplication); ++j) {
if (!strcmp(xfer->paths[i], allowed_duplication[j]))
break;
}
if (j < ARRAY_SIZE(allowed_duplication))
continue;
for (j = i + 1; j < xfer->path_count; ++j) {
if (!strcmp(xfer->paths[i], xfer->paths[j])) {
fprintf(stderr,
"Detect duplicated file names:\n");
err = -EINVAL;
break;
}
}
if (j < xfer->path_count)
break;
}
if (xfer->verbose > 1)
fprintf(stderr, "Handled file names:\n");
if (err < 0 || xfer->verbose > 1) {
for (i = 0; i < xfer->path_count; ++i)
fprintf(stderr, " %d: %s\n", i, xfer->paths[i]);
}
return err;
}