22 LV2_Atom_Forge &forge,
const int64_t frameTime,
const float speed
33 lv2_atom_forge_set_buffer(&forge, buf, port->mMinimumSize);
34 LV2_Atom_Forge_Frame seqFrame;
35 const auto seq =
reinterpret_cast<LV2_Atom_Sequence *
>(
36 lv2_atom_forge_sequence_head(&forge, &seqFrame, 0));
37 if (port->mWantsPosition) {
38 lv2_atom_forge_frame_time(&forge, frameTime);
39 LV2_Atom_Forge_Frame posFrame;
40 lv2_atom_forge_object(&forge, &posFrame, 0, urid_Position);
41 lv2_atom_forge_key(&forge, urid_Speed);
42 lv2_atom_forge_float(&forge, speed);
43 lv2_atom_forge_key(&forge, urid_Frame);
44 lv2_atom_forge_long(&forge, frameTime);
45 lv2_atom_forge_pop(&forge, &posFrame);
49 const auto ring =
mRing.get();
52 if (forge.offset +
sizeof(LV2_Atom_Event) + atom.size < forge.size){
53 lv2_atom_forge_frame_time(&forge, frameTime);
54 lv2_atom_forge_write(&forge, &atom,
sizeof(atom));
56 forge.offset += atom.size;
57 seq->atom.size += atom.size;
61 wxLogError(
wxT(
"LV2 sequence buffer overflow"));
64 lv2_atom_forge_pop(&forge, &seqFrame);
66 LV2_ATOM_SEQUENCE_FOREACH(seq, ev) {
67 auto o =
reinterpret_cast<LV2_Atom_Object *
>(&ev->body);
68 wxLogDebug(
wxT(
"ev = %lld ev.size %d ev.type %d"), ev->time.frames, ev->body.size, ev->body.type);
81 if (!port->mIsInput) {
83 *
reinterpret_cast<LV2_Atom *
>(buf) = { port->mMinimumSize, urid_Chunk };
88 std::function<
void(
const LV2_Atom *atom, uint32_t
size)>
handler)
90 const auto ring =
mRing.get();
91 const auto minimumSize =
mpPort->mMinimumSize;
92 const auto space = std::make_unique<char[]>(minimumSize);
93 auto atom =
reinterpret_cast<LV2_Atom*
>(space.get());
97 uint32_t
size = lv2_atom_total_size(atom);
98 if (
size < minimumSize) {
100 LV2_ATOM_CONTENTS(LV2_Atom, atom), atom->size);
105 wxLogError(
wxT(
"LV2 sequence buffer overflow"));
113 const auto ring =
mRing.get();
114 LV2_ATOM_SEQUENCE_FOREACH(
115 reinterpret_cast<LV2_Atom_Sequence *
>(
mBuffer.get()), ev
117 zix_ring_write(ring, &ev->body, ev->body.size +
sizeof(LV2_Atom));
122 const void *buffer, uint32_t buffer_size)
131 for (; s > 0 && --s;)
141 return std::make_unique<LV2EffectOutputs>(*
this);
149 assert(srcValues.size() == dstValues.size());
150 copy(srcValues.begin(), srcValues.end(), dstValues.data());
159 auto numPorts = lilv_plugin_get_num_ports(&plug);
160 Floats minimumVals {numPorts};
161 Floats maximumVals {numPorts};
162 Floats defaultVals {numPorts};
163 lilv_plugin_get_port_ranges_float(&plug,
164 minimumVals.get(), maximumVals.get(), defaultVals.get());
166 for (
size_t i = 0; i < numPorts; ++i) {
167 const auto port = lilv_plugin_get_port_by_index(&plug, i);
168 int index = lilv_port_get_index(&plug, port);
172 if (lilv_port_is_a(&plug, port, node_InputPort))
174 else if (lilv_port_is_a(&plug, port, node_OutputPort))
182 const auto symbol =
LilvString(lilv_port_get_symbol(&plug, port));
187 if (
LilvNodePtr group{ lilv_port_get(&plug, port, node_Group) }) {
191 lilv_world_get(
gWorld, group.get(), node_Label,
nullptr));
192 if (groupMsg.empty())
194 lilv_world_get(
gWorld, group.get(), node_Name,
nullptr));
195 if (groupMsg.empty())
200 groupName =
XO(
"Effect Settings");
203 const auto latencyIndex = lilv_plugin_get_latency_port_index(&plug);
206 LilvNodePtr designation{ lilv_port_get(&plug, port, node_Designation) };
209 if (lilv_port_is_a(&plug, port, node_AudioPort)) {
210 mAudioPorts.push_back(std::make_shared<LV2AudioPort>(
211 port, index, isInput, symbol,
name, groupName));
215 else if (lilv_port_is_a(&plug, port, node_ControlPort)) {
224 if (
LilvNodePtr unit{ lilv_port_get(&plug, port, node_Unit) })
230 bool hasLo = !std::isnan(minimumVals[i]);
231 bool hasHi = !std::isnan(maximumVals[i]);
232 float min = hasLo ? minimumVals[i] : 0.0f;
233 float max = hasHi ? maximumVals[i] : 1.0f;
234 float def = !std::isnan(defaultVals[i])
243 bool toggle = isInput &&
244 lilv_port_has_property(&plug, port, node_Toggled);
245 bool enumeration = isInput &&
246 lilv_port_has_property(&plug, port, node_Enumeration);
247 bool integer = isInput &&
248 lilv_port_has_property(&plug, port, node_Integer);
250 lilv_port_has_property(&plug, port, node_SampleRate);
254 bool trigger = isInput &&
255 lilv_port_has_property(&plug, port, node_Trigger);
257 bool logarithmic = isInput &&
258 lilv_port_has_property(&plug, port, node_Logarithmic);
261 std::vector<double> scaleValues;
262 wxArrayString scaleLabels;
264 using LilvScalePointsPtr =
266 LilvScalePointsPtr points{
267 lilv_port_get_scale_points(&plug, port) };
268 LILV_FOREACH(scale_points, j, points.get()) {
269 const auto point = lilv_scale_points_get(points.get(), j);
270 scaleValues.push_back(
271 lilv_node_as_float(lilv_scale_point_get_value(point)));
272 scaleLabels.push_back(
273 LilvString(lilv_scale_point_get_label(point)));
278 std::make_shared<LV2ControlPort>(
279 port, index, isInput, symbol,
name, groupName,
280 move(scaleValues), std::move(scaleLabels), units,
281 min, max, def, hasLo, hasHi,
283 trigger, logarithmic));
287 else if (controlPort->mIndex == latencyIndex)
291 else if (lilv_port_is_a(&plug, port, node_AtomPort)) {
292 uint32_t minimumSize = 8192;
293 if (
LilvNodePtr min{ lilv_port_get(&plug, port, node_MinimumSize) }
294 ; lilv_node_is_int(
min.get())
296 if (
auto value = lilv_node_as_int(
min.get())
299 minimumSize = std::max<uint32_t>(minimumSize, value);
302 lilv_port_supports_event(&plug, port, node_Position);
303 bool isMidi = lilv_port_supports_event(&plug, port, node_MidiEvent);
306 mAtomPorts.push_back(std::make_shared<LV2AtomPort>(
307 port, index, isInput, symbol,
name, groupName,
308 minimumSize, isMidi, wantsPosition));
309 bool isControl = lilv_node_equals(designation.get(), node_Control);
318 else if (lilv_port_is_a(&plug, port, node_CVPort)) {
325 if (!std::isnan(minimumVals[i]))
326 hasLo =
true,
min = minimumVals[i];
327 if (!std::isnan(maximumVals[i]))
328 hasHi =
true, max = maximumVals[i];
329 if (!std::isnan(defaultVals[i]))
330 def = defaultVals[i];
335 mCVPorts.push_back(std::make_shared<LV2CVPort>(
336 port, index, isInput, symbol,
name, groupName,
337 min, max, def, hasLo, hasHi));
349 const char *port_symbol,
void *user_data, uint32_t *
size, uint32_t *type)
352 return ports.GetPortValue(
settings, port_symbol,
size, type);
357 const char *port_symbol, uint32_t *
size, uint32_t *type)
const
359 wxString symbol = wxString::FromUTF8(port_symbol);
362 if (port->mSymbol == symbol) {
363 *
size =
sizeof(float);
364 *type = LV2Symbols::urid_Float;
377 const char *port_symbol,
void *user_data,
378 const void *value, uint32_t
size, uint32_t type)
381 ports.SetPortValue(
settings, port_symbol, value,
size, type);
386 const char *port_symbol,
const void *value, uint32_t
size, uint32_t type)
389 wxString symbol = wxString::FromUTF8(port_symbol);
392 if (port->mSymbol == symbol) {
395 if (type == urid_Bool &&
size ==
sizeof(
bool))
396 dst = *
static_cast<const bool *
>(value) ? 1.0f : 0.0f;
397 else if (type == urid_Double &&
size ==
sizeof(
double))
398 dst = *
static_cast<const double *
>(value);
399 else if (type == urid_Float &&
size ==
sizeof(
float))
400 dst = *
static_cast<const float *
>(value);
401 else if (type == urid_Int &&
size ==
sizeof(int32_t))
402 dst = *
static_cast<const int32_t *
>(value);
403 else if (type == urid_Long &&
size ==
sizeof(int64_t))
404 dst = *
static_cast<const int64_t *
>(value);
414 SetValueData data{ *
this,
settings };
423 std::make_shared<LV2AtomPortState>(atomPort));
440 state.mLo = controlPort->mMin;
441 state.mHi = controlPort->mMax;
442 state.mLst = controlPort->mDef;
Declare URI identifiers used in calls to the lv2 library and a mapping of them to integers.
wxString LilvString(const LilvNode *node)
std::unique_ptr< Type, Lilv_deleter< Type, f > > Lilv_ptr
Generate classes of smart pointers to lv2 resources.
wxString LilvStringMove(LilvNode *node)
Lilv_ptr< LilvNode, lilv_node_free > LilvNodePtr
static Settings & settings()
TranslatableString Verbatim(wxString str)
Require calls to the one-argument constructor to go through this distinct global function name.
Hold values to send to effect output meters.
size_t Discretize(float value) const
Map a real number to one of the scale points.
const std::vector< double > mScaleValues
LV2PortStates(const LV2Ports &ports)
LV2CVPortStateArray mCVPortStates
LV2AtomPortStateArray mAtomPortStates
LV2AtomPortStatePtr mControlIn
LV2PortUIStates(const LV2PortStates &states, const LV2Ports &ports)
LV2ControlPortStateArray mControlPortStates
LV2AtomPortStatePtr mControlOut
std::unordered_map< TranslatableString, std::vector< int > > mGroupMap
void EmitPortValues(const LilvState &state, LV2EffectSettings &settings) const
std::optional< size_t > mControlInIdx
const void * GetPortValue(const LV2EffectSettings &settings, const char *port_symbol, uint32_t *size, uint32_t *type) const
TranslatableStrings mGroups
LV2Ports(const LilvPlugin &plug)
LV2ControlPortArray mControlPorts
LV2AtomPortArray mAtomPorts
std::optional< size_t > mControlOutIdx
void SetPortValue(LV2EffectSettings &settings, const char *port_symbol, const void *value, uint32_t size, uint32_t type) const
std::unordered_map< uint32_t, size_t > mControlPortMap
LV2AudioPortArray mAudioPorts
Holds a msgid for the translation catalog; may also bind format arguments.
uint32_t zix_ring_read(ZixRing *ring, void *dst, uint32_t size)
uint32_t zix_ring_write(ZixRing *ring, const void *src, uint32_t size)
uint32_t zix_ring_skip(ZixRing *ring, uint32_t size)
constexpr auto sampleRate
const void * get_value_func(const char *port_symbol, void *user_data, uint32_t *size, uint32_t *type)
void set_value_func(const char *port_symbol, void *user_data, const void *value, uint32_t size, uint32_t type)
AuthorizationHandler handler
void copy(const T *src, T *dst, int32_t n)
void SendToInstance(LV2_Atom_Forge &forge, int64_t frameTime, float speed)
Transfer incoming events from the ring buffer to the event buffer.
const std::unique_ptr< uint8_t[]> mBuffer
const Lilv_ptr< ZixRing, zix_ring_free > mRing
void SendToDialog(std::function< void(const LV2_Atom *atom, uint32_t size)> handler)
Dialog can poll one ring buffer for messages at idle time.
void ReceiveFromDialog(const void *buffer, uint32_t buffer_size)
Dialog pushes to other ring buffer when it gets a user interface event.
void ReceiveFromInstance()
Take responses from the instance and send cross-thread for the dialog.
void ResetForInstanceOutput()
const LV2AtomPortPtr mpPort
Carry output control port information back to main thread.
std::unique_ptr< EffectOutputs > Clone() const override
void Assign(EffectOutputs &&src) override
Update one Outputs object from another.
~LV2EffectOutputs() override
std::vector< float > values
vector of values in correspondence with the control ports
Storage locations to be connected to LV2 control ports.