Browse Source

Carla old-lv2-midi API support (for zynadd)

tags/v0.9.0
falkTX 14 years ago
parent
commit
9e6cd1043e
12 changed files with 553 additions and 98 deletions
  1. +132
    -0
      src/carla-includes/lv2/lv2-midifunctions.h
  2. +177
    -0
      src/carla-includes/lv2/lv2-midiport.h
  3. +2
    -3
      src/carla/carla_backend.h
  4. +1
    -1
      src/carla/carla_bridge.cpp
  5. +0
    -7
      src/carla/carla_plugin.h
  6. +2
    -2
      src/carla/dssi.cpp
  7. +2
    -2
      src/carla/ladspa.cpp
  8. +211
    -53
      src/carla/lv2.cpp
  9. +20
    -20
      src/carla/lv2_rdf.h
  10. +2
    -5
      src/carla/sf2.cpp
  11. +2
    -2
      src/carla/vst.cpp
  12. +2
    -3
      src/carla_backend.py

+ 132
- 0
src/carla-includes/lv2/lv2-midifunctions.h View File

@@ -0,0 +1,132 @@
/****************************************************************************
lv2-midifunctions.h - support file for using MIDI in LV2 plugins
Copyright (C) 2006-2007 Lars Luthman <lars.luthman@gmail.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program 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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 01222-1307 USA

****************************************************************************/

/** @file
This file contains static helper functions for the LV2 MIDI datatype
extension.
*/

#ifndef LV2_MIDIFUNCTIONS
#define LV2_MIDIFUNCTIONS

#include <string.h>

#include "lv2-midiport.h"


/** This structure contains information about a MIDI port buffer, the
current period size, and the position in the MIDI data buffer that
we are currently reading from or writing to. It needs to be recreated
or at least reinitialised every process() call. */
typedef struct {

/** The MIDI port structure that we want to read or write. */
LV2_MIDI* midi;
/** The number of frames in this process cycle. */
uint32_t frame_count;
/** The current position in the data buffer. Should be initialised to 0. */
uint32_t position;

} LV2_MIDIState;


/** This function reads one event from the port associated with the @c state
parameter and writes its timestamp, size and a pointer to its data bytes
into the parameters @c timestamp, @c size and @c data, respectively.
It does not advance the read position in the MIDI data buffer, two
subsequent calls to lv2midi_get_event() will read the same event.
The function returns the timestamp for the read event, or the @c frame_count
member of @c state if there are no more events in the buffer. */
static double lv2midi_get_event(LV2_MIDIState* state,
double* timestamp,
uint32_t* size,
unsigned char** data) {
if (state->position >= state->midi->size) {
state->position = state->midi->size;
*timestamp = state->frame_count;
*size = 0;
*data = NULL;
return *timestamp;
}
*timestamp = *(double*)(state->midi->data + state->position);
*size = *(uint32_t*)(state->midi->data + state->position + sizeof(double));
*data = state->midi->data + state->position +
sizeof(double) + sizeof(uint32_t);
return *timestamp;
}


/** This function advances the read/write position in @c state to the next
event and returns its timestamp, or the @c frame_count member of @c state
is there are no more events. */
static double lv2midi_step(LV2_MIDIState* state) {

if (state->position + sizeof(double) + sizeof(uint32_t) >= state->midi->size) {
state->position = state->midi->size;
return state->frame_count;
}
state->position += sizeof(double);
uint32_t size = *(uint32_t*)(state->midi->data + state->position);
state->position += sizeof(uint32_t);
state->position += size;
if (state->position >= state->midi->size)
return state->frame_count;
return *(double*)(state->midi->data + state->position);
}


/** This function writes one MIDI event to the port buffer associated with
@c state. It returns 0 when the event was written successfully to the
buffer, and -1 when there was not enough room. The read/write position
is advanced automatically. */
static int lv2midi_put_event(LV2_MIDIState* state,
double timestamp,
uint32_t size,
const unsigned char* data) {

if (state->midi->capacity - state->midi->size <
sizeof(double) + sizeof(uint32_t) + size)
return -1;
*(double*)(state->midi->data + state->midi->size) = timestamp;
state->midi->size += sizeof(double);
*(uint32_t*)(state->midi->data + state->midi->size) = size;
state->midi->size += sizeof(uint32_t);
memcpy(state->midi->data + state->midi->size, data, size);
state->midi->size += size;
++state->midi->event_count;
return 0;
}


#endif


+ 177
- 0
src/carla-includes/lv2/lv2-midiport.h View File

@@ -0,0 +1,177 @@
/****************************************************************************
lv2-midiport.h - header file for using MIDI in LV2 plugins
Copyright (C) 2006 Lars Luthman <lars.luthman@gmail.com>
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program 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 Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 01222-1307 USA

****************************************************************************/

/** @file
This file contains the specification for an LV2 MIDI port extension.
*/

#ifndef LV2_MIDIPORT_H
#define LV2_MIDIPORT_H


