| @@ -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); | |||
| @@ -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; | |||
| }; | |||
| @@ -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) | |||
| @@ -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 { | |||
| @@ -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); | |||
| } | |||
| // ------------------------------------------------------------------- | |||
| @@ -163,8 +163,11 @@ protected: | |||
| continue; | |||
| status -= channel; | |||
| midiEvent.data[0] = status; | |||
| //writeMidiEvent(channel, midiEvent); | |||
| midiEvent.portOffset = channel; | |||
| midiEvent.data[0] = status; | |||
| writeMidiEvent(&midiEvent); | |||
| } | |||
| } | |||
| @@ -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'] | |||
| @@ -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, | |||