OSDN Git Service

axfer: add support for a container of Microsoft/IBM RIFF/Wave format
[android-x86/external-alsa-utils.git] / axfer / main.c
1 // SPDX-License-Identifier: GPL-2.0
2 // main.c - an entry point for this program.
3 //
4 // Copyright (c) 2018 Takashi Sakamoto <o-takashi@sakamocchi.jp>
5 //
6 // Originally written as 'aplay', by Michael Beck and Jaroslav Kysela.
7 //
8 // Licensed under the terms of the GNU General Public License, version 2.
9
10 #include "subcmd.h"
11 #include "misc.h"
12
13 #include "version.h"
14
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <stdbool.h>
18 #include <string.h>
19
20 enum subcmds {
21         SUBCMD_TRANSFER = 0,
22         SUBCMD_LIST,
23         SUBCMD_HELP,
24         SUBCMD_VERSION,
25 };
26
27 static void print_version(const char *const cmdname)
28 {
29         printf("%s: version %s\n", cmdname, SND_UTIL_VERSION_STR);
30 }
31
32 static void print_help(void)
33 {
34         printf("help\n");
35 }
36
37 static void decide_subcmd(int argc, char *const *argv, enum subcmds *subcmd)
38 {
39         static const char *const subcmds[] = {
40                 [SUBCMD_TRANSFER] = "transfer",
41                 [SUBCMD_LIST] = "list",
42                 [SUBCMD_HELP] = "help",
43                 [SUBCMD_VERSION] = "version",
44         };
45         static const struct {
46                 const char *const name;
47                 enum subcmds subcmd;
48         } long_opts[] = {
49                 {"--list-devices",      SUBCMD_LIST},
50                 {"--list-pcms",         SUBCMD_LIST},
51                 {"--help",              SUBCMD_HELP},
52                 {"--version",           SUBCMD_VERSION},
53         };
54         static const struct {
55                 unsigned char c;
56                 enum subcmds subcmd;
57         } short_opts[] = {
58                 {'l', SUBCMD_LIST},
59                 {'L', SUBCMD_LIST},
60                 {'h', SUBCMD_HELP},
61         };
62         char *pos;
63         int i, j;
64
65         if (argc == 1) {
66                 *subcmd = SUBCMD_HELP;
67                 return;
68         }
69
70         // sub-command system.
71         for (i = 0; i < ARRAY_SIZE(subcmds); ++i) {
72                 if (!strcmp(argv[1], subcmds[i])) {
73                         *subcmd = i;
74                         return;
75                 }
76         }
77
78         // Original command system. For long options.
79         for (i = 0; i < ARRAY_SIZE(long_opts); ++i) {
80                 for (j = 0; j < argc; ++j) {
81                         if (!strcmp(long_opts[i].name, argv[j])) {
82                                 *subcmd = long_opts[i].subcmd;
83                                 return;
84                         }
85                 }
86         }
87
88         // Original command system. For short options.
89         for (i = 1; i < argc; ++i) {
90                 // Pick up short options only.
91                 if (argv[i][0] != '-' || argv[i][0] == '\0' ||
92                     argv[i][1] == '-' || argv[i][1] == '\0')
93                         continue;
94                 for (pos = argv[i]; *pos != '\0'; ++pos) {
95                         for (j = 0; j < ARRAY_SIZE(short_opts); ++j) {
96                                 if (*pos == short_opts[j].c) {
97                                         *subcmd = short_opts[j].subcmd;
98                                         return;
99                                 }
100                         }
101                 }
102         }
103
104         *subcmd = SUBCMD_TRANSFER;
105 }
106
107 static bool decide_direction(int argc, char *const *argv,
108                              snd_pcm_stream_t *direction)
109 {
110         static const struct {
111                 const char *const name;
112                 snd_pcm_stream_t direction;
113         } long_opts[] = {
114                 {"--capture",   SND_PCM_STREAM_CAPTURE},
115                 {"--playback",  SND_PCM_STREAM_PLAYBACK},
116         };
117         static const struct {
118                 unsigned char c;
119                 snd_pcm_stream_t direction;
120         } short_opts[] = {
121                 {'C',           SND_PCM_STREAM_CAPTURE},
122                 {'P',           SND_PCM_STREAM_PLAYBACK},
123         };
124         static const char *const aliases[] = {
125                 [SND_PCM_STREAM_CAPTURE] = "arecord",
126                 [SND_PCM_STREAM_PLAYBACK] = "aplay",
127         };
128         int i, j;
129         char *pos;
130
131         // Original command system. For long options.
132         for (i = 0; i < ARRAY_SIZE(long_opts); ++i) {
133                 for (j = 0; j < argc; ++j) {
134                         if (!strcmp(long_opts[i].name, argv[j])) {
135                                 *direction = long_opts[i].direction;
136                                 return true;
137                         }
138                 }
139         }
140
141         // Original command system. For short options.
142         for (i = 1; i < argc; ++i) {
143                 // Pick up short options only.
144                 if (argv[i][0] != '-' || argv[i][0] == '\0' ||
145                     argv[i][1] == '-' || argv[i][1] == '\0')
146                         continue;
147                 for (pos = argv[i]; *pos != '\0'; ++pos) {
148                         for (j = 0; j < ARRAY_SIZE(short_opts); ++j) {
149                                 if (*pos == short_opts[j].c) {
150                                         *direction = short_opts[j].direction;
151                                         return true;
152                                 }
153                         }
154                 }
155         }
156
157         // If not decided yet, judge according to command name.
158         for (i = 0; i < ARRAY_SIZE(aliases); ++i) {
159                 for (pos = argv[0] + strlen(argv[0]); pos != argv[0]; --pos) {
160                         if (strstr(pos, aliases[i]) != NULL) {
161                                 *direction = i;
162                                 return true;
163                         }
164                 }
165         }
166
167         return false;
168 }
169
170 int main(int argc, char *const *argv)
171 {
172         snd_pcm_stream_t direction;
173         enum subcmds subcmd;
174         int err = 0;
175
176         if (!decide_direction(argc, argv, &direction))
177                 subcmd = SUBCMD_HELP;
178         else
179                 decide_subcmd(argc, argv, &subcmd);
180
181         if (subcmd == SUBCMD_TRANSFER)
182                 printf("execute 'transfer' subcmd.\n");
183         else if (subcmd == SUBCMD_LIST)
184                 err = subcmd_list(argc, argv, direction);
185         else if (subcmd == SUBCMD_VERSION)
186                 print_version(argv[0]);
187         else
188                 print_help();
189         if (err < 0)
190                 return EXIT_FAILURE;
191
192         return EXIT_SUCCESS;
193 }