Blame seq/aseqnet/aseqnet.c

Packit Service a9274b
/*
Packit Service a9274b
 * network server/client for ALSA sequencer
Packit Service a9274b
 *   ver.0.1
Packit Service a9274b
 *
Packit Service a9274b
 * Copyright (C) 1999-2000 Takashi Iwai
Packit Service a9274b
 * 
Packit Service a9274b
 *  This program is free software; you can redistribute it and/or modify
Packit Service a9274b
 *  it under the terms of the GNU General Public License version 2 as
Packit Service a9274b
 *  published by the Free Software Foundation.
Packit Service a9274b
 * 
Packit Service a9274b
 *  This program is distributed in the hope that it will be useful,
Packit Service a9274b
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service a9274b
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit Service a9274b
 *  GNU General Public License for more details.
Packit Service a9274b
 *
Packit Service a9274b
 */
Packit Service a9274b
Packit Service a9274b
#include <stdio.h>
Packit Service a9274b
#include <stdlib.h>
Packit Service a9274b
#include <ctype.h>
Packit Service a9274b
#include <string.h>
Packit Service a9274b
#include <netinet/in.h>
Packit Service a9274b
#include <sys/socket.h>
Packit Service a9274b
#include <netdb.h>
Packit Service a9274b
#include <locale.h>
Packit Service a9274b
#include <alsa/asoundlib.h>
Packit Service a9274b
#include <getopt.h>
Packit Service a9274b
#include <signal.h>
Packit Service a9274b
#include <assert.h>
Packit Service a9274b
#include "aconfig.h"
Packit Service a9274b
#include "gettext.h"
Packit Service a9274b
Packit Service a9274b
/*
Packit Service a9274b
 * prototypes
Packit Service a9274b
 */
Packit Service a9274b
static void usage(void);
Packit Service a9274b
static void init_buf(void);
Packit Service a9274b
static void init_pollfds(void);
Packit Service a9274b
static void close_files(void);
Packit Service a9274b
static void init_seq(char *source, char *dest);
Packit Service a9274b
static int get_port(char *service);
Packit Service a9274b
static void sigterm_exit(int sig);
Packit Service a9274b
static void init_server(int port);
Packit Service a9274b
static void init_client(char *server, int port);
Packit Service a9274b
static void do_loop(void);
Packit Service a9274b
static int copy_local_to_remote(void);
Packit Service a9274b
static int copy_remote_to_local(int fd);
Packit Service a9274b
Packit Service a9274b
/*
Packit Service a9274b
 * default TCP port number
Packit Service a9274b
 */
Packit Service a9274b
#define DEFAULT_PORT	40002
Packit Service a9274b
Packit Service a9274b
/*
Packit Service a9274b
 * local input buffer
Packit Service a9274b
 */
Packit Service a9274b
static char *readbuf;
Packit Service a9274b
static int max_rdlen;
Packit Service a9274b
static char *writebuf;
Packit Service a9274b
static int cur_wrlen, max_wrlen;
Packit Service a9274b
Packit Service a9274b
#define MAX_BUF_EVENTS	200
Packit Service a9274b
#define MAX_CONNECTION	10
Packit Service a9274b
Packit Service a9274b
static snd_seq_t *handle;
Packit Service a9274b
static struct pollfd *seqifds = NULL;
Packit Service a9274b
static struct pollfd *seqofds = NULL;
Packit Service a9274b
static struct pollfd *pollfds = NULL;
Packit Service a9274b
static int seqifds_count = 0;
Packit Service a9274b
static int seqofds_count = 0;
Packit Service a9274b
static int pollfds_count = 0;
Packit Service a9274b
static int sockfd, netfd[MAX_CONNECTION] = {[0 ... MAX_CONNECTION-1] = -1};
Packit Service a9274b
static int max_connection;
Packit Service a9274b
static int cur_connected;
Packit Service a9274b
static int seq_port;
Packit Service a9274b
Packit Service a9274b
static int server_mode;
Packit Service a9274b
static int verbose = 0;
Packit Service a9274b
static int info = 0;
Packit Service a9274b
Packit Service a9274b
Packit Service a9274b
/*
Packit Service a9274b
 * main routine
Packit Service a9274b
 */
