From 928bbc4f1087b275e6b6e6505e4ea0551af4478e Mon Sep 17 00:00:00 2001 From: Jaroslav Kysela Date: Thu, 26 Aug 1999 10:23:28 +0000 Subject: [PATCH] More sequencer extension (event hop counter, get information about subscription).. --- include/seq.h | 5 +++ src/seq/seq.c | 38 ++++++++++++++++ test/README.aconnect | 5 ++- test/aconnect.c | 100 ++++++++++++++++++++++++++++++++----------- 4 files changed, 123 insertions(+), 25 deletions(-) diff --git a/include/seq.h b/include/seq.h index 9a7ca2b5..7ce96b27 100644 --- a/include/seq.h +++ b/include/seq.h @@ -29,8 +29,10 @@ int snd_seq_delete_port(snd_seq_t *handle, snd_seq_port_info_t *info); int snd_seq_get_port_info(snd_seq_t *handle, int port, snd_seq_port_info_t *info); int snd_seq_get_any_port_info(snd_seq_t *handle, int client, int port, snd_seq_port_info_t *info); int snd_seq_set_port_info(snd_seq_t *handle, int port, snd_seq_port_info_t *info); +int snd_seq_get_port_subscription(snd_seq_t *handle, snd_seq_port_subscribe_t *sub); int snd_seq_subscribe_port(snd_seq_t *handle, snd_seq_port_subscribe_t *sub); int snd_seq_unsubscribe_port(snd_seq_t *handle, snd_seq_port_subscribe_t *sub); +int snd_seq_query_port_subscribers(snd_seq_t *seq, snd_seq_query_subs_t * subs); int snd_seq_get_queue_status(snd_seq_t *handle, int q, snd_seq_queue_status_t *status); int snd_seq_get_queue_tempo(snd_seq_t *handle, int q, snd_seq_queue_tempo_t *tempo); int snd_seq_set_queue_tempo(snd_seq_t *handle, int q, snd_seq_queue_tempo_t *tempo); @@ -46,6 +48,9 @@ int snd_seq_alloc_queue(snd_seq_t *handle); int snd_seq_free_queue(snd_seq_t *handle, int q); int snd_seq_get_client_pool(snd_seq_t *handle, snd_seq_client_pool_t * info); int snd_seq_set_client_pool(snd_seq_t *handle, snd_seq_client_pool_t * info); +int snd_seq_query_next_client(snd_seq_t *handle, snd_seq_client_info_t * info); +int snd_seq_query_next_port(snd_seq_t *handle, snd_seq_port_info_t * info); + /* event routines */ snd_seq_event_t *snd_seq_create_event(void); int snd_seq_free_event(snd_seq_event_t *ev); diff --git a/src/seq/seq.c b/src/seq/seq.c index f8f77592..dcb9feb7 100644 --- a/src/seq/seq.c +++ b/src/seq/seq.c @@ -237,6 +237,15 @@ int snd_seq_set_port_info(snd_seq_t *seq, int port, snd_seq_port_info_t * info) return 0; } +int snd_seq_get_port_subscription(snd_seq_t *seq, snd_seq_port_subscribe_t * sub) +{ + if (!seq || !sub) + return -EINVAL; + if (ioctl(seq->fd, SND_SEQ_IOCTL_GET_SUBSCRIPTION, sub) < 0) + return -errno; + return 0; +} + int snd_seq_subscribe_port(snd_seq_t *seq, snd_seq_port_subscribe_t * sub) { if (!seq || !sub) @@ -255,6 +264,15 @@ int snd_seq_unsubscribe_port(snd_seq_t *seq, snd_seq_port_subscribe_t * sub) return 0; } +int snd_seq_query_port_subscribers(snd_seq_t *seq, snd_seq_query_subs_t * subs) +{ + if (!seq || !subs) + return -EINVAL; + if (ioctl(seq->fd, SND_SEQ_IOCTL_QUERY_SUBS, subs) < 0) + return -errno; + return 0; +} + int snd_seq_get_queue_status(snd_seq_t *seq, int q, snd_seq_queue_status_t * status) { if (!seq || !status) @@ -804,6 +822,26 @@ int snd_seq_set_client_pool(snd_seq_t *seq, snd_seq_client_pool_t *info) return 0; } +int snd_seq_query_next_client(snd_seq_t *seq, snd_seq_client_info_t *info) +{ + if (!seq || !info) + return -EINVAL; + info->client = seq->client; + if (ioctl(seq->fd, SND_SEQ_IOCTL_QUERY_NEXT_CLIENT, info) < 0) + return -errno; + return 0; +} + +int snd_seq_query_next_port(snd_seq_t *seq, snd_seq_port_info_t *info) +{ + if (!seq || !info) + return -EINVAL; + info->client = seq->client; + if (ioctl(seq->fd, SND_SEQ_IOCTL_QUERY_NEXT_PORT, info) < 0) + return -errno; + return 0; +} + void snd_seq_set_bit(int nr, void *array) { ((unsigned int *)array)[nr >> 5] |= 1UL << (nr & 31); diff --git a/test/README.aconnect b/test/README.aconnect index 1350c8db..ecc4f842 100644 --- a/test/README.aconnect +++ b/test/README.aconnect @@ -1,6 +1,6 @@ ================================================================ aconnect - control subscriptions - ver.0.1 + ver.0.1.1 Copyright (C) 1999 Takashi Iwai ================================================================ @@ -40,6 +40,9 @@ 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 -l together with -i or -o shows subscribers and tracking +for each port. + 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 diff --git a/test/aconnect.c b/test/aconnect.c index 906f01e2..cd81ab7d 100644 --- a/test/aconnect.c +++ b/test/aconnect.c @@ -1,6 +1,6 @@ /* * connect / disconnect two subscriber ports - * ver.0.1 + * ver.0.1.1 * * Copyright (C) 1999 Takashi Iwai * @@ -22,10 +22,8 @@ #include #include #include -#include -#include +#include -#define DEVICE_FILE "/dev/snd/seq" #define DEFAULT_QUEUE 0 static void usage(void) @@ -35,12 +33,15 @@ static void usage(void) 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, " aconnect -i [-g group] [-l]\n"); fprintf(stderr, " list input ports\n"); - fprintf(stderr, " aconnect -o [-g group]\n"); + fprintf(stderr, " aconnect -o [-g group] [-l]\n"); fprintf(stderr, " list output ports\n"); } +/* + * parse command line to client:port + */ static void parse_address(snd_seq_addr_t *addr, char *arg) { char *p; @@ -52,6 +53,9 @@ static void parse_address(snd_seq_addr_t *addr, char *arg) addr->port = 0; } +/* + * check permission (capability) of specified port + */ static int check_permission(snd_seq_port_info_t *pinfo, char *group, int perm) { if ((pinfo->capability & perm) == perm && @@ -64,10 +68,44 @@ static int check_permission(snd_seq_port_info_t *pinfo, char *group, int perm) return 0; } +/* + * list subscribers of specified type + */ +static void list_each_subs(snd_seq_t *seq, snd_seq_query_subs_t *subs, int type, char *msg) +{ + subs->type = type; + subs->index = 0; + while (snd_seq_query_port_subscribers(seq, subs) >= 0) { + if (subs->index == 0) + printf("\t%s: %d:%d:%d", msg, + subs->addr.queue, subs->addr.client, subs->addr.port); + else + printf(", %d:%d:%d", subs->addr.queue, subs->addr.client, subs->addr.port); + subs->index++; + } + if (subs->index) + printf("\n"); +} + +/* + * list subscribers + */ +static void list_subscribers(snd_seq_t *seq, int client, int port) +{ + snd_seq_query_subs_t subs; + memset(&subs, 0, sizeof(subs)); + subs.client = client; + subs.port = port; + list_each_subs(seq, &subs, SND_SEQ_QUERY_SUBS_READ, "Read Subscribers"); + list_each_subs(seq, &subs, SND_SEQ_QUERY_SUBS_WRITE, "Write Subscribers"); + list_each_subs(seq, &subs, SND_SEQ_QUERY_SUBS_READ_TRACK, "Read Tracking"); + list_each_subs(seq, &subs, SND_SEQ_QUERY_SUBS_WRITE_TRACK, "Write Tracking"); +} + /* * list all ports */ -static void list_ports(int fd, char *group, int perm) +static void list_ports(snd_seq_t *seq, char *group, int perm, int list_subs) { snd_seq_client_info_t cinfo; snd_seq_port_info_t pinfo; @@ -76,14 +114,14 @@ static void list_ports(int fd, char *group, int perm) cinfo.client = -1; cinfo.name[0] = 0; cinfo.group[0] = 0; - while (ioctl(fd, SND_SEQ_IOCTL_QUERY_NEXT_CLIENT, &cinfo) >= 0) { + while (snd_seq_query_next_client(seq, &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) { + 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", @@ -92,6 +130,8 @@ static void list_ports(int fd, char *group, int perm) 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); } /* reset query names */ pinfo.name[0] = 0; @@ -110,16 +150,17 @@ enum { int main(int argc, char **argv) { - int c, fd; + int c; + snd_seq_t *seq; int queue = DEFAULT_QUEUE; int command = SUBSCRIBE; - char *device = DEVICE_FILE; char *group = ""; int client; + int list_subs = 0; snd_seq_client_info_t cinfo; snd_seq_port_subscribe_t subs; - while ((c = getopt(argc, argv, "diog:D:q:")) != -1) { + while ((c = getopt(argc, argv, "diog:D:q:l")) != -1) { switch (c) { case 'd': command = UNSUBSCRIBE; @@ -133,37 +174,41 @@ int main(int argc, char **argv) case 'g': group = optarg; break; - case 'D': - device = optarg; - break; case 'q': queue = atoi(optarg); break; + case 'l': + list_subs = 1; + break; default: usage(); exit(1); } } - if ((fd = open(device, O_RDWR)) < 0) { + if (snd_seq_open(&seq, SND_SEQ_OPEN) < 0) { fprintf(stderr, "can't open sequencer\n"); return 1; } if (command == LIST_INPUT) { - list_ports(fd, group, SND_SEQ_PORT_CAP_READ|SND_SEQ_PORT_CAP_SUBS_READ); + 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) { - list_ports(fd, group, SND_SEQ_PORT_CAP_WRITE|SND_SEQ_PORT_CAP_SUBS_WRITE); + list_ports(seq, group, SND_SEQ_PORT_CAP_WRITE|SND_SEQ_PORT_CAP_SUBS_WRITE, list_subs); + snd_seq_close(seq); return 0; } if (optind + 2 > argc) { + snd_seq_close(seq); usage(); exit(1); } - if (ioctl(fd, SND_SEQ_IOCTL_CLIENT_ID, &client) < 0) { + if ((client = snd_seq_client_id(seq)) < 0) { + snd_seq_close(seq); fprintf(stderr, "can't get client id\n"); return 1; } @@ -174,7 +219,8 @@ int main(int argc, char **argv) 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) { + if (snd_seq_set_client_info(seq, &cinfo) < 0) { + snd_seq_close(seq); fprintf(stderr, "can't set client info\n"); return 0; } @@ -188,24 +234,30 @@ int main(int argc, char **argv) subs.realtime = 0; if (command == UNSUBSCRIBE) { - if (ioctl(fd, SND_SEQ_IOCTL_GET_SUBSCRIPTION, &subs) < 0) { + if (snd_seq_get_port_subscription(seq, &subs) < 0) { + snd_seq_close(seq); fprintf(stderr, "No subscription is found\n"); return 1; } - if (ioctl(fd, SND_SEQ_IOCTL_UNSUBSCRIBE_PORT, &subs) < 0) { + if (snd_seq_unsubscribe_port(seq, &subs) < 0) { + snd_seq_close(seq); fprintf(stderr, "Disconnection failed (errno=%d)\n", errno); return 1; } } else { - if (ioctl(fd, SND_SEQ_IOCTL_GET_SUBSCRIPTION, &subs) >= 0) { + if (snd_seq_get_port_subscription(seq, &subs) < 0) { + snd_seq_close(seq); fprintf(stderr, "Connection is already subscribed\n"); return 1; } - if (ioctl(fd, SND_SEQ_IOCTL_SUBSCRIBE_PORT, &subs) < 0) { + if (snd_seq_subscribe_port(seq, &subs) < 0) { + snd_seq_close(seq); fprintf(stderr, "Connection failed (errno=%d)\n", errno); return 1; } } + snd_seq_close(seq); + return 0; } -- 2.47.1