aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHanspeter Portner <dev@open-music-kontrollers.ch>2015-09-23 23:35:33 +0200
committerHanspeter Portner <dev@open-music-kontrollers.ch>2015-09-23 23:35:33 +0200
commit0f5f290f74de93771ea8e99e4e5c7251352eeb14 (patch)
tree46140eb1e1c9f220011d0f655e1baf9fec5b6a66
parent0be628fc73275ce5697e725a2d18d65b6f828e14 (diff)
downloadmoony.lv2-0f5f290f74de93771ea8e99e4e5c7251352eeb14.tar.xz
add several improvements.
-rw-r--r--timely.h185
1 files changed, 130 insertions, 55 deletions
diff --git a/timely.h b/timely.h
index 5a83911..4f19015 100644
--- a/timely.h
+++ b/timely.h
@@ -25,8 +25,9 @@
#include <lv2/lv2plug.in/ns/ext/time/time.h>
typedef enum _timely_mask_t timely_mask_t;
-typedef void (*timely_cb_t)(int64_t frame, LV2_URID type, const LV2_Atom *atom, void *data);
typedef struct _timely_t timely_t;
+typedef void (*timely_cb_t)(timely_t *timely, int64_t frames, LV2_URID type,
+ const LV2_Atom *atom, void *data);
enum _timely_mask_t {
TIMELY_MASK_BAR_BEAT = (1 << 0),
@@ -57,7 +58,7 @@ struct _timely_t {
float bar_beat;
int64_t bar;
- uint32_t beat_unit;
+ int32_t beat_unit;
float beats_per_bar;
float beats_per_minute;
@@ -81,10 +82,12 @@ struct _timely_t {
} window;
struct {
- LV2_Atom_Long bar;
- LV2_Atom_Float bar_beat;
+ LV2_Atom_Int i;
+ LV2_Atom_Long h;
+ LV2_Atom_Float f;
} atom;
+ bool first;
timely_mask_t mask;
timely_cb_t cb;
void *data;
@@ -116,81 +119,76 @@ _timely_deatomize(timely_t *timely, int64_t frames, const LV2_Atom_Object *obj)
lv2_atom_object_query(obj, q);
+ // send speed first upon transport stop
+ if(speed && (speed->body != timely->pos.speed) && (speed->body == 0.f) )
+ {
+ timely->pos.speed = speed->body;
+ if(timely->cb && (timely->mask & TIMELY_MASK_SPEED) )
+ timely->cb(timely, frames, timely->urid.time_speed, (const LV2_Atom *)speed, timely->data);
+ }
+
if(beat_unit && (beat_unit->body != timely->pos.beat_unit) )
{
timely->pos.beat_unit = beat_unit->body;
if(timely->cb && (timely->mask & TIMELY_MASK_BEAT_UNIT) )
- timely->cb(frames, timely->urid.time_beatUnit, (const LV2_Atom *)beat_unit, timely->data);
+ timely->cb(timely, frames, timely->urid.time_beatUnit, (const LV2_Atom *)beat_unit, timely->data);
}
if(beats_per_bar && (beats_per_bar->body != timely->pos.beats_per_bar) )
{
timely->pos.beats_per_bar = beats_per_bar->body;
if(timely->cb && (timely->mask & TIMELY_MASK_BEATS_PER_BAR) )
- timely->cb(frames, timely->urid.time_beatsPerBar, (const LV2_Atom *)beats_per_bar, timely->data);
+ timely->cb(timely, frames, timely->urid.time_beatsPerBar, (const LV2_Atom *)beats_per_bar, timely->data);
}
if(beats_per_minute && (beats_per_minute->body != timely->pos.beats_per_minute) )
{
timely->pos.beats_per_minute = beats_per_minute->body;
if(timely->cb && (timely->mask & TIMELY_MASK_BEATS_PER_MINUTE) )
- timely->cb(frames, timely->urid.time_beatsPerMinute, (const LV2_Atom *)beats_per_minute, timely->data);
+ timely->cb(timely, frames, timely->urid.time_beatsPerMinute, (const LV2_Atom *)beats_per_minute, timely->data);
}
if(frame && (frame->body != timely->pos.frame) )
{
timely->pos.frame = frame->body;
if(timely->cb && (timely->mask & TIMELY_MASK_FRAME) )
- timely->cb(frames, timely->urid.time_frame, (const LV2_Atom *)frame, timely->data);
+ timely->cb(timely, frames, timely->urid.time_frame, (const LV2_Atom *)frame, timely->data);
}
if(frames_per_second && (frames_per_second->body != timely->pos.frames_per_second) )
{
timely->pos.frames_per_second = frames_per_second->body;
if(timely->cb && (timely->mask & TIMELY_MASK_FRAMES_PER_SECOND) )
- timely->cb(frames, timely->urid.time_framesPerSecond, (const LV2_Atom *)frames_per_second, timely->data);
- }
-
- if(speed && (speed->body != timely->pos.speed) )
- {
- timely->pos.speed = speed->body;
- if(timely->cb && (timely->mask & TIMELY_MASK_SPEED) )
- timely->cb(frames, timely->urid.time_speed, (const LV2_Atom *)speed, timely->data);
+ timely->cb(timely, frames, timely->urid.time_framesPerSecond, (const LV2_Atom *)frames_per_second, timely->data);
}
if(bar_beat && (bar_beat->body != timely->pos.bar_beat) )
{
timely->pos.bar_beat = bar_beat->body;
if(timely->cb && (timely->mask & TIMELY_MASK_BAR_BEAT) )
- timely->cb(frames, timely->urid.time_barBeat, (const LV2_Atom *)bar_beat, timely->data);
- }
- else if(0.f != timely->pos.bar_beat) // calculate
- {
- timely->pos.bar_beat = 0.f;
- timely->atom.bar_beat.body = timely->pos.bar_beat;
- if(timely->cb && (timely->mask & TIMELY_MASK_BAR_BEAT) )
- timely->cb(frames, timely->urid.time_barBeat, (const LV2_Atom *)&timely->atom.bar_beat, timely->data);
+ timely->cb(timely, frames, timely->urid.time_barBeat, (const LV2_Atom *)bar_beat, timely->data);
}
if(bar && (bar->body != timely->pos.bar) )
{
timely->pos.bar = bar->body;
if(timely->cb && (timely->mask & TIMELY_MASK_BAR) )
- timely->cb(frames, timely->urid.time_bar, (const LV2_Atom *)bar, timely->data);
+ timely->cb(timely, frames, timely->urid.time_bar, (const LV2_Atom *)bar, timely->data);
}
- else if(0 != timely->pos.bar) // calculate
+
+ // send speed last upon transport start
+ if(speed && (speed->body != timely->pos.speed) && (speed->body != 0.f) )
{
- timely->pos.bar = 0;
- timely->atom.bar.body = timely->pos.bar;
- if(timely->cb && (timely->mask & TIMELY_MASK_BAR) )
- timely->cb(frames, timely->urid.time_bar, (const LV2_Atom *)&timely->atom.bar, timely->data);
+ timely->pos.speed = speed->body;
+ if(timely->cb && (timely->mask & TIMELY_MASK_SPEED) )
+ timely->cb(timely, frames, timely->urid.time_speed, (const LV2_Atom *)speed, timely->data);
}
}
static inline void
_timely_refresh(timely_t *timely)
{
- timely->frames_per_beat = 240.f / (timely->pos.beats_per_minute * timely->pos.beat_unit)
+ timely->frames_per_beat = 240.0 / (timely->pos.beats_per_minute * timely->pos.beat_unit)
* timely->pos.frames_per_second;
timely->frames_per_bar = timely->frames_per_beat * timely->pos.beats_per_bar;
@@ -215,7 +213,7 @@ timely_init(timely_t *timely, LV2_URID_Map *map, double rate,
timely->data = data;
timely->urid.atom_object = map->map(map->handle, LV2_ATOM__Object);
- timely->urid.time_position = map->map(map->handle, LV2_TIME__position);
+ timely->urid.time_position = map->map(map->handle, LV2_TIME__Position);
timely->urid.time_barBeat = map->map(map->handle, LV2_TIME__barBeat);
timely->urid.time_bar = map->map(map->handle, LV2_TIME__bar);
timely->urid.time_beatUnit = map->map(map->handle, LV2_TIME__beatUnit);
@@ -225,63 +223,140 @@ timely_init(timely_t *timely, LV2_URID_Map *map, double rate,
timely->urid.time_framesPerSecond = map->map(map->handle, LV2_TIME__framesPerSecond);
timely->urid.time_speed = map->map(map->handle, LV2_TIME__speed);
- timely->atom.bar.atom.size = sizeof(int64_t);
- timely->atom.bar.atom.type = map->map(map->handle, LV2_ATOM__Int);
+ timely->atom.i.atom.size = sizeof(int32_t);
+ timely->atom.i.atom.type = map->map(map->handle, LV2_ATOM__Int);
+
+ timely->atom.h.atom.size = sizeof(int64_t);
+ timely->atom.h.atom.type = map->map(map->handle, LV2_ATOM__Long);
- timely->atom.bar_beat.atom.size = sizeof(float);
- timely->atom.bar_beat.atom.type = map->map(map->handle, LV2_ATOM__Float);
+ timely->atom.f.atom.size = sizeof(float);
+ timely->atom.f.atom.type = map->map(map->handle, LV2_ATOM__Float);
+ timely->pos.speed = 0.f;
timely->pos.bar_beat = 0.f;
timely->pos.bar = 0;
timely->pos.beat_unit = 4;
timely->pos.beats_per_bar = 4.f;
- timely->pos.beats_per_minute = 120.0f;
+ timely->pos.beats_per_minute = 120.f;
timely->pos.frame = 0;
timely->pos.frames_per_second = rate;
- timely->pos.speed = 0.f;
- //TODO send updates for initial values?
-
+
_timely_refresh(timely);
+
+ timely->first = true;
}
static void
timely_advance(timely_t *timely, const LV2_Atom_Object *obj,
uint32_t from, uint32_t to)
{
- if(timely->pos.speed > 0.f)
+ if(timely->first)
{
- for(unsigned i=from; i<to; i++)
+ timely->first = false;
+
+ // send initial values
+ if(timely->cb)
{
- timely->offset.bar += 1;
- timely->offset.beat += 1;
+ if(timely->mask & TIMELY_MASK_SPEED)
+ {
+ timely->atom.f.body = timely->pos.speed;
+ timely->cb(timely, 0, timely->urid.time_speed, (const LV2_Atom *)&timely->atom.f, timely->data);
+ }
- if(timely->offset.bar >= timely->window.bar)
+ if(timely->mask & TIMELY_MASK_BEAT_UNIT)
{
- timely->pos.bar += 1;
- timely->offset.bar -= timely->window.bar;
+ timely->atom.i.body = timely->pos.beat_unit;
+ timely->cb(timely, 0, timely->urid.time_beatUnit, (const LV2_Atom *)&timely->atom.i, timely->data);
+ }
- timely->atom.bar.body = timely->pos.bar;
- if(timely->cb && (timely->mask & TIMELY_MASK_BAR) )
- timely->cb(i, timely->urid.time_bar, (const LV2_Atom *)&timely->atom.bar, timely->data);
+ if(timely->mask & TIMELY_MASK_BEATS_PER_BAR)
+ {
+ timely->atom.f.body = timely->pos.beats_per_bar;
+ timely->cb(timely, 0, timely->urid.time_beatsPerBar, (const LV2_Atom *)&timely->atom.f, timely->data);
+ }
+
+ if(timely->mask & TIMELY_MASK_BEATS_PER_MINUTE)
+ {
+ timely->atom.f.body = timely->pos.beats_per_minute;
+ timely->cb(timely, 0, timely->urid.time_beatsPerMinute, (const LV2_Atom *)&timely->atom.f, timely->data);
+ }
+
+ if(timely->mask & TIMELY_MASK_FRAME)
+ {
+ timely->atom.h.body = timely->pos.frame;
+ timely->cb(timely, 0, timely->urid.time_frame, (const LV2_Atom *)&timely->atom.h, timely->data);
+ }
+
+ if(timely->mask & TIMELY_MASK_FRAMES_PER_SECOND)
+ {
+ timely->atom.f.body = timely->pos.frames_per_second;
+ timely->cb(timely, 0, timely->urid.time_framesPerSecond, (const LV2_Atom *)&timely->atom.f, timely->data);
}
+
+ if(timely->mask & TIMELY_MASK_BAR_BEAT)
+ {
+ timely->atom.f.body = timely->pos.bar_beat;
+ timely->cb(timely, 0, timely->urid.time_barBeat, (const LV2_Atom *)&timely->atom.f, timely->data);
+ }
+
+ if(timely->mask & TIMELY_MASK_BAR)
+ {
+ timely->atom.h.body = timely->pos.bar;
+ timely->cb(timely, 0, timely->urid.time_bar, (const LV2_Atom *)&timely->atom.h, timely->data);
+ }
+ }
+ }
+
+ // are we rolling?
+ if(timely->pos.speed > 0.f)
+ {
+ if( (timely->offset.beat == 0) && (timely->pos.bar_beat == 0) )
+ {
+ timely->atom.f.body = timely->pos.bar_beat;
+ if(timely->cb && (timely->mask & TIMELY_MASK_BAR_BEAT) )
+ timely->cb(timely, from, timely->urid.time_barBeat, (const LV2_Atom *)&timely->atom.f, timely->data);
+ }
+
+ if( (timely->offset.bar == 0) && (timely->pos.bar == 0) )
+ {
+ timely->atom.h.body = timely->pos.bar;
+ if(timely->cb && (timely->mask & TIMELY_MASK_BAR) )
+ timely->cb(timely, from, timely->urid.time_bar, (const LV2_Atom *)&timely->atom.h, timely->data);
+ }
- if(timely->offset.beat >= timely->window.beat)
+ for(unsigned i=from; i<to; i++)
+ {
+ if( (timely->offset.beat >= timely->window.beat) )
{
- timely->pos.bar_beat += 1;
+ timely->pos.bar_beat = floor(timely->pos.bar_beat) + 1;
timely->offset.beat -= timely->window.beat;
if(timely->pos.bar_beat >= timely->pos.beats_per_bar)
timely->pos.bar_beat = 0;
- timely->atom.bar_beat.body = timely->pos.bar_beat;
+ timely->atom.f.body = timely->pos.bar_beat;
if(timely->cb && (timely->mask & TIMELY_MASK_BAR_BEAT) )
- timely->cb(i, timely->urid.time_barBeat, (const LV2_Atom *)&timely->atom.bar_beat, timely->data);
+ timely->cb(timely, i, timely->urid.time_barBeat, (const LV2_Atom *)&timely->atom.f, timely->data);
}
- timely->pos.frame += to - from;
+ if(timely->offset.bar >= timely->window.bar)
+ {
+ timely->pos.bar += 1;
+ timely->offset.bar -= timely->window.bar;
+
+ timely->atom.h.body = timely->pos.bar;
+ if(timely->cb && (timely->mask & TIMELY_MASK_BAR) )
+ timely->cb(timely, i, timely->urid.time_bar, (const LV2_Atom *)&timely->atom.h, timely->data);
+ }
+
+ timely->offset.bar += 1;
+ timely->offset.beat += 1;
}
+
+ timely->pos.frame += to - from;
}
+ // is this a time position event?
if( obj
&& (obj->atom.type == timely->urid.atom_object)
&& (obj->body.otype == timely->urid.time_position) )