diff --git a/source/backend/engine/CarlaEngineInternal.hpp b/source/backend/engine/CarlaEngineInternal.hpp index 0a6722686..4531e8eb1 100644 --- a/source/backend/engine/CarlaEngineInternal.hpp +++ b/source/backend/engine/CarlaEngineInternal.hpp @@ -232,19 +232,11 @@ struct CarlaEngineProtectedData { void doPluginRemove() { CARLA_ASSERT(curPluginCount > 0); + CARLA_ASSERT(nextAction.pluginId < curPluginCount); --curPluginCount; - const unsigned int id(nextAction.pluginId); - - // reset current plugin - plugins[id].plugin = nullptr; - plugins[id].insPeak[0] = 0.0f; - plugins[id].insPeak[1] = 0.0f; - plugins[id].outsPeak[0] = 0.0f; - plugins[id].outsPeak[1] = 0.0f; - // move all plugins 1 spot backwards - for (unsigned int i=id; i < curPluginCount; ++i) + for (unsigned int i=nextAction.pluginId; i < curPluginCount; ++i) { CarlaPlugin* const plugin(plugins[i+1].plugin); @@ -261,6 +253,15 @@ struct CarlaEngineProtectedData { plugins[i].outsPeak[0] = 0.0f; plugins[i].outsPeak[1] = 0.0f; } + + const unsigned int id(curPluginCount); + + // reset now last plugin + plugins[id].plugin = nullptr; + plugins[id].insPeak[0] = 0.0f; + plugins[id].insPeak[1] = 0.0f; + plugins[id].outsPeak[0] = 0.0f; + plugins[id].outsPeak[1] = 0.0f; } void doPluginsSwitch() diff --git a/source/backend/native/midi-file.cpp b/source/backend/native/midi-file.cpp index 1e56ee8db..39fe63bb3 100644 --- a/source/backend/native/midi-file.cpp +++ b/source/backend/native/midi-file.cpp @@ -55,7 +55,7 @@ protected: void process(float**, float**, const uint32_t frames, const uint32_t, const MidiEvent* const) override { - const TimeInfo* const timePos = getTimeInfo(); + const TimeInfo* const timePos(getTimeInfo()); if (timePos->playing) { @@ -66,18 +66,20 @@ protected: MidiEvent midiEvent; midiEvent.port = 0; - midiEvent.time = timePos->frame; + midiEvent.time = 0; midiEvent.data[0] = MIDI_STATUS_CONTROL_CHANGE; midiEvent.data[1] = MIDI_CONTROL_ALL_NOTES_OFF; midiEvent.data[2] = 0; midiEvent.data[3] = 0; - midiEvent.size = 2; + midiEvent.size = 3; for (int i=0; i < MAX_MIDI_CHANNELS; ++i) { - midiEvent.data[0] += i; + midiEvent.data[0] = MIDI_STATUS_CONTROL_CHANGE+i; PluginDescriptorClass::writeMidiEvent(&midiEvent); } + + carla_stdout("WAS PLAYING BEFORE, NOW STOPPED"); } fWasPlayingBefore = timePos->playing; @@ -128,7 +130,7 @@ private: if (smf_t* const smf = smf_load(filename)) { smf_event_t* event; - const double sampleRate = getSampleRate(); + const double sampleRate(getSampleRate()); while ((event = smf_get_next_event(smf)) != nullptr) { @@ -143,7 +145,7 @@ private: if (event->midi_buffer_length <= 0 || event->midi_buffer_length > MAX_EVENT_DATA_SIZE) continue; - const uint32_t time = event->time_seconds*sampleRate; + const uint32_t time(event->time_seconds*sampleRate); #if 1 fMidiOut.addRaw(time, event->midi_buffer, event->midi_buffer_length); diff --git a/source/backend/plugin/Lv2Plugin.cpp b/source/backend/plugin/Lv2Plugin.cpp index 016bf6418..62356f916 100644 --- a/source/backend/plugin/Lv2Plugin.cpp +++ b/source/backend/plugin/Lv2Plugin.cpp @@ -15,7 +15,6 @@ * For a full copy of the GNU General Public License see the GPL.txt file */ -#define WANT_LV2 #include "CarlaPluginInternal.hpp" #ifdef WANT_LV2 @@ -511,7 +510,10 @@ public: for (uint32_t i=0; i < kFeatureCount; ++i) { if (fFeatures[i] != nullptr) + { delete fFeatures[i]; + fFeatures[i] = nullptr; + } } for (NonRtList::Itenerator it = fCustomURIDs.begin(); it.valid(); it.next()) @@ -2301,7 +2303,9 @@ public: return; } - // handle events from different APIs + // -------------------------------------------------------------------------------------------------------- + // Handle events from different APIs + LV2_Atom_Buffer_Iterator evInAtomIters[fEventsIn.count]; LV2_Event_Iterator evInEventIters[fEventsIn.count]; LV2_MIDIState evInMidiStates[fEventsIn.count]; @@ -2405,16 +2409,16 @@ public: } } - if (kData->latency > 0) + //if (kData->latency > 0) { //for (i=0; i < kData->audioIn.count; ++i) // carla_zeroFloat(kData->latencyBuffers[i], kData->latency); } kData->needsReset = false; - } - CARLA_PROCESS_CONTINUE_CHECK; + CARLA_PROCESS_CONTINUE_CHECK; + } // -------------------------------------------------------------------------------------------------------- // Special Parameters @@ -2427,134 +2431,136 @@ public: // -------------------------------------------------------------------------------------------------------- // TimeInfo + const EngineTimeInfo& timeInfo(kData->engine->getTimeInfo()); + + if (fFirstActive || fLastTimeInfo != timeInfo) { bool doPostRt; int32_t rindex; - const EngineTimeInfo& timeInfo(kData->engine->getTimeInfo()); - if (fFirstActive || fLastTimeInfo != timeInfo) + // update input ports + for (k=0; k < kData->param.count; ++k) { - // update input ports - for (k=0; k < kData->param.count; ++k) - { - if (kData->param.data[k].type != PARAMETER_LV2_TIME) - continue; + if (kData->param.data[k].type != PARAMETER_LV2_TIME) + continue; - doPostRt = false; - rindex = kData->param.data[k].rindex; + doPostRt = false; + rindex = kData->param.data[k].rindex; - CARLA_ASSERT(rindex >= 0 && rindex < static_cast(fRdfDescriptor->PortCount)); + CARLA_ASSERT(rindex >= 0 && rindex < static_cast(fRdfDescriptor->PortCount)); - switch (fRdfDescriptor->Ports[rindex].Designation) + switch (fRdfDescriptor->Ports[rindex].Designation) + { + // Non-BBT + case LV2_PORT_DESIGNATION_TIME_SPEED: + if (fLastTimeInfo.playing != timeInfo.playing) { - // Non-BBT - case LV2_PORT_DESIGNATION_TIME_SPEED: - if (fLastTimeInfo.playing != timeInfo.playing) - { - fParamBuffers[k] = timeInfo.playing ? 1.0f : 0.0f; - doPostRt = true; - } - break; - case LV2_PORT_DESIGNATION_TIME_FRAME: - if (fLastTimeInfo.frame != timeInfo.frame) - { - fParamBuffers[k] = timeInfo.frame; - doPostRt = true; - } - break; - case LV2_PORT_DESIGNATION_TIME_FRAMES_PER_SECOND: - break; - // BBT - case LV2_PORT_DESIGNATION_TIME_BAR: - if ((timeInfo.valid & EngineTimeInfo::ValidBBT) != 0 && fLastTimeInfo.bbt.bar != timeInfo.bbt.bar) - { - fParamBuffers[k] = timeInfo.bbt.bar - 1; - doPostRt = true; - } - break; - case LV2_PORT_DESIGNATION_TIME_BAR_BEAT: - if ((timeInfo.valid & EngineTimeInfo::ValidBBT) != 0 && (fLastTimeInfo.bbt.tick != timeInfo.bbt.tick || - fLastTimeInfo.bbt.ticksPerBeat != timeInfo.bbt.ticksPerBeat)) - { - fParamBuffers[k] = timeInfo.bbt.beat - 1 + (double(timeInfo.bbt.tick) / timeInfo.bbt.ticksPerBeat); - doPostRt = true; - } - break; - case LV2_PORT_DESIGNATION_TIME_BEAT: - if ((timeInfo.valid & EngineTimeInfo::ValidBBT) != 0 && fLastTimeInfo.bbt.beat != timeInfo.bbt.beat) - { - fParamBuffers[k] = timeInfo.bbt.beat - 1; - doPostRt = true; - } - break; - case LV2_PORT_DESIGNATION_TIME_BEAT_UNIT: - if ((timeInfo.valid & EngineTimeInfo::ValidBBT) != 0 && fLastTimeInfo.bbt.beatType != timeInfo.bbt.beatType) - { - fParamBuffers[k] = timeInfo.bbt.beatType; - doPostRt = true; - } - break; - case LV2_PORT_DESIGNATION_TIME_BEATS_PER_BAR: - if ((timeInfo.valid & EngineTimeInfo::ValidBBT) != 0 && fLastTimeInfo.bbt.beatsPerBar != timeInfo.bbt.beatsPerBar) - { - fParamBuffers[k] = timeInfo.bbt.beatsPerBar; - doPostRt = true; - } - break; - case LV2_PORT_DESIGNATION_TIME_BEATS_PER_MINUTE: - if ((timeInfo.valid & EngineTimeInfo::ValidBBT) != 0 && fLastTimeInfo.bbt.beatsPerMinute != timeInfo.bbt.beatsPerMinute) - { - fParamBuffers[k] = timeInfo.bbt.beatsPerMinute; - doPostRt = true; - } - break; + fParamBuffers[k] = timeInfo.playing ? 1.0f : 0.0f; + doPostRt = true; + } + break; + case LV2_PORT_DESIGNATION_TIME_FRAME: + if (fLastTimeInfo.frame != timeInfo.frame) + { + fParamBuffers[k] = timeInfo.frame; + doPostRt = true; } + break; + case LV2_PORT_DESIGNATION_TIME_FRAMES_PER_SECOND: + break; - if (doPostRt) - postponeRtEvent(kPluginPostRtEventParameterChange, static_cast(k), 1, fParamBuffers[k]); + // BBT + case LV2_PORT_DESIGNATION_TIME_BAR: + if ((timeInfo.valid & EngineTimeInfo::ValidBBT) != 0 && fLastTimeInfo.bbt.bar != timeInfo.bbt.bar) + { + fParamBuffers[k] = timeInfo.bbt.bar - 1; + doPostRt = true; + } + break; + case LV2_PORT_DESIGNATION_TIME_BAR_BEAT: + if ((timeInfo.valid & EngineTimeInfo::ValidBBT) != 0 && (fLastTimeInfo.bbt.tick != timeInfo.bbt.tick || + fLastTimeInfo.bbt.ticksPerBeat != timeInfo.bbt.ticksPerBeat)) + { + fParamBuffers[k] = timeInfo.bbt.beat - 1 + (double(timeInfo.bbt.tick) / timeInfo.bbt.ticksPerBeat); + doPostRt = true; + } + break; + case LV2_PORT_DESIGNATION_TIME_BEAT: + if ((timeInfo.valid & EngineTimeInfo::ValidBBT) != 0 && fLastTimeInfo.bbt.beat != timeInfo.bbt.beat) + { + fParamBuffers[k] = timeInfo.bbt.beat - 1; + doPostRt = true; + } + break; + case LV2_PORT_DESIGNATION_TIME_BEAT_UNIT: + if ((timeInfo.valid & EngineTimeInfo::ValidBBT) != 0 && fLastTimeInfo.bbt.beatType != timeInfo.bbt.beatType) + { + fParamBuffers[k] = timeInfo.bbt.beatType; + doPostRt = true; + } + break; + case LV2_PORT_DESIGNATION_TIME_BEATS_PER_BAR: + if ((timeInfo.valid & EngineTimeInfo::ValidBBT) != 0 && fLastTimeInfo.bbt.beatsPerBar != timeInfo.bbt.beatsPerBar) + { + fParamBuffers[k] = timeInfo.bbt.beatsPerBar; + doPostRt = true; + } + break; + case LV2_PORT_DESIGNATION_TIME_BEATS_PER_MINUTE: + if ((timeInfo.valid & EngineTimeInfo::ValidBBT) != 0 && fLastTimeInfo.bbt.beatsPerMinute != timeInfo.bbt.beatsPerMinute) + { + fParamBuffers[k] = timeInfo.bbt.beatsPerMinute; + doPostRt = true; + } + break; } - for (i = 0; i < fEventsIn.count; ++i) - { - if ((fEventsIn.data[i].type & CARLA_EVENT_DATA_ATOM) == 0 || (fEventsIn.data[i].type & CARLA_EVENT_TYPE_TIME) == 0) - continue; - - uint8_t timeInfoBuf[256] = { 0 }; - lv2_atom_forge_set_buffer(&fAtomForge, timeInfoBuf, sizeof(timeInfoBuf)); + if (doPostRt) + postponeRtEvent(kPluginPostRtEventParameterChange, static_cast(k), 1, fParamBuffers[k]); + } - LV2_Atom_Forge_Frame forgeFrame; - lv2_atom_forge_blank(&fAtomForge, &forgeFrame, 1, CARLA_URI_MAP_ID_TIME_POSITION); - lv2_atom_forge_property_head(&fAtomForge, CARLA_URI_MAP_ID_TIME_SPEED, 0); - lv2_atom_forge_float(&fAtomForge, timeInfo.playing ? 1.0f : 0.0f); - lv2_atom_forge_property_head(&fAtomForge, CARLA_URI_MAP_ID_TIME_FRAME, 0); - lv2_atom_forge_long(&fAtomForge, timeInfo.frame); + for (i = 0; i < fEventsIn.count; ++i) + { + if ((fEventsIn.data[i].type & CARLA_EVENT_DATA_ATOM) == 0 || (fEventsIn.data[i].type & CARLA_EVENT_TYPE_TIME) == 0) + continue; - if (timeInfo.valid & EngineTimeInfo::ValidBBT) - { - lv2_atom_forge_property_head(&fAtomForge, CARLA_URI_MAP_ID_TIME_BAR, 0); - lv2_atom_forge_long(&fAtomForge, timeInfo.bbt.bar - 1); - lv2_atom_forge_property_head(&fAtomForge, CARLA_URI_MAP_ID_TIME_BAR_BEAT, 0); - lv2_atom_forge_float(&fAtomForge, timeInfo.bbt.beat - 1 + (double(timeInfo.bbt.tick) / timeInfo.bbt.ticksPerBeat)); - lv2_atom_forge_property_head(&fAtomForge, CARLA_URI_MAP_ID_TIME_BEAT, 0); - lv2_atom_forge_long(&fAtomForge, timeInfo.bbt.beat -1); - lv2_atom_forge_property_head(&fAtomForge, CARLA_URI_MAP_ID_TIME_BEAT_UNIT, 0); - lv2_atom_forge_float(&fAtomForge, timeInfo.bbt.beatType); - lv2_atom_forge_property_head(&fAtomForge, CARLA_URI_MAP_ID_TIME_BEATS_PER_BAR, 0); - lv2_atom_forge_float(&fAtomForge, timeInfo.bbt.beatsPerBar); - lv2_atom_forge_property_head(&fAtomForge, CARLA_URI_MAP_ID_TIME_BEATS_PER_MINUTE, 0); - lv2_atom_forge_float(&fAtomForge, timeInfo.bbt.beatsPerMinute); - } + uint8_t timeInfoBuf[256] = { 0 }; + lv2_atom_forge_set_buffer(&fAtomForge, timeInfoBuf, sizeof(timeInfoBuf)); - LV2_Atom* atom = (LV2_Atom*)timeInfoBuf; - lv2_atom_buffer_write(&evInAtomIters[i], 0, 0, atom->type, atom->size, LV2NV_ATOM_BODY_CONST(atom)); + LV2_Atom_Forge_Frame forgeFrame; + lv2_atom_forge_blank(&fAtomForge, &forgeFrame, 1, CARLA_URI_MAP_ID_TIME_POSITION); + lv2_atom_forge_property_head(&fAtomForge, CARLA_URI_MAP_ID_TIME_SPEED, 0); + lv2_atom_forge_float(&fAtomForge, timeInfo.playing ? 1.0f : 0.0f); + lv2_atom_forge_property_head(&fAtomForge, CARLA_URI_MAP_ID_TIME_FRAME, 0); + lv2_atom_forge_long(&fAtomForge, timeInfo.frame); - CARLA_ASSERT(atom->size < 256); + if (timeInfo.valid & EngineTimeInfo::ValidBBT) + { + lv2_atom_forge_property_head(&fAtomForge, CARLA_URI_MAP_ID_TIME_BAR, 0); + lv2_atom_forge_long(&fAtomForge, timeInfo.bbt.bar - 1); + lv2_atom_forge_property_head(&fAtomForge, CARLA_URI_MAP_ID_TIME_BAR_BEAT, 0); + lv2_atom_forge_float(&fAtomForge, timeInfo.bbt.beat - 1 + (double(timeInfo.bbt.tick) / timeInfo.bbt.ticksPerBeat)); + lv2_atom_forge_property_head(&fAtomForge, CARLA_URI_MAP_ID_TIME_BEAT, 0); + lv2_atom_forge_long(&fAtomForge, timeInfo.bbt.beat -1); + lv2_atom_forge_property_head(&fAtomForge, CARLA_URI_MAP_ID_TIME_BEAT_UNIT, 0); + lv2_atom_forge_float(&fAtomForge, timeInfo.bbt.beatType); + lv2_atom_forge_property_head(&fAtomForge, CARLA_URI_MAP_ID_TIME_BEATS_PER_BAR, 0); + lv2_atom_forge_float(&fAtomForge, timeInfo.bbt.beatsPerBar); + lv2_atom_forge_property_head(&fAtomForge, CARLA_URI_MAP_ID_TIME_BEATS_PER_MINUTE, 0); + lv2_atom_forge_float(&fAtomForge, timeInfo.bbt.beatsPerMinute); } - kData->postRtEvents.trySplice(); + LV2_Atom* const atom((LV2_Atom*)timeInfoBuf); + lv2_atom_buffer_write(&evInAtomIters[i], 0, 0, atom->type, atom->size, LV2NV_ATOM_BODY_CONST(atom)); - std::memcpy(&fLastTimeInfo, &timeInfo, sizeof(EngineTimeInfo)); + CARLA_ASSERT(atom->size < 256); } + + kData->postRtEvents.trySplice(); + + std::memcpy(&fLastTimeInfo, &timeInfo, sizeof(EngineTimeInfo)); + + CARLA_PROCESS_CONTINUE_CHECK; } // -------------------------------------------------------------------------------------------------------- @@ -2576,10 +2582,10 @@ public: while (fAtomQueueIn.get(&portIndex, &atom)) { - carla_stdout("Event input message sent to plugin DSP, type %i:\"%s\", size:%i/%i", - atom->type, carla_lv2_urid_unmap(this, atom->type), - atom->size, lv2_atom_total_size(atom) - ); + carla_debug("Event input message sent to plugin DSP, type %i:\"%s\", size:%i/%i", + atom->type, carla_lv2_urid_unmap(this, atom->type), + atom->size, lv2_atom_total_size(atom) + ); if (! lv2_atom_buffer_write(&evInAtomIters[k], 0, 0, atom->type, atom->size, LV2NV_ATOM_BODY_CONST(atom))) { @@ -2597,22 +2603,27 @@ public: if (kData->extNotes.mutex.tryLock()) { - k = fEventsIn.ctrlIndex; - - while (! kData->extNotes.data.isEmpty()) + if ((fEventsIn.ctrl->type & CARLA_EVENT_TYPE_MIDI) == 0) { - const ExternalMidiNote& note(kData->extNotes.data.getFirst(true)); + // does not handle MIDI + kData->extNotes.data.clear(); + } + else + { + k = fEventsIn.ctrlIndex; - CARLA_ASSERT(note.channel >= 0 && note.channel < MAX_MIDI_CHANNELS); + while (! kData->extNotes.data.isEmpty()) + { + const ExternalMidiNote& note(kData->extNotes.data.getFirst(true)); - uint8_t midiEvent[3]; - midiEvent[0] = (note.velo > 0) ? MIDI_STATUS_NOTE_ON : MIDI_STATUS_NOTE_OFF; - midiEvent[0] += note.channel; - midiEvent[1] = note.note; - midiEvent[2] = note.velo; + CARLA_ASSERT(note.channel >= 0 && note.channel < MAX_MIDI_CHANNELS); + + uint8_t midiEvent[3]; + midiEvent[0] = (note.velo > 0) ? MIDI_STATUS_NOTE_ON : MIDI_STATUS_NOTE_OFF; + midiEvent[0] += note.channel; + midiEvent[1] = note.note; + midiEvent[2] = note.velo; - if (fEventsIn.ctrl->type & CARLA_EVENT_TYPE_MIDI) - { if (fEventsIn.ctrl->type & CARLA_EVENT_DATA_ATOM) lv2_atom_buffer_write(&evInAtomIters[k], 0, 0, CARLA_URI_MAP_ID_MIDI_EVENT, 3, midiEvent); @@ -2697,7 +2708,7 @@ public: case kEngineEventTypeControl: { - const EngineControlEvent& ctrlEvent = event.ctrl; + const EngineControlEvent& ctrlEvent(event.ctrl); switch (ctrlEvent.type) { @@ -2941,10 +2952,12 @@ public: break; if (ev->body.type == CARLA_URI_MAP_ID_MIDI_EVENT && fEventsOut.ctrl->port != nullptr) + { fEventsOut.ctrl->port->writeMidiEvent(ev->time.frames, data, ev->body.size); + } else if (ev->body.type == CARLA_URI_MAP_ID_ATOM_BLANK) { - //carla_stdout("Event OUTPUT message TO BE SENT TO UI, type blank"); + carla_debug("Event OUTPUT message TO BE SENT TO UI, type blank"); fAtomQueueOut.put(rindex, &ev->body); } @@ -3293,6 +3306,15 @@ public: fExt.options->set(fHandle, &fLv2Options.optSampleRate); } + for (uint32_t k=0; k < kData->param.count; ++k) + { + if (kData->param.data[k].type == PARAMETER_SAMPLE_RATE) + { + fParamBuffers[k] = newSampleRate; + postponeRtEvent(kPluginPostRtEventParameterChange, static_cast(k), 1, fParamBuffers[k]); + } + } + carla_debug("Lv2Plugin::sampleRateChanged(%g) - end", newSampleRate); } @@ -4084,66 +4106,64 @@ public: // --------------------------------------------------------------- // initialize features (part 2) - fFeatures[kFeatureIdBufSizeBounded] = new LV2_Feature; + for (uint32_t i=0; i < kFeatureIdWorker+1; ++i) + fFeatures[i] = new LV2_Feature; + fFeatures[kFeatureIdBufSizeBounded]->URI = LV2_BUF_SIZE__boundedBlockLength; fFeatures[kFeatureIdBufSizeBounded]->data = nullptr; - fFeatures[kFeatureIdBufSizeFixed] = new LV2_Feature; fFeatures[kFeatureIdBufSizeFixed]->URI = LV2_BUF_SIZE__fixedBlockLength; fFeatures[kFeatureIdBufSizeFixed]->data = nullptr; - fFeatures[kFeatureIdBufSizePowerOf2] = new LV2_Feature; fFeatures[kFeatureIdBufSizePowerOf2]->URI = LV2_BUF_SIZE__powerOf2BlockLength; fFeatures[kFeatureIdBufSizePowerOf2]->data = nullptr; - fFeatures[kFeatureIdEvent] = new LV2_Feature; - fFeatures[kFeatureIdEvent]->URI = LV2_EVENT_URI; - fFeatures[kFeatureIdEvent]->data = eventFt; + fFeatures[kFeatureIdEvent]->URI = LV2_EVENT_URI; + fFeatures[kFeatureIdEvent]->data = eventFt; - fFeatures[kFeatureIdLogs] = new LV2_Feature; - fFeatures[kFeatureIdLogs]->URI = LV2_LOG__log; - fFeatures[kFeatureIdLogs]->data = logFt; + fFeatures[kFeatureIdHardRtCapable]->URI = LV2_CORE__hardRTCapable; + fFeatures[kFeatureIdHardRtCapable]->data = nullptr; - fFeatures[kFeatureIdOptions] = new LV2_Feature; - fFeatures[kFeatureIdOptions]->URI = LV2_OPTIONS__options; - fFeatures[kFeatureIdOptions]->data = fLv2Options.opts; + fFeatures[kFeatureIdInPlaceBroken]->URI = LV2_CORE__inPlaceBroken; + fFeatures[kFeatureIdInPlaceBroken]->data = nullptr; - fFeatures[kFeatureIdPrograms] = new LV2_Feature; - fFeatures[kFeatureIdPrograms]->URI = LV2_PROGRAMS__Host; - fFeatures[kFeatureIdPrograms]->data = programsFt; + fFeatures[kFeatureIdIsLive]->URI = LV2_CORE__isLive; + fFeatures[kFeatureIdIsLive]->data = nullptr; + + fFeatures[kFeatureIdLogs]->URI = LV2_LOG__log; + fFeatures[kFeatureIdLogs]->data = logFt; + + fFeatures[kFeatureIdOptions]->URI = LV2_OPTIONS__options; + fFeatures[kFeatureIdOptions]->data = fLv2Options.opts; + + fFeatures[kFeatureIdPrograms]->URI = LV2_PROGRAMS__Host; + fFeatures[kFeatureIdPrograms]->data = programsFt; - fFeatures[kFeatureIdRtMemPool] = new LV2_Feature; fFeatures[kFeatureIdRtMemPool]->URI = LV2_RTSAFE_MEMORY_POOL__Pool; fFeatures[kFeatureIdRtMemPool]->data = rtMemPoolFt; - fFeatures[kFeatureIdStateMakePath] = new LV2_Feature; fFeatures[kFeatureIdStateMakePath]->URI = LV2_STATE__makePath; fFeatures[kFeatureIdStateMakePath]->data = stateMakePathFt; - fFeatures[kFeatureIdStateMapPath] = new LV2_Feature; fFeatures[kFeatureIdStateMapPath]->URI = LV2_STATE__mapPath; fFeatures[kFeatureIdStateMapPath]->data = stateMapPathFt; - fFeatures[kFeatureIdStrictBounds] = new LV2_Feature; - fFeatures[kFeatureIdStrictBounds]->URI = LV2_PORT_PROPS__supportsStrictBounds; - fFeatures[kFeatureIdStrictBounds]->data = nullptr; + fFeatures[kFeatureIdStrictBounds]->URI = LV2_PORT_PROPS__supportsStrictBounds; + fFeatures[kFeatureIdStrictBounds]->data = nullptr; - fFeatures[kFeatureIdUriMap] = new LV2_Feature; fFeatures[kFeatureIdUriMap]->URI = LV2_URI_MAP_URI; fFeatures[kFeatureIdUriMap]->data = uriMapFt; - fFeatures[kFeatureIdUridMap] = new LV2_Feature; fFeatures[kFeatureIdUridMap]->URI = LV2_URID__map; fFeatures[kFeatureIdUridMap]->data = uridMapFt; - fFeatures[kFeatureIdUridUnmap] = new LV2_Feature; fFeatures[kFeatureIdUridUnmap]->URI = LV2_URID__unmap; fFeatures[kFeatureIdUridUnmap]->data = uridUnmapFt; - fFeatures[kFeatureIdWorker] = new LV2_Feature; - fFeatures[kFeatureIdWorker]->URI = LV2_WORKER__schedule; - fFeatures[kFeatureIdWorker]->data = workerFt; + fFeatures[kFeatureIdWorker]->URI = LV2_WORKER__schedule; + fFeatures[kFeatureIdWorker]->data = workerFt; + // check if it's possible to use non-fixed buffer size if (! needsFixedBuffer()) fFeatures[kFeatureIdBufSizeFixed]->URI = LV2_BUF_SIZE__boundedBlockLength; @@ -4601,7 +4621,7 @@ public: } // ------------------------------------------------------- - // initialize ui features + // initialize ui features (part 1) QString guiTitle(QString("%1 (GUI)").arg((const char*)fName)); @@ -4620,31 +4640,48 @@ public: uiExternalHostFt->ui_closed = carla_lv2_external_ui_closed; uiExternalHostFt->plugin_human_id = carla_strdup(guiTitle.toUtf8().constData()); - fFeatures[kFeatureIdUiDataAccess] = new LV2_Feature; + // ------------------------------------------------------- + // initialize ui features (part 2) + + for (uint32_t i=kFeatureIdUiDataAccess; i < kFeatureCount; ++i) + fFeatures[i] = new LV2_Feature; + fFeatures[kFeatureIdUiDataAccess]->URI = LV2_DATA_ACCESS_URI; fFeatures[kFeatureIdUiDataAccess]->data = uiDataFt; - fFeatures[kFeatureIdUiInstanceAccess] = new LV2_Feature; fFeatures[kFeatureIdUiInstanceAccess]->URI = LV2_INSTANCE_ACCESS_URI; fFeatures[kFeatureIdUiInstanceAccess]->data = fHandle; - fFeatures[kFeatureIdUiParent] = new LV2_Feature; - fFeatures[kFeatureIdUiParent]->URI = LV2_UI__parent; - fFeatures[kFeatureIdUiParent]->data = nullptr; + fFeatures[kFeatureIdUiIdle]->URI = LV2_UI__idle; + fFeatures[kFeatureIdUiIdle]->data = nullptr; + + fFeatures[kFeatureIdUiFixedSize]->URI = LV2_UI__fixedSize; + fFeatures[kFeatureIdUiFixedSize]->data = nullptr; + + fFeatures[kFeatureIdUiMakeResident]->URI = LV2_UI__makeResident; + fFeatures[kFeatureIdUiMakeResident]->data = nullptr; + + fFeatures[kFeatureIdUiNoUserResize]->URI = LV2_UI__noUserResize; + fFeatures[kFeatureIdUiNoUserResize]->data = nullptr; + + fFeatures[kFeatureIdUiParent]->URI = LV2_UI__parent; + fFeatures[kFeatureIdUiParent]->data = nullptr; + + fFeatures[kFeatureIdUiPortMap]->URI = LV2_UI__portMap; + fFeatures[kFeatureIdUiPortMap]->data = uiPortMapFt; + + fFeatures[kFeatureIdUiPortSubscribe]->URI = LV2_UI__portSubscribe; + fFeatures[kFeatureIdUiPortSubscribe]->data = nullptr; - fFeatures[kFeatureIdUiPortMap] = new LV2_Feature; - fFeatures[kFeatureIdUiPortMap]->URI = LV2_UI__portMap; - fFeatures[kFeatureIdUiPortMap]->data = uiPortMapFt; + fFeatures[kFeatureIdUiResize]->URI = LV2_UI__resize; + fFeatures[kFeatureIdUiResize]->data = uiResizeFt; - fFeatures[kFeatureIdUiResize] = new LV2_Feature; - fFeatures[kFeatureIdUiResize]->URI = LV2_UI__resize; - fFeatures[kFeatureIdUiResize]->data = uiResizeFt; + fFeatures[kFeatureIdUiTouch]->URI = LV2_UI__touch; + fFeatures[kFeatureIdUiTouch]->data = nullptr; - fFeatures[kFeatureIdExternalUi] = new LV2_Feature; - fFeatures[kFeatureIdExternalUi]->URI = LV2_EXTERNAL_UI__Host; - fFeatures[kFeatureIdExternalUi]->data = uiExternalHostFt; + fFeatures[kFeatureIdExternalUi]->URI = LV2_EXTERNAL_UI__Host; + fFeatures[kFeatureIdExternalUi]->data = uiExternalHostFt; - fFeatures[kFeatureIdExternalUiOld] = new LV2_Feature; fFeatures[kFeatureIdExternalUiOld]->URI = LV2_EXTERNAL_UI_DEPRECATED_URI; fFeatures[kFeatureIdExternalUiOld]->data = uiExternalHostFt; } diff --git a/source/backend/plugin/NativePlugin.cpp b/source/backend/plugin/NativePlugin.cpp index e66a514d4..25de6a960 100644 --- a/source/backend/plugin/NativePlugin.cpp +++ b/source/backend/plugin/NativePlugin.cpp @@ -543,7 +543,7 @@ public: void setCtrlChannel(const int8_t channel, const bool sendOsc, const bool sendCallback) override { - if (channel < MAX_MIDI_CHANNELS) + if (channel < MAX_MIDI_CHANNELS && kData->midiprog.count > 0) kData->midiprog.current = fCurMidiProgs[channel]; CarlaPlugin::setCtrlChannel(channel, sendOsc, sendCallback); @@ -719,7 +719,7 @@ public: if (fDescriptor->ui_set_midi_program != nullptr && kData->midiprog.current >= 0) { - const MidiProgramData& mpData = kData->midiprog.getCurrent(); + const MidiProgramData& mpData(kData->midiprog.getCurrent()); fDescriptor->ui_set_midi_program(fHandle, 0, mpData.bank, mpData.program); // TODO }