diff options
Diffstat (limited to 'alsa-utils/seq/aseqnet/aseqnet.c')
-rw-r--r-- | alsa-utils/seq/aseqnet/aseqnet.c | 609 |
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; -} - |