OSDN Git Service

Disable NLS support when --disable-nls is passed
[android-x86/external-alsa-utils.git] / seq / aconnect / aconnect.c
1 /*
2  * connect / disconnect two subscriber ports
3  *   ver.0.1.3
4  *
5  * Copyright (C) 1999 Takashi Iwai
6  * 
7  *  This program is free software; you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License version 2 as
9  *  published by the Free Software Foundation.
10  * 
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  */
17
18 #include <stdio.h>
19 #include <ctype.h>
20 #include <string.h>
21 #include <stdlib.h>
22 #include <errno.h>
23 #include <fcntl.h>
24 #include <getopt.h>
25 #include <stdarg.h>
26 #include <locale.h>
27 #include <sys/ioctl.h>
28 #include <alsa/asoundlib.h>
29 #include "aconfig.h"
30 #include "gettext.h"
31
32 static void error_handler(const char *file, int line, const char *function, int err, const char *fmt, ...)
33 {
34         va_list arg;
35
36         if (err == ENOENT)      /* Ignore those misleading "warnings" */
37                 return;
38         va_start(arg, fmt);
39         fprintf(stderr, "ALSA lib %s:%i:(%s) ", file, line, function);
40         vfprintf(stderr, fmt, arg);
41         if (err)
42                 fprintf(stderr, ": %s", snd_strerror(err));
43         putc('\n', stderr);
44         va_end(arg);
45 }
46
47 static void usage(void)
48 {
49         printf(_("aconnect - ALSA sequencer connection manager\n"));
50         printf(_("Copyright (C) 1999-2000 Takashi Iwai\n"));
51         printf(_("Usage:\n"));
52         printf(_(" * Connection/disconnection between two ports\n"));
53         printf(_("   aconnect [-options] sender receiver\n"));
54         printf(_("     sender, receiver = client:port pair\n"));
55         printf(_("     -d,--disconnect     disconnect\n"));
56         printf(_("     -e,--exclusive      exclusive connection\n"));
57         printf(_("     -r,--real #         convert real-time-stamp on queue\n"));
58         printf(_("     -t,--tick #         convert tick-time-stamp on queue\n"));
59         printf(_(" * List connected ports (no subscription action)\n"));
60         printf(_("   aconnect -i|-o [-options]\n"));
61         printf(_("     -i,--input          list input (readable) ports\n"));
62         printf(_("     -o,--output         list output (writable) ports\n"));
63         printf(_("     -l,--list           list current connections of each port\n"));
64         printf(_(" * Remove all exported connections\n"));
65         printf(_("     -x, --removeall\n"));
66 }
67
68 /*
69  * check permission (capability) of specified port
70  */
71
72 #define LIST_INPUT      1
73 #define LIST_OUTPUT     2
74
75 #define perm_ok(pinfo,bits) ((snd_seq_port_info_get_capability(pinfo) & (bits)) == (bits))
76
77 static int check_permission(snd_seq_port_info_t *pinfo, int perm)
78 {
79         if (perm) {
80                 if (perm & LIST_INPUT) {
81                         if (perm_ok(pinfo, SND_SEQ_PORT_CAP_READ|SND_SEQ_PORT_CAP_SUBS_READ))
82                                 goto __ok;
83                 }
84                 if (perm & LIST_OUTPUT) {
85                         if (perm_ok(pinfo, SND_SEQ_PORT_CAP_WRITE|SND_SEQ_PORT_CAP_SUBS_WRITE))
86                                 goto __ok;
87                 }
88                 return 0;
89         }
90  __ok:
91         if (snd_seq_port_info_get_capability(pinfo) & SND_SEQ_PORT_CAP_NO_EXPORT)
92                 return 0;
93         return 1;
94 }
95
96 /*
97  * list subscribers of specified type
98  */
99 static void list_each_subs(snd_seq_t *seq, snd_seq_query_subscribe_t *subs, int type, const char *msg)
100 {
101         int count = 0;
102         snd_seq_query_subscribe_set_type(subs, type);
103         snd_seq_query_subscribe_set_index(subs, 0);
104         while (snd_seq_query_port_subscribers(seq, subs) >= 0) {
105                 const snd_seq_addr_t *addr;
106                 if (count++ == 0)
107                         printf("\t%s: ", msg);
108                 else
109                         printf(", ");
110                 addr = snd_seq_query_subscribe_get_addr(subs);
111                 printf("%d:%d", addr->client, addr->port);
112                 if (snd_seq_query_subscribe_get_exclusive(subs))
113                         printf("[ex]");
114                 if (snd_seq_query_subscribe_get_time_update(subs))
115                         printf("[%s:%d]",
116                                (snd_seq_query_subscribe_get_time_real(subs) ? "real" : "tick"),
117                                snd_seq_query_subscribe_get_queue(subs));
118                 snd_seq_query_subscribe_set_index(subs, snd_seq_query_subscribe_get_index(subs) + 1);
119         }
120         if (count > 0)
121                 printf("\n");
122 }
123
124 /*
125  * list subscribers
126  */
127 static void list_subscribers(snd_seq_t *seq, const snd_seq_addr_t *addr)
128 {
129         snd_seq_query_subscribe_t *subs;
130         snd_seq_query_subscribe_alloca(&subs);
131         snd_seq_query_subscribe_set_root(subs, addr);
132         list_each_subs(seq, subs, SND_SEQ_QUERY_SUBS_READ, _("Connecting To"));
133         list_each_subs(seq, subs, SND_SEQ_QUERY_SUBS_WRITE, _("Connected From"));
134 }
135
136 /*
137  * search all ports
138  */
139 typedef void (*action_func_t)(snd_seq_t *seq, snd_seq_client_info_t *cinfo, snd_seq_port_info_t *pinfo, int count);
140
141 static void do_search_port(snd_seq_t *seq, int perm, action_func_t do_action)
142 {
143         snd_seq_client_info_t *cinfo;
144         snd_seq_port_info_t *pinfo;
145         int count;
146
147         snd_seq_client_info_alloca(&cinfo);
148         snd_seq_port_info_alloca(&pinfo);
149         snd_seq_client_info_set_client(cinfo, -1);
150         while (snd_seq_query_next_client(seq, cinfo) >= 0) {
151                 /* reset query info */
152                 snd_seq_port_info_set_client(pinfo, snd_seq_client_info_get_client(cinfo));
153                 snd_seq_port_info_set_port(pinfo, -1);
154                 count = 0;
155                 while (snd_seq_query_next_port(seq, pinfo) >= 0) {
156                         if (check_permission(pinfo, perm)) {
157                                 do_action(seq, cinfo, pinfo, count);
158                                 count++;
159                         }
160                 }
161         }
162 }
163
164
165 static void print_port(snd_seq_t *seq, snd_seq_client_info_t *cinfo,
166                        snd_seq_port_info_t *pinfo, int count)
167 {
168         if (! count) {
169                 printf(_("client %d: '%s' [type=%s]\n"),
170                        snd_seq_client_info_get_client(cinfo),
171                        snd_seq_client_info_get_name(cinfo),
172                        (snd_seq_client_info_get_type(cinfo) == SND_SEQ_USER_CLIENT ?
173                         _("user") : _("kernel")));
174         }
175         printf("  %3d '%-16s'\n",
176                snd_seq_port_info_get_port(pinfo),
177                snd_seq_port_info_get_name(pinfo));
178 }
179
180 static void print_port_and_subs(snd_seq_t *seq, snd_seq_client_info_t *cinfo,
181                                 snd_seq_port_info_t *pinfo, int count)
182 {
183         print_port(seq, cinfo, pinfo, count);
184         list_subscribers(seq, snd_seq_port_info_get_addr(pinfo));
185 }
186
187
188 /*
189  * remove all (exported) connections
190  */
191 static void remove_connection(snd_seq_t *seq, snd_seq_client_info_t *cinfo,
192                               snd_seq_port_info_t *pinfo, int count)
193 {
194         snd_seq_query_subscribe_t *query;
195
196         snd_seq_query_subscribe_alloca(&query);
197         snd_seq_query_subscribe_set_root(query, snd_seq_port_info_get_addr(pinfo));
198
199         snd_seq_query_subscribe_set_type(query, SND_SEQ_QUERY_SUBS_READ);
200         snd_seq_query_subscribe_set_index(query, 0);
201         for (; snd_seq_query_port_subscribers(seq, query) >= 0;
202              snd_seq_query_subscribe_set_index(query, snd_seq_query_subscribe_get_index(query) + 1)) {
203                 snd_seq_port_info_t *port;
204                 snd_seq_port_subscribe_t *subs;
205                 const snd_seq_addr_t *sender = snd_seq_query_subscribe_get_root(query);
206                 const snd_seq_addr_t *dest = snd_seq_query_subscribe_get_addr(query);
207                 snd_seq_port_info_alloca(&port);
208                 if (snd_seq_get_any_port_info(seq, dest->client, dest->port, port) < 0)
209                         continue;
210                 if (!(snd_seq_port_info_get_capability(port) & SND_SEQ_PORT_CAP_SUBS_WRITE))
211                         continue;
212                 if (snd_seq_port_info_get_capability(port) & SND_SEQ_PORT_CAP_NO_EXPORT)
213                         continue;
214                 snd_seq_port_subscribe_alloca(&subs);
215                 snd_seq_port_subscribe_set_queue(subs, snd_seq_query_subscribe_get_queue(query));
216                 snd_seq_port_subscribe_set_sender(subs, sender);
217                 snd_seq_port_subscribe_set_dest(subs, dest);
218                 snd_seq_unsubscribe_port(seq, subs);
219         }
220
221         snd_seq_query_subscribe_set_type(query, SND_SEQ_QUERY_SUBS_WRITE);
222         snd_seq_query_subscribe_set_index(query, 0);
223         for (; snd_seq_query_port_subscribers(seq, query) >= 0;
224              snd_seq_query_subscribe_set_index(query, snd_seq_query_subscribe_get_index(query) + 1)) {
225                 snd_seq_port_info_t *port;
226                 snd_seq_port_subscribe_t *subs;
227                 const snd_seq_addr_t *dest = snd_seq_query_subscribe_get_root(query);
228                 const snd_seq_addr_t *sender = snd_seq_query_subscribe_get_addr(query);
229                 snd_seq_port_info_alloca(&port);
230                 if (snd_seq_get_any_port_info(seq, sender->client, sender->port, port) < 0)
231                         continue;
232                 if (!(snd_seq_port_info_get_capability(port) & SND_SEQ_PORT_CAP_SUBS_READ))
233                         continue;
234                 if (snd_seq_port_info_get_capability(port) & SND_SEQ_PORT_CAP_NO_EXPORT)
235                         continue;
236                 snd_seq_port_subscribe_alloca(&subs);
237                 snd_seq_port_subscribe_set_queue(subs, snd_seq_query_subscribe_get_queue(query));
238                 snd_seq_port_subscribe_set_sender(subs, sender);
239                 snd_seq_port_subscribe_set_dest(subs, dest);
240                 snd_seq_unsubscribe_port(seq, subs);
241         }
242 }
243
244 static void remove_all_connections(snd_seq_t *seq)
245 {
246         do_search_port(seq, 0, remove_connection);
247 }
248
249
250 /*
251  * main..
252  */
253
254 enum {
255         SUBSCRIBE, UNSUBSCRIBE, LIST, REMOVE_ALL
256 };
257
258 static struct option long_option[] = {
259         {"disconnect", 0, NULL, 'd'},
260         {"input", 0, NULL, 'i'},
261         {"output", 0, NULL, 'o'},
262         {"real", 1, NULL, 'r'},
263         {"tick", 1, NULL, 't'},
264         {"exclusive", 0, NULL, 'e'},
265         {"list", 0, NULL, 'l'},
266         {"removeall", 0, NULL, 'x'},
267         {NULL, 0, NULL, 0},
268 };
269
270 int main(int argc, char **argv)
271 {
272         int c;
273         snd_seq_t *seq;
274         int queue = 0, convert_time = 0, convert_real = 0, exclusive = 0;
275         int command = SUBSCRIBE;
276         int list_perm = 0;
277         int client;
278         int list_subs = 0;
279         snd_seq_port_subscribe_t *subs;
280         snd_seq_addr_t sender, dest;
281
282 #ifdef ENABLE_NLS
283         setlocale(LC_ALL, "");
284         textdomain(PACKAGE);
285 #endif
286
287         while ((c = getopt_long(argc, argv, "dior:t:elx", long_option, NULL)) != -1) {
288                 switch (c) {
289                 case 'd':
290                         command = UNSUBSCRIBE;
291                         break;
292                 case 'i':
293                         command = LIST;
294                         list_perm |= LIST_INPUT;
295                         break;
296                 case 'o':
297                         command = LIST;
298                         list_perm |= LIST_OUTPUT;
299                         break;
300                 case 'e':
301                         exclusive = 1;
302                         break;
303                 case 'r':
304                         queue = atoi(optarg);
305                         convert_time = 1;
306                         convert_real = 1;
307                         break;
308                 case 't':
309                         queue = atoi(optarg);
310                         convert_time = 1;
311                         convert_real = 0;
312                         break;
313                 case 'l':
314                         list_subs = 1;
315                         break;
316                 case 'x':
317                         command = REMOVE_ALL;
318                         break;
319                 default:
320                         usage();
321                         exit(1);
322                 }
323         }
324
325         if (snd_seq_open(&seq, "default", SND_SEQ_OPEN_DUPLEX, 0) < 0) {
326                 fprintf(stderr, _("can't open sequencer\n"));
327                 return 1;
328         }
329         
330         snd_lib_error_set_handler(error_handler);
331
332         switch (command) {
333         case LIST:
334                 do_search_port(seq, list_perm,
335                                list_subs ? print_port_and_subs : print_port);
336                 snd_seq_close(seq);
337                 return 0;
338         case REMOVE_ALL:
339                 remove_all_connections(seq);
340                 snd_seq_close(seq);
341                 return 0;
342         }
343
344         /* connection or disconnection */
345
346         if (optind + 2 > argc) {
347                 snd_seq_close(seq);
348                 usage();
349                 exit(1);
350         }
351
352         if ((client = snd_seq_client_id(seq)) < 0) {
353                 snd_seq_close(seq);
354                 fprintf(stderr, _("can't get client id\n"));
355                 return 1;
356         }
357
358         /* set client info */
359         if (snd_seq_set_client_name(seq, "ALSA Connector") < 0) {
360                 snd_seq_close(seq);
361                 fprintf(stderr, _("can't set client info\n"));
362                 return 1;
363         }
364
365         /* set subscription */
366         if (snd_seq_parse_address(seq, &sender, argv[optind]) < 0) {
367                 snd_seq_close(seq);
368                 fprintf(stderr, _("invalid sender address %s\n"), argv[optind]);
369                 return 1;
370         }
371         if (snd_seq_parse_address(seq, &dest, argv[optind + 1]) < 0) {
372                 snd_seq_close(seq);
373                 fprintf(stderr, _("invalid destination address %s\n"), argv[optind + 1]);
374                 return 1;
375         }
376         snd_seq_port_subscribe_alloca(&subs);
377         snd_seq_port_subscribe_set_sender(subs, &sender);
378         snd_seq_port_subscribe_set_dest(subs, &dest);
379         snd_seq_port_subscribe_set_queue(subs, queue);
380         snd_seq_port_subscribe_set_exclusive(subs, exclusive);
381         snd_seq_port_subscribe_set_time_update(subs, convert_time);
382         snd_seq_port_subscribe_set_time_real(subs, convert_real);
383
384         if (command == UNSUBSCRIBE) {
385                 if (snd_seq_get_port_subscription(seq, subs) < 0) {
386                         snd_seq_close(seq);
387                         fprintf(stderr, _("No subscription is found\n"));
388                         return 1;
389                 }
390                 if (snd_seq_unsubscribe_port(seq, subs) < 0) {
391                         snd_seq_close(seq);
392                         fprintf(stderr, _("Disconnection failed (%s)\n"), snd_strerror(errno));
393                         return 1;
394                 }
395         } else {
396                 if (snd_seq_get_port_subscription(seq, subs) == 0) {
397                         snd_seq_close(seq);
398                         fprintf(stderr, _("Connection is already subscribed\n"));
399                         return 1;
400                 }
401                 if (snd_seq_subscribe_port(seq, subs) < 0) {
402                         snd_seq_close(seq);
403                         fprintf(stderr, _("Connection failed (%s)\n"), snd_strerror(errno));
404                         return 1;
405                 }
406         }
407
408         snd_seq_close(seq);
409
410         return 0;
411 }