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