Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
100 changes: 74 additions & 26 deletions axfer/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -70,14 +70,9 @@ static void print_help(void)
printf("help\n");
}

static void decide_subcmd(int argc, char *const *argv, enum subcmds *subcmd)
// Backward compatibility to aplay(1).
static bool decide_subcmd(int argc, char *const *argv, enum subcmds *subcmd)
{
static const char *const subcmds[] = {
[SUBCMD_TRANSFER] = "transfer",
[SUBCMD_LIST] = "list",
[SUBCMD_HELP] = "help",
[SUBCMD_VERSION] = "version",
};
static const struct {
const char *const name;
enum subcmds subcmd;
Expand All @@ -98,25 +93,15 @@ static void decide_subcmd(int argc, char *const *argv, enum subcmds *subcmd)
char *pos;
int i, j;

if (argc == 1) {
*subcmd = SUBCMD_HELP;
return;
}

// sub-command system.
for (i = 0; i < ARRAY_SIZE(subcmds); ++i) {
if (!strcmp(argv[1], subcmds[i])) {
*subcmd = i;
return;
}
}
if (argc == 1)
return false;

// Original command system. For long options.
for (i = 0; i < ARRAY_SIZE(long_opts); ++i) {
for (j = 0; j < argc; ++j) {
if (!strcmp(long_opts[i].name, argv[j])) {
*subcmd = long_opts[i].subcmd;
return;
return true;
}
}
}
Expand All @@ -131,15 +116,16 @@ static void decide_subcmd(int argc, char *const *argv, enum subcmds *subcmd)
for (j = 0; j < ARRAY_SIZE(short_opts); ++j) {
if (*pos == short_opts[j].c) {
*subcmd = short_opts[j].subcmd;
return;
return true;
}
}
}
}

*subcmd = SUBCMD_TRANSFER;
return false;
}