Packit Service a9274b
Packit Service a9274b
static const struct option long_option[] = {
Packit Service a9274b
	{"port", 1, NULL, 'p'},
Packit Service a9274b
	{"source", 1, NULL, 's'},
Packit Service a9274b
	{"dest", 1, NULL, 'd'},
Packit Service a9274b
	{"help", 0, NULL, 'h'},
Packit Service a9274b
	{"verbose", 0, NULL, 'v'},
Packit Service a9274b
	{"info", 0, NULL, 'i'},
Packit Service a9274b
	{NULL, 0, NULL, 0},
Packit Service a9274b
};
Packit Service a9274b
Packit Service a9274b
int main(int argc, char **argv)
Packit Service a9274b
{
Packit Service a9274b
	int c;
Packit Service a9274b
	int port = DEFAULT_PORT;
Packit Service a9274b
	char *source = NULL, *dest = NULL;
Packit Service a9274b
Packit Service a9274b
#ifdef ENABLE_NLS
Packit Service a9274b
	setlocale(LC_ALL, "");
Packit Service a9274b
	textdomain(PACKAGE);
Packit Service a9274b
#endif
Packit Service a9274b
Packit Service a9274b
	while ((c = getopt_long(argc, argv, "p:s:d:vi", long_option, NULL)) != -1) {
Packit Service a9274b
		switch (c) {
Packit Service a9274b
		case 'p':
Packit Service a9274b
			if (isdigit(*optarg))
Packit Service a9274b
				port = atoi(optarg);
Packit Service a9274b
			else
Packit Service a9274b
				port = get_port(optarg);
Packit Service a9274b
			break;
Packit Service a9274b
		case 's':
Packit Service a9274b
			source = optarg;
Packit Service a9274b
			break;
Packit Service a9274b
		case 'd':
Packit Service a9274b
			dest = optarg;
Packit Service a9274b
			break;
Packit Service a9274b
		case 'v':
Packit Service a9274b
			verbose++;
Packit Service a9274b
			break;
Packit Service a9274b
		case 'i':
Packit Service a9274b
			info++;
Packit Service a9274b
			break;
Packit Service a9274b
		default:
Packit Service a9274b
			usage();
Packit Service a9274b
			exit(1);
Packit Service a9274b
		}
Packit Service a9274b
	}
Packit Service a9274b
Packit Service a9274b
	signal(SIGINT, sigterm_exit);
Packit Service a9274b
	signal(SIGTERM, sigterm_exit);
Packit Service a9274b
Packit Service a9274b
	init_buf();
Packit Service a9274b
	init_seq(source, dest);
Packit Service a9274b
Packit Service a9274b
	if (optind >= argc) {
Packit Service a9274b
		server_mode = 1;
Packit Service a9274b
		max_connection = MAX_CONNECTION;
Packit Service a9274b
		init_pollfds();
Packit Service a9274b
		init_server(port);
Packit Service a9274b
	} else {
Packit Service a9274b
		server_mode = 0;
Packit Service a9274b
		max_connection = 1;
Packit Service a9274b
		init_pollfds();
Packit Service a9274b
		init_client(argv[optind], port);
Packit Service a9274b
	}
Packit Service a9274b
Packit Service a9274b
	do_loop();
Packit Service a9274b
Packit Service a9274b
	close_files();
Packit Service a9274b
Packit Service a9274b
	return 0;
Packit Service a9274b
}
Packit Service a9274b
Packit Service a9274b
Packit Service a9274b
/*
Packit Service a9274b
 * print usage
Packit Service a9274b
 */