/** This data structure is used to contain the MIDI events for one run()
cycle. The port buffer for an LV2 port of the type
<http://ll-plugins.nongnu.org/lv2/ext/MidiPort> should be a pointer
to an instance of this struct.

To store two Note On events on MIDI channel 0 in a buffer, with timestamps
12 and 35.5, you could use something like this code (assuming that
midi_data is a variable of type LV2_MIDI):
@code
uint32_t buffer_offset = 0;
*(double*)(midi_data->data + buffer_offset) = 12;
buffer_offset += sizeof(double);
*(uint32_t*)(midi_data->data + buffer_offset) = 3;
buffer_offset += sizeof(uint32_t);
midi_data->data[buffer_offset++] = 0x90;
midi_data->data[buffer_offset++] = 0x48;
midi_data->data[buffer_offset++] = 0x64;
++midi_data->event_count;
*(double*)(midi_data->data + buffer_offset) = 35.5;
buffer_offset += sizeof(double);
*(uint32_t*)(midi_data->data + buffer_offset) = 3;
buffer_offset += sizeof(uint32_t);
midi_data->data[buffer_offset++] = 0x90;
midi_data->data[buffer_offset++] = 0x55;
midi_data->data[buffer_offset++] = 0x64;
++midi_data->event_count;
midi_data->size = buffer_offset;
@endcode
This would be done by the host in the case of an input port, and by the
plugin in the case of an output port. Whoever is writing events to the
buffer must also take care not to exceed the capacity of the data buffer.
To read events from a buffer, you could do something like this:
@code
uint32_t buffer_offset = 0;
uint32_t i;
for (i = 0; i < midi_data->event_count; ++i) {
double timestamp = *(double*)(midi_data->data + buffer_offset);
buffer_offset += sizeof(double);
uint32_t size = *(uint32_t*)(midi_data->data + buffer_offset);
buffer_offset += sizeof(uint32_t);
do_something_with_event(timestamp, size,
midi_data->data + buffer_offset);
buffer_offset += size;
}
@endcode
If you think this looks like too much code to simply read and write MIDI
events, take a look at the helper functions in lv2-midifunctions.h. They
are not an official part of this extension, but they can be convenient.
*/
typedef struct {

/** The number of MIDI events in the data buffer.
INPUT PORTS: It's the host's responsibility to set this field to the
number of MIDI events contained in the data buffer before calling the
plugin's run() function. The plugin may not change this field.
OUTPUT PORTS: It's the plugin's responsibility to set this field to the
number of MIDI events it has stored in the data buffer before returning
from the run() function. Any initial value should be ignored by the
plugin.
*/
uint32_t event_count;
/** The size of the data buffer in bytes. It is set by the host and may not
be changed by the plugin. The host is allowed to change this between
run() calls.
*/
uint32_t capacity;
/** The size of the initial part of the data buffer that actually contains
data.
INPUT PORTS: It's the host's responsibility to set this field to the
number of bytes used by all MIDI events it has written to the buffer
(including timestamps and size fields) before calling the plugin's
run() function. The plugin may not change this field.
OUTPUT PORTS: It's the plugin's responsibility to set this field to
the number of bytes used by all MIDI events it has written to the
buffer (including timestamps and size fields) before returning from
the run() function. Any initial value should be ignored by the plugin.
*/
uint32_t size;
/** The data buffer that is used to store MIDI events. The events are packed
after each other, and the format of each event is as follows:
First there is a timestamp, which should have the type "double",
i.e. have the same bit size as a double and the same bit layout as a
double (whatever that is on the current platform). This timestamp gives
the offset from the beginning of the current cycle, in frames, that
the MIDI event occurs on. It must be strictly smaller than the 'nframes'
parameter to the current run() call. The MIDI events in the buffer must
be ordered by their timestamp, e.g. an event with a timestamp of 123.23
must be stored after an event with a timestamp of 65.0.
The second part of the event is a size field, which should have the type
"uint32_t" (as defined in the standard C header stddef.h). It should
contain the size of the MIDI data for this event, i.e. the number of
bytes used to store the actual MIDI event. The bytes used by the
timestamp and the size field should not be counted.
The third part of the event is the actual MIDI data. There are some
requirements that must be followed:
* Running status is not allowed. Every event must have its own status
byte.
* Note On events with velocity 0 are not allowed. These events are
equivalent to Note Off in standard MIDI streams, but in order to make
plugins and hosts easier to write, as well as more efficient, only
proper Note Off events are allowed as Note Off.
* "Realtime events" (status bytes 0xF8 to 0xFF) are allowed, but may not
occur inside other events like they are allowed to in hardware MIDI
streams.
* All events must be fully contained in a single data buffer, i.e. events
may not "wrap around" by storing the first few bytes in one buffer and
then wait for the next run() call to store the rest of the event. If
there isn't enough space in the current data buffer to store an event,
the event will either have to wait until next run() call, be ignored,
or compensated for in some more clever way.
* All events must be valid MIDI events. This means for example that
only the first byte in each event (the status byte) may have the eighth
bit set, that Note On and Note Off events are always 3 bytes long etc.
The MIDI writer (host or plugin) is responsible for writing valid MIDI
events to the buffer, and the MIDI reader (plugin or host) can assume
that all events are valid.
On a platform where double is 8 bytes the data buffer layout for a
3-byte event followed by a 4-byte event may look something like this:
_______________________________________________________________
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | ...
|TIMESTAMP 1 |SIZE 1 |DATA |TIMESTAMP 2 |SIZE 2 |DATA | ...
*/
unsigned char* data;

} LV2_MIDI;