// Backward compatibility to aplay(1).
static bool decide_direction(int argc, char *const *argv,
snd_pcm_stream_t *direction)
{
Expand Down Expand Up @@ -203,16 +189,78 @@ static bool decide_direction(int argc, char *const *argv,
return false;
}

static bool detect_subcmd(int argc, char *const *argv, enum subcmds *subcmd)
{
static const char *const subcmds[] = {
[SUBCMD_TRANSFER] = "transfer",
[SUBCMD_LIST] = "list",
[SUBCMD_HELP] = "help",
[SUBCMD_VERSION] = "version",
};
int i;

if (argc < 2)
return false;

for (i = 0; i < ARRAY_SIZE(subcmds); ++i) {
if (!strcmp(argv[1], subcmds[i])) {
*subcmd = i;
return true;
}
}

return false;
}

static bool detect_direction(int argc, char *const *argv,
snd_pcm_stream_t *direction)
{
if (argc < 3)
return false;

if (!strcmp(argv[2], "capture")) {
*direction = SND_PCM_STREAM_CAPTURE;
return true;
}

if (!strcmp(argv[2], "playback")) {
*direction = SND_PCM_STREAM_PLAYBACK;
return true;
}

return false;
}

int main(int argc, char *const *argv)
{
snd_pcm_stream_t direction;
enum subcmds subcmd;
int err = 0;

if (!decide_direction(argc, argv, &direction))
subcmd = SUBCMD_HELP;
else
decide_subcmd(argc, argv, &subcmd);
// For compatibility to aplay(1) implementation.
if (strstr(argv[0], "arecord") == argv[0] + strlen(argv[0]) - 7 ||
strstr(argv[0], "aplay") == argv[0] + strlen(argv[0]) - 5) {
if (!decide_direction(argc, argv, &direction))
direction = SND_PCM_STREAM_PLAYBACK;
if (!decide_subcmd(argc, argv, &subcmd))
subcmd = SUBCMD_TRANSFER;
} else {
// The first option should be one of subcommands.
if (!detect_subcmd(argc, argv, &subcmd))
subcmd = SUBCMD_HELP;
// The second option should be either 'capture' or 'direction'
// if subcommand is neither 'version' nor 'help'.
if (subcmd != SUBCMD_VERSION && subcmd != SUBCMD_HELP) {
if (!detect_direction(argc, argv, &direction)) {
subcmd = SUBCMD_HELP;
} else {
// argv[0] is needed for unparsed option to use
// getopt_long(3).
argc -= 2;
argv += 2;
}
}
}

if (subcmd == SUBCMD_TRANSFER)
err = subcmd_transfer(argc, argv, direction);
Expand Down
85 changes: 59 additions & 26 deletions axfer/subcmd-list.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,13 @@
#include "misc.h"

#include <getopt.h>
#include <stdbool.h>

enum list_op {
LIST_OP_DEVICE = 0,
LIST_OP_PCM,
LIST_OP_HELP,
};

static int dump_device(snd_ctl_t *handle, const char *id, const char *name,
snd_pcm_stream_t direction, snd_pcm_info_t *info)
Expand Down Expand Up @@ -189,46 +196,72 @@ static void print_help(void)
printf("help for list sub-command.\n");
}

int subcmd_list(int argc, char *const *argv, snd_pcm_stream_t direction)
// Backward compatibility to aplay(1).
static bool decide_operation(int argc, char *const *argv, enum list_op *op)
{
static const struct {
const char *const category;
int (*func)(snd_pcm_stream_t direction);
} ops[] = {
{"device", list_devices},
{"pcm", list_pcms},
};
int i;
static const char *s_opts = "hlL";
static const struct option l_opts[] = {
{"list-devices", 0, NULL, 'l'},
{"list-pcms", 0, NULL, 'L'},
{NULL, 0, NULL, 0}
};
int c;

// Renewed command system.
if (argc > 2 && !strcmp(argv[1], "list")) {
for (i = 0; i < ARRAY_SIZE(ops); ++i) {
if (!strcmp(ops[i].category, argv[2]))
return ops[i].func(direction);
}
}

// Original command system.
optind = 0;
opterr = 0;
while (1) {
c = getopt_long(argc, argv, s_opts, l_opts, NULL);
int c = getopt_long(argc, argv, s_opts, l_opts, NULL);
if (c < 0)
break;
if (c == 'l')
return list_devices(direction);
if (c == 'L')
return list_pcms(direction);
if (c == 'l') {
*op = LIST_OP_DEVICE;
return true;
}
if (c == 'L') {
*op = LIST_OP_PCM;
return true;
}
}

print_help();
return false;
}

return 0;
static int detect_operation(int argc, char *const *argv, enum list_op *op)
{
static const char *const ops[] = {
[LIST_OP_DEVICE] = "device",
[LIST_OP_PCM] = "pcm",
};
int i;

if (argc < 2)
return false;

for (i = 0; i < ARRAY_SIZE(ops); ++i) {
if (!strcmp(argv[1], ops[i])) {
*op = i;
return true;
}
}

return false;
}

int subcmd_list(int argc, char *const *argv, snd_pcm_stream_t direction)
{
enum list_op op = LIST_OP_HELP;
int err = 0;

// Renewed command system.
if (!detect_operation(argc, argv, &op) &&
!decide_operation(argc, argv, &op))
err = -EINVAL;

if (op == LIST_OP_DEVICE)
err = list_devices(direction);
else if (op == LIST_OP_PCM)
err = list_pcms(direction);
else
print_help();

return err;
}
7 changes: 0 additions & 7 deletions axfer/subcmd-transfer.c
Original file line number Diff line number Diff line change
Expand Up @@ -435,13 +435,6 @@ int subcmd_transfer(int argc, char *const *argv, snd_pcm_stream_t direction)
uint64_t actual_frame_count = 0;
int err = 0;

// Renewed command system.
if (argc > 2 && !strcmp(argv[1], "transfer")) {
// Go ahead to parse file paths properly.
--argc;
++argv;
}

err = prepare_signal_handler(&ctx);
if (err < 0)
return err;
Expand Down