Packit Service a9274b
static void usage(void)
Packit Service a9274b
{
Packit Service a9274b
	printf(_("aseqnet - network client/server on ALSA sequencer\n"));
Packit Service a9274b
	printf(_("  Copyright (C) 1999 Takashi Iwai\n"));
Packit Service a9274b
	printf(_("usage:\n"));
Packit Service a9274b
	printf(_("  server mode: aseqnet [-options]\n"));
Packit Service a9274b
	printf(_("  client mode: aseqnet [-options] server_host\n"));
Packit Service a9274b
	printf(_("options:\n"));
Packit Service a9274b
	printf(_("  -p,--port # : specify TCP port (digit or service name)\n"));
Packit Service a9274b
	printf(_("  -s,--source addr : read from given addr (client:port)\n"));
Packit Service a9274b
	printf(_("  -d,--dest addr : write to given addr (client:port)\n"));
Packit Service a9274b
	printf(_("  -v, --verbose : print verbose messages\n"));
Packit Service a9274b
	printf(_("  -i, --info : print certain received events\n"));
Packit Service a9274b
}
Packit Service a9274b
Packit Service a9274b
Packit Service a9274b
/*
Packit Service a9274b
 * allocate and initialize buffers
Packit Service a9274b
 */
Packit Service a9274b
static void init_buf(void)
Packit Service a9274b
{
Packit Service a9274b
	max_wrlen = MAX_BUF_EVENTS * sizeof(snd_seq_event_t);
Packit Service a9274b
	max_rdlen = MAX_BUF_EVENTS * sizeof(snd_seq_event_t);
Packit Service a9274b
	writebuf = malloc(max_wrlen);
Packit Service a9274b
	readbuf = malloc(max_rdlen);
Packit Service a9274b
	if (writebuf == NULL || readbuf == NULL) {
Packit Service a9274b
		fprintf(stderr, _("can't malloc\n"));
Packit Service a9274b
		exit(1);
Packit Service a9274b
	}
Packit Service a9274b
	memset(writebuf, 0, max_wrlen);
Packit Service a9274b
	memset(readbuf, 0, max_rdlen);
Packit Service a9274b
	cur_wrlen = 0;
Packit Service a9274b
}
Packit Service a9274b
Packit Service a9274b
/*
Packit Service a9274b
 * allocate and initialize poll array
Packit Service a9274b
 */
Packit Service a9274b
static void init_pollfds(void)
Packit Service a9274b
{
Packit Service a9274b
	pollfds_count = seqifds_count + seqofds_count + 1 + max_connection;
Packit Service a9274b
	pollfds = (struct pollfd *)calloc(pollfds_count, sizeof(struct pollfd));
Packit Service a9274b
	assert(pollfds);
Packit Service a9274b
}
Packit Service a9274b
Packit Service a9274b
/*
Packit Service a9274b
 * close all files
Packit Service a9274b
 */
Packit Service a9274b
static void close_files(void)
Packit Service a9274b
{
Packit Service a9274b
	int i;
Packit Service a9274b
	if (verbose)
Packit Service a9274b
		fprintf(stderr, _("closing files..\n"));
Packit Service a9274b
	for (i = 0; i < max_connection; i++) {
Packit Service a9274b
		if (netfd[i] >= 0)
Packit Service a9274b
			close(netfd[i]);
Packit Service a9274b
	}
Packit Service a9274b
	if (sockfd >= 0)
Packit Service a9274b
		close(sockfd);
Packit Service a9274b
}
Packit Service a9274b
Packit Service a9274b
Packit Service a9274b
/*
Packit Service a9274b
 * initialize sequencer
Packit Service a9274b
 */
