summaryrefslogtreecommitdiff
path: root/client
diff options
context:
space:
mode:
authorChristian Pointner <equinox@spreadspace.org>2015-10-12 07:45:36 +0200
committerChristian Pointner <equinox@spreadspace.org>2015-10-12 07:45:36 +0200
commit72f7565e3210dfc8c068962fdcae7c99db5d6557 (patch)
tree6c54e6a0cfb3eefd91b7a724dc3b1b5e5c922058 /client
parentadded support for midi (diff)
added inital osc support
Diffstat (limited to 'client')
-rw-r--r--client/Makefile1
-rw-r--r--client/dolmetschctl-client.c44
-rw-r--r--client/midi.c34
-rw-r--r--client/midi.h4
-rw-r--r--client/osc.c166
-rw-r--r--client/osc.h52
6 files changed, 259 insertions, 42 deletions
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 <alsa/asoundlib.h>
#include "midi.h"
-/* #include "osc.h" */
+#include "osc.h"
void print_version()
@@ -61,8 +61,7 @@ void print_usage()
printf(" -o <host>:<port> 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 <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, 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 <poll.h>
#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 <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 <stdlib.h>
+#include <string.h>
+#include <error.h>
+#include <assert.h>
+
+#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 <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/>.
+ */
+
+#ifndef DOLMETSCHCTL_osc_h_INCLUDED
+#define DOLMETSCHCTL_osc_h_INCLUDED
+
+#include "lo/lo.h"
+#include <poll.h>
+
+#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