Browse Source

Carla: Midi-Split (internal) plugin works now, other fixes

tags/v0.9.0
falkTX 13 years ago
parent
commit
778f81e6f4
8 changed files with 100 additions and 82 deletions
  1. +2
    -0
      c++/carla-backend/carla_engine.cpp
  2. +20
    -17
      c++/carla-backend/carla_native.cpp
  3. +49
    -49
      c++/carla-backend/lv2.cpp
  4. +2
    -1
      c++/carla-backend/plugins/carla_native.h
  5. +2
    -2
      c++/carla-backend/plugins/carla_nativemm.h
  6. +5
    -2
      c++/carla-backend/plugins/midi-split.cpp
  7. +17
    -11
      src/carla.py
  8. +3
    -0
      src/carla_backend.py

+ 2
- 0
c++/carla-backend/carla_engine.cpp View File

@@ -286,7 +286,9 @@ short CarlaEngine::addPlugin(const BinaryType btype, const PluginType ptype, con
case PLUGIN_NONE:
break;
case PLUGIN_INTERNAL:
#ifndef BUILD_BRIDGE
plugin = CarlaPlugin::newNative(init);
#endif
break;
case PLUGIN_LADSPA:
plugin = CarlaPlugin::newLADSPA(init, extra);


+ 20
- 17
c++/carla-backend/carla_native.cpp View File

@@ -91,7 +91,6 @@ public:

midiEventCount = 0;
memset(midiEvents, 0, sizeof(::MidiEvent) * MAX_MIDI_EVENTS * 2);
memset(midiEventOffsets, 0, sizeof(uint32_t) * MAX_MIDI_EVENTS * 2);
}

