From: Jaroslav Kysela Date: Fri, 20 Aug 1999 20:27:07 +0000 (+0000) Subject: Added aconnect example.. X-Git-Tag: v1.0.3~1444 X-Git-Url: https://git.alsa-project.org/?a=commitdiff_plain;h=a234679700c5565cbb2bd98e429cded1dc2587f4;p=alsa-lib.git Added aconnect example.. --- diff --git a/test/Makefile.am b/test/Makefile.am index 97a52ea8..08df9b83 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -1,5 +1,5 @@ check_PROGRAMS=control mixer switches pause pcm latency seq \ - playmidi1 timer loopback + playmidi1 timer loopback aconnect control_LDADD=../src/libasound.la mixer_LDADD=../src/libasound.la @@ -11,6 +11,7 @@ seq_LDADD=../src/libasound.la playmidi1_LDADD=../src/libasound.la timer_LDADD=../src/libasound.la loopback_LDADD=../src/libasound.la +aconnect_LDADD=../src/libasound.la INCLUDES=-I$(top_srcdir)/include CFLAGS=-static -Wall -pipe -g diff --git a/test/README.aconnect b/test/README.aconnect new file mode 100644 index 00000000..1350c8db --- /dev/null +++ b/test/README.aconnect @@ -0,0 +1,47 @@ +================================================================ + aconnect - control subscriptions + ver.0.1 + Copyright (C) 1999 Takashi Iwai +================================================================ + +aconnect is a utility to control subscriptions of two ports as the +third "manager" client. + +For example, the following connects two ports, from 64:0 to 65:0. + + % aconnect 64:0 65:0 + +To disconnect the existing subscription, use -d option. + + % aconnect -d 64:0 65:0 + +To see which port is available as input port, run the following +command: + + % aconnect -i + client 0: 'System' [group=system] [type=kernel] + 0 'Timer ' [group=system] + 1 'Announce ' [group=system] + client 64: '0: MIDI Synth' [group=] [type=kernel] + 0 'card 0: synth-midi: 0' [group=device] + +Similary, to see the output ports, use -o flag. + + % aconnect -o + client 64: '0: MIDI Synth' [group=] [type=kernel] + 0 'card 0: synth-midi: 0' [group=device] + client 65: 'AWE Wave Table Synth : 0' [group=device] [type=kernel] + 0 'Emu8000 port 0 ' [group=device] + 1 'Emu8000 port 1 ' [group=device] + 2 'Emu8000 port 2 ' [group=device] + 3 'Emu8000 port 3 ' [group=device] + +Some ports may have permission for its own group. +In such a case, change the group of aconnect to the appropriate one by +using -g option. + +The option -D specifies the sequencer device file (as default, +/dev/snd/seq). Usually, you don't have to change it. +The option -q specifies the queue number. The argument must be a +valid queue number, usually from 0 to 7. + diff --git a/test/aconnect.c b/test/aconnect.c new file mode 100644 index 00000000..aaf0ef1d --- /dev/null +++ b/test/aconnect.c @@ -0,0 +1,210 @@ +/* + * connect / disconnect two subscriber ports + * ver.0.1 + * + * Copyright (C) 1999 Takashi Iwai + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DEVICE_FILE "/dev/snd/seq" +#define DEFAULT_QUEUE 0 + +static void usage(void) +{ + fprintf(stderr, "connect / disconnect two subscriber ports\n"); + fprintf(stderr, "copyright (C) 1999 Takashi Iwai\n"); + fprintf(stderr, "usage: aconnect [-d] [-q queue] [-g group] sender receiver\n"); + fprintf(stderr, " -d = disconnect\n"); + fprintf(stderr, " sender, receiver = client:port\n"); + fprintf(stderr, " aconnect -i [-g group]\n"); + fprintf(stderr, " list input ports\n"); + fprintf(stderr, " aconnect -o [-g group]\n"); + fprintf(stderr, " list output ports\n"); +} + +static void parse_address(snd_seq_addr_t *addr, char *arg) +{ + char *p; + + addr->client = atoi(arg); + if ((p = strchr(arg, ':')) != NULL) + addr->port = atoi(p + 1); + else + addr->port = 0; +} + +static int check_permission(snd_seq_port_info_t *pinfo, char *group, int perm) +{ + if ((pinfo->capability & perm) == perm && + ! (pinfo->capability & SND_SEQ_PORT_CAP_NO_EXPORT)) + return 1; + if (*group && strcmp(pinfo->group, group) == 0 && + (pinfo->cap_group & perm) == perm && + ! (pinfo->cap_group & SND_SEQ_PORT_CAP_NO_EXPORT)) + return 1; + return 0; +} + +/* + * list all ports + */ +static void list_ports(int fd, char *group, int perm) +{ + snd_seq_client_info_t cinfo; + snd_seq_port_info_t pinfo; + int client_printed; + + cinfo.client = -1; + cinfo.name[0] = 0; + cinfo.group[0] = 0; + while (ioctl(fd, SND_SEQ_IOCTL_QUERY_NEXT_CLIENT, &cinfo) >= 0) { + /* reset query info */ + pinfo.client = cinfo.client; + pinfo.port = -1; + pinfo.name[0] = 0; + strncpy(pinfo.group, group, sizeof(pinfo.group)); + client_printed = 0; + while (ioctl(fd, SND_SEQ_IOCTL_QUERY_NEXT_PORT, &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); + } + /* reset query names */ + pinfo.name[0] = 0; + strncpy(pinfo.group, group, sizeof(pinfo.group)); + } + /* reset query names */ + cinfo.name[0] = 0; + cinfo.group[0] = 0; + } +} + + +enum { + SUBSCRIBE, UNSUBSCRIBE, LIST_INPUT, LIST_OUTPUT +}; + +int main(int argc, char **argv) +{ + int c, fd; + int queue = DEFAULT_QUEUE; + int command = SUBSCRIBE; + char *device = DEVICE_FILE; + char *group = ""; + int client; + snd_seq_client_info_t cinfo; + snd_seq_port_subscribe_t subs; + + while ((c = getopt(argc, argv, "diog:D:q:")) != -1) { + switch (c) { + case 'd': + command = UNSUBSCRIBE; + break; + case 'i': + command = LIST_INPUT; + break; + case 'o': + command = LIST_OUTPUT; + break; + case 'g': + group = optarg; + break; + case 'D': + device = optarg; + break; + case 'q': + queue = atoi(optarg); + break; + default: + usage(); + exit(1); + } + } + + if ((fd = open(device, O_RDWR)) < 0) { + fprintf(stderr, "can't open sequencer\n"); + return 1; + } + + if (command == LIST_INPUT) { + list_ports(fd, group, SND_SEQ_PORT_CAP_IN|SND_SEQ_PORT_CAP_SUBS_IN); + return 0; + } else if (command == LIST_OUTPUT) { + list_ports(fd, group, SND_SEQ_PORT_CAP_OUT|SND_SEQ_PORT_CAP_SUBS_OUT); + return 0; + } + + if (optind + 2 > argc) { + usage(); + exit(1); + } + + if (ioctl(fd, SND_SEQ_IOCTL_CLIENT_ID, &client) < 0) { + fprintf(stderr, "can't get client id\n"); + return 1; + } + + /* set client info */ + memset(&cinfo, 0, sizeof(cinfo)); + cinfo.client = client; + cinfo.type = USER_CLIENT; + strcpy(cinfo.name, "ALSA Connector"); + strncpy(cinfo.group, group, sizeof(cinfo.group) - 1); + if (ioctl(fd, SND_SEQ_IOCTL_SET_CLIENT_INFO, &cinfo) < 0) { + fprintf(stderr, "can't set client info\n"); + return 0; + } + + /* set subscription */ + parse_address(&subs.sender, argv[optind]); + parse_address(&subs.dest, argv[optind + 1]); + subs.sender.queue = subs.dest.queue = queue; + subs.exclusive = 0; + subs.realtime = 0; + + if (command == UNSUBSCRIBE) { + if (ioctl(fd, SND_SEQ_IOCTL_GET_SUBSCRIPTION, &subs) < 0) { + fprintf(stderr, "No subscription is found\n"); + return 1; + } + if (ioctl(fd, SND_SEQ_IOCTL_UNSUBSCRIBE_PORT, &subs) < 0) { + fprintf(stderr, "Disconnection failed (errno=%d)\n", errno); + return 1; + } + } else { + if (ioctl(fd, SND_SEQ_IOCTL_GET_SUBSCRIPTION, &subs) >= 0) { + fprintf(stderr, "Connection is already subscribed\n"); + return 1; + } + if (ioctl(fd, SND_SEQ_IOCTL_SUBSCRIBE_PORT, &subs) < 0) { + fprintf(stderr, "Connection failed (errno=%d)\n", errno); + return 1; + } + } + + return 0; +}