#endif

+ 2
- 3
src/carla/carla_backend.h View File

@@ -43,9 +43,8 @@ const unsigned int PLUGIN_CAN_BALANCE = 0x40;
// parameter hints
const unsigned int PARAMETER_IS_ENABLED = 0x01;
const unsigned int PARAMETER_IS_AUTOMABLE = 0x02;
const unsigned int PARAMETER_HAS_STRICT_BOUNDS = 0x04;
const unsigned int PARAMETER_USES_SCALEPOINTS = 0x08;
const unsigned int PARAMETER_USES_SAMPLERATE = 0x10;
const unsigned int PARAMETER_USES_SCALEPOINTS = 0x04;
const unsigned int PARAMETER_USES_SAMPLERATE = 0x08;

enum BinaryType {
BINARY_NONE = 0,


+ 1
- 1
src/carla/carla_bridge.cpp View File

@@ -151,7 +151,7 @@ public:
m_name = get_unique_name(info->name);
m_filename = strdup(filename);

// TODO - get bridge binary here
// FIXME - verify if path exists, if not return false
m_thread->setOscData(binarytype2str(m_binary), label, plugintype2str(m_type));
m_thread->start();



+ 0
- 7
src/carla/carla_plugin.h View File

@@ -357,12 +357,6 @@ public:
return 0.0;
}

// FIXME - remove this?
// double get_default_parameter_value(uint32_t param_id)
// {
// return param.ranges[param_id].def;
// }