~NativePlugin()
@@ -540,13 +539,13 @@ public:
{
if (portHints & PORT_HINT_IS_OUTPUT)
{
j = aOut.count++;
j = mOut.count++;
mOut.ports[j] = (CarlaEngineMidiPort*)x_client->addPort(CarlaEnginePortTypeMIDI, portName, false);
mOut.rindexes[j] = i;
}
else
{
j = aIn.count++;
j = mIn.count++;
mIn.ports[j] = (CarlaEngineMidiPort*)x_client->addPort(CarlaEnginePortTypeMIDI, portName, true);
mIn.rindexes[j] = i;
}
@@ -684,6 +683,8 @@ public:

aIn.count = aIns;
aOut.count = aOuts;
mIn.count = mIns;
mOut.count = mOuts;
param.count = params;

// plugin checks
@@ -811,7 +812,6 @@ public:
// reset MIDI
midiEventCount = 0;
memset(midiEvents, 0, sizeof(::MidiEvent) * MAX_MIDI_EVENTS * 2);
memset(midiEventOffsets, 0, sizeof(uint32_t) * MAX_MIDI_EVENTS * 2);

CARLA_PROCESS_CONTINUE_CHECK;

@@ -984,7 +984,7 @@ public:
case CarlaEngineEventAllSoundOff:
if (cinEvent->channel == m_ctrlInChannel)
{
if (midi.portMin && ! allNotesOffSent)
if (mIn.count > 0 && ! allNotesOffSent)
sendMidiAllNotesOff();

if (descriptor->deactivate)
@@ -1006,7 +1006,7 @@ public:
case CarlaEngineEventAllNotesOff:
if (cinEvent->channel == m_ctrlInChannel)
{
if (midi.portMin && ! allNotesOffSent)
if (mIn.count > 0 && ! allNotesOffSent)
sendMidiAllNotesOff();

allNotesOffSent = true;
@@ -1055,13 +1055,17 @@ public:
// ----------------------------------------------------------------------------------------------------
// MIDI Input (System)

for (i=0; i < mIn.count; i++)
{
if (! mIn.ports[i])
continue;

const CarlaEngineMidiEvent* minEvent;
uint32_t time, nEvents = midi.portMin->getEventCount();
uint32_t time, nEvents = mIn.ports[i]->getEventCount();

for (i=0; i < nEvents && midiEventCount < MAX_MIDI_EVENTS; i++)
for (k=0; k < nEvents && midiEventCount < MAX_MIDI_EVENTS; k++)
{
minEvent = midi.portMin->getEvent(i);
minEvent = mIn.ports[i]->getEvent(k);

if (! minEvent)
continue;
@@ -1081,8 +1085,9 @@ public:
::MidiEvent* const midiEvent = &midiEvents[midiEventCount];
memset(midiEvent, 0, sizeof(::MidiEvent));

midiEvent->size = minEvent->size;
midiEvent->portOffset = i;
midiEvent->time = minEvent->time;
midiEvent->size = minEvent->size;

if (MIDI_IS_STATUS_NOTE_OFF(status))
{
@@ -1287,7 +1292,7 @@ public:
if (MIDI_IS_STATUS_NOTE_ON(data[0]) && data[2] == 0)
data[0] -= 0x10;

const uint32_t portOffset = midiEventOffsets[i];
const uint32_t portOffset = midiEvents[i].portOffset;

if (portOffset < mOut.count)
mOut.ports[portOffset]->writeEvent(midiEvents[i].time, data, 3);
@@ -1420,7 +1425,7 @@ public:
return nullptr;
}

bool handleWriteMidiEvent(uint32_t portOffset, MidiEvent* event)
bool handleWriteMidiEvent(MidiEvent* event)
{
Q_ASSERT(m_enabled);
Q_ASSERT(mOut.count > 0);
@@ -1435,7 +1440,7 @@ public:

if (! isProcessing)
{
qCritical("NativePlugin::handleWriteMidiEvent(%i, %p) - received MIDI out events outside audio thread, ignoring", portOffset, event);
qCritical("NativePlugin::handleWriteMidiEvent(%p) - received MIDI out events outside audio thread, ignoring", event);
return false;
}

@@ -1443,7 +1448,6 @@ public:
return false;

memcpy(&midiEvents[midiEventCount], event, sizeof(::MidiEvent));
midiEventOffsets[midiEventCount] = portOffset;
midiEventCount += 1;

return true;
@@ -1467,10 +1471,10 @@ public:
return ((NativePlugin*)handle)->handleGetTimeInfo();
}

static bool carla_host_write_midi_event(HostHandle handle, uint32_t port_offset, MidiEvent* event)
static bool carla_host_write_midi_event(HostHandle handle, MidiEvent* event)
{
Q_ASSERT(handle);
return ((NativePlugin*)handle)->handleWriteMidiEvent(port_offset, event);
return ((NativePlugin*)handle)->handleWriteMidiEvent(event);
}

// -------------------------------------------------------------------
@@ -1567,7 +1571,6 @@ private:

uint32_t midiEventCount;
::MidiEvent midiEvents[MAX_MIDI_EVENTS*2];
uint32_t midiEventOffsets[MAX_MIDI_EVENTS*2];

static std::vector<const PluginDescriptor*> pluginDescriptors;
};


+ 49
- 49
c++/carla-backend/lv2.cpp View File

@@ -2052,7 +2052,7 @@ public:
case CarlaEngineEventAllSoundOff:
if (cinEvent->channel == m_ctrlInChannel)
{
if (midi.portMin && ! allNotesOffSent)
if (evIn.count > 0 && ! allNotesOffSent)
sendMidiAllNotesOff();

if (descriptor->deactivate)
@@ -2074,7 +2074,7 @@ public:
case CarlaEngineEventAllNotesOff:
if (cinEvent->channel == m_ctrlInChannel)
{
if (midi.portMin && ! allNotesOffSent)
if (evIn.count > 0 && ! allNotesOffSent)
sendMidiAllNotesOff();

allNotesOffSent = true;
@@ -2107,7 +2107,7 @@ public:
midiEvent[1] = extMidiNotes[i].note;
midiEvent[2] = extMidiNotes[i].velo;

// send to all midi inputs
// send to first midi input
for (k=0; k < evIn.count; k++)
{
if (evIn.data[k].type & CARLA_EVENT_TYPE_MIDI)
@@ -2132,6 +2132,8 @@ public:
{
lv2midi_put_event(&evInMidiStates[k], 0, 3, midiEvent);
}

break;
}
}

@@ -2148,66 +2150,64 @@ public:
// ----------------------------------------------------------------------------------------------------
// MIDI Input (System)

for (i=0; i < evIn.count; i++)
{
for (i=0; i < evIn.count; i++)
{
if (! evIn.data[i].port)
continue;
if (! evIn.data[i].port)
continue;

const CarlaEngineMidiEvent* minEvent;
uint32_t time, nEvents = evIn.data[i].port->getEventCount();
const CarlaEngineMidiEvent* minEvent;
uint32_t time, nEvents = evIn.data[i].port->getEventCount();

for (k=0; k < nEvents && midiEventCount < MAX_MIDI_EVENTS; k++)
{
minEvent = evIn.data[i].port->getEvent(k);
for (k=0; k < nEvents && midiEventCount < MAX_MIDI_EVENTS; k++)
{
minEvent = evIn.data[i].port->getEvent(k);

if (! minEvent)
continue;
if (! minEvent)
continue;

time = minEvent->time - framesOffset;
time = minEvent->time - framesOffset;

if (time >= frames)
continue;
if (time >= frames)
continue;

uint8_t status = minEvent->data[0];
uint8_t channel = status & 0x0F;
uint8_t status = minEvent->data[0];
uint8_t channel = status & 0x0F;

// Fix bad note-off
if (MIDI_IS_STATUS_NOTE_ON(status) && minEvent->data[2] == 0)
status -= 0x10;
// Fix bad note-off
if (MIDI_IS_STATUS_NOTE_ON(status) && minEvent->data[2] == 0)
status -= 0x10;

// only 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))
// only 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))
{
if (evIn.data[i].type & CARLA_EVENT_DATA_ATOM)
{
if (evIn.data[i].type & CARLA_EVENT_DATA_ATOM)
{
LV2_Atom_Event* const aev = getLv2AtomEvent(evIn.data[i].atom, evInAtomOffsets[i]);
aev->time.frames = time;
aev->body.type = CARLA_URI_MAP_ID_MIDI_EVENT;
aev->body.size = minEvent->size;
memcpy(LV2_ATOM_BODY(&aev->body), minEvent->data, minEvent->size);

const uint32_t evInPadSize = lv2_atom_pad_size(sizeof(LV2_Atom_Event) + minEvent->size);
evInAtomOffsets[i] += evInPadSize;
evIn.data[i].atom->atom.size += evInPadSize;
}
else if (evIn.data[i].type & CARLA_EVENT_DATA_EVENT)
{
lv2_event_write(&evInEventIters[i], time, 0, CARLA_URI_MAP_ID_MIDI_EVENT, minEvent->size, minEvent->data);
}
else if (evIn.data[i].type & CARLA_EVENT_DATA_MIDI_LL)
{
lv2midi_put_event(&evInMidiStates[i], time, minEvent->size, minEvent->data);
}
LV2_Atom_Event* const aev = getLv2AtomEvent(evIn.data[i].atom, evInAtomOffsets[i]);
aev->time.frames = time;
aev->body.type = CARLA_URI_MAP_ID_MIDI_EVENT;
aev->body.size = minEvent->size;
memcpy(LV2_ATOM_BODY(&aev->body), minEvent->data, minEvent->size);

if (MIDI_IS_STATUS_NOTE_OFF(status))
postponeEvent(PluginPostEventNoteOff, channel, minEvent->data[1], 0.0);
else if (MIDI_IS_STATUS_NOTE_ON(status))
postponeEvent(PluginPostEventNoteOn, channel, minEvent->data[1], minEvent->data[2]);
const uint32_t evInPadSize = lv2_atom_pad_size(sizeof(LV2_Atom_Event) + minEvent->size);
evInAtomOffsets[i] += evInPadSize;
evIn.data[i].atom->atom.size += evInPadSize;
}
else if (evIn.data[i].type & CARLA_EVENT_DATA_EVENT)
{
lv2_event_write(&evInEventIters[i], time, 0, CARLA_URI_MAP_ID_MIDI_EVENT, minEvent->size, minEvent->data);
}
else if (evIn.data[i].type & CARLA_EVENT_DATA_MIDI_LL)
{
lv2midi_put_event(&evInMidiStates[i], time, minEvent->size, minEvent->data);
}

midiEventCount += 1;
if (MIDI_IS_STATUS_NOTE_OFF(status))
postponeEvent(PluginPostEventNoteOff, channel, minEvent->data[1], 0.0);
else if (MIDI_IS_STATUS_NOTE_ON(status))
postponeEvent(PluginPostEventNoteOn, channel, minEvent->data[1], minEvent->data[2]);
}

midiEventCount += 1;
}
} // End of MIDI Input (System)



+ 2
- 1
c++/carla-backend/plugins/carla_native.h View File

@@ -73,6 +73,7 @@ typedef struct _ParameterRanges {
} ParameterRanges;

typedef struct _MidiEvent {
uint32_t portOffset;
uint32_t time;
uint8_t size;
uint8_t data[4];
@@ -108,7 +109,7 @@ typedef struct _HostDescriptor {
uint32_t (*get_buffer_size)(HostHandle handle);
double (*get_sample_rate)(HostHandle handle);
const TimeInfo* (*get_time_info)(HostHandle handle);
bool (*write_midi_event)(HostHandle handle, uint32_t port_offset, MidiEvent* event);
bool (*write_midi_event)(HostHandle handle, MidiEvent* event);
} HostDescriptor;

typedef struct _PluginPortScalePoint {


+ 2
- 2
c++/carla-backend/plugins/carla_nativemm.h View File

@@ -97,12 +97,12 @@ public:
return nullptr;
}

void writeMidiEvent(uint32_t portOffset, MidiEvent* event)
void writeMidiEvent(MidiEvent* event)
{
Q_ASSERT(host);

if (host)
host->write_midi_event(host->handle, portOffset, event);
host->write_midi_event(host->handle, event);
}

// -------------------------------------------------------------------


+ 5
- 2
c++/carla-backend/plugins/midi-split.cpp View File

@@ -163,8 +163,11 @@ protected:
continue;

status -= channel;
midiEvent.data[0] = status;
//writeMidiEvent(channel, midiEvent);

midiEvent.portOffset = channel;
midiEvent.data[0] = status;

writeMidiEvent(&midiEvent);
}
}



+ 17
- 11
src/carla.py View File

@@ -648,7 +648,12 @@ class PluginDatabaseW(QDialog, ui_carla_database.Ui_PluginDatabaseW):
QDialog.__init__(self, parent)
self.setupUi(self)

self.warning_old_shown = False
self.m_showOldWarning = False

self.settings = self.parent().settings
self.settings_db = self.parent().settings_db
self.loadSettings()

self.b_add.setEnabled(False)

if BINARY_NATIVE in (BINARY_POSIX32, BINARY_WIN32):
@@ -656,10 +661,6 @@ class PluginDatabaseW(QDialog, ui_carla_database.Ui_PluginDatabaseW):
else:
self.ch_bridged.setText(self.tr("Bridged (32bit)"))

self.settings = self.parent().settings
self.settings_db = self.parent().settings_db
self.loadSettings()

if not (LINUX or MACOS):
self.ch_bridged_wine.setChecked(False)
self.ch_bridged_wine.setEnabled(False)
@@ -706,6 +707,9 @@ class PluginDatabaseW(QDialog, ui_carla_database.Ui_PluginDatabaseW):

self.ret_plugin = None

if self.m_showOldWarning:
QTimer.singleShot(0, self, SLOT("slot_showOldWarning()"))

def showFilters(self, yesno):
self.tb_filters.setArrowType(Qt.UpArrow if yesno else Qt.DownArrow)
self.frame.setVisible(yesno)
@@ -832,10 +836,8 @@ class PluginDatabaseW(QDialog, ui_carla_database.Ui_PluginDatabaseW):
def addPluginToTable(self, plugin, ptype):
index = self.last_table_index

if "build" not in plugin.keys():
if not self.warning_old_shown:
QMessageBox.warning(self, self.tr("Warning"), self.tr("You're using a Carla-Database from an old version of Carla, please update *all* the plugins"))
self.warning_old_shown = True
if self.m_showOldWarning or 'API' not in plugin.keys() or plugin['API'] < PLUGIN_QUERY_API_VERSION:
self.m_showOldWarning = True
return

if plugin['build'] == BINARY_NATIVE:
@@ -1005,6 +1007,10 @@ class PluginDatabaseW(QDialog, ui_carla_database.Ui_PluginDatabaseW):
text in self.tableWidget.item(i, 13).text().lower())):
self.tableWidget.hideRow(i)

@pyqtSlot()
def slot_showOldWarning(self):
QMessageBox.warning(self, self.tr("Warning"), self.tr("You're using a Carla-Database from an old version of Carla, please update *all* the plugins"))

def saveSettings(self):
self.settings.setValue("PluginDatabase/Geometry", self.saveGeometry())
self.settings.setValue("PluginDatabase/TableGeometry", self.tableWidget.horizontalHeader().saveState())
@@ -1790,8 +1796,8 @@ class CarlaMainW(QMainWindow, ui_carla.Ui_CarlaMainW):
plugin = None

if plugin:
btype = plugin['build']
ptype = plugin['type']
btype = plugin['build']
ptype = plugin['type']
filename = plugin['binary']
name = x_save_state_dict['Name']
label = plugin['label']


+ 3
- 0
src/carla_backend.py View File

@@ -502,7 +502,10 @@ def findDSSIGUI(filename, name, label):
# ------------------------------------------------------------------------------------------------
# Plugin Query

PLUGIN_QUERY_API_VERSION = 1

PyPluginInfo = {
'API': PLUGIN_QUERY_API_VERSION,
'build': 0, # BINARY_NONE
'type': 0, # PLUGIN_NONE,
'hints': 0x0,


Loading…
Cancel
Save