diff options
Diffstat (limited to 'app/dolmetschctl-client.c')
-rw-r--r-- | app/dolmetschctl-client.c | 192 |
1 files changed, 192 insertions, 0 deletions
diff --git a/app/dolmetschctl-client.c b/app/dolmetschctl-client.c new file mode 100644 index 0000000..9815924 --- /dev/null +++ b/app/dolmetschctl-client.c @@ -0,0 +1,192 @@ +/* + * dolmetschctl + * + * + * Copyright (C) 2015 Christian Pointner <equinox@spreadspace.org> + * + * This file is part of dolmetschctl. + * + * dolmetschctl is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * dolmetschctl 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. + * + * You should have received a copy of the GNU General Public License + * along with dolmetschctl. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "config.h" + +#include <stdio.h> +#include <unistd.h> +#include <ctype.h> +#include <error.h> + +#include <lo/lo.h> +#include <alsa/asoundlib.h> + +#include "midi_client.h" +#include "osc_client.h" + + +void print_version() +{ + printf("%s\n", VERSION_STRING_0); +#if defined(__clang__) + printf("%s, using CLANG %s\n", VERSION_STRING_1, __clang_version__); +#elif defined(__GNUC__) + printf("%s, using GCC %d.%d.%d\n", VERSION_STRING_1, __GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__); +#else + printf("%s\n", VERSION_STRING_1); +#endif + + printf("linked against alsa-lib Version %s\n", snd_asoundlib_version()); + char verstr[32]; + lo_version(verstr, sizeof(verstr), 0, 0, 0, 0, 0, 0, 0); + printf("linked against liblo Version %s\n", verstr); +} + +void print_usage() +{ + printf("\ndolmetschctl-client <options>\n"); + printf(" -h print this and exit\n"); + printf(" -v print version information and exit\n"); + printf(" -m <dev> the MIDI control device name to use, i.e. hw:2,0,0\n"); + printf(" (use `amidi -l` to list all available devices)'\n"); + printf(" -o <host>:<port> the UDP host/port to send OSC messages to\n"); +} + +int main_loop(midi_t* m, osc_t* o) +{ + int ret = 0; + + printf("main_loop just started\n"); + + int midi_npfds_offset = 0; + int midi_npfds = midi_get_poll_fd_count(m); + assert(midi_npfds > 0); + + int osc_npfds_offset = midi_npfds_offset + midi_npfds; + int osc_npfds = osc_get_poll_fd_count(o); + assert(osc_npfds > 0); + + int npfds = midi_npfds + osc_npfds; + struct pollfd *pfds = alloca(npfds * sizeof(struct pollfd)); + if(!pfds) { + error(0, 0, "error while allocating poll fds - stack corrupted??"); + return -1; + } + + printf("main_loop running with %d pollfds...\n", npfds); + for (;;) { + midi_get_poll_fds(m, &(pfds[midi_npfds_offset]), midi_npfds); + osc_get_poll_fds(o, &(pfds[osc_npfds_offset]), osc_npfds); + + int err = poll(pfds, npfds, 200); + if(err < 0 && errno != EINTR) { + error(0, errno, "poll failed"); + break; + } + if(err <= 0) { + // timeout or EINTR + continue; + } + + ret = midi_handle_revents(m, &(pfds[midi_npfds_offset]), midi_npfds, o); + if(ret) + break; + +// ret = osc_handle_revents(o, &(pfds[osc_npfds_offset]), osc_npfds, m); + ret = osc_handle_revents(o, &(pfds[osc_npfds_offset]), osc_npfds); + if(ret) + break; + } + + return ret; +} + +int main(int argc, char* argv[]) +{ + int helpflag = 0; + int versionflag = 0; + char* midi_dev = NULL; + char* osc_target = NULL; + + int c; + opterr = 0; + while ((c = getopt (argc, argv, "vhm:o:")) != -1) { + switch (c) { + case 'h': + helpflag = 1; + break; + case 'v': + versionflag = 1; + break; + case 'm': + midi_dev = optarg; + break; + case 'o': + osc_target = optarg; + break; + case '?': + if (optopt == 'm' || optopt == 'o') + error(0, 0, "Option -%c requires an argument.\n", optopt); + else if (isprint (optopt)) + error(0, 0, "Unknown option `-%c'.\n", optopt); + else + error(0, 0, "Unknown option character `\\x%x'.\n", optopt); + return -1; + default: + return -1; + } + } + + if(helpflag) { + print_usage(); + return 0; + } + + if(versionflag) { + print_version(); + return 0; + } + + if(!midi_dev){ + error(0, 0, "MIDI device name must be set"); + print_usage(); + return -1; + } + + if(!osc_target){ + error(0, 0, "OSC target (host/port) name must be set"); + print_usage(); + return -1; + } + + char* port = osc_target; + char* host = strsep(&port, ":"); + char* remain = port; + strsep(&remain, ":"); + if(!host || !port || remain) { + error(0, 0, "'%s' is not a valid targets, must be in the format <host>:<port>", osc_target); + print_usage(); + return -1; + } + + midi_t m; + if(midi_init(&m, midi_dev)) + return -1; + + osc_t o; + if(osc_init(&o, &m, host, port)) + return -1; + + int ret = main_loop(&m, &o); + + return ret; +} |