|
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 |
|