Packit Service a9274b
static void init_seq(char *source, char *dest)
Packit Service a9274b
{
Packit Service a9274b
	snd_seq_addr_t addr;
Packit Service a9274b
	int err, counti, counto;
Packit Service a9274b
Packit Service a9274b
	if (snd_seq_open(&handle, "default", SND_SEQ_OPEN_DUPLEX, 0) < 0) {
Packit Service a9274b
		perror("snd_seq_open");
Packit Service a9274b
		exit(1);
Packit Service a9274b
	}
Packit Service a9274b
	if (seqifds)
Packit Service a9274b
		free(seqifds);
Packit Service a9274b
	if (seqofds)
Packit Service a9274b
		free(seqofds);
Packit Service a9274b
	counti = seqifds_count = snd_seq_poll_descriptors_count(handle, POLLIN);
Packit Service a9274b
	assert(counti > 0);
Packit Service a9274b
	counto = seqofds_count = snd_seq_poll_descriptors_count(handle, POLLOUT);
Packit Service a9274b
	assert(counto > 0);
Packit Service a9274b
	seqifds = (struct pollfd *)calloc(counti, sizeof(struct pollfd));
Packit Service a9274b
	assert(seqifds);
Packit Service a9274b
	seqofds = (struct pollfd *)calloc(counto, sizeof(struct pollfd));
Packit Service a9274b
	assert(seqofds);
Packit Service a9274b
	err = snd_seq_poll_descriptors(handle, seqifds, counti, POLLIN);
Packit Service a9274b
	assert(err == counti);
Packit Service a9274b
	err = snd_seq_poll_descriptors(handle, seqofds, counto, POLLOUT);
Packit Service a9274b
	assert(err == counto);
Packit Service a9274b
Packit Service a9274b
	snd_seq_nonblock(handle, 1);
Packit Service a9274b
Packit Service a9274b
	/* set client info */
Packit Service a9274b
	if (server_mode)
Packit Service a9274b
		snd_seq_set_client_name(handle, "Net Server");
Packit Service a9274b
	else
Packit Service a9274b
		snd_seq_set_client_name(handle, "Net Client");
Packit Service a9274b
Packit Service a9274b
	/* create a port */
Packit Service a9274b
	seq_port = snd_seq_create_simple_port(handle, "Network",
Packit Service a9274b
					      SND_SEQ_PORT_CAP_READ |
Packit Service a9274b
					      SND_SEQ_PORT_CAP_WRITE |
Packit Service a9274b
					      SND_SEQ_PORT_CAP_SUBS_READ |
Packit Service a9274b
					      SND_SEQ_PORT_CAP_SUBS_WRITE,
Packit Service a9274b
					      SND_SEQ_PORT_TYPE_MIDI_GENERIC);
Packit Service a9274b
	if (seq_port < 0) {
Packit Service a9274b
		perror("create seq port");
Packit Service a9274b
		exit(1);
Packit Service a9274b
	}
Packit Service a9274b
	if (verbose)
Packit Service a9274b
		fprintf(stderr, _("sequencer opened: %d:%d\n"),
Packit Service a9274b
			snd_seq_client_id(handle), seq_port);
Packit Service a9274b
Packit Service a9274b
	/* explicit subscriptions */
Packit Service a9274b
	if (source) {
Packit Service a9274b
		/* read subscription */
Packit Service a9274b
		if (snd_seq_parse_address(handle, &addr, source) < 0) {
Packit Service a9274b
			fprintf(stderr, _("invalid source address %s\n"), source);
Packit Service a9274b
			exit(1);
Packit Service a9274b
		}
Packit Service a9274b
		if (snd_seq_connect_from(handle, seq_port, addr.client, addr.port)) {
Packit Service a9274b
			perror("read subscription");
Packit Service a9274b
			exit(1);
Packit Service a9274b
		}
Packit Service a9274b
	}
Packit Service a9274b
	if (dest) {
Packit Service a9274b
		/* write subscription */
Packit Service a9274b
		if (snd_seq_parse_address(handle, &addr, dest) < 0) {
Packit Service a9274b
			fprintf(stderr, _("invalid destination address %s\n"), dest);
Packit Service a9274b
			exit(1);
Packit Service a9274b
		}
Packit Service a9274b
		if (snd_seq_connect_to(handle, seq_port, addr.client, addr.port)) {
Packit Service a9274b
			perror("write subscription");
Packit Service a9274b
			exit(1);
Packit Service a9274b
		}
Packit Service a9274b
	}
Packit Service a9274b
}
Packit Service a9274b
Packit Service a9274b
Packit Service a9274b
/*
Packit Service a9274b
 * convert from string to TCP port number
Packit Service a9274b
 */