virtual void get_label(char* buf_str)
{
*buf_str = 0;
@@ -856,7 +850,6 @@ public:
{
post_events.lock.lock();

// FIXME?
memcpy(post_events_dst, post_events.data, sizeof(PluginPostEvent)*MAX_POST_EVENTS);

for (unsigned short i=0; i < MAX_POST_EVENTS; i++)


+ 2
- 2
src/carla/dssi.cpp View File

@@ -759,7 +759,7 @@ public:

if (param.port_cin)
{
jack_default_audio_sample_t* pin_buffer = (jack_default_audio_sample_t*)jack_port_get_buffer(param.port_cin, nframes);
void* pin_buffer = jack_port_get_buffer(param.port_cin, nframes);

jack_midi_event_t pin_event;
uint32_t n_pin_events = jack_midi_get_event_count(pin_buffer);
@@ -1125,7 +1125,7 @@ public:

if (param.port_cout)
{
jack_default_audio_sample_t* cout_buffer = (jack_default_audio_sample_t*)jack_port_get_buffer(param.port_cout, nframes);
void* cout_buffer = jack_port_get_buffer(param.port_cout, nframes);
jack_midi_clear_buffer(cout_buffer);

double value;


+ 2
- 2
src/carla/ladspa.cpp View File

@@ -643,7 +643,7 @@ public:

if (param.port_cin)
{
jack_default_audio_sample_t* pin_buffer = (jack_default_audio_sample_t*)jack_port_get_buffer(param.port_cin, nframes);
void* pin_buffer = jack_port_get_buffer(param.port_cin, nframes);

jack_midi_event_t pin_event;
uint32_t n_pin_events = jack_midi_get_event_count(pin_buffer);
@@ -848,7 +848,7 @@ public:

if (param.port_cout)
{
jack_default_audio_sample_t* cout_buffer = (jack_default_audio_sample_t*)jack_port_get_buffer(param.port_cout, nframes);
void* cout_buffer = jack_port_get_buffer(param.port_cout, nframes);
jack_midi_clear_buffer(cout_buffer);

double value;


+ 211
- 53
src/carla/lv2.cpp View File

@@ -30,30 +30,39 @@
#include "lv2/ui.h"
#include "lv2_rdf.h"

#include "lv2/lv2-midiport.h"
#include "lv2/lv2-midifunctions.h"

// static max values
const unsigned int MAX_EVENT_BUFFER = 0x7FFF; // 32767
const unsigned int MAX_EVENT_BUFFER = 8192; // 0x7FFF; // 32767

// extra plugin hints
const unsigned int PLUGIN_HAS_EXTENSION_STATE = 0x1000;
const unsigned int PLUGIN_HAS_EXTENSION_DYNPARAM = 0x2000;

// parameter hints
const unsigned int PARAMETER_HAS_STRICT_BOUNDS = 0x100;

// feature ids
const uint32_t lv2_feature_id_uri_map = 0;
const uint32_t lv2_feature_id_urid_map = 1;
const uint32_t lv2_feature_id_urid_unmap = 2;
const uint32_t lv2_feature_id_event = 3;
//const uint32_t lv2_feature_id_rtmempool = 4;
const uint32_t lv2_feature_id_rtmempool = 4;
//const uint32_t lv2_feature_id_data_access = 5;
//const uint32_t lv2_feature_id_instance_access = 6;
//const uint32_t lv2_feature_id_ui_resize = 7;
//const uint32_t lv2_feature_id_ui_parent = 8;
//const uint32_t lv2_feature_id_external_ui = 9;
//const uint32_t lv2_feature_id_external_ui_old = 10;
const uint32_t lv2_feature_count = 4;
const uint32_t lv2_feature_count = 5;

// event types
const unsigned int CARLA_EVENT_TYPE_MIDI = 0x1;
const unsigned int CARLA_EVENT_TYPE_TIME = 0x2;
// event data/types
const unsigned int CARLA_EVENT_DATA_ATOM = 0x01;
const unsigned int CARLA_EVENT_DATA_EVENT = 0x02;
const unsigned int CARLA_EVENT_DATA_MIDI_LL = 0x04;
const unsigned int CARLA_EVENT_TYPE_MIDI = 0x10;
const unsigned int CARLA_EVENT_TYPE_TIME = 0x20;

// pre-set uri[d] map ids
const uint32_t CARLA_URI_MAP_ID_NULL = 0;
@@ -70,7 +79,10 @@ enum Lv2ParameterDataType {
struct EventData {
unsigned int types;
jack_port_t* port;
LV2_Event_Buffer* buffer;
union {
LV2_Event_Buffer* e;
LV2_MIDI* m;
} buffer;
};

struct PluginEventData {
@@ -428,7 +440,7 @@ public:
CarlaPlugin::set_custom_data(dtype, key, value, gui_send);
}

virtual void set_gui_data(int, void* ptr)
virtual void set_gui_data(int, void* /*ptr*/)
{
// switch(gui.type)
// {
@@ -468,7 +480,7 @@ public:
// }
}

virtual void show_gui(bool yesno)
virtual void show_gui(bool /*yesno*/)
{
// switch(gui.type)
// {
@@ -597,6 +609,7 @@ public:
ains = aouts = cv_ins = cv_outs = ev_ins = ev_outs = params = 0;

const uint32_t PortCount = rdf_descriptor->PortCount;
unsigned int event_data_type = 0;

for (uint32_t i=0; i<PortCount; i++)
{
@@ -621,6 +634,15 @@ public:
ev_ins += 1;
else if (LV2_IS_PORT_OUTPUT(PortType))
ev_outs += 1;
event_data_type = CARLA_EVENT_DATA_EVENT;
}
else if (LV2_IS_PORT_MIDI_LL(PortType))
{
if (LV2_IS_PORT_INPUT(PortType))
ev_ins += 1;
else if (LV2_IS_PORT_OUTPUT(PortType))
ev_outs += 1;
event_data_type = CARLA_EVENT_DATA_MIDI_LL;
}
else if (LV2_IS_PORT_CONTROL(PortType))
params += 1;
@@ -651,9 +673,27 @@ public:

for (j=0; j < ev_ins; j++)
{
evin.data[j].types = 0;
evin.data[j].port = nullptr;
evin.data[j].buffer = lv2_event_buffer_new(MAX_EVENT_BUFFER, LV2_EVENT_AUDIO_STAMP);
evin.data[j].port = nullptr;

if (event_data_type == CARLA_EVENT_DATA_ATOM)
{
evin.data[j].types = CARLA_EVENT_DATA_ATOM;
// TODO
}
else if (event_data_type == CARLA_EVENT_DATA_EVENT)
{
evin.data[j].types = CARLA_EVENT_DATA_EVENT;
evin.data[j].buffer.e = lv2_event_buffer_new(MAX_EVENT_BUFFER, LV2_EVENT_AUDIO_STAMP);
}
else if (event_data_type == CARLA_EVENT_DATA_MIDI_LL)
{
evin.data[j].types = CARLA_EVENT_DATA_MIDI_LL;
evin.data[j].buffer.m = new LV2_MIDI;
evin.data[j].buffer.m->capacity = MAX_EVENT_BUFFER;
evin.data[j].buffer.m->data = new unsigned char [MAX_EVENT_BUFFER];
}
else
evin.data[j].types = 0;
}
}

@@ -663,9 +703,27 @@ public:

for (j=0; j < ev_outs; j++)
{
evout.data[j].types = 0;
evout.data[j].port = nullptr;
evout.data[j].buffer = lv2_event_buffer_new(MAX_EVENT_BUFFER, LV2_EVENT_AUDIO_STAMP);
evout.data[j].port = nullptr;

if (event_data_type == CARLA_EVENT_DATA_ATOM)
{
evout.data[j].types = CARLA_EVENT_DATA_ATOM;
// TODO
}
else if (event_data_type == CARLA_EVENT_DATA_EVENT)
{
evout.data[j].types = CARLA_EVENT_DATA_EVENT;
evout.data[j].buffer.e = lv2_event_buffer_new(MAX_EVENT_BUFFER, LV2_EVENT_AUDIO_STAMP);
}
else if (event_data_type == CARLA_EVENT_DATA_MIDI_LL)
{
evout.data[j].types = CARLA_EVENT_DATA_MIDI_LL;
evout.data[j].buffer.m = new LV2_MIDI;
evout.data[j].buffer.m->capacity = MAX_EVENT_BUFFER;
evout.data[j].buffer.m->data = new unsigned char [MAX_EVENT_BUFFER];
}
else
evout.data[j].types = 0;
}
}

@@ -685,7 +743,7 @@ public:
{
const LV2_Property PortType = rdf_descriptor->Ports[i].Type;

if (LV2_IS_PORT_AUDIO(PortType) || LV2_IS_PORT_CV(PortType) || LV2_IS_PORT_EVENT(PortType))
if (LV2_IS_PORT_AUDIO(PortType) || LV2_IS_PORT_CV(PortType) || LV2_IS_PORT_EVENT(PortType) || LV2_IS_PORT_MIDI_LL(PortType))
{
#ifndef BUILD_BRIDGE
if (carla_options.global_jack_client)
@@ -737,7 +795,7 @@ public:
if (LV2_IS_PORT_INPUT(PortType))
{
j = evin.count++;
descriptor->connect_port(handle, i, evin.data[j].buffer);
descriptor->connect_port(handle, i, evin.data[j].buffer.e);

if (LV2_IS_PORT_EVENT_MIDI(PortType))
{
@@ -747,13 +805,12 @@ public:
if (LV2_IS_PORT_EVENT_TIME(PortType))
{
evin.data[j].types |= CARLA_EVENT_TYPE_TIME;
//wants_time_pos = true;
}
}
else if (LV2_IS_PORT_OUTPUT(PortType))
{
j = evout.count++;
descriptor->connect_port(handle, i, evout.data[j].buffer);
descriptor->connect_port(handle, i, evout.data[j].buffer.e);

if (LV2_IS_PORT_EVENT_MIDI(PortType))
{
@@ -768,6 +825,27 @@ public:
else
qWarning("WARNING - Got a broken Port (Event, but not input or output)");
}
else if (LV2_IS_PORT_MIDI_LL(PortType))
{
if (LV2_IS_PORT_INPUT(PortType))
{
j = evin.count++;
descriptor->connect_port(handle, i, evin.data[j].buffer.m);

evin.data[j].types |= CARLA_EVENT_TYPE_MIDI;
evin.data[j].port = jack_port_register(jack_client, port_name, JACK_DEFAULT_MIDI_TYPE, JackPortIsInput, 0);
}
else if (LV2_IS_PORT_OUTPUT(PortType))
{
j = evout.count++;
descriptor->connect_port(handle, i, evout.data[j].buffer.m);

evout.data[j].types |= CARLA_EVENT_TYPE_MIDI;
evout.data[j].port = jack_port_register(jack_client, port_name, JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput, 0);
}
else
qWarning("WARNING - Got a broken Port (Midi, but not input or output)");
}
else if (LV2_IS_PORT_CONTROL(PortType))
{
const LV2_Property PortProps = rdf_descriptor->Ports[i].Properties;
@@ -997,11 +1075,13 @@ public:

jack_default_audio_sample_t* ains_buffer[ain.count];
jack_default_audio_sample_t* aouts_buffer[aout.count];

LV2_Event_Iterator evin_iters[evin.count];
void* evins_buffer[evin.count];
void* evouts_buffer[evout.count];

// different midi APIs
LV2_MIDIState evin_states[evin.count];
LV2_Event_Iterator evin_iters[evin.count];

for (i=0; i < ain.count; i++)
ains_buffer[i] = (jack_default_audio_sample_t*)jack_port_get_buffer(ain.ports[i], nframes);

@@ -1010,21 +1090,46 @@ public:

for (i=0; i < evin.count; i++)
{
lv2_event_buffer_reset(evin.data[i].buffer, LV2_EVENT_AUDIO_STAMP, (uint8_t*)(evin.data[i].buffer + 1));
lv2_event_begin(&evin_iters[i], evin.data[i].buffer);
if (evin.data[i].types & CARLA_EVENT_DATA_ATOM)
{
}
else if (evin.data[i].types & CARLA_EVENT_DATA_EVENT)
{
lv2_event_buffer_reset(evin.data[i].buffer.e, LV2_EVENT_AUDIO_STAMP, (uint8_t*)(evin.data[i].buffer.e + 1));
lv2_event_begin(&evin_iters[i], evin.data[i].buffer.e);
}
else if (evin.data[i].types & CARLA_EVENT_DATA_MIDI_LL)
{
evin_states[i].midi = evin.data[i].buffer.m;
evin_states[i].frame_count = nframes;
evin_states[i].position = 0;

evin_states[i].midi->event_count = 0;
evin_states[i].midi->size = 0;
}

if (evin.data[i].port)
evins_buffer[i] = (jack_default_audio_sample_t*)jack_port_get_buffer(evin.data[i].port, nframes);
evins_buffer[i] = jack_port_get_buffer(evin.data[i].port, nframes);
else
evins_buffer[i] = nullptr;
}

for (i=0; i < evout.count; i++)
{
lv2_event_buffer_reset(evout.data[i].buffer, LV2_EVENT_AUDIO_STAMP, (uint8_t*)(evout.data[i].buffer + 1));
if (evin.data[i].types & CARLA_EVENT_DATA_ATOM)
{
}
else if (evin.data[i].types & CARLA_EVENT_DATA_EVENT)
{
lv2_event_buffer_reset(evout.data[i].buffer.e, LV2_EVENT_AUDIO_STAMP, (uint8_t*)(evout.data[i].buffer.e + 1));
}
else if (evin.data[i].types & CARLA_EVENT_DATA_MIDI_LL)
{
// not needed
}

if (evout.data[i].port)
evouts_buffer[i] = (jack_default_audio_sample_t*)jack_port_get_buffer(evout.data[i].port, nframes);
evouts_buffer[i] = jack_port_get_buffer(evout.data[i].port, nframes);
else
evouts_buffer[i] = nullptr;
}
@@ -1052,7 +1157,7 @@ public:

if (param.port_cin)
{
jack_default_audio_sample_t* pin_buffer = (jack_default_audio_sample_t*)jack_port_get_buffer(param.port_cin, nframes);
void* pin_buffer = jack_port_get_buffer(param.port_cin, nframes);

jack_midi_event_t pin_event;
uint32_t n_pin_events = jack_midi_get_event_count(pin_buffer);
@@ -1195,19 +1300,22 @@ public:
{
if (ext_midi_notes[i].valid)
{
uint8_t midi_event[4] = { 0 };
midi_event[0] = ext_midi_notes[i].onoff ? MIDI_STATUS_NOTE_ON : MIDI_STATUS_NOTE_OFF;
midi_event[1] = ext_midi_notes[i].note;
midi_event[2] = ext_midi_notes[i].velo;

// send to all midi inputs
for (k=0; k < evin.count; k++)
{
if (evins_buffer[k] == nullptr || (evin.data[k].types & CARLA_EVENT_TYPE_MIDI) == 0)
continue;

uint8_t* midi_event = lv2_event_reserve(&evin_iters[k], 0, 0, CARLA_URI_MAP_ID_EVENT_MIDI, 3);

if (midi_event)
if (evin.data[k].types & CARLA_EVENT_TYPE_MIDI)
{
midi_event[0] = ext_midi_notes[i].onoff ? MIDI_STATUS_NOTE_ON : MIDI_STATUS_NOTE_OFF;
midi_event[1] = ext_midi_notes[i].note;
midi_event[2] = ext_midi_notes[i].velo;
if (evin.data[k].types & CARLA_EVENT_DATA_ATOM)
continue; // TODO
else if (evin.data[k].types & CARLA_EVENT_DATA_EVENT)
lv2_event_write(&evin_iters[k], 0, 0, CARLA_URI_MAP_ID_EVENT_MIDI, 3, midi_event);
else if (evin.data[k].types & CARLA_EVENT_DATA_MIDI_LL)
lv2midi_put_event(&evin_states[k], 0, 3, midi_event);
}
}

@@ -1229,7 +1337,7 @@ public:

for (i=0; i < evin.count; i++)
{
if (evins_buffer[i] == nullptr || (evin.data[i].types & CARLA_EVENT_TYPE_MIDI) == 0)
if (evins_buffer[i] == nullptr)
continue;

jack_midi_event_t min_event;
@@ -1252,7 +1360,12 @@ public:
// write supported status types
if (MIDI_IS_STATUS_NOTE_OFF(status) || MIDI_IS_STATUS_NOTE_ON(status) || MIDI_IS_STATUS_POLYPHONIC_AFTERTOUCH(status) || MIDI_IS_STATUS_AFTERTOUCH(status) || MIDI_IS_STATUS_PITCH_WHEEL_CONTROL(status))
{
lv2_event_write(&evin_iters[i], min_event.time, 0, CARLA_URI_MAP_ID_EVENT_MIDI, min_event.size, min_event.buffer);
if (evin.data[i].types & CARLA_EVENT_DATA_ATOM)
continue; // TODO
else if (evin.data[i].types & CARLA_EVENT_DATA_EVENT)
lv2_event_write(&evin_iters[i], min_event.time, 0, CARLA_URI_MAP_ID_EVENT_MIDI, min_event.size, min_event.buffer);
else if (evin.data[i].types & CARLA_EVENT_DATA_MIDI_LL)
lv2midi_put_event(&evin_states[i], min_event.time, min_event.size, min_event.buffer);

if (MIDI_IS_STATUS_NOTE_OFF(status))
postpone_event(PostEventNoteOff, min_event.buffer[1], 0.0);
@@ -1377,7 +1490,7 @@ public:

if (param.port_cout)
{
jack_default_audio_sample_t* cout_buffer = (jack_default_audio_sample_t*)jack_port_get_buffer(param.port_cout, nframes);
void* cout_buffer = jack_port_get_buffer(param.port_cout, nframes);
jack_midi_clear_buffer(cout_buffer);

double value, rvalue;
@@ -1413,24 +1526,44 @@ public:

for (i=0; i < evout.count; i++)
{
if (evouts_buffer[i] == nullptr || (evout.data[i].types & CARLA_EVENT_TYPE_MIDI) == 0)
if (evouts_buffer[i] == nullptr)
continue;

jack_midi_clear_buffer(evouts_buffer[i]);

LV2_Event* ev;
uint8_t* data;
if (evin.data[i].types & CARLA_EVENT_DATA_ATOM)
{
}
else if (evin.data[i].types & CARLA_EVENT_DATA_EVENT)
{
LV2_Event* ev;
LV2_Event_Iterator iter;

LV2_Event_Iterator iter;
lv2_event_begin(&iter, evout.data[i].buffer);
uint8_t* data;
lv2_event_begin(&iter, evout.data[i].buffer.e);

for (k=0; k < iter.buf->event_count; k++)
{
ev = lv2_event_get(&iter, &data);
if (ev && data)
jack_midi_event_write(evouts_buffer[i], ev->frames, data, ev->size);

for (k=0; k < iter.buf->event_count; k++)
lv2_event_increment(&iter);
}
}
else if (evin.data[i].types & CARLA_EVENT_DATA_MIDI_LL)
{
ev = lv2_event_get(&iter, &data);
if (ev && data)
jack_midi_event_write(evouts_buffer[i], ev->frames, data, ev->size);
LV2_MIDIState state = { evout.data[i].buffer.m, nframes, 0 };

uint32_t event_size;
double event_timestamp;
unsigned char* event_data;

lv2_event_increment(&iter);
while (lv2midi_get_event(&state, &event_timestamp, &event_size, &event_data) < nframes)
{
jack_midi_event_write(evouts_buffer[i], event_timestamp, event_data, event_size);
lv2midi_step(&state);
}
}
} // End of MIDI Output

@@ -1463,7 +1596,20 @@ public:
if (evin.count > 0)
{
for (uint32_t i=0; i < evin.count; i++)
free(evin.data[i].buffer);
{
if (evin.data[i].types & CARLA_EVENT_DATA_ATOM)
{
}
else if (evin.data[i].types & CARLA_EVENT_DATA_EVENT)
{
free(evin.data[i].buffer.e);
}
else if (evin.data[i].types & CARLA_EVENT_DATA_MIDI_LL)
{
delete[] evin.data[i].buffer.m->data;
delete evin.data[i].buffer.m;
}
}

delete[] evin.data;
}
@@ -1471,7 +1617,20 @@ public:
if (evout.count > 0)
{
for (uint32_t i=0; i < evout.count; i++)
free(evout.data[i].buffer);
{
if (evout.data[i].types & CARLA_EVENT_DATA_ATOM)
{
}
else if (evout.data[i].types & CARLA_EVENT_DATA_EVENT)
{
free(evout.data[i].buffer.e);
}
else if (evout.data[i].types & CARLA_EVENT_DATA_MIDI_LL)
{
delete[] evout.data[i].buffer.m->data;
delete evout.data[i].buffer.m;
}
}

delete[] evout.data;
}
@@ -1550,7 +1709,6 @@ public:
uint32_t i = 0;
while ((descriptor = descfn(i++)))
{
qDebug("%s | %s", descriptor->URI, URI);
if (strcmp(descriptor->URI, URI) == 0)
break;
}
@@ -1563,7 +1721,7 @@ public:
for (i=0; i < rdf_descriptor->PortCount; i++)
{
LV2_Property PortType = rdf_descriptor->Ports[i].Type;
if (bool(LV2_IS_PORT_AUDIO(PortType) || LV2_IS_PORT_CONTROL(PortType) || LV2_IS_PORT_EVENT(PortType)) == false)
if (bool(LV2_IS_PORT_AUDIO(PortType) || LV2_IS_PORT_CONTROL(PortType) || LV2_IS_PORT_EVENT(PortType) || LV2_IS_PORT_MIDI_LL(PortType)) == false)
{
if (! LV2_IS_PORT_OPTIONAL(rdf_descriptor->Ports[i].Properties))
{


+ 20
- 20
src/carla/lv2_rdf.h View File

@@ -766,26 +766,26 @@ inline bool is_lv2_feature_supported(const char* uri)
return false;
}

inline bool is_lv2_ui_feature_supported(const char */*uri*/)
inline bool is_lv2_ui_feature_supported(const char* uri)
{
// if (strcmp(uri, "http://lv2plug.in/ns/lv2core#hardRTCapable") == 0)
// return true;
// else if (strcmp(uri, "http://lv2plug.in/ns/lv2core#inPlaceBroken") == 0)
// return true;
// else if (strcmp(uri, "http://lv2plug.in/ns/lv2core#isLive") == 0)
// return true;
// else if (strcmp(uri, "http://lv2plug.in/ns/ext/event") == 0)
// return true;
// else if (strcmp(uri, "http://lv2plug.in/ns/ext/state#makePath") == 0)
// return false; // TODO
// else if (strcmp(uri, "http://lv2plug.in/ns/ext/state#mapPath") == 0)
// return false; // TODO
// else if (strcmp(uri, "http://lv2plug.in/ns/ext/uri-map") == 0)
// return true;
// else if (strcmp(uri, "http://lv2plug.in/ns/ext/urid#map") == 0)
// return true;
// else if (strcmp(uri, "http://lv2plug.in/ns/ext/urid#unmap") == 0)
// return true;
if (strcmp(uri, "http://lv2plug.in/ns/lv2core#hardRTCapable") == 0)
return true;
else if (strcmp(uri, "http://lv2plug.in/ns/lv2core#inPlaceBroken") == 0)
return true;
else if (strcmp(uri, "http://lv2plug.in/ns/lv2core#isLive") == 0)
return true;
else if (strcmp(uri, "http://lv2plug.in/ns/ext/event") == 0)
return true;
else if (strcmp(uri, "http://lv2plug.in/ns/ext/state#makePath") == 0)
return false; // TODO
else if (strcmp(uri, "http://lv2plug.in/ns/ext/state#mapPath") == 0)
return false; // TODO
else if (strcmp(uri, "http://lv2plug.in/ns/ext/uri-map") == 0)
return true;
else if (strcmp(uri, "http://lv2plug.in/ns/ext/urid#map") == 0)
return true;
else if (strcmp(uri, "http://lv2plug.in/ns/ext/urid#unmap") == 0)
return true;
// else if (strcmp(uri, "http://lv2plug.in/ns/ext/data-access") == 0)
// return true;
// else if (strcmp(uri, "http://lv2plug.in/ns/ext/instance-access") == 0)
@@ -806,7 +806,7 @@ inline bool is_lv2_ui_feature_supported(const char */*uri*/)
// return true;
// else if (strcmp(uri, "http://nedko.arnaudov.name/lv2/external_ui/") == 0)
// return true;
// else
else
return false;
}



+ 2
- 5
src/carla/sf2.cpp View File

@@ -366,9 +366,6 @@ public:

param.port_cout = jack_port_register(jack_client, port_name, JACK_DEFAULT_MIDI_TYPE, JackPortIsOutput, 0);

// TODO - auto-assign midi ccs
// TODO - verify min/max values

// ----------------------
j = Sf2ReverbOnOff;
param.data[j].index = j;
@@ -714,7 +711,7 @@ public:
// Parameters Input [Automation]

{
jack_default_audio_sample_t* pin_buffer = (jack_default_audio_sample_t*)jack_port_get_buffer(param.port_cin, nframes);
void* pin_buffer = jack_port_get_buffer(param.port_cin, nframes);

jack_midi_event_t pin_event;
uint32_t n_pin_events = jack_midi_get_event_count(pin_buffer);
@@ -1047,7 +1044,7 @@ public:
// Control Output

{
jack_default_audio_sample_t* cout_buffer = (jack_default_audio_sample_t*)jack_port_get_buffer(param.port_cout, nframes);
void* cout_buffer = jack_port_get_buffer(param.port_cout, nframes);
jack_midi_clear_buffer(cout_buffer);

k = Sf2VoiceCount;


+ 2
- 2
src/carla/vst.cpp View File

@@ -637,7 +637,7 @@ public:

if (param.port_cin)
{
jack_default_audio_sample_t* pin_buffer = (jack_default_audio_sample_t*)jack_port_get_buffer(param.port_cin, nframes);
void* pin_buffer = jack_port_get_buffer(param.port_cin, nframes);

jack_midi_event_t pin_event;
uint32_t n_pin_events = jack_midi_get_event_count(pin_buffer);
@@ -1208,7 +1208,7 @@ public:
{
VstEvents* events = (VstEvents*)ptr;

jack_default_audio_sample_t* mout_buffer = (jack_default_audio_sample_t*)jack_port_get_buffer(plugin->mout.ports[0], get_buffer_size());
void* mout_buffer = jack_port_get_buffer(plugin->mout.ports[0], get_buffer_size());
jack_midi_clear_buffer(mout_buffer);

for (int32_t i=0; i < events->numEvents; i++)


+ 2
- 3
src/carla_backend.py View File

@@ -624,9 +624,8 @@ PLUGIN_CAN_BALANCE = 0x40
# parameter hints
PARAMETER_IS_ENABLED = 0x01
PARAMETER_IS_AUTOMABLE = 0x02
PARAMETER_HAS_STRICT_BOUNDS = 0x04
PARAMETER_USES_SCALEPOINTS = 0x08
PARAMETER_USES_SAMPLERATE = 0x10
PARAMETER_USES_SCALEPOINTS = 0x04
PARAMETER_USES_SAMPLERATE = 0x08

# enum BinaryType
BINARY_NONE = 0


Loading…
Cancel
Save