2018-11-13 07:41:13 +01:00
|
|
|
// SPDX-License-Identifier: GPL-2.0
|
|
|
|
// main.c - an entry point for this program.
|
|
|
|
//
|
|
|
|
// Copyright (c) 2018 Takashi Sakamoto <o-takashi@sakamocchi.jp>
|
|
|
|
//
|
|
|
|
// Originally written as 'aplay', by Michael Beck and Jaroslav Kysela.
|
|
|
|
//
|
|
|
|
// Licensed under the terms of the GNU General Public License, version 2.
|
|
|
|
|
|
|
|
#include "subcmd.h"
|
|
|
|
#include "misc.h"
|
|
|
|
|
|
|
|
#include "version.h"
|
|
|
|
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <stdbool.h>
|
|
|
|
#include <string.h>
|
|
|
|
|
|
|
|
enum subcmds {
|
|
|
|
SUBCMD_TRANSFER = 0,
|
|
|
|
SUBCMD_LIST,
|
|
|
|
SUBCMD_HELP,
|
|
|
|
SUBCMD_VERSION,
|
|
|
|
};
|
|
|
|
|
|
|
|
static void print_version(const char *const cmdname)
|
|
|
|
{
|
|
|
|
printf("%s: version %s\n", cmdname, SND_UTIL_VERSION_STR);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void print_help(void)
|
|
|
|
{
|
|
|
|
printf("help\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
static void 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;
|
|
|
|
} long_opts[] = {
|
|
|
|
{"--list-devices", SUBCMD_LIST},
|
|
|
|
{"--list-pcms", SUBCMD_LIST},
|
|
|
|
{"--help", SUBCMD_HELP},
|
|
|
|
{"--version", SUBCMD_VERSION},
|
|
|
|
};
|
|
|
|
static const struct {
|
|
|
|
unsigned char c;
|
|
|
|
enum subcmds subcmd;
|
|
|
|
} short_opts[] = {
|
|
|
|
{'l', SUBCMD_LIST},
|
|
|
|
{'L', SUBCMD_LIST},
|
|
|
|
{'h', SUBCMD_HELP},
|
|
|
|
};
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// 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;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Original command system. For short options.
|
|
|
|
for (i = 1; i < argc; ++i) {
|
|
|
|
// Pick up short options only.
|
|
|
|
if (argv[i][0] != '-' || argv[i][0] == '\0' ||
|
|
|
|
argv[i][1] == '-' || argv[i][1] == '\0')
|
|
|
|
continue;
|
|
|
|
for (pos = argv[i]; *pos != '\0'; ++pos) {
|
|
|
|
for (j = 0; j < ARRAY_SIZE(short_opts); ++j) {
|
|
|
|
if (*pos == short_opts[j].c) {
|
|
|
|
*subcmd = short_opts[j].subcmd;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
*subcmd = SUBCMD_TRANSFER;
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool decide_direction(int argc, char *const *argv,
|
|
|
|
snd_pcm_stream_t *direction)
|
|
|
|
{
|
|
|
|
static const struct {
|
|
|
|
const char *const name;
|
|
|
|
snd_pcm_stream_t direction;
|
|
|
|
} long_opts[] = {
|
|
|
|
{"--capture", SND_PCM_STREAM_CAPTURE},
|
|
|
|
{"--playback", SND_PCM_STREAM_PLAYBACK},
|
|
|
|
};
|
|
|
|
static const struct {
|
|
|
|
unsigned char c;
|
|
|
|
snd_pcm_stream_t direction;
|
|
|
|
} short_opts[] = {
|
|
|
|
{'C', SND_PCM_STREAM_CAPTURE},
|
|
|
|
{'P', SND_PCM_STREAM_PLAYBACK},
|
|
|
|
};
|
|
|
|
static const char *const aliases[] = {
|
|
|
|
[SND_PCM_STREAM_CAPTURE] = "arecord",
|
|
|
|
[SND_PCM_STREAM_PLAYBACK] = "aplay",
|
|
|
|
};
|
|
|
|
int i, j;
|
|
|
|
char *pos;
|
|
|
|
|
|
|
|
// 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])) {
|
|
|
|
*direction = long_opts[i].direction;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Original command system. For short options.
|
|
|
|
for (i = 1; i < argc; ++i) {
|
|
|
|
// Pick up short options only.
|
|
|
|
if (argv[i][0] != '-' || argv[i][0] == '\0' ||
|
|
|
|
argv[i][1] == '-' || argv[i][1] == '\0')
|
|
|
|
continue;
|
|
|
|
for (pos = argv[i]; *pos != '\0'; ++pos) {
|
|
|
|
for (j = 0; j < ARRAY_SIZE(short_opts); ++j) {
|
|
|
|
if (*pos == short_opts[j].c) {
|
|
|
|
*direction = short_opts[j].direction;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// If not decided yet, judge according to command name.
|
|
|
|
for (i = 0; i < ARRAY_SIZE(aliases); ++i) {
|
|
|
|
for (pos = argv[0] + strlen(argv[0]); pos != argv[0]; --pos) {
|
|
|
|
if (strstr(pos, aliases[i]) != NULL) {
|
|
|
|
*direction = i;
|
|
|
|
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);
|
|
|
|
|
|
|
|
if (subcmd == SUBCMD_TRANSFER)
|
|
|
|
printf("execute 'transfer' subcmd.\n");
|
|
|
|
else if (subcmd == SUBCMD_LIST)
|
2018-11-13 07:41:14 +01:00
|
|
|
err = subcmd_list(argc, argv, direction);
|
2018-11-13 07:41:13 +01:00
|
|
|
else if (subcmd == SUBCMD_VERSION)
|
|
|
|
print_version(argv[0]);
|
|
|
|
else
|
|
|
|
print_help();
|
|
|
|
if (err < 0)
|
|
|
|
return EXIT_FAILURE;
|
|
|
|
|
|
|
|
return EXIT_SUCCESS;
|
|
|
|
}
|