mirror of
https://github.com/alsa-project/alsa-utils
synced 2024-11-09 17:45:41 +01:00
axfer: add an entry point for this command
This commit adds a new command, 'axfer' ('ALSA transfer'), to transfer data frames described in asound.h. This command is intended to replace current aplay. The most of features and command line parameters come from aplay as much as possible, while it has more better feature and code to maintain. This commit adds an entry point for this command. Current option system of aplay is still available, while this command has a sub-command system like commands in iproute2. Currently, two sub-commands are supported; 'list' and 'transfer'. The 'list' sub-command has the same effect as '-l' and '-L' options of aplay. The 'transfer' sub-command has the same effect as the main feature of aplay. For the sub-command system, an option for stream direction is required; '-P' for playback and '-C' for capture. If you create symbolic links to this binary for aplay/arecord, please execute: $ ln -s axfer aplay $ ln -s axfer arecord Actual code for each sub-command will be implemented in later commits. Signed-off-by: Takashi Sakamoto <o-takashi@sakamocchi.jp> Signed-off-by: Takashi Iwai <tiwai@suse.de>
This commit is contained in:
parent
6c81444a52
commit
a452b98235
6 changed files with 248 additions and 2 deletions
|
@ -14,7 +14,7 @@ if ALSACONF
|
||||||
SUBDIRS += alsaconf
|
SUBDIRS += alsaconf
|
||||||
endif
|
endif
|
||||||
if HAVE_PCM
|
if HAVE_PCM
|
||||||
SUBDIRS += aplay iecset speaker-test
|
SUBDIRS += aplay iecset speaker-test axfer
|
||||||
if ALSALOOP
|
if ALSALOOP
|
||||||
SUBDIRS += alsaloop
|
SUBDIRS += alsaloop
|
||||||
endif
|
endif
|
||||||
|
|
23
axfer/Makefile.am
Normal file
23
axfer/Makefile.am
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
bin_PROGRAMS = \
|
||||||
|
axfer
|
||||||
|
|
||||||
|
# To include headers for gettext and version.
|
||||||
|
AM_CPPFLAGS = \
|
||||||
|
-I$(top_srcdir)/include
|
||||||
|
|
||||||
|
# Unit tests.
|
||||||
|
SUBDIRS =
|
||||||
|
|
||||||
|
LIBRT = @LIBRT@
|
||||||
|
LDADD = \
|
||||||
|
$(LIBINTL) \
|
||||||
|
$(LIBRT)
|
||||||
|
|
||||||
|
noinst_HEADERS = \
|
||||||
|
misc.h \
|
||||||
|
subcmd.h
|
||||||
|
|
||||||
|
axfer_SOURCES = \
|
||||||
|
misc.h \
|
||||||
|
subcmd.h \
|
||||||
|
main.c
|
193
axfer/main.c
Normal file
193
axfer/main.c
Normal file
|
@ -0,0 +1,193 @@
|
||||||
|
// 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)
|
||||||
|
printf("execute 'list' subcmd.\n");
|
||||||
|
else if (subcmd == SUBCMD_VERSION)
|
||||||
|
print_version(argv[0]);
|
||||||
|
else
|
||||||
|
print_help();
|
||||||
|
if (err < 0)
|
||||||
|
return EXIT_FAILURE;
|
||||||
|
|
||||||
|
return EXIT_SUCCESS;
|
||||||
|
}
|
16
axfer/misc.h
Normal file
16
axfer/misc.h
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0
|
||||||
|
//
|
||||||
|
// misc.h - a header file for miscellaneous tools.
|
||||||
|
//
|
||||||
|
// Copyright (c) 2018 Takashi Sakamoto <o-takashi@sakamocchi.jp>
|
||||||
|
//
|
||||||
|
// Licensed under the terms of the GNU General Public License, version 2.
|
||||||
|
|
||||||
|
#ifndef __ALSA_UTILS_AXFER_MISC__H_
|
||||||
|
#define __ALSA_UTILS_AXFER_MISC__H_
|
||||||
|
|
||||||
|
#include <gettext.h>
|
||||||
|
|
||||||
|
#define ARRAY_SIZE(array) (sizeof(array)/sizeof(array[0]))
|
||||||
|
|
||||||
|
#endif
|
14
axfer/subcmd.h
Normal file
14
axfer/subcmd.h
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
// SPDX-License-Identifier: GPL-2.0
|
||||||
|
//
|
||||||
|
// subcmd.h - a header for each sub-commands.
|
||||||
|
//
|
||||||
|
// Copyright (c) 2018 Takashi Sakamoto <o-takashi@sakamocchi.jp>
|
||||||
|
//
|
||||||
|
// Licensed under the terms of the GNU General Public License, version 2.
|
||||||
|
|
||||||
|
#ifndef __ALSA_UTILS_AXFER_SUBCMD__H_
|
||||||
|
#define __ALSA_UTILS_AXFER_SUBCMD__H_
|
||||||
|
|
||||||
|
#include <alsa/asoundlib.h>
|
||||||
|
|
||||||
|
#endif
|
|
@ -430,4 +430,4 @@ AC_OUTPUT(Makefile alsactl/Makefile alsactl/init/Makefile \
|
||||||
utils/alsa-utils.spec seq/Makefile seq/aconnect/Makefile \
|
utils/alsa-utils.spec seq/Makefile seq/aconnect/Makefile \
|
||||||
seq/aplaymidi/Makefile seq/aseqdump/Makefile seq/aseqnet/Makefile \
|
seq/aplaymidi/Makefile seq/aseqdump/Makefile seq/aseqnet/Makefile \
|
||||||
speaker-test/Makefile speaker-test/samples/Makefile \
|
speaker-test/Makefile speaker-test/samples/Makefile \
|
||||||
alsaloop/Makefile alsa-info/Makefile)
|
alsaloop/Makefile alsa-info/Makefile axfer/Makefile)
|
||||||
|
|
Loading…
Reference in a new issue