1 /*
2  * Copyright (C) 2020 Linux Studio Plugins Project <https://lsp-plug.in/>
3  *           (C) 2020 Vladimir Sadovnikov <sadko4u@gmail.com>
4  *
5  * This file is part of lsp-plugins
6  * Created on: 23 окт. 2015 г.
7  *
8  * lsp-plugins is free software: you can redistribute it and/or modify
9  * it under the terms of the GNU Lesser General Public License as published by
10  * the Free Software Foundation, either version 3 of the License, or
11  * any later version.
12  *
13  * lsp-plugins is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16  * GNU Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public License
19  * along with lsp-plugins. If not, see <https://www.gnu.org/licenses/>.
20  */
21 
22 #ifndef CONTAINER_LV2_EXTENSIONS_H_
23 #define CONTAINER_LV2_EXTENSIONS_H_
24 
25 // LV2 includes
26 #include <lv2.h>
27 #include <lv2/lv2plug.in/ns/ext/atom/atom.h>
28 #include <lv2/lv2plug.in/ns/ext/atom/forge.h>
29 #include <lv2/lv2plug.in/ns/ext/atom/util.h>
30 #include <lv2/lv2plug.in/ns/ext/urid/urid.h>
31 #include <lv2/lv2plug.in/ns/ext/state/state.h>
32 #include <lv2/lv2plug.in/ns/ext/patch/patch.h>
33 #include <lv2/lv2plug.in/ns/ext/midi/midi.h>
34 #include <lv2/lv2plug.in/ns/ext/worker/worker.h>
35 #include <lv2/lv2plug.in/ns/ext/time/time.h>
36 #include <lv2/lv2plug.in/ns/ext/options/options.h>
37 #include <lv2/lv2plug.in/ns/ext/port-props/port-props.h>
38 #include <lv2/lv2plug.in/ns/ext/port-groups/port-groups.h>
39 #include <lv2/lv2plug.in/ns/ext/resize-port/resize-port.h>
40 #include <lv2/lv2plug.in/ns/ext/buf-size/buf-size.h>
41 #include <lv2/lv2plug.in/ns/extensions/units/units.h>
42 #include <lv2/lv2plug.in/ns/extensions/ui/ui.h>
43 #include <lv2/lv2plug.in/ns/ext/instance-access/instance-access.h>
44 
45 // Non-official features
46 #include <3rdparty/ardour/inline-display.h>
47 #include <container/lv2/osc.h>
48 
49 // Include common definitions
50 #include <container/const.h>
51 
52 // Some definitions that may be lacking in LV2
53 #ifndef LV2_ATOM__Object
54     #define LV2_ATOM__Object            LV2_ATOM_PREFIX "Object"
55 #endif /* LV2_ATOM__Object */
56 
57 #ifndef LV2_STATE__StateChanged
58     #define LV2_STATE__StateChanged     LV2_STATE_PREFIX "StateChanged"
59 #endif /* LV2_STATE__StateChanged */
60 
61 #pragma pack(push, 1)
62 typedef struct LV2_Atom_Midi
63 {
64     LV2_Atom    atom;
65     uint8_t     body[8];
66 } LV2_Atom_Midi;
67 #pragma pack(pop)
68 
69 #define LV2PORT_MAX_BLOCK_LENGTH        8192
70 
71 namespace lsp
72 {
73     #define LSP_LV2_ATOM_KEY_SIZE       (sizeof(uint32_t) * 2)
74     #define LSP_LV2_SIZE_PAD(size)      ALIGN_SIZE((size + 0x200), 0x200)
75 
76     struct LV2Extensions;
77     class LV2Wrapper;
78 
79     class LV2Serializable
80     {
81         protected:
82             LV2Extensions          *pExt;
83             LV2_URID                urid;
84 
85         public:
LV2Serializable(LV2Extensions * ext)86             explicit LV2Serializable(LV2Extensions *ext)
87             {
88                 pExt        = ext;
89                 urid        = 0;
90             }
91 
~LV2Serializable()92             virtual ~LV2Serializable()
93             {
94             }
95 
96         public:
serialize()97             virtual void serialize() {};
98 
deserialize(const void * data)99             virtual void deserialize(const void *data) {};
100 
101         public:
get_urid()102             inline LV2_URID         get_urid() const        { return urid; };
103     };
104 
105     struct LV2Extensions
106     {
107         public:
108             LV2_Atom_Forge          forge;
109 
110             // Extension interfaces
111             LV2_URID_Map           *map;
112             LV2_URID_Unmap         *unmap;
113             LV2_Worker_Schedule    *sched;
114             LV2_Inline_Display     *iDisplay;
115             LV2_State_Map_Path     *mapPath;
116             LV2UI_Resize           *ui_resize;
117             LV2Wrapper             *pWrapper;
118 
119             // State interface
120             LV2_State_Store_Function    hStore;
121             LV2_State_Retrieve_Function hRetrieve;
122             LV2_State_Handle            hHandle;
123 
124             // Plugin URI and URID
125             const char             *uriPlugin;
126             LV2_URID                uridPlugin;
127 
128             // Miscellaneous URIDs
129             LV2_URID                uridAtomTransfer;
130             LV2_URID                uridEventTransfer;
131             LV2_URID                uridObject;
132             LV2_URID                uridBlank;
133             LV2_URID                uridStateChanged;
134             LV2_URID                uridUINotification;
135             LV2_URID                uridConnectUI;
136             LV2_URID                uridDisconnectUI;
137             LV2_URID                uridDumpState;
138             LV2_URID                uridPathType;
139             LV2_URID                uridMidiEventType;
140             LV2_URID                uridKvtKeys;
141             LV2_URID                uridKvtObject;
142             LV2_URID                uridKvtType;
143             LV2_URID                uridKvtPropertyType;
144             LV2_URID                uridKvtPropertyValue;
145             LV2_URID                uridKvtPropertyFlags;
146             LV2_URID                uridBlobType;
147             LV2_URID                uridContentType;
148             LV2_URID                uridContent;
149             LV2_URID                uridTypeUInt;
150             LV2_URID                uridTypeULong;
151 
152             LV2_URID                uridPatchGet;
153             LV2_URID                uridPatchSet;
154             LV2_URID                uridPatchMessage;
155             LV2_URID                uridPatchProperty;
156             LV2_URID                uridPatchValue;
157 
158             LV2_URID                uridAtomUrid;
159             LV2_URID                uridChunk;
160             LV2_URID                uridUpdateRate;
161 
162             LV2_URID                uridTimePosition;
163             LV2_URID                uridTimeFrame;
164             LV2_URID                uridTimeFrameRate;
165             LV2_URID                uridTimeSpeed;
166             LV2_URID                uridTimeBarBeat;
167             LV2_URID                uridTimeBar;
168             LV2_URID                uridTimeBeatUnit;
169             LV2_URID                uridTimeBeatsPerBar;
170             LV2_URID                uridTimeBeatsPerMinute;
171 
172             LV2_URID                uridMaxBlockLength;
173 
174             // OSC-related URIDs
175             LV2_URID                uridOscBundle;
176             LV2_URID                uridOscBundleTimetag;
177             LV2_URID                uridOscBundleItems;
178             LV2_URID                uridOscMessage;
179             LV2_URID                uridOscMessagePath;
180             LV2_URID                uridOscMessageArguments;
181             LV2_URID                uridOscTimetag;
182             LV2_URID                uridOscTimetagIntegral;
183             LV2_URID                uridOscTimetagFraction;
184             LV2_URID                uridOscNil;
185             LV2_URID                uridOscImpulse;
186             LV2_URID                uridOscChar;
187             LV2_URID                uridOscRgba;
188             LV2_URID                uridOscRawPacket;
189 
190             // LSP-related URIDs
191             LV2_URID                uridMeshType;
192             LV2_URID                uridMeshItems;
193             LV2_URID                uridMeshDimensions;
194             LV2_URID                uridMeshData;
195             LV2_URID                uridFrameBufferType;
196             LV2_URID                uridFrameBufferRows;        // Number of rows
197             LV2_URID                uridFrameBufferCols;        // Number of cols
198             LV2_URID                uridFrameBufferFirstRowID;  // First row identifier
199             LV2_URID                uridFrameBufferLastRowID;   // Last row identifier
200             LV2_URID                uridFrameBufferData;        // Frame buffer row data
201             LV2_URID                uridStreamType;             // Stream data type
202             LV2_URID                uridStreamDimensions;       // Stream dimensions
203             LV2_URID                uridStreamFrame;            // Stream frame
204             LV2_URID                uridStreamFrameType;        // Stream frame type
205             LV2_URID                uridStreamFrameId;          // Number of frame
206             LV2_URID                uridStreamFrameSize;        // Size of frame
207             LV2_URID                uridStreamFrameData;        // Frame data
208 
209             LV2UI_Controller        ctl;
210             LV2UI_Write_Function    wf;
211             ssize_t                 nAtomIn;            // Atom input port identifier
212             ssize_t                 nAtomOut;           // Atom output port identifier
213             size_t                  nMaxBlockLength;    // Maximum size of audio block passed to plugin
214             uint8_t                *pBuffer;            // Atom serialization buffer
215             size_t                  nBufSize;           // Atom serialization buffer size
216             float                   fUIRefreshRate;     // UI refresh rate
217             void                   *pParentWindow;      // Parent window handle
218 
219         public:
LV2ExtensionsLV2Extensions220             inline LV2Extensions(const LV2_Feature* const* feat, const char *uri, LV2UI_Controller lv2_ctl, LV2UI_Write_Function lv2_write)
221             {
222                 map                 = NULL;
223                 unmap               = NULL;
224                 ui_resize           = NULL;
225                 sched               = NULL;
226                 iDisplay            = NULL;
227                 mapPath             = NULL;
228                 pParentWindow       = NULL;
229                 pWrapper            = NULL;
230                 fUIRefreshRate      = MESH_REFRESH_RATE;
231                 nMaxBlockLength     = LV2PORT_MAX_BLOCK_LENGTH;
232 
233                 const LV2_Options_Option *opts = NULL;
234 
235                 // Scan features
236                 if (feat != NULL)
237                 {
238                     for (size_t i=0; feat[i]; ++i)
239                     {
240                         const LV2_Feature *f = feat[i];
241 
242                         lsp_trace("Host reported extension uri=%s, data=%p", f->URI, f->data);
243 
244                         if (!strcmp(f->URI, LV2_URID__map))
245                             map = reinterpret_cast<LV2_URID_Map *>(f->data);
246                         else if (!strcmp(f->URI, LV2_URID__unmap))
247                             unmap = reinterpret_cast<LV2_URID_Unmap *>(f->data);
248                         else if (!strcmp(f->URI, LV2_WORKER__schedule))
249                             sched = reinterpret_cast<LV2_Worker_Schedule *>(f->data);
250                         else if (!strcmp(f->URI, LV2_UI__parent))
251                             pParentWindow   = f->data;
252                         else if (!strcmp(f->URI, LV2_UI__resize))
253                             ui_resize = reinterpret_cast<LV2UI_Resize *>(f->data);
254                         else if (!strcmp(f->URI, LV2_INLINEDISPLAY__queue_draw))
255                             iDisplay = reinterpret_cast<LV2_Inline_Display *>(f->data);
256                     #if LSP_LV2_NO_INSTANCE_ACCESS != 1
257                         else if (!strcmp(f->URI, LV2_INSTANCE_ACCESS_URI))
258                             pWrapper = reinterpret_cast<LV2Wrapper *>(f->data);
259                     #endif
260                         else if (!strcmp(f->URI, LV2_OPTIONS__options))
261                         {
262                             lsp_trace("Received options from host");
263                             opts = reinterpret_cast<const LV2_Options_Option *>(f->data);
264                         }
265                     }
266 
267                     lsp_trace("Plugin instance wrapper pointer: %p", pWrapper);
268                 }
269 
270                 // Initialize basic URIDs
271                 ctl                         = lv2_ctl;
272                 wf                          = lv2_write;
273                 nAtomIn                     = -1;
274                 nAtomOut                    = -1;
275                 pBuffer                     = NULL;
276                 nBufSize                    = 0;
277 
278                 uriPlugin                   = uri;
279                 uridPlugin                  = (map != NULL) ? map->map(map->handle, uriPlugin) : -1;
280 
281                 if (map != NULL)
282                     lv2_atom_forge_init(&forge, map);
283 
284                 uridAtomTransfer            = map_uri(LV2_ATOM__atomTransfer);
285                 uridEventTransfer           = map_uri(LV2_ATOM__eventTransfer);
286                 uridObject                  = forge.Object;
287                 uridBlank                   = map_uri(LV2_ATOM__Blank);
288                 uridStateChanged            = map_uri(LV2_STATE__StateChanged);
289                 uridUINotification          = map_type("UINotification");
290                 uridConnectUI               = map_primitive("ui_connect");
291                 uridDisconnectUI            = map_primitive("ui_disconnect");
292                 uridDumpState               = map_primitive("dumpState");
293                 uridPathType                = forge.Path;
294                 uridMidiEventType           = map_uri(LV2_MIDI__MidiEvent);
295                 uridKvtObject               = map_primitive("KVT");
296                 uridKvtType                 = map_type("KVT");
297                 uridKvtPropertyType         = map_type("KVTProperty");
298                 uridKvtPropertyValue        = map_field("KVTProperty#value");
299                 uridKvtPropertyFlags        = map_field("KVTProperty#flags");
300                 uridBlobType                = map_type("Blob");
301                 uridContentType             = map_field("Blob#ContentType");
302                 uridContent                 = map_field("Blob#Content");
303 
304                 uridTypeUInt                = map_uri(LV2_ATOM_PREFIX "UInt" );
305                 uridTypeULong               = map_uri(LV2_ATOM_PREFIX "ULong" );
306 
307                 uridPatchGet                = map_uri(LV2_PATCH__Get);
308                 uridPatchSet                = map_uri(LV2_PATCH__Set);
309                 uridPatchMessage            = map_uri(LV2_PATCH__Message);
310                 uridPatchProperty           = map_uri(LV2_PATCH__property);
311                 uridPatchValue              = map_uri(LV2_PATCH__value);
312                 uridAtomUrid                = forge.URID;
313                 uridChunk                   = forge.Chunk;
314                 uridUpdateRate              = map_uri(LV2_UI__updateRate);
315 
316                 uridTimePosition            = map_uri(LV2_TIME__Position);
317                 uridTimeFrame               = map_uri(LV2_TIME__frame);
318                 uridTimeFrameRate           = map_uri(LV2_TIME__framesPerSecond);
319                 uridTimeSpeed               = map_uri(LV2_TIME__speed);
320                 uridTimeBarBeat             = map_uri(LV2_TIME__barBeat);
321                 uridTimeBar                 = map_uri(LV2_TIME__bar);
322                 uridTimeBeatUnit            = map_uri(LV2_TIME__beatUnit);
323                 uridTimeBeatsPerBar         = map_uri(LV2_TIME__beatsPerBar);
324                 uridTimeBeatsPerMinute      = map_uri(LV2_TIME__beatsPerMinute);
325 
326                 uridMaxBlockLength          = map_uri(LV2_BUF_SIZE__maxBlockLength);
327 
328                 // OSC-related URIDs
329                 uridOscBundle               = map_uri(LV2_OSC__Bundle);
330                 uridOscBundleTimetag        = map_uri(LV2_OSC__bundleTimetag);
331                 uridOscBundleItems          = map_uri(LV2_OSC__bundleItems);
332                 uridOscMessage              = map_uri(LV2_OSC__Message);
333                 uridOscMessagePath          = map_uri(LV2_OSC__messagePath);
334                 uridOscMessageArguments     = map_uri(LV2_OSC__messageArguments);
335                 uridOscTimetag              = map_uri(LV2_OSC__Timetag);
336                 uridOscTimetagIntegral      = map_uri(LV2_OSC__timetagIntegral);
337                 uridOscTimetagFraction      = map_uri(LV2_OSC__timetagFraction);
338                 uridOscNil                  = map_uri(LV2_OSC__Nil);
339                 uridOscImpulse              = map_uri(LV2_OSC__Impulse);
340                 uridOscChar                 = map_uri(LV2_OSC__Char);
341                 uridOscRgba                 = map_uri(LV2_OSC__RGBA);
342                 uridOscRawPacket            = map_uri(LV2_OSC__RawPacket);
343 
344                 // LSP-related URIDs
345                 uridMeshType                = map_type("Mesh");
346                 uridMeshItems               = map_field("Mesh#items");
347                 uridMeshDimensions          = map_field("Mesh#dimensions");
348                 uridMeshData                = map_field("Mesh#data");
349 
350                 uridFrameBufferType         = map_type("FrameBuffer");
351                 uridFrameBufferRows         = map_field("FrameBuffer#rows");
352                 uridFrameBufferCols         = map_field("FrameBuffer#columns");
353                 uridFrameBufferFirstRowID   = map_field("FrameBuffer#firstRowID");
354                 uridFrameBufferLastRowID    = map_field("FrameBuffer#lastRowID");
355                 uridFrameBufferData         = map_field("FrameBuffer#data");
356 
357                 uridStreamType              = map_type("Stream");
358                 uridStreamDimensions        = map_field("Stream#dimensions");
359                 uridStreamFrame             = map_field("Stream#frame");
360                 uridStreamFrameType         = map_type("StreamFrame");
361                 uridStreamFrameId           = map_field("StreamFrame#id");
362                 uridStreamFrameSize         = map_field("StreamFrame#size");
363                 uridStreamFrameData         = map_field("StreamFrame#data");
364 
365                 // Decode passed options if they are present
366                 if (opts != NULL)
367                 {
368                     lsp_trace("Decoding passed options");
369                     while ((opts->key != 0) && (opts->value != 0))
370                     {
371                         lsp_trace("context = %d (%s), subject=%d, key = %d (%s), size = %d, type=%d (%s), value=%p",
372                                 int(opts->context),
373                                 (opts->context == LV2_OPTIONS_INSTANCE) ? "instance" :
374                                 (opts->context == LV2_OPTIONS_RESOURCE) ? "resource" :
375                                 (opts->context == LV2_OPTIONS_BLANK)    ? "blank" :
376                                 (opts->context == LV2_OPTIONS_PORT)     ? "port" : "unknown",
377                                 int(opts->subject),
378                                 int(opts->key), unmap_urid(opts->key),
379                                 int(opts->size),
380                                 int(opts->type), unmap_urid(opts->type),
381                                 opts->value
382                         );
383 
384                         // Update Rate for the UI
385                         if ((opts->context == LV2_OPTIONS_INSTANCE) &&
386                             (opts->key == uridUpdateRate) &&
387                             (opts->value != NULL))
388                         {
389                             if ((opts->type == forge.Float) && (opts->size == sizeof(float)))
390                                 fUIRefreshRate  = *reinterpret_cast<const float *>(opts->value);
391                             else if ((opts->type == forge.Double) && (opts->size == sizeof(double)))
392                                 fUIRefreshRate  = *reinterpret_cast<const double *>(opts->value);
393                             else if ((opts->type == forge.Int) && (opts->size == sizeof(int32_t)))
394                                 fUIRefreshRate  = *reinterpret_cast<const int32_t *>(opts->value);
395                             else if ((opts->type == forge.Long) && (opts->size == sizeof(int64_t)))
396                                 fUIRefreshRate  = *reinterpret_cast<const int64_t *>(opts->value);
397                             if (fUIRefreshRate < 0)
398                                 fUIRefreshRate = MESH_REFRESH_RATE;
399                             lsp_trace("UI refresh rate has been set to %f", fUIRefreshRate);
400                         }
401 
402                         if ((opts->context == LV2_OPTIONS_INSTANCE) &&
403                             (opts->key == uridMaxBlockLength) &&
404                             (opts->value != NULL))
405                         {
406                             ssize_t blk_len = nMaxBlockLength;
407                             if ((opts->type == forge.Int) && (opts->size == sizeof(int32_t)))
408                                 blk_len = *reinterpret_cast<const int32_t *>(opts->value);
409                             else if ((opts->type == forge.Long) && (opts->size == sizeof(int64_t)))
410                                 blk_len = *reinterpret_cast<const int64_t *>(opts->value);
411                             if (blk_len > 0)
412                                 nMaxBlockLength = blk_len;
413                             lsp_trace("MaxBlockLength has been set to %d", int(nMaxBlockLength));
414                         }
415 
416                         opts++;
417                     }
418                 }
419             }
420 
~LV2ExtensionsLV2Extensions421             ~LV2Extensions()
422             {
423                 lsp_trace("destroy");
424 
425                 // Drop atom buffer
426                 if (pBuffer != NULL)
427                 {
428                     delete [] pBuffer;
429                     pBuffer     = NULL;
430                 }
431             }
432 
433         public:
ui_refresh_rateLV2Extensions434             inline float ui_refresh_rate() const
435             {
436                 return fUIRefreshRate;
437             }
438 
parent_windowLV2Extensions439             inline void *parent_window()
440             {
441                 return pParentWindow;
442             }
443 
atom_supportedLV2Extensions444             inline bool atom_supported() const
445             {
446                 return map != NULL;
447             }
448 
unmap_uridLV2Extensions449             inline const char *unmap_urid(LV2_URID urid)
450             {
451                 return (unmap != NULL) ? unmap->unmap(unmap->handle, urid) : NULL;
452             }
453 
wrapperLV2Extensions454             inline LV2Wrapper *wrapper()
455             {
456                 return pWrapper;
457             }
458 
write_dataLV2Extensions459             inline void write_data(
460                     uint32_t         port_index,
461                     uint32_t         buffer_size,
462                     uint32_t         port_protocol,
463                     const void*      buffer)
464             {
465                 if ((ctl == NULL) || (wf == NULL))
466                     return;
467                 wf(ctl, port_index, buffer_size, port_protocol, buffer);
468             }
469 
forge_objectLV2Extensions470             inline LV2_Atom *forge_object(LV2_Atom_Forge_Frame* frame, LV2_URID id, LV2_URID otype)
471             {
472                 const LV2_Atom_Object a = {
473                     { sizeof(LV2_Atom_Object_Body), uridObject },
474                     { id, otype }
475                 };
476                 return reinterpret_cast<LV2_Atom *>(
477                     lv2_atom_forge_push(&forge, frame, lv2_atom_forge_write(&forge, &a, sizeof(a)))
478                 );
479             }
480 
forge_vectorLV2Extensions481             inline LV2_Atom_Vector *forge_vector(
482                     uint32_t        child_size,
483                     uint32_t        child_type,
484                     uint32_t        n_elems,
485                     const void*     elems)
486             {
487                 return reinterpret_cast<LV2_Atom_Vector *>(
488                     lv2_atom_forge_vector(&forge, child_size, child_type, n_elems, elems)
489                 );
490             }
491 
forge_sequence_headLV2Extensions492             inline LV2_Atom_Forge_Ref forge_sequence_head(LV2_Atom_Forge_Frame* frame, uint32_t unit)
493             {
494                 return lv2_atom_forge_sequence_head(&forge, frame, unit);
495             }
496 
forge_keyLV2Extensions497             inline LV2_Atom_Forge_Ref forge_key(LV2_URID key)
498             {
499                 const uint32_t body[] = { key, 0 };
500                 return lv2_atom_forge_write(&forge, body, sizeof(body));
501             }
502 
forge_uridLV2Extensions503             inline LV2_Atom_Forge_Ref forge_urid(LV2_URID urid)
504             {
505                 const LV2_Atom_URID a = { { sizeof(LV2_URID), forge.URID }, urid };
506                 return lv2_atom_forge_write(&forge, &a, sizeof(LV2_Atom_URID));
507             }
508 
forge_pathLV2Extensions509             inline LV2_Atom_Forge_Ref forge_path(const char *str)
510             {
511                 size_t len = ::strlen(str);
512                 return lv2_atom_forge_typed_string(&forge, forge.Path, str, len);
513             }
514 
forge_stringLV2Extensions515             inline LV2_Atom_Forge_Ref forge_string(const char *str)
516             {
517                 size_t len = ::strlen(str);
518                 return lv2_atom_forge_typed_string(&forge, forge.String, str, len);
519             }
520 
forge_popLV2Extensions521             inline void forge_pop(LV2_Atom_Forge_Frame* frame)
522             {
523                 lv2_atom_forge_pop(&forge, frame);
524             }
525 
forge_floatLV2Extensions526             inline LV2_Atom_Forge_Ref forge_float(float val)
527             {
528                 const LV2_Atom_Float a = { { sizeof(float), forge.Float }, val };
529                 return lv2_atom_forge_primitive(&forge, &a.atom);
530             }
531 
forge_intLV2Extensions532             inline LV2_Atom_Forge_Ref forge_int(int32_t val)
533             {
534                 const LV2_Atom_Int a    = { { sizeof(int32_t), forge.Int }, val };
535                 return lv2_atom_forge_primitive(&forge, &a.atom);
536             }
537 
forge_longLV2Extensions538             inline LV2_Atom_Forge_Ref forge_long(int64_t val)
539             {
540                 const LV2_Atom_Long a = { { sizeof(val), forge.Long }, val };
541                 return lv2_atom_forge_primitive(&forge, &a.atom);
542             }
543 
forge_padLV2Extensions544             inline void forge_pad(size_t size)
545             {
546                 lv2_atom_forge_pad(&forge, size);
547             }
548 
forge_rawLV2Extensions549             inline LV2_Atom_Forge_Ref forge_raw(const void* data, size_t size)
550             {
551                 return lv2_atom_forge_raw(&forge, data, size);
552             }
553 
forge_primitiveLV2Extensions554             inline LV2_Atom_Forge_Ref forge_primitive(const LV2_Atom *atom)
555             {
556                 return lv2_atom_forge_primitive(&forge, atom);
557             }
558 
forge_set_bufferLV2Extensions559             inline void forge_set_buffer(void* buf, size_t size)
560             {
561                 lv2_atom_forge_set_buffer(&forge, reinterpret_cast<uint8_t *>(buf), size);
562             }
563 
forge_frame_timeLV2Extensions564             inline LV2_Atom_Forge_Ref forge_frame_time(int64_t frames)
565             {
566                 return lv2_atom_forge_write(&forge, &frames, sizeof(frames));
567             }
568 
resize_uiLV2Extensions569             inline void resize_ui(ssize_t width, ssize_t height)
570             {
571                 if (ui_resize != NULL)
572                     ui_resize->ui_resize(ui_resize->handle, width, height);
573             }
574 
map_uriLV2Extensions575             inline LV2_URID map_uri(const char *fmt...)
576             {
577                 if (map == NULL)
578                     return -1;
579 
580                 va_list vl;
581                 char tmpbuf[2048];
582 
583                 va_start(vl, fmt);
584                 vsnprintf(tmpbuf, sizeof(tmpbuf), fmt, vl);
585                 va_end(vl);
586 
587                 LV2_URID res = map->map(map->handle, tmpbuf);
588                 lsp_trace("URID for <%s> is %d (0x%x)", tmpbuf, int(res), int(res));
589                 return res;
590             }
591 
map_portLV2Extensions592             inline LV2_URID map_port(const char *id)
593             {
594                 return map_uri("%s/ports#%s", uriPlugin, id);
595             }
596 
map_typeLV2Extensions597             inline LV2_URID map_type(const char *id)
598             {
599                 return map_uri("%s/types#%s", LSP_TYPE_URI(lv2), id);
600             }
601 
map_fieldLV2Extensions602             inline LV2_URID map_field(const char *id)
603             {
604                 return map_uri("%s/%s", LSP_TYPE_URI(lv2), id);
605             }
606 
map_kvtLV2Extensions607             inline LV2_URID map_kvt(const char *id)
608             {
609                 return map_uri(LSP_KVT_URI "%s", id);
610             }
611 
map_primitiveLV2Extensions612             inline LV2_URID map_primitive(const char *id)
613             {
614                 return map_uri("%s/%s", uriPlugin, id);
615             }
616 
init_state_contextLV2Extensions617             inline void init_state_context(
618                 LV2_State_Store_Function    store,
619                 LV2_State_Retrieve_Function retrieve,
620                 LV2_State_Handle            handle,
621                 uint32_t                    flags,
622                 const LV2_Feature *const *  features
623             )
624             {
625                 hStore          = store;
626                 hRetrieve       = retrieve;
627                 hHandle         = handle;
628 
629                 for (size_t i=0; features[i]; ++i)
630                 {
631                     const LV2_Feature *f = features[i];
632                     lsp_trace("Host reported state extension uri=%s, data=%p", f->URI, f->data);
633 
634                     if (!::strcmp(f->URI, LV2_STATE__mapPath))
635                         mapPath = reinterpret_cast<LV2_State_Map_Path *>(f->data);
636                 }
637             }
638 
store_valueLV2Extensions639             inline void store_value(LV2_URID urid, LV2_URID type, const void *data, size_t size)
640             {
641                 if ((hStore == NULL) || (hHandle == NULL))
642                     return;
643                 hStore(hHandle, urid, data, size, type, LV2_STATE_IS_POD | LV2_STATE_IS_PORTABLE);
644             }
645 
retrieve_valueLV2Extensions646             inline const void *retrieve_value(LV2_URID urid, uint32_t *type, size_t *size)
647             {
648                 if ((hRetrieve == NULL) || (hHandle == NULL))
649                     return NULL;
650 
651                 uint32_t t_flags;
652                 lsp_trace("retrieve %d (%s)", urid, unmap_urid(urid));
653                 const void *ptr   = hRetrieve(hHandle, urid, size, type, &t_flags);
654                 lsp_trace("retrieved ptr = %p, size=%d, type=%d, flags=0x%x", ptr, int(*size), int(*type), int(t_flags));
655 
656                 return ptr;
657             }
658 
restore_valueLV2Extensions659             inline const void *restore_value(LV2_URID urid, LV2_URID type, size_t *size)
660             {
661                 uint32_t t_type;
662                 size_t t_size;
663                 const void *ptr = retrieve_value(urid, &t_type, &t_size);
664                 if (t_type != type)
665                     return NULL;
666 
667                 lsp_trace("retrieved type = %d (%s)", int(t_type), unmap_urid(t_type));
668                 *size    = t_size;
669                 return ptr;
670             }
671 
reset_state_contextLV2Extensions672             inline void reset_state_context()
673             {
674                 hStore          = NULL;
675                 hRetrieve       = NULL;
676                 hHandle         = NULL;
677                 mapPath         = NULL;
678             }
679 
ui_create_atom_transportLV2Extensions680             inline bool ui_create_atom_transport(size_t port, size_t buf_size)
681             {
682                 // Remember IDs of atom ports
683                 nAtomOut    = port++;
684                 nAtomIn     = port;
685 
686                 // Allocate buffer
687                 nBufSize    = buf_size;
688                 pBuffer     = new uint8_t[nBufSize];
689                 if (pBuffer == NULL)
690                     return false;
691 
692                 lsp_trace("Atom rx_id=%d, tx_id=%d, buf_size=%d, buffer=%p", int(nAtomIn), int(nAtomOut), int(nBufSize), pBuffer);
693                 return true;
694             }
695 
ui_connect_to_pluginLV2Extensions696             inline bool ui_connect_to_plugin()
697             {
698                 if (map == NULL)
699                     return false;
700                 if (pWrapper != NULL)
701                     return true;
702 
703                 // Prepare forge for transfer
704                 LV2_Atom_Forge_Frame    frame;
705                 forge_set_buffer(pBuffer, nBufSize);
706 
707                 // Send CONNECT UI message
708                 lsp_trace("Sending CONNECT UI message");
709                 LV2_Atom *msg = forge_object(&frame, uridConnectUI, uridUINotification);
710                 forge_pop(&frame);
711                 write_data(nAtomOut, lv2_atom_total_size(msg), uridEventTransfer, msg);
712 
713                 return true;
714             }
715 
request_state_dumpLV2Extensions716             inline bool request_state_dump()
717             {
718                 if (map == NULL)
719                     return false;
720 
721                 // Prepare forge for transfer
722                 LV2_Atom_Forge_Frame    frame;
723                 forge_set_buffer(pBuffer, nBufSize);
724 
725                 // Send DUMP STATE message
726                 lsp_trace("Sending DUMP STATE message");
727                 LV2_Atom *msg = forge_object(&frame, uridDumpState, uridUINotification);
728                 forge_pop(&frame);
729                 write_data(nAtomOut, lv2_atom_total_size(msg), uridEventTransfer, msg);
730 
731                 return true;
732             }
733 
ui_disconnect_from_pluginLV2Extensions734             inline void ui_disconnect_from_plugin()
735             {
736                 if (map == NULL)
737                     return;
738                 if (pWrapper != NULL)
739                     return;
740 
741                 // Prepare ofrge for transfer
742                 LV2_Atom_Forge_Frame    frame;
743                 forge_set_buffer(pBuffer, nBufSize);
744 
745                 // Send DISCONNECT UI message
746                 lsp_trace("Sending DISCONNECT UI message");
747                 LV2_Atom *msg = forge_object(&frame, uridDisconnectUI, uridUINotification);
748                 forge_pop(&frame);
749                 write_data(nAtomOut, lv2_atom_total_size(msg), uridEventTransfer, msg);
750             }
751 
ui_write_patchLV2Extensions752             bool ui_write_patch(LV2Serializable *p)
753             {
754                 if ((map == NULL) || (p->get_urid() <= 0))
755                     return false;
756 
757                 // Forge PATCH SET message
758                 LV2_Atom_Forge_Frame    frame;
759                 forge_set_buffer(pBuffer, nBufSize);
760 
761                 forge_frame_time(0);
762                 LV2_Atom *msg = forge_object(&frame, uridChunk, uridPatchSet);
763                 forge_key(uridPatchProperty);
764                 forge_urid(p->get_urid());
765                 forge_key(uridPatchValue);
766                 p->serialize();
767                 forge_pop(&frame);
768 
769                 write_data(nAtomOut, lv2_atom_total_size(msg), uridEventTransfer, msg);
770                 return true;
771             }
772     };
773 
774     typedef struct LV2Mesh
775     {
776         size_t                  nMaxItems;
777         size_t                  nBuffers;
778         mesh_t                 *pMesh;
779         uint8_t                *pData;
780 
LV2MeshLV2Mesh781         LV2Mesh()
782         {
783             nMaxItems       = 0;
784             nBuffers        = 0;
785             pMesh           = NULL;
786             pData           = NULL;
787         }
788 
~LV2MeshLV2Mesh789         ~LV2Mesh()
790         {
791             // Simply delete root structure
792             if (pData != NULL)
793             {
794                 delete [] (pData);
795                 pData       = NULL;
796             }
797             pMesh       = NULL;
798         }
799 
initLV2Mesh800         void init(const port_t *meta, LV2Extensions *ext)
801         {
802             // Calculate sizes
803             nBuffers            = meta->step;
804             nMaxItems           = meta->start;
805 
806             size_t hdr_size     = ALIGN_SIZE(sizeof(mesh_t) + sizeof(float *) * nBuffers, DEFAULT_ALIGN);
807             size_t urid_size    = ALIGN_SIZE(sizeof(LV2_URID) * nBuffers, DEFAULT_ALIGN);
808             size_t buf_size     = ALIGN_SIZE(sizeof(float) * nMaxItems, DEFAULT_ALIGN);
809             size_t to_alloc     = hdr_size + urid_size + buf_size * nBuffers;
810 
811             lsp_trace("buffers = %d, max_items=%d, hdr_size=%d, urid_size=%d, buf_size=%d, to_alloc=%d",
812                     int(nBuffers), int(nMaxItems), int(hdr_size), int(urid_size), int(buf_size), int(to_alloc));
813             pData               = new uint8_t[to_alloc + DEFAULT_ALIGN];
814             if (pData == NULL)
815                 return;
816             uint8_t *ptr        = ALIGN_PTR(pData, DEFAULT_ALIGN);
817             pMesh               = reinterpret_cast<mesh_t *>(ptr);
818             ptr                += hdr_size;
819 
820             lsp_trace("ptr = %p, pMesh = %p", ptr, pMesh);
821 
822             for (size_t i=0; i<nBuffers; ++i)
823             {
824                 lsp_trace("bufs[%d] = %p", int(i), ptr);
825                 pMesh->pvData[i]    = reinterpret_cast<float *>(ptr);
826                 ptr                += buf_size;
827             }
828 
829             lsp_assert(ptr <= &pData[to_alloc + DEFAULT_ALIGN]);
830 
831             pMesh->nState       = M_WAIT;
832             pMesh->nBuffers     = 0;
833             pMesh->nItems       = 0;
834 
835             lsp_trace("Initialized");
836         }
837 
size_of_portLV2Mesh838         static size_t size_of_port(const port_t *meta)
839         {
840             size_t hdr_size     = sizeof(LV2_Atom_Int) + sizeof(LV2_Atom_Int) + 0x100; // Some extra bytes
841             size_t prop_size    = sizeof(uint32_t) * 2;
842             size_t vector_size  = prop_size + sizeof(LV2_Atom_Vector) + meta->start * sizeof(float);
843 
844             return LSP_LV2_SIZE_PAD(size_t(hdr_size + vector_size * meta->step));
845         }
846     } LV2Mesh;
847 
848     #define PATCH_OVERHEAD  (sizeof(LV2_Atom_Property) + sizeof(LV2_Atom_URID) + sizeof(LV2_Atom) + 0x20)
849 
lv2_all_port_sizes(const port_t * ports,bool in,bool out)850     inline long lv2_all_port_sizes(const port_t *ports, bool in, bool out)
851     {
852         long size           = 0;
853 
854         for (const port_t *p = ports; (p->id != NULL) && (p->name != NULL); ++p)
855         {
856 //            if (p->role != R_PORT_SET)
857 //            {
858 //                if (IS_OUT_PORT(p) && (!out))
859 //                    continue;
860 //                else if (IS_IN_PORT(p) && (!in))
861 //                    continue;
862 //            }
863 
864             switch (p->role)
865             {
866                 case R_CONTROL:
867                 case R_METER:
868                     size            += PATCH_OVERHEAD + sizeof(LV2_Atom_Float);
869                     break;
870                 case R_MESH:
871                     if (IS_OUT_PORT(p) && (!out))
872                         break;
873                     else if (IS_IN_PORT(p) && (!in))
874                         break;
875                     size            += LV2Mesh::size_of_port(p);
876                     break;
877                 case R_STREAM:
878                 {
879                     if (IS_OUT_PORT(p) && (!out))
880                         break;
881                     else if (IS_IN_PORT(p) && (!in))
882                         break;
883 
884                     size_t vector_len   = sizeof(LV2_Atom_Vector) + 4 * sizeof(LV2_Atom_Int) + sizeof(float) * STREAM_MAX_FRAME_SIZE;
885                     size_t frm_size     = sizeof(LV2_Atom_Object) + 8 * sizeof(LV2_Atom_Int) + size_t(p->min) * vector_len;
886                     size_t data_size    = sizeof(LV2_Atom_Object) + 8 * sizeof(LV2_Atom_Int) + STREAM_BULK_MAX * frm_size;
887                     size               += data_size;
888                     break;
889                 }
890                 case R_FBUFFER:
891                     if (IS_OUT_PORT(p) && (!out))
892                         break;
893                     else if (IS_IN_PORT(p) && (!in))
894                         break;
895                     size           += (4 * sizeof(LV2_Atom_Int) + 0x100) + // Headers
896                                         size_t(p->step) * FRAMEBUFFER_BULK_MAX * sizeof(float);
897                     break;
898                 case R_OSC:
899                     size           += OSC_BUFFER_MAX;
900                     break;
901                 case R_MIDI:
902                     if (IS_OUT_PORT(p) && (!out))
903                         break;
904                     else if (IS_IN_PORT(p) && (!in))
905                         break;
906                     size            += (sizeof(LV2_Atom_Event) + 0x10) * MIDI_EVENTS_MAX; // Size of atom event + pad for MIDI data
907                     break;
908                 case R_PATH: // Both sizes: IN and OUT
909                     size            += PATCH_OVERHEAD + PATH_MAX;
910                     break;
911                 case R_PORT_SET:
912                     if ((p->members != NULL) && (p->items != NULL))
913                     {
914                         size_t items        = list_size(p->items);
915                         size               += items * lv2_all_port_sizes(p->members, in, out); // Add some overhead
916                         size               += sizeof(LV2_Atom_Int) + 0x10;
917                     }
918                     break;
919                 default:
920                     break;
921             }
922         }
923 
924         // Update state size
925         return LSP_LV2_SIZE_PAD(size); // Add some extra bytes for
926     }
927 
928     #undef PATCH_OVERHEAD
929 }
930 
931 
932 #endif /* CONTAINER_LV2_EXTENSIONS_H_ */
933