From: Takashi Iwai Date: Thu, 31 Aug 2000 11:20:34 +0000 (+0000) Subject: Add -x option for removing all exported connections X-Git-Tag: v1.0.3~324 X-Git-Url: https://git.alsa-project.org/?a=commitdiff_plain;h=c786b1b6d583bd8bd9de9ef0521d6c5f97b2ad62;p=alsa-utils.git Add -x option for removing all exported connections --- diff --git a/seq/aconnect/aconnect.1 b/seq/aconnect/aconnect.1 index b47b4c2..4d75924 100644 --- a/seq/aconnect/aconnect.1 +++ b/seq/aconnect/aconnect.1 @@ -1,4 +1,4 @@ -.TH aconnect 1 "January 1, 2000" +.TH aconnect 1 "August 31, 2000" .LO 1 .SH NAME aconnect \- ALSA sequencer connection manager @@ -9,6 +9,9 @@ aconnect \- ALSA sequencer connection manager .br .B aconnect \-i|-o [-options] +.br +.B aconnect +\-x .SH DESCRIPTION .B aconnect @@ -59,6 +62,12 @@ client 64: '0: MIDI Synth' [group=] [type=kernel] Similary, to see the output ports, use .B \-o flag. +.PP +You can remove all existing exported connections using +.B \-x +option. This function is useful for terminating the ALSA drivers, +because the modules with sequencer connections cannot be unloaded +unless their connections are removed. .SH OPTIONS .SS CONNNECTION MANAGEMENT @@ -120,8 +129,13 @@ and mean the connection includes real-time and tick conversion on the listed queue, respectively. +.SS REMOVE ALL CONNECTIONS +.TP +.B \-x, --removeall +Remove all exported connections. + .SH "SEE ALSO" aseqnet(1), aseqview(1) .SH AUTHOR -Takashi Iwai . +Takashi Iwai diff --git a/seq/aconnect/aconnect.c b/seq/aconnect/aconnect.c index 935e88c..f380256 100644 --- a/seq/aconnect/aconnect.c +++ b/seq/aconnect/aconnect.c @@ -44,6 +44,8 @@ static void usage(void) fprintf(stderr, " -o,--output list output (writable) ports\n"); fprintf(stderr, " -g,--group name specify the group name\n"); fprintf(stderr, " -l,--list list current connections of each port\n"); + fprintf(stderr, " * Remove all exported connections\n"); + fprintf(stderr, " -x, --removeall\n"); } /* @@ -116,13 +118,15 @@ static void list_subscribers(snd_seq_t *seq, int client, int port) } /* - * list all ports + * search all ports */ -static void list_ports(snd_seq_t *seq, char *group, int perm, int list_subs) +typedef void (*action_func_t)(snd_seq_t *seq, snd_seq_client_info_t *cinfo, snd_seq_port_info_t *pinfo, int count); + +static void do_search_port(snd_seq_t *seq, char *group, int perm, action_func_t do_action) { snd_seq_client_info_t cinfo; snd_seq_port_info_t pinfo; - int client_printed; + int count; cinfo.client = -1; cinfo.name[0] = 0; @@ -133,18 +137,11 @@ static void list_ports(snd_seq_t *seq, char *group, int perm, int list_subs) pinfo.port = -1; pinfo.name[0] = 0; strncpy(pinfo.group, group, sizeof(pinfo.group)); - client_printed = 0; + count = 0; while (snd_seq_query_next_port(seq, &pinfo) >= 0) { if (check_permission(&pinfo, group, perm)) { - if (! client_printed) { - printf("client %d: '%s' [group=%s] [type=%s]\n", - cinfo.client, cinfo.name, cinfo.group, - (cinfo.type == USER_CLIENT ? "user" : "kernel")); - client_printed = 1; - } - printf(" %3d '%-16s' [group=%s]\n", pinfo.port, pinfo.name, pinfo.group); - if (list_subs) - list_subscribers(seq, pinfo.client, pinfo.port); + do_action(seq, &cinfo, &pinfo, count); + count++; } /* reset query names */ pinfo.name[0] = 0; @@ -157,8 +154,101 @@ static void list_ports(snd_seq_t *seq, char *group, int perm, int list_subs) } +static void print_port(snd_seq_t *seq, snd_seq_client_info_t *cinfo, + snd_seq_port_info_t *pinfo, int count) +{ + if (! count) { + printf("client %d: '%s' [group=%s] [type=%s]\n", + cinfo->client, cinfo->name, cinfo->group, + (cinfo->type == USER_CLIENT ? "user" : "kernel")); + } + printf(" %3d '%-16s' [group=%s]\n", + pinfo->port, pinfo->name, pinfo->group); +} + +static void print_port_and_subs(snd_seq_t *seq, snd_seq_client_info_t *cinfo, + snd_seq_port_info_t *pinfo, int count) +{ + print_port(seq, cinfo, pinfo, count); + list_subscribers(seq, pinfo->client, pinfo->port); +} + + +/* + * list all ports + */ + +static void list_ports(snd_seq_t *seq, char *group, int perm, int list_subs) +{ + if (list_subs) + do_search_port(seq, group, perm, print_port_and_subs); + else + do_search_port(seq, group, perm, print_port); +} + +/* + * remove all (exported) connections + */ +static void remove_connection(snd_seq_t *seq, snd_seq_client_info_t *cinfo, + snd_seq_port_info_t *pinfo, int count) +{ + snd_seq_query_subs_t query; + + memset(&query, 0, sizeof(query)); + query.client = pinfo->client; + query.port = pinfo->port; + + query.type = SND_SEQ_QUERY_SUBS_READ; + query.index = 0; + for (query.index = 0; snd_seq_query_port_subscribers(seq, &query) >= 0; + query.index++) { + snd_seq_port_info_t port; + snd_seq_port_subscribe_t subs; + if (snd_seq_get_any_port_info(seq, query.addr.client, query.addr.port, &port) < 0) + continue; + if (port.capability & SND_SEQ_PORT_CAP_NO_EXPORT) + continue; + memset(&subs, 0, sizeof(subs)); + subs.queue = query.queue; + subs.sender.client = query.client; + subs.sender.port = query.port; + subs.dest.client = query.addr.client; + subs.dest.port = query.addr.port; + snd_seq_unsubscribe_port(seq, &subs); + } + + query.type = SND_SEQ_QUERY_SUBS_WRITE; + query.index = 0; + for (query.index = 0; snd_seq_query_port_subscribers(seq, &query) >= 0; + query.index++) { + snd_seq_port_info_t port; + snd_seq_port_subscribe_t subs; + if (snd_seq_get_any_port_info(seq, query.addr.client, query.addr.port, &port) < 0) + continue; + if (port.capability & SND_SEQ_PORT_CAP_NO_EXPORT) + continue; + memset(&subs, 0, sizeof(subs)); + subs.queue = query.queue; + subs.sender.client = query.addr.client; + subs.sender.port = query.addr.port; + subs.dest.client = query.client; + subs.dest.port = query.port; + snd_seq_unsubscribe_port(seq, &subs); + } +} + +static void remove_all_connections(snd_seq_t *seq) +{ + do_search_port(seq, "", 0, remove_connection); +} + + +/* + * main.. + */ + enum { - SUBSCRIBE, UNSUBSCRIBE, LIST_INPUT, LIST_OUTPUT + SUBSCRIBE, UNSUBSCRIBE, LIST_INPUT, LIST_OUTPUT, REMOVE_ALL }; static struct option long_option[] = { @@ -170,6 +260,7 @@ static struct option long_option[] = { {"tick", 1, NULL, 't'}, {"exclusive", 0, NULL, 'e'}, {"list", 0, NULL, 'l'}, + {"removeall", 0, NULL, 'x'}, {NULL, 0, NULL, 0}, }; @@ -185,7 +276,7 @@ int main(int argc, char **argv) snd_seq_client_info_t cinfo; snd_seq_port_subscribe_t subs; - while ((c = getopt_long(argc, argv, "diog:r:t:el", long_option, NULL)) != -1) { + while ((c = getopt_long(argc, argv, "diog:r:t:elx", long_option, NULL)) != -1) { switch (c) { case 'd': command = UNSUBSCRIBE; @@ -215,6 +306,9 @@ int main(int argc, char **argv) case 'l': list_subs = 1; break; + case 'x': + command = REMOVE_ALL; + break; default: usage(); exit(1); @@ -226,16 +320,23 @@ int main(int argc, char **argv) return 1; } - if (command == LIST_INPUT) { + switch (command) { + case LIST_INPUT: list_ports(seq, group, SND_SEQ_PORT_CAP_READ|SND_SEQ_PORT_CAP_SUBS_READ, list_subs); snd_seq_close(seq); return 0; - } else if (command == LIST_OUTPUT) { + case LIST_OUTPUT: list_ports(seq, group, SND_SEQ_PORT_CAP_WRITE|SND_SEQ_PORT_CAP_SUBS_WRITE, list_subs); snd_seq_close(seq); return 0; + case REMOVE_ALL: + remove_all_connections(seq); + snd_seq_close(seq); + return 0; } + /* connection or disconnection */ + if (optind + 2 > argc) { snd_seq_close(seq); usage();