aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHanspeter Portner <dev@open-music-kontrollers.ch>2017-03-22 22:55:23 +0100
committerHanspeter Portner <dev@open-music-kontrollers.ch>2017-03-22 22:55:23 +0100
commitce87996f72f3a3eb294e2f8458434cb437235dad (patch)
tree03ac85809a3d279b5380dac8996a04b11695c5f8
parentd405ab264332903f908a5668bb95cf05cc43e8c7 (diff)
downloadvm.lv2-ce87996f72f3a3eb294e2f8458434cb437235dad.tar.xz
prototype vm:atom plugin.
-rw-r--r--VERSION2
-rw-r--r--manifest.ttl.in8
-rw-r--r--vm.c198
-rw-r--r--vm.ttl231
-rw-r--r--vm_ui.ttl5
5 files changed, 404 insertions, 40 deletions
diff --git a/VERSION b/VERSION
index 4cb3d35..9ff3725 100644
--- a/VERSION
+++ b/VERSION
@@ -1 +1 @@
-0.1.2879
+0.1.2881
diff --git a/manifest.ttl.in b/manifest.ttl.in
index 2c96c8f..fd51fa9 100644
--- a/manifest.ttl.in
+++ b/manifest.ttl.in
@@ -43,6 +43,14 @@ vm:audio
ui:ui vm:vm_ui ;
rdfs:seeAlso <vm.ttl> .
+vm:atom
+ a lv2:Plugin ;
+ lv2:minorVersion @VM_MINOR_VERSION@ ;
+ lv2:microVersion @VM_MICRO_VERSION@ ;
+ lv2:binary <vm@CMAKE_SHARED_MODULE_SUFFIX@> ;
+ ui:ui vm:vm_ui ;
+ rdfs:seeAlso <vm.ttl> .
+
vm:vm_ui
a ui:@VM_UI_TYPE@ ;
ui:binary <vm_ui@CMAKE_SHARED_MODULE_SUFFIX@> ;
diff --git a/vm.c b/vm.c
index bf54432..e2f0a11 100644
--- a/vm.c
+++ b/vm.c
@@ -28,11 +28,23 @@
#define REG_MAX 0x20
#define REG_MASK (REG_MAX - 1)
+typedef union _vm_port_t vm_port_t;
+typedef union _vm_const_port_t vm_const_port_t;
typedef struct _vm_stack_t vm_stack_t;
typedef struct _plughandle_t plughandle_t;
typedef double num_t;
+union _vm_port_t {
+ float *flt;
+ LV2_Atom_Sequence *seq;
+};
+
+union _vm_const_port_t {
+ const float *flt;
+ const LV2_Atom_Sequence *seq;
+};
+
struct _vm_stack_t {
num_t slots [SLOT_MAX];
num_t regs [REG_MAX];
@@ -51,8 +63,8 @@ struct _plughandle_t {
const LV2_Atom_Sequence *control;
LV2_Atom_Sequence *notify;
- const float *in [CTRL_MAX];
- float *out [CTRL_MAX];
+ vm_const_port_t in [CTRL_MAX];
+ vm_port_t out [CTRL_MAX];
num_t in0 [CTRL_MAX];
num_t out0 [CTRL_MAX];
@@ -244,7 +256,7 @@ connect_port(LV2_Handle instance, uint32_t port, void *data)
case 7:
case 8:
case 9:
- handle->in[port - 2] = data;
+ handle->in[port - 2].flt = data;
break;
case 10:
case 11:
@@ -254,7 +266,7 @@ connect_port(LV2_Handle instance, uint32_t port, void *data)
case 15:
case 16:
case 17:
- handle->out[port - 10] = data;
+ handle->out[port - 10].flt = data;
break;
}
}
@@ -871,25 +883,25 @@ run_control(LV2_Handle instance, uint32_t nsamples)
{
const float *in [CTRL_MAX ] = {
- handle->in[0],
- handle->in[1],
- handle->in[2],
- handle->in[3],
- handle->in[4],
- handle->in[5],
- handle->in[6],
- handle->in[7]
+ handle->in[0].flt,
+ handle->in[1].flt,
+ handle->in[2].flt,
+ handle->in[3].flt,
+ handle->in[4].flt,
+ handle->in[5].flt,
+ handle->in[6].flt,
+ handle->in[7].flt
};
float *out [CTRL_MAX ] = {
- handle->out[0],
- handle->out[1],
- handle->out[2],
- handle->out[3],
- handle->out[4],
- handle->out[5],
- handle->out[6],
- handle->out[7]
+ handle->out[0].flt,
+ handle->out[1].flt,
+ handle->out[2].flt,
+ handle->out[3].flt,
+ handle->out[4].flt,
+ handle->out[5].flt,
+ handle->out[6].flt,
+ handle->out[7].flt
};
const bool notify = true;
@@ -910,7 +922,7 @@ run_control(LV2_Handle instance, uint32_t nsamples)
}
static void
-run_cv(LV2_Handle instance, uint32_t nsamples)
+run_cv_audio(LV2_Handle instance, uint32_t nsamples)
{
plughandle_t *handle = instance;
@@ -938,28 +950,29 @@ run_cv(LV2_Handle instance, uint32_t nsamples)
handle->needs_sync = false;
}
+ //FIXME needs to be muxed with control
for(unsigned i = 0; i < nsamples; i++)
{
const float *in [CTRL_MAX ] = {
- &handle->in[0][i],
- &handle->in[1][i],
- &handle->in[2][i],
- &handle->in[3][i],
- &handle->in[4][i],
- &handle->in[5][i],
- &handle->in[6][i],
- &handle->in[7][i]
+ &handle->in[0].flt[i],
+ &handle->in[1].flt[i],
+ &handle->in[2].flt[i],
+ &handle->in[3].flt[i],
+ &handle->in[4].flt[i],
+ &handle->in[5].flt[i],
+ &handle->in[6].flt[i],
+ &handle->in[7].flt[i]
};
float *out [CTRL_MAX ] = {
- &handle->out[0][i],
- &handle->out[1][i],
- &handle->out[2][i],
- &handle->out[3][i],
- &handle->out[4][i],
- &handle->out[5][i],
- &handle->out[6][i],
- &handle->out[7][i]
+ &handle->out[0].flt[i],
+ &handle->out[1].flt[i],
+ &handle->out[2].flt[i],
+ &handle->out[3].flt[i],
+ &handle->out[4].flt[i],
+ &handle->out[5].flt[i],
+ &handle->out[6].flt[i],
+ &handle->out[7].flt[i]
};
const bool notify = (i == 0);
@@ -980,6 +993,100 @@ run_cv(LV2_Handle instance, uint32_t nsamples)
}
static void
+run_atom(LV2_Handle instance, uint32_t nsamples)
+{
+ plughandle_t *handle = instance;
+
+ const uint32_t capacity = handle->notify->atom.size;
+ LV2_Atom_Forge_Frame frame;
+ lv2_atom_forge_set_buffer(&handle->forge, (uint8_t *)handle->notify, capacity);
+ handle->ref = lv2_atom_forge_sequence_head(&handle->forge, &frame, 0);
+
+ int64_t last_t = 0;
+ LV2_ATOM_SEQUENCE_FOREACH(handle->control, ev)
+ {
+ const LV2_Atom *atom= &ev->body;
+ const LV2_Atom_Object *obj = (const LV2_Atom_Object *)&ev->body;
+
+ if(!timely_advance(&handle->timely, obj, last_t, ev->time.frames))
+ props_advance(&handle->props, &handle->forge, ev->time.frames, obj, &handle->ref);
+
+ last_t = ev->time.frames;
+ }
+ timely_advance(&handle->timely, NULL, last_t, nsamples);
+
+ if(handle->needs_sync)
+ {
+ props_set(&handle->props, &handle->forge, nsamples - 1, handle->vm_graph, &handle->ref);
+ handle->needs_sync = false;
+ }
+
+ float pin [CTRL_MAX];
+ float pout [CTRL_MAX];
+
+ for(unsigned i = 0; i < CTRL_MAX; i++)
+ {
+ pin[i] = handle->in0[i];
+ pout[i] = handle->out0[i];
+ }
+
+ const float *in [CTRL_MAX ] = {
+ &pin[0],
+ &pin[1],
+ &pin[2],
+ &pin[3],
+ &pin[4],
+ &pin[5],
+ &pin[6],
+ &pin[7]
+ };
+
+ float *out [CTRL_MAX ] = {
+ &pout[0],
+ &pout[1],
+ &pout[2],
+ &pout[3],
+ &pout[4],
+ &pout[5],
+ &pout[6],
+ &pout[7]
+ };
+
+ //FIXME needs to be muxed with control
+ for(unsigned i = 0; i < CTRL_MAX; i++)
+ {
+ LV2_ATOM_SEQUENCE_FOREACH(handle->in[i].seq, ev)
+ {
+ const LV2_Atom_Float *f32 = (const LV2_Atom_Float *)&ev->body;
+
+ //printf("got atom:Float: %u %f\n", i, f32->body);
+
+ if(f32->atom.type == handle->forge.Float)
+ {
+ pin[i] = f32->body;
+
+ const bool notify = true; //FIXME
+ run_internal(handle, nsamples - 1, notify, in, out); //FIXME use ev.time.frames
+
+ //FIXME send floats to output sequences
+ }
+ }
+ }
+
+ if(handle->ref)
+ handle->ref = lv2_atom_forge_frame_time(&handle->forge, nsamples - 1);
+ if(handle->ref)
+ handle->ref = lv2_atom_forge_long(&handle->forge, handle->off);
+
+ if(handle->ref)
+ lv2_atom_forge_pop(&handle->forge, &frame);
+ else
+ lv2_atom_sequence_clear(handle->notify);
+
+ handle->off += nsamples;
+}
+
+static void
cleanup(LV2_Handle instance)
{
plughandle_t *handle = instance;
@@ -1060,7 +1167,7 @@ static const LV2_Descriptor vm_cv = {
.instantiate = instantiate,
.connect_port = connect_port,
.activate = NULL,
- .run = run_cv,
+ .run = run_cv_audio,
.deactivate = NULL,
.cleanup = cleanup,
.extension_data = extension_data
@@ -1071,7 +1178,18 @@ static const LV2_Descriptor vm_audio = {
.instantiate = instantiate,
.connect_port = connect_port,
.activate = NULL,
- .run = run_cv,
+ .run = run_cv_audio,
+ .deactivate = NULL,
+ .cleanup = cleanup,
+ .extension_data = extension_data
+};
+
+static const LV2_Descriptor vm_atom = {
+ .URI = VM_PREFIX"atom",
+ .instantiate = instantiate,
+ .connect_port = connect_port,
+ .activate = NULL,
+ .run = run_atom,
.deactivate = NULL,
.cleanup = cleanup,
.extension_data = extension_data
@@ -1088,6 +1206,8 @@ lv2_descriptor(uint32_t index)
return &vm_cv;
case 2:
return &vm_audio;
+ case 3:
+ return &vm_atom;
default:
return NULL;
diff --git a/vm.ttl b/vm.ttl
index 1cf9169..ac2f0ed 100644
--- a/vm.ttl
+++ b/vm.ttl
@@ -757,10 +757,232 @@ vm:audio
]
] .
+# Plugin
+vm:atom
+ a lv2:Plugin,
+ lv2:ConverterPlugin ;
+ doap:name "VM Atom" ;
+ doap:license lic:Artistic-2.0 ;
+ lv2:project proj:vm ;
+ lv2:requiredFeature urid:map, work:schedule, state:loadDefaultState ;
+ lv2:optionalFeature lv2:isLive, lv2:hardRTCapable, log:log, state:threadSafeRestore ;
+ lv2:extensionData state:interface, work:interface ;
+
+ lv2:port [
+ a lv2:InputPort ,
+ atom:AtomPort ;
+ atom:bufferType atom:Sequence ;
+ atom:supports time:Position ,
+ patch:Message ;
+ lv2:index 0 ;
+ lv2:symbol "control" ;
+ lv2:name "Control" ;
+ lv2:designation lv2:control ;
+ rsz:minimumSize 8192 ;
+ ] , [
+ a lv2:OutputPort ,
+ atom:AtomPort ;
+ atom:bufferType atom:Sequence ;
+ atom:supports patch:Message ;
+ lv2:index 1 ;
+ lv2:symbol "notify" ;
+ lv2:name "Notify" ;
+ lv2:designation lv2:control ;
+ rsz:minimumSize 8192 ;
+ ] , [
+ a lv2:InputPort,
+ atom:AtomPort;
+ atom:bufferType atom:Sequence ;
+ atom:supports atom:Float ;
+ lv2:index 2 ;
+ lv2:symbol "event_in_0" ;
+ lv2:name "Event In 0" ;
+ lv2:minimum -1.0;
+ lv2:maximum 1.0;
+ lv2:default 0.0;
+ ] , [
+ a lv2:InputPort,
+ atom:AtomPort;
+ atom:bufferType atom:Sequence ;
+ atom:supports atom:Float ;
+ lv2:index 3 ;
+ lv2:symbol "event_in_1" ;
+ lv2:name "Event In 1" ;
+ lv2:minimum -1.0;
+ lv2:maximum 1.0;
+ lv2:default 0.0;
+ ] , [
+ a lv2:InputPort,
+ atom:AtomPort;
+ atom:bufferType atom:Sequence ;
+ atom:supports atom:Float ;
+ lv2:index 4 ;
+ lv2:symbol "event_in_2" ;
+ lv2:name "Event In 2" ;
+ lv2:minimum -1.0;
+ lv2:maximum 1.0;
+ lv2:default 0.0;
+ ] , [
+ a lv2:InputPort,
+ atom:AtomPort;
+ atom:bufferType atom:Sequence ;
+ atom:supports atom:Float ;
+ lv2:index 5 ;
+ lv2:symbol "event_in_3" ;
+ lv2:name "Event In 3" ;
+ lv2:minimum -1.0;
+ lv2:maximum 1.0;
+ lv2:default 0.0;
+ ] , [
+ a lv2:InputPort,
+ atom:AtomPort;
+ atom:bufferType atom:Sequence ;
+ atom:supports atom:Float ;
+ lv2:index 6 ;
+ lv2:symbol "event_in_4" ;
+ lv2:name "Event In 4" ;
+ lv2:minimum -1.0;
+ lv2:maximum 1.0;
+ lv2:default 0.0;
+ ] , [
+ a lv2:InputPort,
+ atom:AtomPort;
+ atom:bufferType atom:Sequence ;
+ atom:supports atom:Float ;
+ lv2:index 7 ;
+ lv2:symbol "event_in_5" ;
+ lv2:name "Event In 5" ;
+ lv2:minimum -1.0;
+ lv2:maximum 1.0;
+ lv2:default 0.0;
+ ] , [
+ a lv2:InputPort,
+ atom:AtomPort;
+ atom:bufferType atom:Sequence ;
+ atom:supports atom:Float ;
+ lv2:index 8 ;
+ lv2:symbol "event_in_6" ;
+ lv2:name "Event In 6" ;
+ lv2:minimum -1.0;
+ lv2:maximum 1.0;
+ lv2:default 0.0;
+ ] , [
+ a lv2:InputPort,
+ atom:AtomPort;
+ atom:bufferType atom:Sequence ;
+ atom:supports atom:Float ;
+ lv2:index 9 ;
+ lv2:symbol "event_in_7" ;
+ lv2:name "Event In 7" ;
+ lv2:minimum -1.0;
+ lv2:maximum 1.0;
+ lv2:default 0.0;
+ ] , [
+ a lv2:OutputPort,
+ atom:AtomPort;
+ atom:bufferType atom:Sequence ;
+ atom:supports atom:Float ;
+ lv2:index 10 ;
+ lv2:symbol "event_out_0" ;
+ lv2:name "Event Out 0" ;
+ lv2:minimum -1.0;
+ lv2:maximum 1.0;
+ ] , [
+ a lv2:OutputPort,
+ atom:AtomPort;
+ atom:bufferType atom:Sequence ;
+ atom:supports atom:Float ;
+ lv2:index 11 ;
+ lv2:symbol "event_out_1" ;
+ lv2:name "Event Out 1" ;
+ lv2:minimum -1.0;
+ lv2:maximum 1.0;
+ ] , [
+ a lv2:OutputPort,
+ atom:AtomPort;
+ atom:bufferType atom:Sequence ;
+ atom:supports atom:Float ;
+ lv2:index 12 ;
+ lv2:symbol "event_out_2" ;
+ lv2:name "Event Out 2" ;
+ lv2:minimum -1.0;
+ lv2:maximum 1.0;
+ ] , [
+ a lv2:OutputPort,
+ atom:AtomPort;
+ atom:bufferType atom:Sequence ;
+ atom:supports atom:Float ;
+ lv2:index 13 ;
+ lv2:symbol "event_out_3" ;
+ lv2:name "Event Out 3" ;
+ lv2:minimum -1.0;
+ lv2:maximum 1.0;
+ ] , [
+ a lv2:OutputPort,
+ atom:AtomPort;
+ atom:bufferType atom:Sequence ;
+ atom:supports atom:Float ;
+ lv2:index 14 ;
+ lv2:symbol "event_out_4" ;
+ lv2:name "Event Out 4" ;
+ lv2:minimum -1.0;
+ lv2:maximum 1.0;
+ ] , [
+ a lv2:OutputPort,
+ atom:AtomPort;
+ atom:bufferType atom:Sequence ;
+ atom:supports atom:Float ;
+ lv2:index 15 ;
+ lv2:symbol "event_out_5" ;
+ lv2:name "Event Out 5" ;
+ lv2:minimum -1.0;
+ lv2:maximum 1.0;
+ ] , [
+ a lv2:OutputPort,
+ atom:AtomPort;
+ atom:bufferType atom:Sequence ;
+ atom:supports atom:Float ;
+ lv2:index 16 ;
+ lv2:symbol "event_out_6" ;
+ lv2:name "Event Out 6" ;
+ lv2:minimum -1.0;
+ lv2:maximum 1.0;
+ ] , [
+ a lv2:OutputPort,
+ atom:AtomPort;
+ atom:bufferType atom:Sequence ;
+ atom:supports atom:Float ;
+ lv2:index 17 ;
+ lv2:symbol "event_out_7" ;
+ lv2:name "Event Out 7" ;
+ lv2:minimum -1.0;
+ lv2:maximum 1.0;
+ ] ;
+
+ #patch:writable
+ # vm:graph ;
+
+ state:state [
+ vm:graph [
+ a atom:Tuple ;
+ rdf:value (
+ 7 vm:opInput
+ 6 vm:opInput
+ 5 vm:opInput
+ 4 vm:opInput
+ 3 vm:opInput
+ 2 vm:opInput
+ 1 vm:opInput
+ 0 vm:opInput
+ )
+ ]
+ ] .
+
vm:add
a pset:Preset ;
lv2:appliesTo vm:control ,
vm:cv ,
+ vm:atom ,
vm:audio ;
rdfs:label "Add" ;
state:state [
@@ -778,6 +1000,7 @@ vm:sub
a pset:Preset ;
lv2:appliesTo vm:control ,
vm:cv ,
+ vm:atom ,
vm:audio ;
rdfs:label "Subtract" ;
state:state [
@@ -795,6 +1018,7 @@ vm:mul
a pset:Preset ;
lv2:appliesTo vm:control ,
vm:cv ,
+ vm:atom ,
vm:audio ;
rdfs:label "Multiply" ;
state:state [
@@ -812,6 +1036,7 @@ vm:div
a pset:Preset ;
lv2:appliesTo vm:control ,
vm:cv ,
+ vm:atom ,
vm:audio ;
rdfs:label "Divide" ;
state:state [
@@ -829,6 +1054,7 @@ vm:mod
a pset:Preset ;
lv2:appliesTo vm:control ,
vm:cv ,
+ vm:atom ,
vm:audio ;
rdfs:label "Modulo" ;
state:state [
@@ -846,6 +1072,7 @@ vm:pow
a pset:Preset ;
lv2:appliesTo vm:control ,
vm:cv ,
+ vm:atom ,
vm:audio ;
rdfs:label "Power" ;
state:state [
@@ -863,6 +1090,7 @@ vm:dBFS
a pset:Preset ;
lv2:appliesTo vm:control ,
vm:cv ,
+ vm:atom ,
vm:audio ;
rdfs:label "dBFS" ;
lv2:port [
@@ -887,6 +1115,7 @@ vm:rand
a pset:Preset ;
lv2:appliesTo vm:control ,
vm:cv ,
+ vm:atom ,
vm:audio ;
rdfs:label "Random" ;
state:state [
@@ -909,6 +1138,7 @@ vm:sampleAndHold
a pset:Preset ;
lv2:appliesTo vm:control ,
vm:cv ,
+ vm:atom ,
vm:audio ;
rdfs:label "Sample and hold" ;
state:state [
@@ -930,6 +1160,7 @@ vm:lfo
a pset:Preset ;
lv2:appliesTo vm:control ,
vm:cv ,
+ vm:atom ,
vm:audio ;
rdfs:label "LFO" ;
state:state [
diff --git a/vm_ui.ttl b/vm_ui.ttl
index 4338b8d..849d795 100644
--- a/vm_ui.ttl
+++ b/vm_ui.ttl
@@ -37,6 +37,11 @@ vm:vm_ui
lv2:symbol "notify" ;
ui:protocol atom:eventTransfer
] ;
+ ui:portNotification [
+ ui:plugin vm:atom ;
+ lv2:symbol "notify" ;
+ ui:protocol atom:eventTransfer
+ ] ;
lv2:requiredFeature ui:idleInterface, urid:map, urid:unmap ;
lv2:optionalFeature log:log ;
lv2:extensionData ui:idleInterface .