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