Packit Service a9274b
static int get_port(char *service)
Packit Service a9274b
{
Packit Service a9274b
	struct servent *sp;
Packit Service a9274b
Packit Service a9274b
	if ((sp = getservbyname(service, "tcp")) == NULL){
Packit Service a9274b
		fprintf(stderr, _("service '%s' is not found in /etc/services\n"), service);
Packit Service a9274b
		return -1;
Packit Service a9274b
	}
Packit Service a9274b
	return sp->s_port;
Packit Service a9274b
}
Packit Service a9274b
Packit Service a9274b
/*
Packit Service a9274b
 * signal handler
Packit Service a9274b
 */
Packit Service a9274b
static void sigterm_exit(int sig)
Packit Service a9274b
{
Packit Service a9274b
	close_files();
Packit Service a9274b
	exit(1);
Packit Service a9274b
}
Packit Service a9274b
Packit Service a9274b
Packit Service a9274b
/*
Packit Service a9274b
 * initialize network server
Packit Service a9274b
 */
Packit Service a9274b
static void init_server(int port)
Packit Service a9274b
{
Packit Service a9274b
	int i;
Packit Service a9274b
	int curstate = 1;
Packit Service a9274b
	struct sockaddr_in addr;
Packit Service a9274b
Packit Service a9274b
	memset(&addr, 0, sizeof(addr));
Packit Service a9274b
Packit Service a9274b
	addr.sin_family = AF_INET;
Packit Service a9274b
	addr.sin_addr.s_addr = INADDR_ANY;
Packit Service a9274b
	addr.sin_port = htons(port);
Packit Service a9274b
Packit Service a9274b
	sockfd = socket(AF_INET, SOCK_STREAM, 0);
Packit Service a9274b
	if (sockfd < 0)  {
Packit Service a9274b
		perror("create socket");
Packit Service a9274b
		exit(1);
Packit Service a9274b
	}
Packit Service a9274b
	setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &curstate, sizeof(curstate));
Packit Service a9274b
	/* the return value is ignored.. */
Packit Service a9274b
Packit Service a9274b
	if (bind(sockfd, (struct sockaddr *)&addr, sizeof(addr)) < 0)  {
Packit Service a9274b
		perror("can't bind");
Packit Service a9274b
		exit(1);
Packit Service a9274b
	}
Packit Service a9274b
Packit Service a9274b
	if (listen(sockfd, 5) < 0)  {
Packit Service a9274b
		perror("can't listen");
Packit Service a9274b
		exit(1);
Packit Service a9274b
	}
Packit Service a9274b
Packit Service a9274b
	cur_connected = 0;
Packit Service a9274b
	for (i = 0; i < max_connection; i++)
Packit Service a9274b
		netfd[i] = -1;
Packit Service a9274b
}
Packit Service a9274b
Packit Service a9274b
/*
Packit Service a9274b
 * start connection on server
Packit Service a9274b
 */
Packit Service a9274b
static void start_connection(void)
Packit Service a9274b
{
Packit Service a9274b
	struct sockaddr_in addr;
Packit Service a9274b
	int i;
Packit Service a9274b
	socklen_t addr_len;
Packit Service a9274b
Packit Service a9274b
	for (i = 0; i < max_connection; i++) {
Packit Service a9274b
		if (netfd[i] < 0)
Packit Service a9274b
			break;
Packit Service a9274b
	}
Packit Service a9274b
	if (i >= max_connection) {
Packit Service a9274b
		fprintf(stderr, _("too many connections!\n"));
Packit Service a9274b
		exit(1);
Packit Service a9274b
	}
Packit Service a9274b
	memset(&addr, 0, sizeof(addr));
Packit Service a9274b
	addr_len = sizeof(addr);
Packit Service a9274b
	netfd[i] = accept(sockfd, (struct sockaddr *)&addr, &addr_len);
Packit Service a9274b
	if (netfd[i] < 0) {
Packit Service a9274b
		perror("accept");
Packit Service a9274b
		exit(1);
Packit Service a9274b
	}
Packit Service a9274b
	if (verbose)
Packit Service a9274b
		fprintf(stderr, _("accepted[%d]\n"), netfd[i]);
Packit Service a9274b
	cur_connected++;
Packit Service a9274b
}
Packit Service a9274b
Packit Service a9274b
/*
Packit Service a9274b
 * initialize network client
Packit Service a9274b
 */
