diff --git a/c++/carla-backend/lv2.cpp b/c++/carla-backend/lv2.cpp index 6624ed2..0f7aad8 100644 --- a/c++/carla-backend/lv2.cpp +++ b/c++/carla-backend/lv2.cpp @@ -201,6 +201,11 @@ const char* lv2bridge2str(const LV2_Property type) } } +LV2_Atom_Event* getLv2AtomEvent(LV2_Atom_Sequence* const atom, const uint32_t offset) +{ + return (LV2_Atom_Event*)((char*)LV2_ATOM_CONTENTS(LV2_Atom_Sequence, atom) + offset); +} + class Lv2Plugin : public CarlaPlugin { public: @@ -243,6 +248,9 @@ public: suil.host = nullptr; #endif + lastTimePosPlaying = false; + lastTimePosFrame = 0; + for (uint32_t i=0; i < CARLA_URI_MAP_ID_COUNT; i++) customURIDs.push_back(nullptr); @@ -527,9 +535,7 @@ public: if (rdf_descriptor && rindex < (int32_t)rdf_descriptor->PortCount) { const LV2_RDF_Port* const port = &rdf_descriptor->Ports[rindex]; - - if (port) - return port->ScalePointCount; + return port->ScalePointCount; } return 0; @@ -556,12 +562,10 @@ public: { const LV2_RDF_Port* const port = &rdf_descriptor->Ports[rindex]; - if (port && scalePointId < port->ScalePointCount) + if (scalePointId < port->ScalePointCount) { const LV2_RDF_PortScalePoint* const portScalePoint = &port->ScalePoints[scalePointId]; - - if (portScalePoint) - return portScalePoint->Value; + return portScalePoint->Value; } } @@ -743,11 +747,11 @@ public: { const LV2_RDF_Port* const port = &rdf_descriptor->Ports[rindex]; - if (port && scalePointId < port->ScalePointCount) + if (scalePointId < port->ScalePointCount) { const LV2_RDF_PortScalePoint* const portScalePoint = &port->ScalePoints[scalePointId]; - if (portScalePoint && portScalePoint->Label) + if (portScalePoint->Label) { strncpy(strBuf, portScalePoint->Label, STR_MAX); return; @@ -1772,7 +1776,7 @@ public: double aInsPeak[2] = { 0.0 }; double aOutsPeak[2] = { 0.0 }; - // handle midi from different APIs + // handle events from different APIs uint32_t evInAtomOffsets[evIn.count]; LV2_Event_Iterator evInEventIters[evIn.count]; LV2_MIDIState evInMidiStates[evIn.count]; @@ -2027,7 +2031,7 @@ public: CARLA_PROCESS_CONTINUE_CHECK; // -------------------------------------------------------------------------------------------------------- - // MIDI Input + // Event Input if (evIn.count > 0 && m_active && m_activeBefore) { @@ -2054,15 +2058,15 @@ public: { if (evIn.data[k].type & CARLA_EVENT_DATA_ATOM) { - LV2_Atom_Event* const aev = (LV2_Atom_Event*)((char*)LV2_ATOM_CONTENTS(LV2_Atom_Sequence, evIn.data[k].atom) + evInAtomOffsets[k]); + LV2_Atom_Event* const aev = getLv2AtomEvent(evIn.data[k].atom, evInAtomOffsets[k]); aev->time.frames = 0; aev->body.type = CARLA_URI_MAP_ID_MIDI_EVENT; aev->body.size = 3; memcpy(LV2_ATOM_BODY(&aev->body), midiEvent, 3); - const uint32_t padSize = lv2_atom_pad_size(sizeof(LV2_Atom_Event) + 3); - evInAtomOffsets[k] += padSize; - evIn.data[k].atom->atom.size += padSize; + const uint32_t evInPadSize = lv2_atom_pad_size(sizeof(LV2_Atom_Event) + 3); + evInAtomOffsets[k] += evInPadSize; + evIn.data[k].atom->atom.size += evInPadSize; } else if (evIn.data[k].type & CARLA_EVENT_DATA_EVENT) { @@ -2121,15 +2125,15 @@ public: { if (evIn.data[i].type & CARLA_EVENT_DATA_ATOM) { - LV2_Atom_Event* const aev = (LV2_Atom_Event*)((char*)LV2_ATOM_CONTENTS(LV2_Atom_Sequence, evIn.data[i].atom) + evInAtomOffsets[i]); + 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 padSize = lv2_atom_pad_size(sizeof(LV2_Atom_Event) + minEvent->size); - evInAtomOffsets[i] += padSize; - evIn.data[i].atom->atom.size += padSize; + 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) { @@ -2151,7 +2155,87 @@ public: } } // End of MIDI Input (System) - } // End of MIDI Input + // ---------------------------------------------------------------------------------------------------- + // Message Input + + { + for (i=0; i < evIn.count; i++) + { + if (! evIn.data[i].type & CARLA_EVENT_TYPE_MESSAGE) + continue; + + // messages only supported in Atom type ports + Q_ASSERT(evIn.data[i].type & CARLA_EVENT_DATA_ATOM); + +#if 0 + // send transport info if changed + const CarlaTimeInfo* const timeInfo = x_engine->getTimeInfo(); + + if (timeInfo->playing != lastTimePosPlaying || timeInfo->frame != lastTimePosFrame) + { + uint8_t posBuf[256]; + LV2_Atom* const lv2Pos = (LV2_Atom*)posBuf; + + LV2_Atom_Forge tempForge; + LV2_Atom_Forge* const forge = &tempForge; + lv2_atom_forge_set_buffer(forge, posBuf, sizeof(uint8_t)*256); + + //LV2_Atom_Forge_Frame frame; + //lv2_atom_forge_blank(forge, &frame, 1, jalv->urids.time_Position); + //lv2_atom_forge_property_head(forge, jalv->urids.time_frame, 0); + lv2_atom_forge_long(forge, timeInfo->frame); + //lv2_atom_forge_property_head(forge, jalv->urids.time_position, 0); + lv2_atom_forge_long(forge, timeInfo->time); + //lv2_atom_forge_property_head(forge, jalv->urids.time_speed, 0); + lv2_atom_forge_float(forge, timeInfo->playing ? 1.0 : 0.0); + + if (timeInfo->valid & CarlaEngineTimeBBT) + { + //lv2_atom_forge_property_head(forge, jalv->urids.time_bar, 0); + lv2_atom_forge_float(forge, timeInfo->bbt.bar - 1); + + //lv2_atom_forge_property_head(forge, jalv->urids.time_barBeat, 0); + lv2_atom_forge_float(forge, timeInfo->bbt.beat - 1 + (timeInfo->bbt.tick / timeInfo->bbt.ticks_per_beat)); + + //lv2_atom_forge_property_head(forge, jalv->urids.time_beat, 0); + lv2_atom_forge_float(forge, timeInfo->bbt.beat - 1); // FIXME: -1 ? + + //lv2_atom_forge_property_head(forge, jalv->urids.time_beatUnit, 0); + lv2_atom_forge_float(forge, timeInfo->bbt.beat_type); + + //lv2_atom_forge_property_head(forge, jalv->urids.time_beatsPerBar, 0); + lv2_atom_forge_float(forge, timeInfo->bbt.beats_per_bar); + + //lv2_atom_forge_property_head(forge, jalv->urids.time_beatsPerMinute, 0); + lv2_atom_forge_float(forge, timeInfo->bbt.beats_per_minute); + } + + LV2_Atom_Event* const aev = getLv2AtomEvent(evIn.data[i].atom, evInAtomOffsets[i]); + aev->time.frames = framesOffset; + aev->body.type = lv2Pos->type; + aev->body.size = lv2Pos->size; + memcpy(LV2_ATOM_BODY(&aev->body), LV2_ATOM_BODY(lv2Pos), lv2Pos->size); + + const uint32_t evInPadSize = lv2_atom_pad_size(sizeof(LV2_Atom_Event) + lv2Pos->size); + evInAtomOffsets[i] += evInPadSize; + evIn.data[i].atom->atom.size += evInPadSize; + + lastTimePosPlaying = timeInfo->playing; + lastTimePosFrame = timeInfo->playing ? timeInfo->frame + frames : timeInfo->frame; + } +#endif + + // TODO - get messages from ringbuffer + + //LV2_Atom_Event* const aev = getLv2AtomEvent(evIn.data[i].atom, evInAtomOffsets[i]); + //aev->time.frames = framesOffset; + //aev->body.type = CARLA_URI_MAP_ID_ATOM_TRANSFER_EVENT; + //aev->body.size = 0; // message size + //memcpy(LV2_ATOM_BODY(&aev->body), nullptr /* message data body */, 0 /* message size */); + } + } + + } // End of Event Input CARLA_PROCESS_CONTINUE_CHECK; @@ -2179,17 +2263,30 @@ public: switch (rdf_descriptor->Ports[rindex].Designation) { + // Non-BBT + case LV2_PORT_DESIGNATION_TIME_FRAME: + setParameterValue(k, timeInfo->frame, false, false, false); + break; + case LV2_PORT_DESIGNATION_TIME_FRAMES_PER_SECOND: + break; + case LV2_PORT_DESIGNATION_TIME_POSITION: + setParameterValue(k, timeInfo->time, false, false, false); + break; + case LV2_PORT_DESIGNATION_TIME_SPEED: + setParameterValue(k, timeInfo->playing ? 1.0 : 0.0, false, false, false); + break; + // BBT case LV2_PORT_DESIGNATION_TIME_BAR: if (timeInfo->valid & CarlaEngineTimeBBT) - setParameterValue(k, timeInfo->bbt.bar, false, false, false); + setParameterValue(k, timeInfo->bbt.bar - 1, false, false, false); break; case LV2_PORT_DESIGNATION_TIME_BAR_BEAT: if (timeInfo->valid & CarlaEngineTimeBBT) - setParameterValue(k, timeInfo->bbt.tick, false, false, false); + setParameterValue(k, timeInfo->bbt.beat - 1 + (timeInfo->bbt.tick / timeInfo->bbt.ticks_per_beat), false, false, false); break; case LV2_PORT_DESIGNATION_TIME_BEAT: - if (timeInfo->valid & CarlaEngineTimeBBT) - setParameterValue(k, timeInfo->bbt.beat, false, false, false); + if (timeInfo->valid & CarlaEngineTimeBBT) // FIXME: -1 ? + setParameterValue(k, timeInfo->bbt.beat - 1, false, false, false); break; case LV2_PORT_DESIGNATION_TIME_BEAT_UNIT: if (timeInfo->valid & CarlaEngineTimeBBT) @@ -2203,18 +2300,6 @@ public: if (timeInfo->valid & CarlaEngineTimeBBT) setParameterValue(k, timeInfo->bbt.beats_per_minute, false, false, false); break; - - case LV2_PORT_DESIGNATION_TIME_FRAME: - setParameterValue(k, timeInfo->frame, false, false, false); - break; - case LV2_PORT_DESIGNATION_TIME_FRAMES_PER_SECOND: - break; - case LV2_PORT_DESIGNATION_TIME_POSITION: - setParameterValue(k, timeInfo->time, false, false, false); - break; - case LV2_PORT_DESIGNATION_TIME_SPEED: - setParameterValue(k, timeInfo->playing ? 1.0 : 0.0, false, false, false); - break; } } } @@ -2436,10 +2521,13 @@ public: CARLA_PROCESS_CONTINUE_CHECK; // -------------------------------------------------------------------------------------------------------- - // MIDI Output + // Event Output if (evOut.count > 0 && m_active) { + // ---------------------------------------------------------------------------------------------------- + // MIDI Output + for (i=0; i < evOut.count; i++) { if (! evOut.data[i].port) @@ -2499,7 +2587,13 @@ public: } } } - } // End of MIDI Output + + // ---------------------------------------------------------------------------------------------------- + // Message Output + + // TODO + + } // End of Event Output CARLA_PROCESS_CONTINUE_CHECK; @@ -4253,6 +4347,9 @@ private: Lv2PluginEventData evOut; float* paramBuffers; std::vector customURIDs; + + bool lastTimePosPlaying; + uint32_t lastTimePosFrame; }; CarlaPlugin* CarlaPlugin::newLV2(const initializer& init)