mirror of
https://github.com/alsa-project/alsa-lib.git
synced 2025-10-29 05:40:25 -04:00
Added aconnect example..
This commit is contained in:
parent
b38a572356
commit
a234679700
3 changed files with 259 additions and 1 deletions
|
|
@ -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
|
||||
|
|
|
|||
47
test/README.aconnect
Normal file
47
test/README.aconnect
Normal file
|
|
@ -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.
|
||||
|
||||
210
test/aconnect.c
Normal file
210
test/aconnect.c
Normal file
|
|
@ -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 <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <linux/asound.h>
|
||||
#include <linux/asequencer.h>
|
||||
|
||||
#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;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue