3 * Copyright (C) 2011-2022 Filipe Coelho <falktx@falktx.com>
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License as
7 * published by the Free Software Foundation; either version 2 of
8 * the License, or any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * For a full copy of the GNU General Public License see the doc/GPL.txt file.
18 #include "CarlaBridgeFormat.hpp"
19 #include "CarlaBridgeToolkit.hpp"
21 #include "CarlaLibUtils.hpp"
22 #include "CarlaLv2Utils.hpp"
23 #include "CarlaMIDI.h"
24 #include "LinkedList.hpp"
26 #include "water/files/File.h"
29 # include "CarlaMacUtils.hpp"
35 #define URI_CARLA_ATOM_WORKER_IN "http://kxstudio.sf.net/ns/carla/atomWorkerIn"
36 #define URI_CARLA_ATOM_WORKER_RESP "http://kxstudio.sf.net/ns/carla/atomWorkerResp"
37 #define URI_CARLA_PARAMETER_CHANGE "http://kxstudio.sf.net/ns/carla/parameterChange"
41 CARLA_BRIDGE_UI_START_NAMESPACE
43 // --------------------------------------------------------------------------------------------------------------------
45 static double gInitialSampleRate
= 44100.0;
46 static const char* const kNullWindowTitle
= "TestUI";
47 static const uint32_t kNullWindowTitleSize
= 6;
48 static const char* const kUnmapFallback
= "urn:null";
74 kUridAtomTransferAtom
,
75 kUridAtomTransferEvent
,
78 kUridBufNominalLength
,
96 kUridTimeBeatsPerMinute
,
98 kUridTimeFramesPerSecond
,
100 kUridTimeTicksPerBeat
,
102 kUridParamSampleRate
,
104 kUridBackgroundColor
,
105 kUridForegroundColor
,
110 // custom carla props
111 kUridCarlaAtomWorkerIn
,
112 kUridCarlaAtomWorkerResp
,
113 kUridCarlaParameterChange
,
114 kUridCarlaTransientWindowId
,
120 enum CarlaLv2Features
{
125 kFeatureIdStateFreePath
,
126 kFeatureIdStateMakePath
,
127 kFeatureIdStateMapPath
,
131 kFeatureIdUiIdleInterface
,
132 kFeatureIdUiFixedSize
,
133 kFeatureIdUiMakeResident
,
134 kFeatureIdUiMakeResident2
,
135 kFeatureIdUiNoUserResize
,
138 kFeatureIdUiPortSubscribe
,
139 kFeatureIdUiRequestValue
,
145 // --------------------------------------------------------------------------------------------------------------------
147 struct Lv2PluginOptions
{
162 int64_t transientWinId
;
166 LV2_Options_Option opts
[Count
];
168 Lv2PluginOptions() noexcept
169 : sampleRate(static_cast<float>(gInitialSampleRate
)),
175 LV2_Options_Option
& optSampleRate(opts
[SampleRate
]);
176 optSampleRate
.context
= LV2_OPTIONS_INSTANCE
;
177 optSampleRate
.subject
= 0;
178 optSampleRate
.key
= kUridParamSampleRate
;
179 optSampleRate
.size
= sizeof(float);
180 optSampleRate
.type
= kUridAtomFloat
;
181 optSampleRate
.value
= &sampleRate
;
183 LV2_Options_Option
& optBackgroundColor(opts
[BackgroundColor
]);
184 optBackgroundColor
.context
= LV2_OPTIONS_INSTANCE
;
185 optBackgroundColor
.subject
= 0;
186 optBackgroundColor
.key
= kUridBackgroundColor
;
187 optBackgroundColor
.size
= sizeof(int32_t);
188 optBackgroundColor
.type
= kUridAtomInt
;
189 optBackgroundColor
.value
= &bgColor
;
191 LV2_Options_Option
& optForegroundColor(opts
[ForegroundColor
]);
192 optForegroundColor
.context
= LV2_OPTIONS_INSTANCE
;
193 optForegroundColor
.subject
= 0;
194 optForegroundColor
.key
= kUridForegroundColor
;
195 optForegroundColor
.size
= sizeof(int32_t);
196 optForegroundColor
.type
= kUridAtomInt
;
197 optForegroundColor
.value
= &fgColor
;
200 LV2_Options_Option
& optScaleFactor(opts
[ScaleFactor
]);
201 optScaleFactor
.context
= LV2_OPTIONS_INSTANCE
;
202 optScaleFactor
.subject
= 0;
203 optScaleFactor
.key
= kUridScaleFactor
;
204 optScaleFactor
.size
= sizeof(float);
205 optScaleFactor
.type
= kUridAtomFloat
;
206 optScaleFactor
.value
= &uiScale
;
209 LV2_Options_Option
& optTransientWinId(opts
[TransientWinId
]);
210 optTransientWinId
.context
= LV2_OPTIONS_INSTANCE
;
211 optTransientWinId
.subject
= 0;
212 optTransientWinId
.key
= kUridCarlaTransientWindowId
;
213 optTransientWinId
.size
= sizeof(int64_t);
214 optTransientWinId
.type
= kUridAtomLong
;
215 optTransientWinId
.value
= &transientWinId
;
217 LV2_Options_Option
& optWindowTitle(opts
[WindowTitle
]);
218 optWindowTitle
.context
= LV2_OPTIONS_INSTANCE
;
219 optWindowTitle
.subject
= 0;
220 optWindowTitle
.key
= kUridWindowTitle
;
221 optWindowTitle
.size
= kNullWindowTitleSize
;
222 optWindowTitle
.type
= kUridAtomString
;
223 optWindowTitle
.value
= kNullWindowTitle
;
225 LV2_Options_Option
& optNull(opts
[Null
]);
226 optNull
.context
= LV2_OPTIONS_INSTANCE
;
228 optNull
.key
= kUridNull
;
230 optNull
.type
= kUridNull
;
231 optNull
.value
= nullptr;
235 // -------------------------------------------------------------------------------------------------------------------
237 static void initAtomForge(LV2_Atom_Forge
& atomForge
) noexcept
239 carla_zeroStruct(atomForge
);
241 atomForge
.Bool
= kUridAtomBool
;
242 atomForge
.Chunk
= kUridAtomChunk
;
243 atomForge
.Double
= kUridAtomDouble
;
244 atomForge
.Float
= kUridAtomFloat
;
245 atomForge
.Int
= kUridAtomInt
;
246 atomForge
.Literal
= kUridAtomLiteral
;
247 atomForge
.Long
= kUridAtomLong
;
248 atomForge
.Object
= kUridAtomObject
;
249 atomForge
.Path
= kUridAtomPath
;
250 atomForge
.Property
= kUridAtomProperty
;
251 atomForge
.Sequence
= kUridAtomSequence
;
252 atomForge
.String
= kUridAtomString
;
253 atomForge
.Tuple
= kUridAtomTuple
;
254 atomForge
.URI
= kUridAtomURI
;
255 atomForge
.URID
= kUridAtomURID
;
256 atomForge
.Vector
= kUridAtomVector
;
258 #if defined(__clang__)
259 # pragma clang diagnostic push
260 # pragma clang diagnostic ignored "-Wdeprecated-declarations"
261 #elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
262 # pragma GCC diagnostic push
263 # pragma GCC diagnostic ignored "-Wdeprecated-declarations"
265 atomForge
.Blank
= kUridAtomBlank
;
266 atomForge
.Resource
= kUridAtomResource
;
267 #if defined(__clang__)
268 # pragma clang diagnostic pop
269 #elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6))
270 # pragma GCC diagnostic pop
274 // --------------------------------------------------------------------------------------------------------------------
276 class CarlaLv2Client
: public CarlaBridgeFormat
280 : CarlaBridgeFormat(),
283 fDescriptor(nullptr),
284 fRdfDescriptor(nullptr),
285 fRdfUiDescriptor(nullptr),
286 fControlDesignatedPort(0),
289 fCustomURIDs(kUridCount
, std::string("urn:null")),
292 CARLA_SAFE_ASSERT(fCustomURIDs
.size() == kUridCount
);
294 carla_zeroPointers(fFeatures
, kFeatureCount
+1);
296 // ------------------------------------------------------------------------------------------------------------
297 // initialize features (part 1)
299 LV2_Log_Log
* const logFt
= new LV2_Log_Log
;
300 logFt
->handle
= this;
301 logFt
->printf
= carla_lv2_log_printf
;
302 logFt
->vprintf
= carla_lv2_log_vprintf
;
304 LV2_State_Free_Path
* const stateFreePathFt
= new LV2_State_Free_Path
;
305 stateFreePathFt
->handle
= this;
306 stateFreePathFt
->free_path
= carla_lv2_state_free_path
;
308 LV2_State_Make_Path
* const stateMakePathFt
= new LV2_State_Make_Path
;
309 stateMakePathFt
->handle
= this;
310 stateMakePathFt
->path
= carla_lv2_state_make_path_tmp
;
312 LV2_State_Map_Path
* const stateMapPathFt
= new LV2_State_Map_Path
;
313 stateMapPathFt
->handle
= this;
314 stateMapPathFt
->abstract_path
= carla_lv2_state_map_abstract_path_tmp
;
315 stateMapPathFt
->absolute_path
= carla_lv2_state_map_absolute_path_tmp
;
317 LV2_Programs_Host
* const programsFt
= new LV2_Programs_Host
;
318 programsFt
->handle
= this;
319 programsFt
->program_changed
= carla_lv2_program_changed
;
321 LV2_URI_Map_Feature
* const uriMapFt
= new LV2_URI_Map_Feature
;
322 uriMapFt
->callback_data
= this;
323 uriMapFt
->uri_to_id
= carla_lv2_uri_to_id
;
325 LV2_URID_Map
* const uridMapFt
= new LV2_URID_Map
;
326 uridMapFt
->handle
= this;
327 uridMapFt
->map
= carla_lv2_urid_map
;
329 LV2_URID_Unmap
* const uridUnmapFt
= new LV2_URID_Unmap
;
330 uridUnmapFt
->handle
= this;
331 uridUnmapFt
->unmap
= carla_lv2_urid_unmap
;
333 LV2UI_Port_Map
* const uiPortMapFt
= new LV2UI_Port_Map
;
334 uiPortMapFt
->handle
= this;
335 uiPortMapFt
->port_index
= carla_lv2_ui_port_map
;
337 LV2UI_Request_Value
* const uiRequestValueFt
= new LV2UI_Request_Value
;
338 uiRequestValueFt
->handle
= this;
339 uiRequestValueFt
->request
= carla_lv2_ui_request_value
;
341 LV2UI_Resize
* const uiResizeFt
= new LV2UI_Resize
;
342 uiResizeFt
->handle
= this;
343 uiResizeFt
->ui_resize
= carla_lv2_ui_resize
;
345 // ------------------------------------------------------------------------------------------------------------
346 // initialize features (part 2)
348 for (uint32_t i
=0; i
< kFeatureCount
; ++i
)
349 fFeatures
[i
] = new LV2_Feature
;
351 fFeatures
[kFeatureIdLogs
]->URI
= LV2_LOG__log
;
352 fFeatures
[kFeatureIdLogs
]->data
= logFt
;
354 fFeatures
[kFeatureIdOptions
]->URI
= LV2_OPTIONS__options
;
355 fFeatures
[kFeatureIdOptions
]->data
= fLv2Options
.opts
;
357 fFeatures
[kFeatureIdPrograms
]->URI
= LV2_PROGRAMS__Host
;
358 fFeatures
[kFeatureIdPrograms
]->data
= programsFt
;
360 fFeatures
[kFeatureIdStateFreePath
]->URI
= LV2_STATE__freePath
;
361 fFeatures
[kFeatureIdStateFreePath
]->data
= stateFreePathFt
;
363 fFeatures
[kFeatureIdStateMakePath
]->URI
= LV2_STATE__makePath
;
364 fFeatures
[kFeatureIdStateMakePath
]->data
= stateMakePathFt
;
366 fFeatures
[kFeatureIdStateMapPath
]->URI
= LV2_STATE__mapPath
;
367 fFeatures
[kFeatureIdStateMapPath
]->data
= stateMapPathFt
;
369 fFeatures
[kFeatureIdUriMap
]->URI
= LV2_URI_MAP_URI
;
370 fFeatures
[kFeatureIdUriMap
]->data
= uriMapFt
;
372 fFeatures
[kFeatureIdUridMap
]->URI
= LV2_URID__map
;
373 fFeatures
[kFeatureIdUridMap
]->data
= uridMapFt
;
375 fFeatures
[kFeatureIdUridUnmap
]->URI
= LV2_URID__unmap
;
376 fFeatures
[kFeatureIdUridUnmap
]->data
= uridUnmapFt
;
378 fFeatures
[kFeatureIdUiIdleInterface
]->URI
= LV2_UI__idleInterface
;
379 fFeatures
[kFeatureIdUiIdleInterface
]->data
= nullptr;
381 fFeatures
[kFeatureIdUiFixedSize
]->URI
= LV2_UI__fixedSize
;
382 fFeatures
[kFeatureIdUiFixedSize
]->data
= nullptr;
384 fFeatures
[kFeatureIdUiMakeResident
]->URI
= LV2_UI__makeResident
;
385 fFeatures
[kFeatureIdUiMakeResident
]->data
= nullptr;
387 fFeatures
[kFeatureIdUiMakeResident2
]->URI
= LV2_UI__makeSONameResident
;
388 fFeatures
[kFeatureIdUiMakeResident2
]->data
= nullptr;
390 fFeatures
[kFeatureIdUiNoUserResize
]->URI
= LV2_UI__noUserResize
;
391 fFeatures
[kFeatureIdUiNoUserResize
]->data
= nullptr;
393 fFeatures
[kFeatureIdUiParent
]->URI
= LV2_UI__parent
;
394 fFeatures
[kFeatureIdUiParent
]->data
= nullptr;
396 fFeatures
[kFeatureIdUiPortMap
]->URI
= LV2_UI__portMap
;
397 fFeatures
[kFeatureIdUiPortMap
]->data
= uiPortMapFt
;
399 fFeatures
[kFeatureIdUiPortSubscribe
]->URI
= LV2_UI__portSubscribe
;
400 fFeatures
[kFeatureIdUiPortSubscribe
]->data
= nullptr;
402 fFeatures
[kFeatureIdUiRequestValue
]->URI
= LV2_UI__requestValue
;
403 fFeatures
[kFeatureIdUiRequestValue
]->data
= uiRequestValueFt
;
405 fFeatures
[kFeatureIdUiResize
]->URI
= LV2_UI__resize
;
406 fFeatures
[kFeatureIdUiResize
]->data
= uiResizeFt
;
408 fFeatures
[kFeatureIdUiTouch
]->URI
= LV2_UI__touch
;
409 fFeatures
[kFeatureIdUiTouch
]->data
= nullptr;
412 ~CarlaLv2Client() override
414 if (fHandle
!= nullptr && fDescriptor
!= nullptr && fDescriptor
->cleanup
!= nullptr)
416 fDescriptor
->cleanup(fHandle
);
420 if (fRdfDescriptor
!= nullptr)
422 delete fRdfDescriptor
;
423 fRdfDescriptor
= nullptr;
426 fRdfUiDescriptor
= nullptr;
428 delete (LV2_Log_Log
*)fFeatures
[kFeatureIdLogs
]->data
;
429 delete (LV2_State_Free_Path
*)fFeatures
[kFeatureIdStateFreePath
]->data
;
430 delete (LV2_State_Make_Path
*)fFeatures
[kFeatureIdStateMakePath
]->data
;
431 delete (LV2_State_Map_Path
*)fFeatures
[kFeatureIdStateMapPath
]->data
;
432 delete (LV2_Programs_Host
*)fFeatures
[kFeatureIdPrograms
]->data
;
433 delete (LV2_URI_Map_Feature
*)fFeatures
[kFeatureIdUriMap
]->data
;
434 delete (LV2_URID_Map
*)fFeatures
[kFeatureIdUridMap
]->data
;
435 delete (LV2_URID_Unmap
*)fFeatures
[kFeatureIdUridUnmap
]->data
;
436 delete (LV2UI_Port_Map
*)fFeatures
[kFeatureIdUiPortMap
]->data
;
437 delete (LV2UI_Request_Value
*)fFeatures
[kFeatureIdUiRequestValue
]->data
;
438 delete (LV2UI_Resize
*)fFeatures
[kFeatureIdUiResize
]->data
;
440 for (uint32_t i
=0; i
< kFeatureCount
; ++i
)
442 if (fFeatures
[i
] != nullptr)
445 fFeatures
[i
] = nullptr;
450 // ----------------------------------------------------------------------------------------------------------------
453 bool init(const int argc
, const char* argv
[]) override
455 const char* pluginURI
= argv
[1];
456 const char* uiURI
= argc
> 2 ? argv
[2] : nullptr;
458 // ------------------------------------------------------------------------------------------------------------
461 Lv2WorldClass
& lv2World(Lv2WorldClass::getInstance());
462 lv2World
.initIfNeeded(std::getenv("LV2_PATH"));
465 Lilv::Node
bundleNode(lv2World
.new_file_uri(nullptr, uiBundle
));
466 CARLA_SAFE_ASSERT_RETURN(bundleNode
.is_uri(), false);
468 CarlaString
sBundle(bundleNode
.as_uri());
470 if (! sBundle
.endsWith("/"))
473 lv2World
.load_bundle(sBundle
);
476 // ------------------------------------------------------------------------------------------------------------
477 // get plugin from lv2_rdf (lilv)
479 fRdfDescriptor
= lv2_rdf_new(pluginURI
, false);
480 CARLA_SAFE_ASSERT_RETURN(fRdfDescriptor
!= nullptr, false);
482 // ------------------------------------------------------------------------------------------------------------
485 if (uiURI
== nullptr)
487 CARLA_SAFE_ASSERT_RETURN(fRdfDescriptor
->UICount
> 0, false);
489 fRdfUiDescriptor
= &fRdfDescriptor
->UIs
[0];
490 uiURI
= fRdfUiDescriptor
->URI
;
494 for (uint32_t i
=0; i
< fRdfDescriptor
->UICount
; ++i
)
496 if (std::strcmp(fRdfDescriptor
->UIs
[i
].URI
, uiURI
) == 0)
498 fRdfUiDescriptor
= &fRdfDescriptor
->UIs
[i
];
504 CARLA_SAFE_ASSERT_RETURN(fRdfUiDescriptor
!= nullptr, false);
506 // ------------------------------------------------------------------------------------------------------------
507 // check if not resizable
509 for (uint32_t i
=0; i
< fRdfUiDescriptor
->FeatureCount
; ++i
)
511 if (std::strcmp(fRdfUiDescriptor
->Features
[i
].URI
, LV2_UI__fixedSize
) == 0 ||
512 std::strcmp(fRdfUiDescriptor
->Features
[i
].URI
, LV2_UI__noUserResize
) == 0)
514 fUiOptions
.isResizable
= false;
519 // ------------------------------------------------------------------------------------------------------------
522 if (! CarlaBridgeFormat::init(argc
, argv
))
525 // ------------------------------------------------------------------------------------------------------------
529 // Binary might be in quarentine due to Apple stupid notarization rules, let's remove that if possible
530 CARLA_BACKEND_NAMESPACE::removeFileFromQuarantine(fRdfUiDescriptor
->Binary
);
533 if (! libOpen(fRdfUiDescriptor
->Binary
))
535 carla_stderr("Failed to load UI binary, error was:\n%s", libError());
539 // ------------------------------------------------------------------------------------------------------------
540 // get DLL main entry
542 const LV2UI_DescriptorFunction ui_descFn
= (LV2UI_DescriptorFunction
)libSymbol("lv2ui_descriptor");
544 if (ui_descFn
== nullptr)
547 // ------------------------------------------------------------------------------------------------------------
548 // get descriptor that matches URI
550 for (uint32_t i
=0; (fDescriptor
= ui_descFn(i
++)) != nullptr;)
552 if (std::strcmp(fDescriptor
->URI
, uiURI
) == 0)
556 if (fDescriptor
== nullptr)
558 carla_stderr("Failed to find UI descriptor");
562 // ------------------------------------------------------------------------------------------------------------
565 #if defined(BRIDGE_COCOA) || defined(BRIDGE_HWND) || defined(BRIDGE_X11)
566 fFeatures
[kFeatureIdUiParent
]->data
= fToolkit
->getContainerId();
569 fHandle
= fDescriptor
->instantiate(fDescriptor
, fRdfDescriptor
->URI
, fRdfUiDescriptor
->Bundle
,
570 carla_lv2_ui_write_function
, this, &fWidget
, fFeatures
);
571 CARLA_SAFE_ASSERT_RETURN(fHandle
!= nullptr, false);
573 #if defined(BRIDGE_COCOA) || defined(BRIDGE_HWND) || defined(BRIDGE_X11)
574 if (fWidget
!= nullptr)
575 fToolkit
->setChildWindow(fWidget
);
578 // ------------------------------------------------------------------------------------------------------------
579 // check for known extensions
581 if (fDescriptor
->extension_data
!= nullptr)
583 fExt
.options
= (const LV2_Options_Interface
*)fDescriptor
->extension_data(LV2_OPTIONS__interface
);
584 fExt
.programs
= (const LV2_Programs_UI_Interface
*)fDescriptor
->extension_data(LV2_PROGRAMS__UIInterface
);
585 fExt
.idle
= (const LV2UI_Idle_Interface
*)fDescriptor
->extension_data(LV2_UI__idleInterface
);
586 fExt
.resize
= (const LV2UI_Resize
*)fDescriptor
->extension_data(LV2_UI__resize
);
589 if (fExt
.programs
!= nullptr && fExt
.programs
->select_program
== nullptr)
590 fExt
.programs
= nullptr;
591 if (fExt
.idle
!= nullptr && fExt
.idle
->idle
== nullptr)
593 if (fExt
.resize
!= nullptr && fExt
.resize
->ui_resize
== nullptr)
594 fExt
.resize
= nullptr;
597 for (uint32_t i
=0; i
<fRdfDescriptor
->PortCount
; ++i
)
599 if (LV2_IS_PORT_DESIGNATION_CONTROL(fRdfDescriptor
->Ports
[i
].Designation
))
601 fControlDesignatedPort
= i
;
609 void idleUI() override
611 #if defined(BRIDGE_COCOA) || defined(BRIDGE_HWND) || defined(BRIDGE_X11)
612 if (fHandle
!= nullptr && fExt
.idle
!= nullptr && fExt
.idle
->idle(fHandle
) != 0)
614 if (isPipeRunning() && ! fQuitReceived
)
615 writeExitingMessageAndWait();
620 // ----------------------------------------------------------------------------------------------------------------
623 void* getWidget() const noexcept override
628 const Options
& getOptions() const noexcept override
633 // ----------------------------------------------------------------------------------------------------------------
636 void dspParameterChanged(const uint32_t index
, const float value
) override
638 CARLA_SAFE_ASSERT_RETURN(fHandle
!= nullptr,)
639 CARLA_SAFE_ASSERT_RETURN(fDescriptor
!= nullptr,);
641 if (fDescriptor
->port_event
== nullptr)
644 fDescriptor
->port_event(fHandle
, index
, sizeof(float), kUridNull
, &value
);
647 void dspParameterChanged(const char* const uri
, const float value
) override
649 CARLA_SAFE_ASSERT_RETURN(fHandle
!= nullptr,)
650 CARLA_SAFE_ASSERT_RETURN(fDescriptor
!= nullptr,);
652 if (fDescriptor
->port_event
== nullptr)
655 uint32_t parameterId
= UINT32_MAX
;
657 for (uint32_t i
=0; i
< fRdfDescriptor
->ParameterCount
; ++i
)
659 const LV2_RDF_Parameter
& rdfParam(fRdfDescriptor
->Parameters
[i
]);
661 if (std::strcmp(rdfParam
.URI
, uri
) == 0)
668 if (parameterId
== UINT32_MAX
)
671 uint8_t atomBuf
[256];
672 LV2_Atom_Forge atomForge
;
673 initAtomForge(atomForge
);
674 lv2_atom_forge_set_buffer(&atomForge
, atomBuf
, sizeof(atomBuf
));
676 LV2_Atom_Forge_Frame forgeFrame
;
677 lv2_atom_forge_object(&atomForge
, &forgeFrame
, kUridNull
, kUridPatchSet
);
679 lv2_atom_forge_key(&atomForge
, kUridCarlaParameterChange
);
680 lv2_atom_forge_bool(&atomForge
, true);
682 lv2_atom_forge_key(&atomForge
, kUridPatchProperty
);
683 lv2_atom_forge_urid(&atomForge
, getCustomURID(uri
));
685 lv2_atom_forge_key(&atomForge
, kUridPatchValue
);
687 switch (fRdfDescriptor
->Parameters
[parameterId
].Type
)
689 case LV2_PARAMETER_TYPE_BOOL
:
690 lv2_atom_forge_bool(&atomForge
, value
> 0.5f
);
692 case LV2_PARAMETER_TYPE_INT
:
693 lv2_atom_forge_int(&atomForge
, static_cast<int32_t>(value
+ 0.5f
));
695 case LV2_PARAMETER_TYPE_LONG
:
696 lv2_atom_forge_long(&atomForge
, static_cast<int64_t>(value
+ 0.5f
));
698 case LV2_PARAMETER_TYPE_FLOAT
:
699 lv2_atom_forge_float(&atomForge
, value
);
701 case LV2_PARAMETER_TYPE_DOUBLE
:
702 lv2_atom_forge_double(&atomForge
, value
);
705 carla_stderr2("dspParameterChanged called for invalid parameter, abort!");
709 lv2_atom_forge_pop(&atomForge
, &forgeFrame
);
711 LV2_Atom
* const atom((LV2_Atom
*)atomBuf
);
712 CARLA_SAFE_ASSERT(atom
->size
< sizeof(atomBuf
));
714 fDescriptor
->port_event(fHandle
,
715 fControlDesignatedPort
,
716 lv2_atom_total_size(atom
),
717 kUridAtomTransferEvent
,
721 void dspProgramChanged(const uint32_t index
) override
723 carla_stderr2("dspProgramChanged(%i) - not handled", index
);
726 void dspMidiProgramChanged(const uint32_t bank
, const uint32_t program
) override
728 CARLA_SAFE_ASSERT_RETURN(fHandle
!= nullptr,)
730 if (fExt
.programs
== nullptr)
733 fExt
.programs
->select_program(fHandle
, bank
, program
);
736 void dspStateChanged(const char* const, const char* const) override
740 void dspNoteReceived(const bool onOff
, const uint8_t channel
, const uint8_t note
, const uint8_t velocity
) override
742 CARLA_SAFE_ASSERT_RETURN(fHandle
!= nullptr,)
743 CARLA_SAFE_ASSERT_RETURN(fDescriptor
!= nullptr,);
745 if (fDescriptor
->port_event
== nullptr)
748 LV2_Atom_MidiEvent midiEv
;
749 midiEv
.atom
.type
= kUridMidiEvent
;
750 midiEv
.atom
.size
= 3;
751 midiEv
.data
[0] = uint8_t((onOff
? MIDI_STATUS_NOTE_ON
: MIDI_STATUS_NOTE_OFF
) | (channel
& MIDI_CHANNEL_BIT
));
752 midiEv
.data
[1] = note
;
753 midiEv
.data
[2] = velocity
;
755 fDescriptor
->port_event(fHandle
, fControlDesignatedPort
, lv2_atom_total_size(midiEv
), kUridAtomTransferEvent
, &midiEv
);
758 void dspAtomReceived(const uint32_t portIndex
, const LV2_Atom
* const atom
) override
760 CARLA_SAFE_ASSERT_RETURN(fHandle
!= nullptr,);
761 CARLA_SAFE_ASSERT_RETURN(fDescriptor
!= nullptr,);
762 CARLA_SAFE_ASSERT_RETURN(atom
!= nullptr,);
764 if (fDescriptor
->port_event
== nullptr)
767 fDescriptor
->port_event(fHandle
, portIndex
, lv2_atom_total_size(atom
), kUridAtomTransferEvent
, atom
);
770 void dspURIDReceived(const LV2_URID urid
, const char* const uri
) override
772 CARLA_SAFE_ASSERT_RETURN(urid
== fCustomURIDs
.size(),);
773 CARLA_SAFE_ASSERT_RETURN(uri
!= nullptr && uri
[0] != '\0',);
775 fCustomURIDs
.push_back(uri
);
778 void uiOptionsChanged(const BridgeFormatOptions
& opts
) override
780 carla_debug("CarlaLv2Client::uiOptionsChanged()");
782 // ------------------------------------------------------------------------------------------------------------
785 const float sampleRatef
= static_cast<float>(opts
.sampleRate
);
787 if (carla_isNotEqual(fLv2Options
.sampleRate
, sampleRatef
))
789 fLv2Options
.sampleRate
= sampleRatef
;
791 if (fExt
.options
!= nullptr && fExt
.options
->set
!= nullptr)
793 LV2_Options_Option options
[2];
794 carla_zeroStructs(options
, 2);
796 LV2_Options_Option
& optSampleRate(options
[0]);
797 optSampleRate
.context
= LV2_OPTIONS_INSTANCE
;
798 optSampleRate
.subject
= 0;
799 optSampleRate
.key
= kUridParamSampleRate
;
800 optSampleRate
.size
= sizeof(float);
801 optSampleRate
.type
= kUridAtomFloat
;
802 optSampleRate
.value
= &fLv2Options
.sampleRate
;
804 fExt
.options
->set(fHandle
, options
);
808 // ------------------------------------------------------------------------------------------------------------
809 // ui colors and scale
811 fLv2Options
.bgColor
= opts
.bgColor
;
812 fLv2Options
.fgColor
= opts
.fgColor
;
813 fLv2Options
.uiScale
= opts
.uiScale
;
815 // ------------------------------------------------------------------------------------------------------------
818 if (opts
.windowTitle
!= nullptr)
819 fUiOptions
.windowTitle
= opts
.windowTitle
;
821 fUiOptions
.windowTitle
.clear();
823 fLv2Options
.opts
[Lv2PluginOptions::WindowTitle
].size
= static_cast<uint32_t>(fUiOptions
.windowTitle
.length());
824 fLv2Options
.opts
[Lv2PluginOptions::WindowTitle
].value
= fUiOptions
.windowTitle
.buffer();
826 // ------------------------------------------------------------------------------------------------------------
829 fLv2Options
.transientWinId
= static_cast<int64_t>(opts
.transientWindowId
);
830 fUiOptions
.transientWindowId
= opts
.transientWindowId
;
832 // ------------------------------------------------------------------------------------------------------------
835 fUiOptions
.isStandalone
= opts
.isStandalone
;
836 fUiOptions
.useTheme
= opts
.useTheme
;
837 fUiOptions
.useThemeColors
= opts
.useThemeColors
;
841 void setScaleFactor(const double scaleFactor
) override
843 fLv2Options
.uiScale
= static_cast<float>(scaleFactor
);
847 void uiResized(const uint width
, const uint height
) override
849 if (fHandle
!= nullptr && fExt
.resize
!= nullptr)
850 fExt
.resize
->ui_resize(fHandle
, static_cast<int>(width
), static_cast<int>(height
));
853 // ----------------------------------------------------------------------------------------------------------------
855 LV2_URID
getCustomURID(const char* const uri
)
857 CARLA_SAFE_ASSERT_RETURN(uri
!= nullptr && uri
[0] != '\0', kUridNull
);
858 carla_debug("CarlaLv2Client::getCustomURID(\"%s\")", uri
);
860 const std::string
s_uri(uri
);
861 const std::ptrdiff_t s_pos(std::find(fCustomURIDs
.begin(), fCustomURIDs
.end(), s_uri
) - fCustomURIDs
.begin());
863 if (s_pos
<= 0 || s_pos
>= INT32_MAX
)
866 const LV2_URID urid
= static_cast<LV2_URID
>(s_pos
);
867 const LV2_URID uriCount
= static_cast<LV2_URID
>(fCustomURIDs
.size());
872 CARLA_SAFE_ASSERT(urid
== uriCount
);
874 fCustomURIDs
.push_back(uri
);
877 writeLv2UridMessage(urid
, uri
);
882 const char* getCustomURIDString(const LV2_URID urid
) const noexcept
884 CARLA_SAFE_ASSERT_RETURN(urid
!= kUridNull
, kUnmapFallback
);
885 CARLA_SAFE_ASSERT_RETURN(urid
< fCustomURIDs
.size(), kUnmapFallback
);
886 carla_debug("CarlaLv2Client::getCustomURIDString(%i)", urid
);
888 return fCustomURIDs
[urid
].c_str();
891 // ----------------------------------------------------------------------------------------------------------------
893 void handleProgramChanged(const int32_t index
)
896 writeReloadProgramsMessage(index
);
899 uint32_t handleUiPortMap(const char* const symbol
)
901 CARLA_SAFE_ASSERT_RETURN(symbol
!= nullptr && symbol
[0] != '\0', LV2UI_INVALID_PORT_INDEX
);
902 carla_debug("CarlaLv2Client::handleUiPortMap(\"%s\")", symbol
);
904 for (uint32_t i
=0; i
< fRdfDescriptor
->PortCount
; ++i
)
906 if (std::strcmp(fRdfDescriptor
->Ports
[i
].Symbol
, symbol
) == 0)
910 return LV2UI_INVALID_PORT_INDEX
;
913 // ----------------------------------------------------------------------------------------------------------------
915 char* handleStateMapToAbstractPath(const char* const absolutePath
)
917 // may already be an abstract path
918 if (! File::isAbsolutePath(absolutePath
))
919 return strdup(absolutePath
);
921 return strdup(File(absolutePath
).getRelativePathFrom(File::getCurrentWorkingDirectory()).toRawUTF8());
924 char* handleStateMapToAbsolutePath(const bool createDir
, const char* const abstractPath
)
928 if (File::isAbsolutePath(abstractPath
))
930 target
= abstractPath
;
934 target
= File::getCurrentWorkingDirectory().getChildFile(abstractPath
);
939 File
dir(target
.getParentDirectory());
941 dir
.createDirectory();
944 return strdup(target
.getFullPathName().toRawUTF8());
947 // ----------------------------------------------------------------------------------------------------------------
949 LV2UI_Request_Value_Status
handleUiRequestValue(const LV2_URID key
,
951 const LV2_Feature
* const* features
)
953 CARLA_SAFE_ASSERT_RETURN(fToolkit
!= nullptr, LV2UI_REQUEST_VALUE_ERR_UNKNOWN
);
954 carla_debug("CarlaLv2Client::handleUIRequestValue(%u, %u, %p)", key
, type
, features
);
956 if (type
!= kUridAtomPath
)
957 return LV2UI_REQUEST_VALUE_ERR_UNSUPPORTED
;
959 const char* const uri
= getCustomURIDString(key
);
960 CARLA_SAFE_ASSERT_RETURN(uri
!= nullptr && uri
!= kUnmapFallback
, LV2UI_REQUEST_VALUE_ERR_UNKNOWN
);
962 // TODO check if a file browser is already open
964 for (uint32_t i
=0; i
< fRdfDescriptor
->ParameterCount
; ++i
)
966 if (fRdfDescriptor
->Parameters
[i
].Type
!= LV2_PARAMETER_TYPE_PATH
)
968 if (std::strcmp(fRdfDescriptor
->Parameters
[i
].URI
, uri
) != 0)
971 // TODO file browser filters, also label for title
976 const CarlaMutexLocker
cml(getPipeLock());
978 writeMessage("requestvalue\n", 13);
980 std::snprintf(tmpBuf
, 0xff-1, "%u\n", key
);
981 tmpBuf
[0xff-1] = '\0';
982 writeMessage(tmpBuf
);
984 std::snprintf(tmpBuf
, 0xff-1, "%u\n", type
);
985 tmpBuf
[0xff-1] = '\0';
986 writeMessage(tmpBuf
);
989 return LV2UI_REQUEST_VALUE_SUCCESS
;
992 return LV2UI_REQUEST_VALUE_ERR_UNSUPPORTED
;
998 int handleUiResize(const int width
, const int height
)
1000 CARLA_SAFE_ASSERT_RETURN(fToolkit
!= nullptr, 1);
1001 CARLA_SAFE_ASSERT_RETURN(width
> 0, 1);
1002 CARLA_SAFE_ASSERT_RETURN(height
> 0, 1);
1003 carla_debug("CarlaLv2Client::handleUiResize(%i, %i)", width
, height
);
1005 fToolkit
->setSize(static_cast<uint
>(width
), static_cast<uint
>(height
));
1009 void handleUiWrite(uint32_t rindex
, uint32_t bufferSize
, uint32_t format
, const void* buffer
)
1011 CARLA_SAFE_ASSERT_RETURN(buffer
!= nullptr,);
1012 CARLA_SAFE_ASSERT_RETURN(bufferSize
> 0,);
1013 carla_debug("CarlaLv2Client::handleUiWrite(%i, %i, %i, %p)", rindex
, bufferSize
, format
, buffer
);
1018 CARLA_SAFE_ASSERT_RETURN(bufferSize
== sizeof(float),);
1020 if (isPipeRunning())
1022 const float value(*(const float*)buffer
);
1023 writeControlMessage(rindex
, value
);
1027 case kUridAtomTransferAtom
:
1028 case kUridAtomTransferEvent
:
1029 CARLA_SAFE_ASSERT_RETURN(bufferSize
>= sizeof(LV2_Atom
),);
1031 if (isPipeRunning())
1033 const LV2_Atom
* const atom((const LV2_Atom
*)buffer
);
1035 // plugins sometimes fail on this, not good...
1036 const uint32_t totalSize
= lv2_atom_total_size(atom
);
1037 const uint32_t paddedSize
= lv2_atom_pad_size(totalSize
);
1039 if (bufferSize
!= totalSize
&& bufferSize
!= paddedSize
)
1040 carla_stderr2("Warning: LV2 UI sending atom with invalid size %u! size: %u, padded-size: %u",
1041 bufferSize
, totalSize
, paddedSize
);
1043 writeLv2AtomMessage(rindex
, atom
);
1048 carla_stderr("CarlaLv2Client::handleUiWrite(%i, %i, %i:\"%s\", %p) - unknown format",
1049 rindex
, bufferSize
, format
, carla_lv2_urid_unmap(this, format
), buffer
);
1054 // ----------------------------------------------------------------------------------------------------------------
1057 LV2UI_Handle fHandle
;
1058 LV2UI_Widget fWidget
;
1059 LV2_Feature
* fFeatures
[kFeatureCount
+1];
1061 const LV2UI_Descriptor
* fDescriptor
;
1062 const LV2_RDF_Descriptor
* fRdfDescriptor
;
1063 const LV2_RDF_UI
* fRdfUiDescriptor
;
1064 uint32_t fControlDesignatedPort
;
1065 Lv2PluginOptions fLv2Options
;
1068 std::vector
<std::string
> fCustomURIDs
;
1071 const LV2_Options_Interface
* options
;
1072 const LV2_Programs_UI_Interface
* programs
;
1073 const LV2UI_Idle_Interface
* idle
;
1074 const LV2UI_Resize
* resize
;
1083 // ----------------------------------------------------------------------------------------------------------------
1086 static int carla_lv2_log_printf(LV2_Log_Handle handle
, LV2_URID type
, const char* fmt
, ...)
1088 CARLA_SAFE_ASSERT_RETURN(handle
!= nullptr, 0);
1089 CARLA_SAFE_ASSERT_RETURN(type
!= kUridNull
, 0);
1090 CARLA_SAFE_ASSERT_RETURN(fmt
!= nullptr, 0);
1093 if (type
== kUridLogTrace
)
1098 va_start(args
, fmt
);
1099 const int ret(carla_lv2_log_vprintf(handle
, type
, fmt
, args
));
1105 static int carla_lv2_log_vprintf(LV2_Log_Handle handle
, LV2_URID type
, const char* fmt
, va_list ap
)
1107 CARLA_SAFE_ASSERT_RETURN(handle
!= nullptr, 0);
1108 CARLA_SAFE_ASSERT_RETURN(type
!= kUridNull
, 0);
1109 CARLA_SAFE_ASSERT_RETURN(fmt
!= nullptr, 0);
1116 std::fprintf(stderr
, "\x1b[31m");
1117 ret
= std::vfprintf(stderr
, fmt
, ap
);
1118 std::fprintf(stderr
, "\x1b[0m");
1122 ret
= std::vfprintf(stdout
, fmt
, ap
);
1127 std::fprintf(stdout
, "\x1b[30;1m");
1128 ret
= std::vfprintf(stdout
, fmt
, ap
);
1129 std::fprintf(stdout
, "\x1b[0m");
1133 case kUridLogWarning
:
1134 ret
= std::vfprintf(stderr
, fmt
, ap
);
1144 // ----------------------------------------------------------------------------------------------------------------
1147 static void carla_lv2_program_changed(LV2_Programs_Handle handle
, int32_t index
)
1149 CARLA_SAFE_ASSERT_RETURN(handle
!= nullptr,);
1150 carla_debug("carla_lv2_program_changed(%p, %i)", handle
, index
);
1152 ((CarlaLv2Client
*)handle
)->handleProgramChanged(index
);
1155 // ----------------------------------------------------------------------------------------------------------------
1158 static void carla_lv2_state_free_path(LV2_State_Free_Path_Handle handle
, char* path
)
1160 CARLA_SAFE_ASSERT_RETURN(handle
!= nullptr,);
1161 carla_debug("carla_lv2_state_free_path(%p, \"%s\")", handle
, path
);
1166 static char* carla_lv2_state_make_path_tmp(LV2_State_Make_Path_Handle handle
, const char* path
)
1168 CARLA_SAFE_ASSERT_RETURN(handle
!= nullptr, nullptr);
1169 CARLA_SAFE_ASSERT_RETURN(path
!= nullptr && path
[0] != '\0', nullptr);
1170 carla_debug("carla_lv2_state_make_path_tmp(%p, \"%s\")", handle
, path
);
1172 return ((CarlaLv2Client
*)handle
)->handleStateMapToAbsolutePath(true, path
);
1175 static char* carla_lv2_state_map_abstract_path_tmp(LV2_State_Map_Path_Handle handle
, const char* absolute_path
)
1177 CARLA_SAFE_ASSERT_RETURN(handle
!= nullptr, nullptr);
1178 CARLA_SAFE_ASSERT_RETURN(absolute_path
!= nullptr && absolute_path
[0] != '\0', nullptr);
1179 carla_debug("carla_lv2_state_map_abstract_path_tmp(%p, \"%s\")", handle
, absolute_path
);
1181 return ((CarlaLv2Client
*)handle
)->handleStateMapToAbstractPath(absolute_path
);
1184 static char* carla_lv2_state_map_absolute_path_tmp(LV2_State_Map_Path_Handle handle
, const char* abstract_path
)
1186 CARLA_SAFE_ASSERT_RETURN(handle
!= nullptr, nullptr);
1187 CARLA_SAFE_ASSERT_RETURN(abstract_path
!= nullptr && abstract_path
[0] != '\0', nullptr);
1188 carla_debug("carla_lv2_state_map_absolute_path_tmp(%p, \"%s\")", handle
, abstract_path
);
1190 return ((CarlaLv2Client
*)handle
)->handleStateMapToAbsolutePath(false, abstract_path
);
1193 // ----------------------------------------------------------------------------------------------------------------
1196 static uint32_t carla_lv2_uri_to_id(LV2_URI_Map_Callback_Data data
, const char* map
, const char* uri
)
1198 carla_debug("carla_lv2_uri_to_id(%p, \"%s\", \"%s\")", data
, map
, uri
);
1199 return carla_lv2_urid_map((LV2_URID_Map_Handle
*)data
, uri
);
1205 // ----------------------------------------------------------------------------------------------------------------
1208 static LV2_URID
carla_lv2_urid_map(LV2_URID_Map_Handle handle
, const char* uri
)
1210 CARLA_SAFE_ASSERT_RETURN(handle
!= nullptr, kUridNull
);
1211 CARLA_SAFE_ASSERT_RETURN(uri
!= nullptr && uri
[0] != '\0', kUridNull
);
1212 carla_debug("carla_lv2_urid_map(%p, \"%s\")", handle
, uri
);
1215 if (std::strcmp(uri
, LV2_ATOM__Blank
) == 0)
1216 return kUridAtomBlank
;
1217 if (std::strcmp(uri
, LV2_ATOM__Bool
) == 0)
1218 return kUridAtomBool
;
1219 if (std::strcmp(uri
, LV2_ATOM__Chunk
) == 0)
1220 return kUridAtomChunk
;
1221 if (std::strcmp(uri
, LV2_ATOM__Double
) == 0)
1222 return kUridAtomDouble
;
1223 if (std::strcmp(uri
, LV2_ATOM__Event
) == 0)
1224 return kUridAtomEvent
;
1225 if (std::strcmp(uri
, LV2_ATOM__Float
) == 0)
1226 return kUridAtomFloat
;
1227 if (std::strcmp(uri
, LV2_ATOM__Int
) == 0)
1228 return kUridAtomInt
;
1229 if (std::strcmp(uri
, LV2_ATOM__Literal
) == 0)
1230 return kUridAtomLiteral
;
1231 if (std::strcmp(uri
, LV2_ATOM__Long
) == 0)
1232 return kUridAtomLong
;
1233 if (std::strcmp(uri
, LV2_ATOM__Number
) == 0)
1234 return kUridAtomNumber
;
1235 if (std::strcmp(uri
, LV2_ATOM__Object
) == 0)
1236 return kUridAtomObject
;
1237 if (std::strcmp(uri
, LV2_ATOM__Path
) == 0)
1238 return kUridAtomPath
;
1239 if (std::strcmp(uri
, LV2_ATOM__Property
) == 0)
1240 return kUridAtomProperty
;
1241 if (std::strcmp(uri
, LV2_ATOM__Resource
) == 0)
1242 return kUridAtomResource
;
1243 if (std::strcmp(uri
, LV2_ATOM__Sequence
) == 0)
1244 return kUridAtomSequence
;
1245 if (std::strcmp(uri
, LV2_ATOM__Sound
) == 0)
1246 return kUridAtomSound
;
1247 if (std::strcmp(uri
, LV2_ATOM__String
) == 0)
1248 return kUridAtomString
;
1249 if (std::strcmp(uri
, LV2_ATOM__Tuple
) == 0)
1250 return kUridAtomTuple
;
1251 if (std::strcmp(uri
, LV2_ATOM__URI
) == 0)
1252 return kUridAtomURI
;
1253 if (std::strcmp(uri
, LV2_ATOM__URID
) == 0)
1254 return kUridAtomURID
;
1255 if (std::strcmp(uri
, LV2_ATOM__Vector
) == 0)
1256 return kUridAtomVector
;
1257 if (std::strcmp(uri
, LV2_ATOM__atomTransfer
) == 0)
1258 return kUridAtomTransferAtom
;
1259 if (std::strcmp(uri
, LV2_ATOM__eventTransfer
) == 0)
1260 return kUridAtomTransferEvent
;
1263 if (std::strcmp(uri
, LV2_BUF_SIZE__maxBlockLength
) == 0)
1264 return kUridBufMaxLength
;
1265 if (std::strcmp(uri
, LV2_BUF_SIZE__minBlockLength
) == 0)
1266 return kUridBufMinLength
;
1267 if (std::strcmp(uri
, LV2_BUF_SIZE__nominalBlockLength
) == 0)
1268 return kUridBufNominalLength
;
1269 if (std::strcmp(uri
, LV2_BUF_SIZE__sequenceSize
) == 0)
1270 return kUridBufSequenceSize
;
1273 if (std::strcmp(uri
, LV2_LOG__Error
) == 0)
1274 return kUridLogError
;
1275 if (std::strcmp(uri
, LV2_LOG__Note
) == 0)
1276 return kUridLogNote
;
1277 if (std::strcmp(uri
, LV2_LOG__Trace
) == 0)
1278 return kUridLogTrace
;
1279 if (std::strcmp(uri
, LV2_LOG__Warning
) == 0)
1280 return kUridLogWarning
;
1283 if (std::strcmp(uri
, LV2_PATCH__Set
) == 0)
1284 return kUridPatchSet
;
1285 if (std::strcmp(uri
, LV2_PATCH__property
) == 0)
1286 return kUridPatchProperty
;
1287 if (std::strcmp(uri
, LV2_PATCH__subject
) == 0)
1288 return kUridPatchSubject
;
1289 if (std::strcmp(uri
, LV2_PATCH__value
) == 0)
1290 return kUridPatchValue
;
1293 if (std::strcmp(uri
, LV2_TIME__Position
) == 0)
1294 return kUridTimePosition
;
1295 if (std::strcmp(uri
, LV2_TIME__bar
) == 0)
1296 return kUridTimeBar
;
1297 if (std::strcmp(uri
, LV2_TIME__barBeat
) == 0)
1298 return kUridTimeBarBeat
;
1299 if (std::strcmp(uri
, LV2_TIME__beat
) == 0)
1300 return kUridTimeBeat
;
1301 if (std::strcmp(uri
, LV2_TIME__beatUnit
) == 0)
1302 return kUridTimeBeatUnit
;
1303 if (std::strcmp(uri
, LV2_TIME__beatsPerBar
) == 0)
1304 return kUridTimeBeatsPerBar
;
1305 if (std::strcmp(uri
, LV2_TIME__beatsPerMinute
) == 0)
1306 return kUridTimeBeatsPerMinute
;
1307 if (std::strcmp(uri
, LV2_TIME__frame
) == 0)
1308 return kUridTimeFrame
;
1309 if (std::strcmp(uri
, LV2_TIME__framesPerSecond
) == 0)
1310 return kUridTimeFramesPerSecond
;
1311 if (std::strcmp(uri
, LV2_TIME__speed
) == 0)
1312 return kUridTimeSpeed
;
1313 if (std::strcmp(uri
, LV2_KXSTUDIO_PROPERTIES__TimePositionTicksPerBeat
) == 0)
1314 return kUridTimeTicksPerBeat
;
1317 if (std::strcmp(uri
, LV2_MIDI__MidiEvent
) == 0)
1318 return kUridMidiEvent
;
1319 if (std::strcmp(uri
, LV2_PARAMETERS__sampleRate
) == 0)
1320 return kUridParamSampleRate
;
1321 if (std::strcmp(uri
, LV2_UI__backgroundColor
) == 0)
1322 return kUridBackgroundColor
;
1323 if (std::strcmp(uri
, LV2_UI__foregroundColor
) == 0)
1324 return kUridForegroundColor
;
1325 #ifndef CARLA_OS_MAC
1326 if (std::strcmp(uri
, LV2_UI__scaleFactor
) == 0)
1327 return kUridScaleFactor
;
1329 if (std::strcmp(uri
, LV2_UI__windowTitle
) == 0)
1330 return kUridWindowTitle
;
1332 // Custom Carla types
1333 if (std::strcmp(uri
, URI_CARLA_ATOM_WORKER_IN
) == 0)
1334 return kUridCarlaAtomWorkerIn
;
1335 if (std::strcmp(uri
, URI_CARLA_ATOM_WORKER_RESP
) == 0)
1336 return kUridCarlaAtomWorkerResp
;
1337 if (std::strcmp(uri
, URI_CARLA_PARAMETER_CHANGE
) == 0)
1338 return kUridCarlaParameterChange
;
1339 if (std::strcmp(uri
, LV2_KXSTUDIO_PROPERTIES__TransientWindowId
) == 0)
1340 return kUridCarlaTransientWindowId
;
1342 // Custom plugin types
1343 return ((CarlaLv2Client
*)handle
)->getCustomURID(uri
);
1346 static const char* carla_lv2_urid_unmap(LV2_URID_Map_Handle handle
, LV2_URID urid
)
1348 CARLA_SAFE_ASSERT_RETURN(handle
!= nullptr, nullptr);
1349 CARLA_SAFE_ASSERT_RETURN(urid
!= kUridNull
, nullptr);
1350 carla_debug("carla_lv2_urid_unmap(%p, %i)", handle
, urid
);
1355 case kUridAtomBlank
:
1356 return LV2_ATOM__Blank
;
1358 return LV2_ATOM__Bool
;
1359 case kUridAtomChunk
:
1360 return LV2_ATOM__Chunk
;
1361 case kUridAtomDouble
:
1362 return LV2_ATOM__Double
;
1363 case kUridAtomEvent
:
1364 return LV2_ATOM__Event
;
1365 case kUridAtomFloat
:
1366 return LV2_ATOM__Float
;
1368 return LV2_ATOM__Int
;
1369 case kUridAtomLiteral
:
1370 return LV2_ATOM__Literal
;
1372 return LV2_ATOM__Long
;
1373 case kUridAtomNumber
:
1374 return LV2_ATOM__Number
;
1375 case kUridAtomObject
:
1376 return LV2_ATOM__Object
;
1378 return LV2_ATOM__Path
;
1379 case kUridAtomProperty
:
1380 return LV2_ATOM__Property
;
1381 case kUridAtomResource
:
1382 return LV2_ATOM__Resource
;
1383 case kUridAtomSequence
:
1384 return LV2_ATOM__Sequence
;
1385 case kUridAtomSound
:
1386 return LV2_ATOM__Sound
;
1387 case kUridAtomString
:
1388 return LV2_ATOM__String
;
1389 case kUridAtomTuple
:
1390 return LV2_ATOM__Tuple
;
1392 return LV2_ATOM__URI
;
1394 return LV2_ATOM__URID
;
1395 case kUridAtomVector
:
1396 return LV2_ATOM__Vector
;
1397 case kUridAtomTransferAtom
:
1398 return LV2_ATOM__atomTransfer
;
1399 case kUridAtomTransferEvent
:
1400 return LV2_ATOM__eventTransfer
;
1403 case kUridBufMaxLength
:
1404 return LV2_BUF_SIZE__maxBlockLength
;
1405 case kUridBufMinLength
:
1406 return LV2_BUF_SIZE__minBlockLength
;
1407 case kUridBufNominalLength
:
1408 return LV2_BUF_SIZE__nominalBlockLength
;
1409 case kUridBufSequenceSize
:
1410 return LV2_BUF_SIZE__sequenceSize
;
1414 return LV2_LOG__Error
;
1416 return LV2_LOG__Note
;
1418 return LV2_LOG__Trace
;
1419 case kUridLogWarning
:
1420 return LV2_LOG__Warning
;
1424 return LV2_PATCH__Set
;
1425 case kUridPatchProperty
:
1426 return LV2_PATCH__property
;
1427 case kUridPatchSubject
:
1428 return LV2_PATCH__subject
;
1429 case kUridPatchValue
:
1430 return LV2_PATCH__value
;
1433 case kUridTimePosition
:
1434 return LV2_TIME__Position
;
1436 return LV2_TIME__bar
;
1437 case kUridTimeBarBeat
:
1438 return LV2_TIME__barBeat
;
1440 return LV2_TIME__beat
;
1441 case kUridTimeBeatUnit
:
1442 return LV2_TIME__beatUnit
;
1443 case kUridTimeBeatsPerBar
:
1444 return LV2_TIME__beatsPerBar
;
1445 case kUridTimeBeatsPerMinute
:
1446 return LV2_TIME__beatsPerMinute
;
1447 case kUridTimeFrame
:
1448 return LV2_TIME__frame
;
1449 case kUridTimeFramesPerSecond
:
1450 return LV2_TIME__framesPerSecond
;
1451 case kUridTimeSpeed
:
1452 return LV2_TIME__speed
;
1453 case kUridTimeTicksPerBeat
:
1454 return LV2_KXSTUDIO_PROPERTIES__TimePositionTicksPerBeat
;
1457 case kUridMidiEvent
:
1458 return LV2_MIDI__MidiEvent
;
1459 case kUridParamSampleRate
:
1460 return LV2_PARAMETERS__sampleRate
;
1461 case kUridBackgroundColor
:
1462 return LV2_UI__backgroundColor
;
1463 case kUridForegroundColor
:
1464 return LV2_UI__foregroundColor
;
1465 #ifndef CARLA_OS_MAC
1466 case kUridScaleFactor
:
1467 return LV2_UI__scaleFactor
;
1469 case kUridWindowTitle
:
1470 return LV2_UI__windowTitle
;
1472 // Custom Carla types
1473 case kUridCarlaAtomWorkerIn
:
1474 return URI_CARLA_ATOM_WORKER_IN
;
1475 case kUridCarlaAtomWorkerResp
:
1476 return URI_CARLA_ATOM_WORKER_RESP
;
1477 case kUridCarlaParameterChange
:
1478 return URI_CARLA_PARAMETER_CHANGE
;
1479 case kUridCarlaTransientWindowId
:
1480 return LV2_KXSTUDIO_PROPERTIES__TransientWindowId
;
1484 return ((CarlaLv2Client
*)handle
)->getCustomURIDString(urid
);
1487 // ----------------------------------------------------------------------------------------------------------------
1488 // UI Port-Map Feature
1490 static uint32_t carla_lv2_ui_port_map(LV2UI_Feature_Handle handle
, const char* symbol
)
1492 CARLA_SAFE_ASSERT_RETURN(handle
!= nullptr, LV2UI_INVALID_PORT_INDEX
);
1493 carla_debug("carla_lv2_ui_port_map(%p, \"%s\")", handle
, symbol
);
1495 return ((CarlaLv2Client
*)handle
)->handleUiPortMap(symbol
);
1498 // ----------------------------------------------------------------------------------------------------------------
1499 // UI Request Parameter Feature
1501 static LV2UI_Request_Value_Status
carla_lv2_ui_request_value(LV2UI_Feature_Handle handle
,
1504 const LV2_Feature
* const* features
)
1506 CARLA_SAFE_ASSERT_RETURN(handle
!= nullptr, LV2UI_REQUEST_VALUE_ERR_UNKNOWN
);
1507 carla_debug("carla_lv2_ui_request_value(%p, %u, %u, %p)", handle
, key
, type
, features
);
1509 return ((CarlaLv2Client
*)handle
)->handleUiRequestValue(key
, type
, features
);
1512 // ----------------------------------------------------------------------------------------------------------------
1513 // UI Resize Feature
1515 static int carla_lv2_ui_resize(LV2UI_Feature_Handle handle
, int width
, int height
)
1517 CARLA_SAFE_ASSERT_RETURN(handle
!= nullptr, 1);
1518 carla_debug("carla_lv2_ui_resize(%p, %i, %i)", handle
, width
, height
);
1520 return ((CarlaLv2Client
*)handle
)->handleUiResize(width
, height
);
1523 // ----------------------------------------------------------------------------------------------------------------
1526 static void carla_lv2_ui_write_function(LV2UI_Controller controller
, uint32_t port_index
, uint32_t buffer_size
, uint32_t format
, const void* buffer
)
1528 CARLA_SAFE_ASSERT_RETURN(controller
!= nullptr,);
1529 carla_debug("carla_lv2_ui_write_function(%p, %i, %i, %i, %p)", controller
, port_index
, buffer_size
, format
, buffer
);
1531 ((CarlaLv2Client
*)controller
)->handleUiWrite(port_index
, buffer_size
, format
, buffer
);
1534 CARLA_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR(CarlaLv2Client
)
1537 // --------------------------------------------------------------------------------------------------------------------
1539 CARLA_BRIDGE_UI_END_NAMESPACE
1541 // --------------------------------------------------------------------------------------------------------------------
1543 int main(int argc
, const char* argv
[])
1545 CARLA_BRIDGE_UI_USE_NAMESPACE
1549 carla_stderr("usage: %s <plugin-uri> [ui-uri]", argv
[0]);
1553 const bool testingModeOnly
= (argc
!= 7);
1555 // try to get sampleRate value
1556 if (const char* const sampleRateStr
= std::getenv("CARLA_SAMPLE_RATE"))
1558 const CarlaScopedLocale csl
;
1559 gInitialSampleRate
= std::atof(sampleRateStr
);
1563 CarlaLv2Client client
;
1568 if (client
.init(argc
, argv
))
1570 client
.exec(testingModeOnly
);
1581 // --------------------------------------------------------------------------------------------------------------------
1583 #include "CarlaMacUtils.cpp"
1585 // --------------------------------------------------------------------------------------------------------------------