Commit 31bcd605 authored by Hanspeter Portner's avatar Hanspeter Portner

add support for scheduled bundle dispatch.

parent 44b13cf5
...@@ -39,9 +39,18 @@ ...@@ -39,9 +39,18 @@
#define FT232_PID 0x6001 #define FT232_PID 0x6001
#define FT4232_PID 0x6011 #define FT4232_PID 0x6011
#define NSECS 1000000000 #define NSECS 1000000000
#define JAN_1970 2208988800ULL
typedef struct _sched_t sched_t;
typedef struct _app_t app_t; typedef struct _app_t app_t;
struct _sched_t {
sched_t *next;
struct timespec to;
size_t len;
uint8_t buf [];
};
struct _app_t { struct _app_t {
uint16_t vid; uint16_t vid;
uint16_t pid; uint16_t pid;
...@@ -55,6 +64,8 @@ struct _app_t { ...@@ -55,6 +64,8 @@ struct _app_t {
struct ftdi_context ftdi; struct ftdi_context ftdi;
sched_t *list;
struct { struct {
int out; int out;
int inp; int inp;
...@@ -119,14 +130,14 @@ static const LV2_OSC_Driver driver = { ...@@ -119,14 +130,14 @@ static const LV2_OSC_Driver driver = {
}; };
static void static void
_handle_osc_packet(app_t *app, const uint8_t *buf, size_t len); _handle_osc_packet(app_t *app, uint64_t timetag, const uint8_t *buf, size_t len);
static void static void
_handle_osc_message(app_t *app, LV2_OSC_Reader *reader, size_t len) _handle_osc_message(app_t *app, LV2_OSC_Reader *reader, size_t len)
{ {
const char *path = "/dmx"; const char *path = "/dmx";
unsigned pos = 0; unsigned pos = 0;
unsigned channel = 0; int32_t channel = 0;
OSC_READER_MESSAGE_FOREACH(reader, arg, len) OSC_READER_MESSAGE_FOREACH(reader, arg, len)
{ {
...@@ -148,6 +159,8 @@ _handle_osc_message(app_t *app, LV2_OSC_Reader *reader, size_t len) ...@@ -148,6 +159,8 @@ _handle_osc_message(app_t *app, LV2_OSC_Reader *reader, size_t len)
} break; } break;
default: default:
{ {
syslog(LOG_DEBUG, "[%s] %"PRIi32" %"PRIi32, __func__,
channel, arg->i);
app->dmx.data[channel++] = arg->i & 0xff; app->dmx.data[channel++] = arg->i & 0xff;
} break; } break;
} }
...@@ -165,12 +178,43 @@ _handle_osc_bundle(app_t *app, LV2_OSC_Reader *reader, size_t len) ...@@ -165,12 +178,43 @@ _handle_osc_bundle(app_t *app, LV2_OSC_Reader *reader, size_t len)
{ {
OSC_READER_BUNDLE_FOREACH(reader, itm, len) OSC_READER_BUNDLE_FOREACH(reader, itm, len)
{ {
_handle_osc_packet(app, itm->body, itm->size); _handle_osc_packet(app, itm->timetag, itm->body, itm->size);
}
}
static sched_t *
_sched_append(sched_t *list, sched_t *elmnt)
{
if(!list)
{
elmnt->next = NULL;
return elmnt;
} }
sched_t *prev = NULL;
for(sched_t *ptr = list; ptr; prev = ptr, ptr = ptr->next)
{
if( (ptr->to.tv_sec > elmnt->to.tv_sec)
&& (ptr->to.tv_nsec > elmnt->to.tv_nsec) )
{
break;
}
}
if(!prev)
{
elmnt->next = list;
return elmnt;
}
elmnt->next = prev->next;
prev->next = elmnt;
return list;
} }
static void static void
_handle_osc_packet(app_t *app, const uint8_t *buf, size_t len) _handle_osc_packet(app_t *app, uint64_t timetag, const uint8_t *buf, size_t len)
{ {
LV2_OSC_Reader reader; LV2_OSC_Reader reader;
lv2_osc_reader_initialize(&reader, buf, len); lv2_osc_reader_initialize(&reader, buf, len);
...@@ -181,7 +225,28 @@ _handle_osc_packet(app_t *app, const uint8_t *buf, size_t len) ...@@ -181,7 +225,28 @@ _handle_osc_packet(app_t *app, const uint8_t *buf, size_t len)
} }
else if(lv2_osc_reader_is_message(&reader)) else if(lv2_osc_reader_is_message(&reader))
{ {
_handle_osc_message(app, &reader, len); if(timetag == LV2_OSC_IMMEDIATE)
{
_handle_osc_message(app, &reader, len);
}
else
{
sched_t *elmnt = malloc(sizeof(sched_t) + len);
if(elmnt)
{
elmnt->next = NULL;
elmnt->to.tv_sec = (timetag >> 32) - JAN_1970;
elmnt->to.tv_nsec = (timetag && 32) * 0x1p-32 * 1e9;
elmnt->len = len;
memcpy(elmnt->buf, buf, len);
app->list = _sched_append(app->list, elmnt);
}
else
{
syslog(LOG_ERR, "[%s] malloc failed", __func__);
}
}
} }
} }
...@@ -372,12 +437,12 @@ _beat(void *data) ...@@ -372,12 +437,12 @@ _beat(void *data)
_thread_priority(app->priority.out); _thread_priority(app->priority.out);
struct timespec to; struct timespec to;
clock_gettime(CLOCK_MONOTONIC, &to); clock_gettime(CLOCK_REALTIME, &to);
while(!done) while(!done)
{ {
// sleep until next beat timestamp // sleep until next beat timestamp
if(clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &to, NULL) == -1) if(clock_nanosleep(CLOCK_REALTIME, TIMER_ABSTIME, &to, NULL) == -1)
{ {
continue; continue;
} }
...@@ -387,11 +452,28 @@ _beat(void *data) ...@@ -387,11 +452,28 @@ _beat(void *data)
size_t len; size_t len;
while( (buf = varchunk_read_request(app->rb.rx, &len)) ) while( (buf = varchunk_read_request(app->rb.rx, &len)) )
{ {
_handle_osc_packet(app, buf, len); _handle_osc_packet(app, LV2_OSC_IMMEDIATE, buf, len);
varchunk_read_advance(app->rb.rx); varchunk_read_advance(app->rb.rx);
} }
// read OSC messages from list
for(sched_t *elmnt = app->list; elmnt; elmnt = app->list)
{
double diff = to.tv_sec - elmnt->to.tv_sec;
diff += (to.tv_nsec - elmnt->to.tv_nsec) * 1e-9;
if(diff < 0.0)
{
break;
}
_handle_osc_packet(app, LV2_OSC_IMMEDIATE, elmnt->buf, elmnt->len);
app->list = elmnt->next;
free(elmnt);
}
// write DMX data // write DMX data
_ftdi_xmit(app); _ftdi_xmit(app);
...@@ -425,6 +507,16 @@ _thread_deinit(app_t *app) ...@@ -425,6 +507,16 @@ _thread_deinit(app_t *app)
pthread_join(app->thread, NULL); pthread_join(app->thread, NULL);
} }
static void
_sched_deinit(app_t *app)
{
for(sched_t *elmnt = app->list; elmnt; elmnt = app->list)
{
app->list = elmnt->next;
free(elmnt);
}
}
static void static void
_version(void) _version(void)
{ {
...@@ -604,6 +696,7 @@ main(int argc __attribute__((unused)), char **argv __attribute__((unused))) ...@@ -604,6 +696,7 @@ main(int argc __attribute__((unused)), char **argv __attribute__((unused)))
} }
_thread_deinit(&app); _thread_deinit(&app);
_sched_deinit(&app);
_ftdi_deinit(&app); _ftdi_deinit(&app);
_osc_deinit(&app); _osc_deinit(&app);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment