From 72f7565e3210dfc8c068962fdcae7c99db5d6557 Mon Sep 17 00:00:00 2001 From: Christian Pointner Date: Mon, 12 Oct 2015 07:45:36 +0200 Subject: added inital osc support --- client/Makefile | 1 + client/dolmetschctl-client.c | 44 +++++++----- client/midi.c | 34 ++++----- client/midi.h | 4 +- client/osc.c | 166 +++++++++++++++++++++++++++++++++++++++++++ client/osc.h | 52 ++++++++++++++ server/osc.c | 2 + 7 files changed, 261 insertions(+), 42 deletions(-) create mode 100644 client/osc.c create mode 100644 client/osc.h diff --git a/client/Makefile b/client/Makefile index d9cab9a..bb767d9 100644 --- a/client/Makefile +++ b/client/Makefile @@ -28,6 +28,7 @@ EXECUTABLE := dolmetschctl-client C_OBJS := slist.o \ midi.o \ + osc.o \ dolmetschctl-client.o C_SRCS := $(C_OBJS:%.o=%.c) diff --git a/client/dolmetschctl-client.c b/client/dolmetschctl-client.c index 1f97475..4dbaf5a 100644 --- a/client/dolmetschctl-client.c +++ b/client/dolmetschctl-client.c @@ -31,7 +31,7 @@ #include #include "midi.h" -/* #include "osc.h" */ +#include "osc.h" void print_version() @@ -61,8 +61,7 @@ void print_usage() printf(" -o : the UDP host/port to send OSC messages to\n"); } -/* int main_loop(midi_t* m, osc_t* o) */ -int main_loop(midi_t* m) +int main_loop(midi_t* m, osc_t* o) { int ret = 0; @@ -72,11 +71,11 @@ int main_loop(midi_t* m) 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 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; + 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??"); @@ -86,7 +85,7 @@ int main_loop(midi_t* m) 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); */ + osc_get_poll_fds(o, &(pfds[osc_npfds_offset]), osc_npfds); int err = poll(pfds, npfds, 200); if(err < 0 && errno != EINTR) { @@ -98,14 +97,14 @@ int main_loop(midi_t* m) continue; } -// ret = midi_handle_revents(m, &(pfds[midi_npfds_offset]), midi_npfds, o); - ret = midi_handle_revents(m, &(pfds[midi_npfds_offset]), midi_npfds); + 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, x); */ - /* 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; @@ -169,16 +168,25 @@ int main(int argc, char* argv[]) 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 :", osc_target); + print_usage(); + return -1; + } + midi_t m; if(midi_init(&m, midi_dev)) return -1; - /* osc_t o; */ - /* if(osc_init(&o, osc_target)) */ - /* return -1; */ + osc_t o; + if(osc_init(&o, host, port)) + return -1; - /* int ret = main_loop(&m, &o); */ - int ret = main_loop(&m); + int ret = main_loop(&m, &o); return ret; } diff --git a/client/midi.c b/client/midi.c index cd4885a..46a4687 100644 --- a/client/midi.c +++ b/client/midi.c @@ -95,8 +95,7 @@ void midi_lang_switch_done(void* data) d->active_ = 1; } -//static int midi_enqueue_lang_switch(midi_t* m, osc_t* o, const char* lang, const u_int8_t* buf, int len) -static int midi_enqueue_lang_switch(midi_t* m, const char* lang, const u_int8_t* buf, int len) +static int midi_enqueue_lang_switch(midi_t* m, osc_t* o, const char* lang, const u_int8_t* buf, int len) { midi_done_data_t* done_data = malloc(sizeof(midi_done_data_t)); assert(done_data); @@ -110,26 +109,23 @@ static int midi_enqueue_lang_switch(midi_t* m, const char* lang, const u_int8_t* return 0; // mixer_switch_lang(x, lang, &midi_lang_switch_done, done_data); } -//static int midi_handle_note_on(midi_t* m, osc_t* o) -static int midi_handle_note_on(midi_t* m) +static int midi_handle_note_on(midi_t* m, osc_t* o) { int ret = 0; switch(m->buf_[1]) { - case NOTE_EN: ret = midi_enqueue_lang_switch(m/*, o*/,"en", done_data_en, sizeof(done_data_en)); break; - case NOTE_DE: ret = midi_enqueue_lang_switch(m/*, o*/, "de", done_data_de, sizeof(done_data_de)); break; + case NOTE_EN: ret = midi_enqueue_lang_switch(m, o,"en", done_data_en, sizeof(done_data_en)); break; + case NOTE_DE: ret = midi_enqueue_lang_switch(m, o, "de", done_data_de, sizeof(done_data_de)); break; default: printf("ignoring unknown note\n"); break; } return ret; } -//static int midi_handle_note_off(midi_t* m, osc_t* o) -static int midi_handle_note_off(midi_t* m) +static int midi_handle_note_off(midi_t* m, osc_t* o) { return 0; } -//static int midi_handle_message(midi_t* m, osc_t* o) -static int midi_handle_message(midi_t* m) +static int midi_handle_message(midi_t* m, osc_t* o) { int i; printf("MIDI: "); @@ -138,18 +134,15 @@ static int midi_handle_message(midi_t* m) int ret = 0; switch(m->buf_[0]) { -// case 0x90: ret = midi_handle_note_on(m, o); break; -// case 0x80: ret = midi_handle_note_off(m, o); break; - case 0x90: ret = midi_handle_note_on(m); break; - case 0x80: ret = midi_handle_note_off(m); break; + case 0x90: ret = midi_handle_note_on(m, o); break; + case 0x80: ret = midi_handle_note_off(m, o); break; default: printf("ignoring unknown midi command\n"); break; } return ret; } -//static int midi_handle_in_revents(midi_t* m, struct pollfd *pfds, int npfds, osc_t* o) -static int midi_handle_in_revents(midi_t* m, struct pollfd *pfds, int npfds) +static int midi_handle_in_revents(midi_t* m, struct pollfd *pfds, int npfds, osc_t* o) { int err; unsigned short revents; @@ -173,8 +166,7 @@ static int midi_handle_in_revents(midi_t* m, struct pollfd *pfds, int npfds) } m->read_idx_ += ret; if(m->read_idx_ >= sizeof(m->buf_)) { -// ret = midi_handle_message(m, o); - ret = midi_handle_message(m); + ret = midi_handle_message(m, o); memset(m->buf_, 0, sizeof(m->buf_)); m->read_idx_ = 0; return ret; @@ -223,16 +215,14 @@ static int midi_handle_out_revents(midi_t* m, struct pollfd *pfds, int npfds) return 0; } -//int midi_handle_revents(midi_t* m, struct pollfd *pfds, int npfds, osc_t* o) -int midi_handle_revents(midi_t* m, struct pollfd *pfds, int npfds) +int midi_handle_revents(midi_t* m, struct pollfd *pfds, int npfds, osc_t* o) { assert(m); if(!m->input_ || !m->output_) return 0; -// int ret = midi_handle_in_revents(m, pfds, m->in_pfds_cnt_, o); - int ret = midi_handle_in_revents(m, pfds, m->in_pfds_cnt_); + int ret = midi_handle_in_revents(m, pfds, m->in_pfds_cnt_, o); if(ret) return ret; diff --git a/client/midi.h b/client/midi.h index 2446103..b6e51fc 100644 --- a/client/midi.h +++ b/client/midi.h @@ -27,6 +27,7 @@ #include #include "slist.h" +#include "osc.h" typedef struct { snd_rawmidi_t* input_; @@ -49,7 +50,6 @@ typedef struct { int midi_init(midi_t* m, const char* device); int midi_get_poll_fd_count(midi_t* m); int midi_get_poll_fds(midi_t* m, struct pollfd *pfds, int npfds); -//int midi_handle_revents(midi_t* m, struct pollfd *pfds, int npfds, osc_t* o); -int midi_handle_revents(midi_t* m, struct pollfd *pfds, int npfds); +int midi_handle_revents(midi_t* m, struct pollfd *pfds, int npfds, osc_t* o); #endif diff --git a/client/osc.c b/client/osc.c new file mode 100644 index 0000000..4ecc28a --- /dev/null +++ b/client/osc.c @@ -0,0 +1,166 @@ +/* + * dolmetschctl + * + * + * Copyright (C) 2015 Christian Pointner + * + * 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 . + */ + +#include "config.h" + +#include +#include +#include +#include +#include + +#include "osc.h" + + +static void print_error(int num, const char *msg, const char *path) +{ + error(0, 0, "liblo server error %d in path %s: %s", num, path, msg); +} + +static int lang_handler(const char *path, const char *types, lo_arg ** argv, + int argc, lo_message msg, void *user_data) +{ + if(argc != 1 || !lo_is_string_type((lo_type)types[0])) + return 1; + + lo_address from = lo_message_get_source(msg); + const char* host = lo_address_get_hostname(from); + const char* port = lo_address_get_port(from); + assert(host && port); + + osc_t* o = (osc_t*)user_data; + assert(o); + osc_task_t* task = malloc(sizeof(osc_task_t)); + assert(task); + + task->self_ = o; + task->state_ = 0; + assert((task->lang_ = strdup(&(argv[0]->s)))); + task->addr_ = lo_address_new(host, port); + assert(task->addr_); + task->msg_ = lo_message_new(); + assert(task->msg_); + assert(!lo_message_add(task->msg_, "s", task->lang_)); + + assert(slist_add(&(o->tasks_), task)); + + return 0; +} + +void free_osc_task(void* ptr) +{ + osc_task_t* task = (osc_task_t*)ptr; + + lo_message_free(task->msg_); + lo_address_free(task->addr_); + free(task->lang_); + free(task); +} + +void osc_lang_switch_task(void* data) +{ + assert(data); + osc_task_t* d = data; + + lo_send_message_from(d->addr_, d->self_->server_, "/lang/switch", d->msg_); + slist_remove(&(d->self_->tasks_), d); +} + +int osc_init(osc_t* o, const char* host, const char* port) +{ + assert(o != NULL); + + o->server_ = NULL; + o->target_ = lo_address_new(host, port); + slist_init(&(o->tasks_), free_osc_task); + + if(!port) + return 0; + + o->server_ = lo_server_new(NULL, print_error); + if(!o->server_) + return -1; + + if(!lo_server_add_method(o->server_, "/lang/ack", "s", lang_handler, (void*)o)) + return -1; + + return 0; +} + + +int osc_get_poll_fd_count(osc_t* o) +{ + assert(o); + + if(!o->server_) + return 0; + + return 1; +} + +int osc_get_poll_fds(osc_t* o, struct pollfd *pfds, int npfds) +{ + assert(o); + + if(!o->server_) + return 0; + + pfds[0].fd = lo_server_get_socket_fd(o->server_); + pfds[0].events = POLLIN; + pfds[0].revents = 0; + + return 0; +} + +//int osc_handle_revents(osc_t* o, struct pollfd *pfds, int npfds, midi_t* m) +int osc_handle_revents(osc_t* o, struct pollfd *pfds, int npfds) +{ + assert(o); + + if(!o->server_) + return 0; + + if(pfds[0].revents & (POLLERR | POLLHUP | POLLNVAL)) { + error(0, 0, "OSC: got POLLERR, POLLHUP or POLLNVAL"); + return -1; + } + if(!(pfds[0].revents & POLLIN)) + return 0; + + lo_server_recv_noblock(o->server_, 0); + + int ret = 0; + slist_element_t* tmp; + for(tmp = o->tasks_.first_; tmp; tmp = tmp->next_) { + osc_task_t* d = (osc_task_t*)(tmp->data_); + if(d->state_ == 0) { +// ret = midi_switch_lang(x, d->lang_, &osc_lang_switch_task, d); + if(ret) + break; + + d->state_ = 1; + } + } + + + return ret; +} diff --git a/client/osc.h b/client/osc.h new file mode 100644 index 0000000..f6ac83d --- /dev/null +++ b/client/osc.h @@ -0,0 +1,52 @@ +/* + * dolmetschctl + * + * + * Copyright (C) 2015 Christian Pointner + * + * 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 . + */ + +#ifndef DOLMETSCHCTL_osc_h_INCLUDED +#define DOLMETSCHCTL_osc_h_INCLUDED + +#include "lo/lo.h" +#include + +#include "slist.h" +//#include "midi.h" + +typedef struct { + lo_server server_; + lo_address target_; + slist_t tasks_; +} osc_t; + +typedef struct { + osc_t* self_; + int state_; + char* lang_; + lo_address addr_; + lo_message msg_; +} osc_task_t; + +int osc_init(osc_t* o, const char* host, const char* port); +int osc_get_poll_fd_count(osc_t* o); +int osc_get_poll_fds(osc_t* o, struct pollfd *pfds, int npfds); +//int osc_handle_revents(osc_t* o, struct pollfd *pfds, int npfds, midi_t* m); +int osc_handle_revents(osc_t* o, struct pollfd *pfds, int npfds); + +#endif diff --git a/server/osc.c b/server/osc.c index 656d400..1011ad8 100644 --- a/server/osc.c +++ b/server/osc.c @@ -23,6 +23,8 @@ #include "config.h" #include +#include +#include #include #include -- cgit v1.2.3