| @@ -195,7 +195,7 @@ public: | |||
| fHandle = fDescriptor->instantiate(&fHost); | |||
| CARLA_SAFE_ASSERT_RETURN(fHandle != nullptr, false); | |||
| carla_zeroStructs(fMidiEvents, kMaxMidiEvents*2); | |||
| carla_zeroStructs(fMidiEvents, kMaxMidiEvents); | |||
| carla_zeroStruct(fTimeInfo); | |||
| // hosts may not send all values, resulting on some invalid data | |||
| @@ -259,34 +259,13 @@ public: | |||
| fIsOffline = (fPorts.freewheel != nullptr && *fPorts.freewheel >= 0.5f); | |||
| if (frames == 0) | |||
| { | |||
| updateParameterOutputs(); | |||
| return; | |||
| } | |||
| // Check for updated parameters | |||
| float curValue; | |||
| return updateParameterOutputs(); | |||
| for (uint32_t i=0; i < fPorts.paramCount; ++i) | |||
| { | |||
| if (fPorts.paramsOut[i]) | |||
| continue; | |||
| CARLA_SAFE_ASSERT_CONTINUE(fPorts.paramsPtr[i] != nullptr) | |||
| curValue = *fPorts.paramsPtr[i]; | |||
| if (carla_isEqual(fPorts.paramsLast[i], curValue)) | |||
| continue; | |||
| fPorts.paramsLast[i] = curValue; | |||
| fDescriptor->set_parameter_value(fHandle, i, curValue); | |||
| } | |||
| if (fDescriptor->midiIns > 0 || fDescriptor->midiOuts > 0 || (fDescriptor->hints & NATIVE_PLUGIN_USES_TIME) != 0) | |||
| // cache midi events and time information | |||
| if (fDescriptor->midiIns > 0 || (fDescriptor->hints & NATIVE_PLUGIN_USES_TIME) != 0) | |||
| { | |||
| fMidiEventCount = 0; | |||
| carla_zeroStructs(fMidiEvents, kMaxMidiEvents*2); | |||
| carla_zeroStructs(fMidiEvents, kMaxMidiEvents); | |||
| if (fDescriptor->hints & NATIVE_PLUGIN_USES_TIME) | |||
| { | |||
| @@ -490,24 +469,59 @@ public: | |||
| continue; | |||
| if (event->time.frames >= frames) | |||
| break; | |||
| if (fMidiEventCount >= kMaxMidiEvents*2) | |||
| if (fMidiEventCount >= kMaxMidiEvents) | |||
| break; | |||
| const uint8_t* const data((const uint8_t*)(event + 1)); | |||
| NativeMidiEvent& nativeEvent(fMidiEvents[fMidiEventCount++]); | |||
| carla_zeroStruct(nativeEvent); | |||
| nativeEvent.port = (uint8_t)i; | |||
| nativeEvent.size = (uint8_t)event->body.size; | |||
| nativeEvent.time = (uint32_t)event->time.frames; | |||
| for (uint32_t j=0; j < event->body.size; ++j) | |||
| uint32_t j=0; | |||
| for (uint32_t size=event->body.size; j<size; ++j) | |||
| nativeEvent.data[j] = data[j]; | |||
| for (; j<4; ++j) | |||
| nativeEvent.data[j] = 0; | |||
| } | |||
| } | |||
| } | |||
| // init midi out data | |||
| if (fDescriptor->midiOuts > 0) | |||
| { | |||
| for (uint32_t i=0, size=fDescriptor->midiOuts; i<size; ++i) | |||
| { | |||
| LV2_Atom_Sequence* const seq(fPorts.midiOuts[i]); | |||
| CARLA_SAFE_ASSERT_CONTINUE(seq != nullptr); | |||
| Ports::MidiOutData& mData(fPorts.midiOutData[i]); | |||
| mData.capacity = seq->atom.size; | |||
| mData.offset = 0; | |||
| } | |||
| } | |||
| // Check for updated parameters | |||
| float curValue; | |||
| for (uint32_t i=0; i < fPorts.paramCount; ++i) | |||
| { | |||
| if (fPorts.paramsOut[i]) | |||
| continue; | |||
| CARLA_SAFE_ASSERT_CONTINUE(fPorts.paramsPtr[i] != nullptr) | |||
| curValue = *fPorts.paramsPtr[i]; | |||
| if (carla_isEqual(fPorts.paramsLast[i], curValue)) | |||
| continue; | |||
| fPorts.paramsLast[i] = curValue; | |||
| fDescriptor->set_parameter_value(fHandle, i, curValue); | |||
| } | |||
| // FIXME | |||
| fDescriptor->process(fHandle, const_cast<float**>(fPorts.audioIns), fPorts.audioOuts, frames, fMidiEvents, fMidiEventCount); | |||
| @@ -566,60 +580,6 @@ public: | |||
| } | |||
| updateParameterOutputs(); | |||
| if (fDescriptor->midiOuts > 0) | |||
| { | |||
| uint32_t capacities[fDescriptor->midiOuts]; | |||
| uint32_t offsets [fDescriptor->midiOuts]; | |||
| for (uint32_t i=0, size=fDescriptor->midiOuts; i<size; ++i) | |||
| { | |||
| LV2_Atom_Sequence* const seq(fPorts.midiOuts[i]); | |||
| CARLA_SAFE_ASSERT_CONTINUE(seq != nullptr); | |||
| capacities[i] = seq->atom.size; | |||
| offsets [i] = 0; | |||
| } | |||
| LV2_Atom_Event* aev; | |||
| uint32_t size; | |||
| // reverse lookup MIDI events | |||
| for (uint32_t i = (kMaxMidiEvents*2)-1; i >= fMidiEventCount; --i) | |||
| { | |||
| if (fMidiEvents[i].data[0] == 0) | |||
| break; | |||
| NativeMidiEvent& nativeEvent(fMidiEvents[i]); | |||
| const uint8_t port(nativeEvent.port); | |||
| CARLA_SAFE_ASSERT_CONTINUE(nativeEvent.port < fDescriptor->midiOuts); | |||
| LV2_Atom_Sequence* const seq(fPorts.midiOuts[port]); | |||
| CARLA_SAFE_ASSERT_CONTINUE(seq != nullptr); | |||
| if (sizeof(LV2_Atom_Event) + nativeEvent.size > capacities[port] - offsets[port]) | |||
| continue; | |||
| if (offsets[port] == 0) | |||
| { | |||
| seq->atom.size = 0; | |||
| seq->atom.type = fURIs.atomSequence; | |||
| seq->body.unit = 0; | |||
| seq->body.pad = 0; | |||
| } | |||
| aev = (LV2_Atom_Event*)(LV2_ATOM_CONTENTS(LV2_Atom_Sequence, seq) + offsets[port]); | |||
| aev->time.frames = nativeEvent.time; | |||
| aev->body.size = nativeEvent.size; | |||
| aev->body.type = fURIs.midiEvent; | |||
| std::memcpy(LV2_ATOM_BODY(&aev->body), nativeEvent.data, nativeEvent.size); | |||
| size = lv2_atom_pad_size(sizeof(LV2_Atom_Event) + nativeEvent.size); | |||
| offsets[port] += size; | |||
| seq->atom.size += size; | |||
| } | |||
| } | |||
| } | |||
| // ------------------------------------------------------------------- | |||
| @@ -936,20 +896,39 @@ protected: | |||
| { | |||
| CARLA_SAFE_ASSERT_RETURN(fDescriptor->midiOuts > 0, false); | |||
| CARLA_SAFE_ASSERT_RETURN(event != nullptr, false); | |||
| CARLA_SAFE_ASSERT_RETURN(event->data[0] != 0, false); | |||
| CARLA_SAFE_ASSERT_RETURN(event->size > 0, false); | |||
| // reverse-find first free event, and put it there | |||
| for (uint32_t i=(kMaxMidiEvents*2)-1; i > fMidiEventCount; --i) | |||
| { | |||
| if (fMidiEvents[i].data[0] != 0) | |||
| continue; | |||
| const uint8_t port(event->port); | |||
| CARLA_SAFE_ASSERT_RETURN(port < fDescriptor->midiOuts, false); | |||
| std::memcpy(&fMidiEvents[i], event, sizeof(NativeMidiEvent)); | |||
| return true; | |||
| LV2_Atom_Sequence* const seq(fPorts.midiOuts[port]); | |||
| CARLA_SAFE_ASSERT_RETURN(seq != nullptr, false); | |||
| Ports::MidiOutData& mData(fPorts.midiOutData[port]); | |||
| if (sizeof(LV2_Atom_Event) + event->size > mData.capacity - mData.offset) | |||
| return false; | |||
| if (mData.offset == 0) | |||
| { | |||
| seq->atom.size = 0; | |||
| seq->atom.type = fURIs.atomSequence; | |||
| seq->body.unit = 0; | |||
| seq->body.pad = 0; | |||
| } | |||
| carla_stdout("NativePlugin::handleWriteMidiEvent(%p) - buffer full", event); | |||
| return false; | |||
| LV2_Atom_Event* const aev = (LV2_Atom_Event*)(LV2_ATOM_CONTENTS(LV2_Atom_Sequence, seq) + mData.offset); | |||
| aev->time.frames = event->time; | |||
| aev->body.size = event->size; | |||
| aev->body.type = fURIs.midiEvent; | |||
| std::memcpy(LV2_ATOM_BODY(&aev->body), event->data, event->size); | |||
| const uint32_t size = lv2_atom_pad_size(sizeof(LV2_Atom_Event) + event->size); | |||
| mData.offset += size; | |||
| seq->atom.size += size; | |||
| return true; | |||
| } | |||
| void handleUiParameterChanged(const uint32_t index, const float value) const | |||
| @@ -1041,7 +1020,7 @@ private: | |||
| LV2_Program_Descriptor fProgramDesc; | |||
| uint32_t fMidiEventCount; | |||
| NativeMidiEvent fMidiEvents[kMaxMidiEvents*2]; | |||
| NativeMidiEvent fMidiEvents[kMaxMidiEvents]; | |||
| NativeTimeInfo fTimeInfo; | |||
| // Lv2 host data | |||
| @@ -1157,8 +1136,19 @@ private: | |||
| } fUI; | |||
| struct Ports { | |||
| // need to save current state | |||
| struct MidiOutData { | |||
| uint32_t capacity; | |||
| uint32_t offset; | |||
| MidiOutData() | |||
| : capacity(0), | |||
| offset(0) {} | |||
| }; | |||
| const LV2_Atom_Sequence** eventsIn; | |||
| /* */ LV2_Atom_Sequence** midiOuts; | |||
| /* */ MidiOutData* midiOutData; | |||
| const float** audioIns; | |||
| /* */ float** audioOuts; | |||
| float* freewheel; | |||
| @@ -1192,6 +1182,12 @@ private: | |||
| midiOuts = nullptr; | |||
| } | |||
| if (midiOutData != nullptr) | |||
| { | |||
| delete[] midiOutData; | |||
| midiOutData = nullptr; | |||
| } | |||
| if (audioIns != nullptr) | |||
| { | |||
| delete[] audioIns; | |||
| @@ -1243,6 +1239,7 @@ private: | |||
| if (desc->midiOuts > 0) | |||
| { | |||
| midiOuts = new LV2_Atom_Sequence*[desc->midiOuts]; | |||
| midiOutData = new MidiOutData[desc->midiOuts]; | |||
| for (uint32_t i=0; i < desc->midiOuts; ++i) | |||
| midiOuts[i] = nullptr; | |||