Packit Service a9274b
static void init_client(char *server, int port)
Packit Service a9274b
{
Packit Service a9274b
	struct sockaddr_in addr;
Packit Service a9274b
	struct hostent *host;
Packit Service a9274b
	int curstate = 1;
Packit Service a9274b
	int fd;
Packit Service a9274b
Packit Service a9274b
	if ((fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0){
Packit Service a9274b
		perror("create socket");
Packit Service a9274b
		exit(1);
Packit Service a9274b
	}
Packit Service a9274b
	if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &curstate, sizeof(curstate)) < 0) {
Packit Service a9274b
		perror("setsockopt");
Packit Service a9274b
		exit(1);
Packit Service a9274b
	}
Packit Service a9274b
	if ((host = gethostbyname(server)) == NULL){
Packit Service a9274b
		fprintf(stderr, _("can't get address %s\n"), server);
Packit Service a9274b
		exit(1);
Packit Service a9274b
	}
Packit Service a9274b
	addr.sin_port = htons(port);
Packit Service a9274b
	addr.sin_family = AF_INET;
Packit Service a9274b
	memcpy(&addr.sin_addr, host->h_addr, host->h_length);
Packit Service a9274b
	if (connect(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
Packit Service a9274b
		perror("connect");
Packit Service a9274b
		exit(1);
Packit Service a9274b
	}
Packit Service a9274b
	if (verbose)
Packit Service a9274b
		fprintf(stderr, _("ok.. connected\n"));
Packit Service a9274b
	netfd[0] = fd;
Packit Service a9274b
	cur_connected = 1;
Packit Service a9274b
}
Packit Service a9274b
Packit Service a9274b
/*
Packit Service a9274b
 * event loop
Packit Service a9274b
 */
Packit Service a9274b
static void do_loop(void)
Packit Service a9274b
{
Packit Service a9274b
	int i, rc, width;
Packit Service a9274b
	int seqifd_ptr, sockfd_ptr = -1, netfd_ptr;
Packit Service a9274b
Packit Service a9274b
	for (;;) {
Packit Service a9274b
		memset(pollfds, 0, pollfds_count * sizeof(struct pollfd));
Packit Service a9274b
		seqifd_ptr = 0;
Packit Service a9274b
		memcpy(pollfds, seqifds, sizeof(*seqifds)*(width = seqifds_count));
Packit Service a9274b
		if (server_mode) {
Packit Service a9274b
			sockfd_ptr = width;
Packit Service a9274b
			pollfds[width].fd = sockfd;
Packit Service a9274b
			pollfds[width].events = POLLIN;
Packit Service a9274b
			width++;
Packit Service a9274b
		}
Packit Service a9274b
		netfd_ptr = width;
Packit Service a9274b
		for (i = 0; i < max_connection; i++) {
Packit Service a9274b
			if (netfd[i] >= 0) {
Packit Service a9274b
				pollfds[width].fd = netfd[i];
Packit Service a9274b
				pollfds[width].events = POLLIN;
Packit Service a9274b
				width++;
Packit Service a9274b
			}
Packit Service a9274b
		}
Packit Service a9274b
		do {
Packit Service a9274b
			rc = poll(pollfds, width, -1);
Packit Service a9274b
		} while (rc <= 0 && errno == EINTR);
Packit Service a9274b
		if (rc <= 0) {
Packit Service a9274b
			perror("poll");
Packit Service a9274b
			exit(1);
Packit Service a9274b
		}
Packit Service a9274b
		if (server_mode) {
Packit Service a9274b
			if (pollfds[sockfd_ptr].revents & (POLLIN|POLLOUT))
Packit Service a9274b
				start_connection();
Packit Service a9274b
		}
Packit Service a9274b
		for (i = 0; i < seqifds_count; i++)
Packit Service a9274b
			if (pollfds[seqifd_ptr + i].revents & (POLLIN|POLLOUT)) {
Packit Service a9274b
				if (copy_local_to_remote())
Packit Service a9274b
					return;
Packit Service a9274b
				break;
Packit Service a9274b
			}
Packit Service a9274b
		for (i = 0; i < max_connection; i++) {
Packit Service a9274b
			if (netfd[i] < 0)
Packit Service a9274b
				continue;
Packit Service a9274b
			if (pollfds[netfd_ptr + i].revents & (POLLIN|POLLOUT)) {
Packit Service a9274b
				if (copy_remote_to_local(netfd[i])) {
Packit Service a9274b
					netfd[i] = -1;
Packit Service a9274b
					cur_connected--;
Packit Service a9274b
					if (cur_connected <= 0)
Packit Service a9274b
						return;
Packit Service a9274b
				}
Packit Service a9274b
			}
Packit Service a9274b
		}
Packit Service a9274b
	}
Packit Service a9274b
}
Packit Service a9274b
Packit Service a9274b
Packit Service a9274b
/*
Packit Service a9274b
 * flush write buffer - send data to the socket
Packit Service a9274b
 */
Packit Service a9274b
static void flush_writebuf(void)
Packit Service a9274b
{
Packit Service a9274b
	if (cur_wrlen) {
Packit Service a9274b
		int i;
Packit Service a9274b
		for (i = 0; i < max_connection; i++) {
Packit Service a9274b
			if (netfd[i] >= 0)
Packit Service a9274b
				write(netfd[i], writebuf, cur_wrlen);
Packit Service a9274b
		}
Packit Service a9274b
		cur_wrlen = 0;
Packit Service a9274b
	}
Packit Service a9274b
}
Packit Service a9274b
Packit Service a9274b
/*
Packit Service a9274b
 * get space from write buffer
Packit Service a9274b
 */
Packit Service a9274b
static char *get_writebuf(int len)
Packit Service a9274b
{
Packit Service a9274b
	char *buf;
Packit Service a9274b
	if (cur_wrlen + len >= max_wrlen)
Packit Service a9274b
		flush_writebuf();
Packit Service a9274b
	buf = writebuf + cur_wrlen;
Packit Service a9274b
	cur_wrlen += len;
Packit Service a9274b
	return buf;
Packit Service a9274b
}
Packit Service a9274b
Packit Service a9274b
static void print_event(snd_seq_event_t *ev)
Packit Service a9274b
{
Packit Service a9274b
	switch (ev->type) {
Packit Service a9274b
	case SND_SEQ_EVENT_CONTROLLER: 
Packit Service a9274b
		printf(_("Channel %2d: Control event : %5d\n"),
Packit Service a9274b
			ev->data.control.channel, ev->data.control.value);
Packit Service a9274b
		break;
Packit Service a9274b
	case SND_SEQ_EVENT_PITCHBEND:
Packit Service a9274b
		printf(_("Channel %2d: Pitchbender   : %5d\n"), 
Packit Service a9274b
			ev->data.control.channel, ev->data.control.value);
Packit Service a9274b
		break;
Packit Service a9274b
	case SND_SEQ_EVENT_NOTEON:
Packit Service a9274b
		printf(_("Channel %2d: Note On event : %5d\n"),
Packit Service a9274b
			ev->data.control.channel, ev->data.note.note);
Packit Service a9274b
		break;
Packit Service a9274b
	case SND_SEQ_EVENT_NOTEOFF: 
Packit Service a9274b
		printf(_("Channel %2d: Note Off event: %5d\n"),
Packit Service a9274b
		       ev->data.control.channel, ev->data.note.note);           
Packit Service a9274b
		break;
Packit Service a9274b
	}
Packit Service a9274b
}
Packit Service a9274b
Packit Service a9274b
#define EVENT_PACKET_SIZE	32
Packit Service a9274b
Packit Service a9274b
/*
Packit Service a9274b
 * copy events from sequencer to port(s)
Packit Service a9274b
 */
Packit Service a9274b
static int copy_local_to_remote(void)
Packit Service a9274b
{
Packit Service a9274b
	int rc;
Packit Service a9274b
	snd_seq_event_t *ev;
Packit Service a9274b
	char *buf;
Packit Service a9274b
Packit Service a9274b
	while ((rc = snd_seq_event_input(handle, &ev)) >= 0 && ev) {
Packit Service a9274b
		if (ev->type >= SND_SEQ_EVENT_CLIENT_START &&
Packit Service a9274b
		    ! snd_seq_ev_is_variable_type(ev)) {
Packit Service a9274b
			snd_seq_free_event(ev);
Packit Service a9274b
			continue;
Packit Service a9274b
		}
Packit Service a9274b
		if (snd_seq_ev_is_variable(ev)) {
Packit Service a9274b
			int len;
Packit Service a9274b
			len = EVENT_PACKET_SIZE + ev->data.ext.len;
Packit Service a9274b
			buf = get_writebuf(len);
Packit Service a9274b
			memcpy(buf, ev, sizeof(snd_seq_event_t));
Packit Service a9274b
			memcpy(buf + EVENT_PACKET_SIZE, ev->data.ext.ptr, ev->data.ext.len);
Packit Service a9274b
		} else {
Packit Service a9274b
			buf = get_writebuf(EVENT_PACKET_SIZE);
Packit Service a9274b
			memcpy(buf, ev, EVENT_PACKET_SIZE);
Packit Service a9274b
		}
Packit Service a9274b
		if (info)
Packit Service a9274b
			print_event(ev);
Packit Service a9274b
		snd_seq_free_event(ev);
Packit Service a9274b
	}
Packit Service a9274b
	flush_writebuf();
Packit Service a9274b
	return 0;
Packit Service a9274b
}
Packit Service a9274b
Packit Service a9274b
/*
Packit Service a9274b
 * copy events from a port to sequencer
Packit Service a9274b
 */
Packit Service a9274b
static int copy_remote_to_local(int fd)
Packit Service a9274b
{
Packit Service a9274b
	int count;
Packit Service a9274b
	char *buf;
Packit Service a9274b
	snd_seq_event_t *ev;
Packit Service a9274b
Packit Service a9274b
	count = read(fd, readbuf, MAX_BUF_EVENTS * sizeof(snd_seq_event_t));
Packit Service a9274b
	buf = readbuf;
Packit Service a9274b
Packit Service a9274b
	if (count == 0) {
Packit Service a9274b
		if (verbose)
Packit Service a9274b
			fprintf(stderr, _("disconnected\n"));
Packit Service a9274b
		return 1;
Packit Service a9274b
	}
Packit Service a9274b
Packit Service a9274b
	while (count > 0) {
Packit Service a9274b
		ev = (snd_seq_event_t*)buf;
Packit Service a9274b
		buf += EVENT_PACKET_SIZE;
Packit Service a9274b
		count -= EVENT_PACKET_SIZE;
Packit Service a9274b
		if (snd_seq_ev_is_variable(ev) && ev->data.ext.len > 0) {
Packit Service a9274b
			ev->data.ext.ptr = buf;
Packit Service a9274b
			buf += ev->data.ext.len;
Packit Service a9274b
			count -= ev->data.ext.len;
Packit Service a9274b
		}
Packit Service a9274b
		snd_seq_ev_set_direct(ev);
Packit Service a9274b
		snd_seq_ev_set_source(ev, seq_port);
Packit Service a9274b
		snd_seq_ev_set_subs(ev);
Packit Service a9274b
		if (info)
Packit Service a9274b
			print_event(ev);
Packit Service a9274b
		snd_seq_event_output(handle, ev);
Packit Service a9274b
	}
Packit Service a9274b
Packit Service a9274b
	snd_seq_drain_output(handle);
Packit Service a9274b
	return 0;
Packit Service a9274b
}
Packit Service a9274b