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_PORTS_H_ 23 #define CONTAINER_LV2_PORTS_H_ 24 25 namespace lsp 26 { 27 // Specify port classes 28 class LV2Port: public IPort 29 { 30 protected: 31 LV2Extensions *pExt; 32 LV2_URID urid; 33 ssize_t nID; 34 bool bVirtual; 35 36 public: LV2Port(const port_t * meta,LV2Extensions * ext,bool virt)37 explicit LV2Port(const port_t *meta, LV2Extensions *ext, bool virt): IPort(meta) 38 { 39 pExt = ext; 40 urid = (meta != NULL) ? pExt->map_port(meta->id) : -1; 41 nID = -1; 42 bVirtual = virt; 43 } ~LV2Port()44 virtual ~LV2Port() 45 { 46 pExt = NULL; 47 urid = -1; 48 nID = -1; 49 } 50 51 public: 52 /** Bind generic port to generic data pointer 53 * 54 * @param data data pointer 55 */ bind(void * data)56 virtual void bind(void *data) { }; 57 58 /** Save state of the port to LV2 state 59 * 60 */ save()61 virtual void save() { }; 62 63 /** Restore state of the port from LV2 state 64 * 65 */ restore()66 virtual void restore() { }; 67 68 /** Serialize state of the port to LV2 Atom 69 * 70 */ serialize()71 virtual void serialize() { }; 72 73 /** Deserialize state of the port from LV2 Atom 74 * @param flags additional flags 75 * @return true if internal state of the port has changed 76 */ deserialize(const void * data,size_t flags)77 virtual bool deserialize(const void *data, size_t flags) { return false; }; 78 79 /** Get type of the LV2 port in terms of Atom 80 * 81 * @return type of the LV2 port in terms of Atom 82 */ get_type_urid()83 virtual LV2_URID get_type_urid() { return 0; }; 84 85 /** Check that the port is pending for transmission 86 * 87 * @return true if the port is pending for transmission 88 */ tx_pending()89 virtual bool tx_pending() { return false; }; 90 91 /** 92 * Callback: UI has connected to backend 93 */ ui_connected()94 virtual void ui_connected() { }; 95 96 /** Get the URID of the port in terms of Atom 97 * 98 * @return UIRD of the port 99 */ get_urid()100 inline LV2_URID get_urid() const { return urid; } 101 102 /** Get the URI of the port 103 * 104 * @return URI of the port 105 */ get_uri()106 inline const char *get_uri() const { return (pExt->unmap_urid(urid)); } 107 108 /** Get port ID 109 * 110 * @return poirt ID 111 */ get_id()112 inline ssize_t get_id() const { return nID; } 113 114 /** Set port ID 115 * 116 * @param id port ID 117 */ set_id(size_t id)118 inline void set_id(size_t id) { nID = id; } 119 120 /** 121 * Check that port is virtual 122 * @return true if port is virtual (non controlled by DAW and stored in PLUGIN STATE) 123 */ is_virtual()124 inline bool is_virtual() const { return bVirtual; } 125 }; 126 127 class LV2PortGroup: public LV2Port 128 { 129 protected: 130 float nCurrRow; 131 size_t nCols; 132 size_t nRows; 133 134 public: LV2PortGroup(const port_t * meta,LV2Extensions * ext,bool virt)135 explicit LV2PortGroup(const port_t *meta, LV2Extensions *ext, bool virt) : LV2Port(meta, ext, virt) 136 { 137 nCurrRow = meta->start; 138 nCols = port_list_size(meta->members); 139 nRows = list_size(meta->items); 140 } 141 ~LV2PortGroup()142 virtual ~LV2PortGroup() 143 { 144 nCurrRow = 0; 145 nCols = 0; 146 nRows = 0; 147 } 148 149 public: getValue()150 virtual float getValue() 151 { 152 return nCurrRow; 153 } 154 setValue(float value)155 virtual void setValue(float value) 156 { 157 nCurrRow = value; 158 } 159 serialize()160 virtual void serialize() 161 { 162 // Serialize and reset pending flag 163 pExt->forge_int(nCurrRow); 164 } 165 deserialize(const void * data,size_t flags)166 virtual bool deserialize(const void *data, size_t flags) 167 { 168 const LV2_Atom_Int *atom = reinterpret_cast<const LV2_Atom_Int *>(data); 169 if ((atom->body >= 0) && (atom->body < int32_t(nRows)) && (nCurrRow != atom->body)) 170 { 171 nCurrRow = atom->body; 172 return true; 173 } 174 175 return false; 176 } 177 save()178 virtual void save() 179 { 180 if (nID >= 0) 181 return; 182 int32_t value = nCurrRow; 183 lsp_trace("save port id=%s, urid=%d (%s), value=%d", pMetadata->id, urid, get_uri(), int(value)); 184 pExt->store_value(urid, pExt->forge.Int, &value, sizeof(float)); 185 } 186 restore()187 virtual void restore() 188 { 189 if (nID >= 0) 190 return; 191 lsp_trace("restore port id=%s, urid=%d (%s)", pMetadata->id, urid, get_uri()); 192 size_t count = 0; 193 const int32_t *data = reinterpret_cast<const int32_t *>(pExt->restore_value(urid, pExt->forge.Int, &count)); 194 if ((count != sizeof(int32_t)) || (data == NULL)) 195 return; 196 197 if (((*data) >= 0) && ((*data) < int32_t(nRows))) 198 nCurrRow = *data; 199 } 200 get_type_urid()201 virtual LV2_URID get_type_urid() 202 { 203 return pExt->forge.Int; 204 } 205 206 public: rows()207 inline size_t rows() const { return nRows; } cols()208 inline size_t cols() const { return nCols; } 209 }; 210 211 class LV2RawPort: public LV2Port 212 { 213 protected: 214 void *pBuffer; 215 216 public: LV2RawPort(const port_t * meta,LV2Extensions * ext,bool virt)217 explicit LV2RawPort(const port_t *meta, LV2Extensions *ext, bool virt) : LV2Port(meta, ext, virt), pBuffer(NULL) { } ~LV2RawPort()218 virtual ~LV2RawPort() { pBuffer = NULL; }; 219 220 public: getBuffer()221 virtual void *getBuffer() { return pBuffer; }; 222 bind(void * data)223 virtual void bind(void *data) 224 { 225 pBuffer = data; 226 }; 227 }; 228 229 class LV2AudioPort: public LV2RawPort 230 { 231 protected: 232 float *pSanitized; 233 float *pFrame; 234 235 public: LV2AudioPort(const port_t * meta,LV2Extensions * ext)236 explicit LV2AudioPort(const port_t *meta, LV2Extensions *ext) : LV2RawPort(meta, ext, false) 237 { 238 pSanitized = NULL; 239 pFrame = NULL; 240 241 if (IS_IN_PORT(pMetadata)) 242 { 243 size_t length = pExt->nMaxBlockLength; 244 pSanitized = reinterpret_cast<float *>(::malloc(sizeof(float) * length)); 245 if (pSanitized != NULL) 246 dsp::fill_zero(pSanitized, length); 247 else 248 lsp_warn("Failed to allocate sanitize buffer for port %s", pMetadata->id); 249 } 250 } 251 ~LV2AudioPort()252 virtual ~LV2AudioPort() 253 { 254 if (pSanitized != NULL) 255 { 256 ::free(pSanitized); 257 pSanitized = NULL; 258 } 259 }; 260 getBuffer()261 virtual void *getBuffer() { return pFrame; }; 262 263 // Should be always called at least once after bind() and before processing sanitize(size_t off,size_t samples)264 void sanitize(size_t off, size_t samples) 265 { 266 pFrame = reinterpret_cast<float *>(pBuffer) + off; 267 if (pSanitized != NULL) 268 { 269 dsp::sanitize2(pSanitized, reinterpret_cast<float *>(pFrame), samples); 270 pFrame = pSanitized; 271 } 272 } 273 }; 274 275 class LV2InputPort: public LV2Port 276 { 277 protected: 278 const float *pData; 279 float fValue; 280 float fPrev; 281 282 public: LV2InputPort(const port_t * meta,LV2Extensions * ext,bool virt)283 explicit LV2InputPort(const port_t *meta, LV2Extensions *ext, bool virt) : LV2Port(meta, ext, virt) 284 { 285 pData = NULL; 286 fValue = meta->start; 287 fPrev = meta->start; 288 } 289 ~LV2InputPort()290 virtual ~LV2InputPort() 291 { 292 pData = NULL; 293 fValue = pMetadata->start; 294 fPrev = pMetadata->start; 295 } 296 297 public: getValue()298 virtual float getValue() 299 { 300 return fValue; 301 } 302 setValue(float value)303 virtual void setValue(float value) 304 { 305 fValue = value; 306 } 307 bind(void * data)308 virtual void bind(void *data) 309 { 310 pData = reinterpret_cast<const float *>(data); 311 }; 312 pre_process(size_t samples)313 virtual bool pre_process(size_t samples) 314 { 315 if ((nID >= 0) && (pData != NULL)) 316 fValue = limit_value(pMetadata, *pData); 317 float old = fPrev; 318 fPrev = fValue; 319 #ifdef LSP_TRACE 320 if (fPrev != old) 321 lsp_trace("Port %s has been changed, value=%f", pMetadata->id, fValue); 322 #endif 323 return fPrev != old; // Value has changed? 324 } 325 save()326 virtual void save() 327 { 328 if (nID >= 0) 329 return; 330 lsp_trace("save port id=%s, urid=%d (%s), value=%f", pMetadata->id, urid, get_uri(), fValue); 331 pExt->store_value(urid, pExt->forge.Float, &fValue, sizeof(float)); 332 } 333 restore()334 virtual void restore() 335 { 336 if (nID >= 0) 337 return; 338 lsp_trace("restore port id=%s, urid=%d (%s)", pMetadata->id, urid, get_uri()); 339 size_t count = 0; 340 const void *data = pExt->restore_value(urid, pExt->forge.Float, &count); 341 if ((count == sizeof(float)) && (data != NULL)) 342 fValue = limit_value(pMetadata, *(reinterpret_cast<const float *>(data))); 343 } 344 deserialize(const void * data,size_t flags)345 virtual bool deserialize(const void *data, size_t flags) 346 { 347 const LV2_Atom_Float *atom = reinterpret_cast<const LV2_Atom_Float *>(data); 348 if (fValue == atom->body) 349 return false; 350 351 fValue = atom->body; 352 return true; 353 } 354 serialize()355 virtual void serialize() 356 { 357 // Serialize and reset pending flag 358 pExt->forge_float(fValue); 359 fPrev = fValue; 360 } 361 get_type_urid()362 virtual LV2_URID get_type_urid() 363 { 364 return pExt->forge.Float; 365 } 366 }; 367 368 class LV2BypassPort: public LV2InputPort 369 { 370 public: LV2BypassPort(const port_t * meta,LV2Extensions * ext)371 explicit LV2BypassPort(const port_t *meta, LV2Extensions *ext) : LV2InputPort(meta, ext, false) { } 372 ~LV2BypassPort()373 virtual ~LV2BypassPort() {} 374 375 public: getValue()376 virtual float getValue() 377 { 378 return pMetadata->max - fValue; 379 } 380 setValue(float value)381 virtual void setValue(float value) 382 { 383 fValue = pMetadata->max - value; 384 } 385 save()386 virtual void save() 387 { 388 if (nID >= 0) 389 return; 390 float value = pMetadata->max - fValue; 391 lsp_trace("save port id=%s, urid=%d (%s), value=%f", pMetadata->id, urid, get_uri(), value); 392 pExt->store_value(urid, pExt->forge.Float, &value, sizeof(float)); 393 } 394 restore()395 virtual void restore() 396 { 397 if (nID >= 0) 398 return; 399 lsp_trace("restore port id=%s, urid=%d (%s)", pMetadata->id, urid, get_uri()); 400 size_t count = 0; 401 const void *data = pExt->restore_value(urid, pExt->forge.Float, &count); 402 if ((count == sizeof(float)) && (data != NULL)) 403 fValue = limit_value(pMetadata, pMetadata->max - *(reinterpret_cast<const float *>(data))); 404 } 405 deserialize(const void * data,size_t flags)406 virtual bool deserialize(const void *data, size_t flags) 407 { 408 const LV2_Atom_Float *atom = reinterpret_cast<const LV2_Atom_Float *>(data); 409 float v = pMetadata->max - atom->body; 410 if (fValue == v) 411 return false; 412 413 fValue = v; 414 return true; 415 } 416 }; 417 418 class LV2OutputPort: public LV2Port 419 { 420 protected: 421 float *pData; 422 float fPrev; 423 float fValue; 424 425 public: LV2OutputPort(const port_t * meta,LV2Extensions * ext)426 explicit LV2OutputPort(const port_t *meta, LV2Extensions *ext) : LV2Port(meta, ext, false) 427 { 428 pData = NULL; 429 fPrev = meta->start; 430 fValue = meta->start; 431 } 432 ~LV2OutputPort()433 virtual ~LV2OutputPort() 434 { 435 pData = NULL; 436 }; 437 438 public: getValue()439 virtual float getValue() 440 { 441 return fValue; 442 } 443 setValue(float value)444 virtual void setValue(float value) 445 { 446 value = limit_value(pMetadata, value); 447 if (pMetadata->flags & F_PEAK) 448 { 449 if (fabs(fValue) < fabs(value)) 450 fValue = value; 451 } 452 else 453 fValue = value; 454 } 455 bind(void * data)456 virtual void bind(void *data) 457 { 458 pData = reinterpret_cast<float *>(data); 459 }; 460 pre_process(size_t samples)461 virtual bool pre_process(size_t samples) 462 { 463 if (pMetadata->flags & F_PEAK) 464 fValue = 0.0f; 465 return false; 466 } 467 post_process(size_t samples)468 virtual void post_process(size_t samples) 469 { 470 // Store data i the port 471 if (pData != NULL) 472 *pData = fValue; 473 474 // Serialize data and reset tx_pending flag 475 fPrev = fValue; 476 477 // // Update data according to peak protocol, only for direct-mapped ports 478 // if ((nID >= 0) && (pMetadata->flags & F_PEAK)) 479 // fValue = 0.0f; 480 } 481 tx_pending()482 virtual bool tx_pending() 483 { 484 if (fValue != fPrev) 485 lsp_trace("pending_value id=%s, prev=%f, value=%f", pMetadata->id, fPrev, fValue); 486 return fValue != fPrev; 487 } 488 serialize()489 virtual void serialize() 490 { 491 // Serialize and reset pending flag 492 pExt->forge_float(fValue); 493 494 // Update data according to peak protocol, only for Atom transport ports 495 if ((nID < 0) && (pMetadata->flags & F_PEAK)) 496 fValue = 0.0f; 497 } 498 get_type_urid()499 virtual LV2_URID get_type_urid() 500 { 501 return pExt->forge.Float; 502 } 503 }; 504 505 class LV2MeshPort: public LV2Port 506 { 507 protected: 508 LV2Mesh sMesh; 509 510 public: LV2MeshPort(const port_t * meta,LV2Extensions * ext)511 explicit LV2MeshPort(const port_t *meta, LV2Extensions *ext): LV2Port(meta, ext, false) 512 { 513 sMesh.init(meta, ext); 514 } 515 ~LV2MeshPort()516 virtual ~LV2MeshPort() 517 { 518 }; 519 520 public: get_type_urid()521 virtual LV2_URID get_type_urid() { return pExt->uridMeshType; }; 522 getBuffer()523 virtual void *getBuffer() 524 { 525 return sMesh.pMesh; 526 } 527 tx_pending()528 virtual bool tx_pending() 529 { 530 mesh_t *mesh = sMesh.pMesh; 531 if (mesh == NULL) 532 return false; 533 534 // Return true only if mesh contains data 535 return mesh->containsData(); 536 }; 537 serialize()538 virtual void serialize() 539 { 540 mesh_t *mesh = sMesh.pMesh; 541 542 // Forge number of vectors (dimensions) 543 pExt->forge_key(pExt->uridMeshDimensions); 544 pExt->forge_int(mesh->nBuffers); 545 546 // Forge number of items per vector 547 pExt->forge_key(pExt->uridMeshItems); 548 pExt->forge_int(mesh->nItems); 549 550 // Forge vectors 551 for (size_t i=0; i < mesh->nBuffers; ++i) 552 { 553 pExt->forge_key(pExt->uridMeshData); 554 pExt->forge_vector(sizeof(float), pExt->forge.Float, mesh->nItems, mesh->pvData[i]); 555 } 556 557 // Set mesh waiting until next frame is allowed 558 mesh->setWaiting(); 559 } 560 }; 561 562 class LV2StreamPort: public LV2Port 563 { 564 protected: 565 stream_t *pStream; 566 uint32_t nFrameID; 567 float *pData; 568 569 public: LV2StreamPort(const port_t * meta,LV2Extensions * ext)570 explicit LV2StreamPort(const port_t *meta, LV2Extensions *ext): LV2Port(meta, ext, false) 571 { 572 pStream = stream_t::create(pMetadata->min, pMetadata->max, pMetadata->start); 573 pData = reinterpret_cast<float *>(::malloc(sizeof(float) * STREAM_MAX_FRAME_SIZE)); 574 nFrameID = 0; 575 } 576 ~LV2StreamPort()577 virtual ~LV2StreamPort() 578 { 579 stream_t::destroy(pStream); 580 pStream = NULL; 581 582 if (pData != NULL) 583 { 584 ::free(pData); 585 pData = NULL; 586 } 587 }; 588 589 public: get_type_urid()590 virtual LV2_URID get_type_urid() { return pExt->uridFrameBufferType; }; 591 getBuffer()592 virtual void *getBuffer() 593 { 594 return pStream; 595 } 596 tx_pending()597 virtual bool tx_pending() 598 { 599 return nFrameID != pStream->frame_id(); 600 } 601 ui_connected()602 virtual void ui_connected() 603 { 604 // We need to replay buffer contents for the connected client 605 lsp_trace("UI connected event"); 606 nFrameID = pStream->frame_id() - pStream->frames(); 607 } 608 serialize()609 virtual void serialize() 610 { 611 // Serialize not more than number of predefined frames 612 uint32_t frame_id = nFrameID; 613 size_t src_id = pStream->frame_id(); 614 size_t delta = src_id - nFrameID; 615 if (delta > pStream->frames()) 616 frame_id = src_id - pStream->frames(); 617 if (delta > STREAM_BULK_MAX) 618 delta = STREAM_BULK_MAX; 619 size_t last_id = frame_id + delta; 620 621 lsp_trace("id = %s, first=%d, last=%d", pMetadata->id, int(frame_id), int(last_id)); 622 623 // Forge frame buffer parameters 624 size_t nbuffers = pStream->channels(); 625 626 pExt->forge_key(pExt->uridStreamDimensions); 627 pExt->forge_int(nbuffers); 628 629 // Forge vectors 630 for ( ; frame_id != last_id; ++frame_id) 631 { 632 LV2_Atom_Forge_Frame frame; 633 size_t size = pStream->get_size(frame_id); 634 // lsp_trace("frame id=%d, size=%d", int(frame_id), int(size)); 635 636 pExt->forge_key(pExt->uridStreamFrame); 637 pExt->forge_object(&frame, pExt->uridBlank, pExt->uridStreamFrameType); 638 { 639 pExt->forge_key(pExt->uridStreamFrameId); 640 pExt->forge_int(frame_id); 641 642 pExt->forge_key(pExt->uridStreamFrameSize); 643 pExt->forge_int(size); 644 645 // Forge vectors 646 for (size_t i=0; i < nbuffers; ++i) 647 { 648 pStream->read(i, pData, 0, size); 649 650 pExt->forge_key(pExt->uridStreamFrameData); 651 pExt->forge_vector(sizeof(float), pExt->forge.Float, size, pData); 652 } 653 } 654 pExt->forge_pop(&frame); 655 } 656 657 // Update current RowID 658 nFrameID = frame_id; 659 } 660 }; 661 662 663 class LV2FrameBufferPort: public LV2Port 664 { 665 protected: 666 frame_buffer_t sFB; 667 size_t nRowID; 668 669 public: LV2FrameBufferPort(const port_t * meta,LV2Extensions * ext)670 explicit LV2FrameBufferPort(const port_t *meta, LV2Extensions *ext): LV2Port(meta, ext, false) 671 { 672 sFB.init(meta->start, meta->step); 673 nRowID = 0; 674 } 675 ~LV2FrameBufferPort()676 virtual ~LV2FrameBufferPort() 677 { 678 }; 679 680 public: get_type_urid()681 virtual LV2_URID get_type_urid() { return pExt->uridFrameBufferType; }; 682 getBuffer()683 virtual void *getBuffer() 684 { 685 return &sFB; 686 } 687 tx_pending()688 virtual bool tx_pending() 689 { 690 return sFB.next_rowid() != nRowID; 691 } 692 ui_connected()693 virtual void ui_connected() 694 { 695 // We need to replay buffer contents for the connected client 696 lsp_trace("UI connected event"); 697 nRowID = sFB.next_rowid() - sFB.rows(); 698 } 699 serialize()700 virtual void serialize() 701 { 702 // Serialize not more than 4 rows 703 size_t delta = sFB.next_rowid() - nRowID; 704 uint32_t first_row = (delta > sFB.rows()) ? sFB.next_rowid() - sFB.rows() : nRowID; 705 if (delta > FRAMEBUFFER_BULK_MAX) 706 delta = FRAMEBUFFER_BULK_MAX; 707 uint32_t last_row = first_row + delta; 708 709 lsp_trace("id = %s, first=%d, last=%d", pMetadata->id, int(first_row), int(last_row)); 710 711 // Forge frame buffer parameters 712 pExt->forge_key(pExt->uridFrameBufferRows); 713 pExt->forge_int(sFB.rows()); 714 pExt->forge_key(pExt->uridFrameBufferCols); 715 pExt->forge_int(sFB.cols()); 716 pExt->forge_key(pExt->uridFrameBufferFirstRowID); 717 pExt->forge_int(first_row); 718 pExt->forge_key(pExt->uridFrameBufferLastRowID); 719 pExt->forge_int(last_row); 720 721 // Forge vectors 722 while (first_row != last_row) 723 { 724 pExt->forge_key(pExt->uridFrameBufferData); 725 pExt->forge_vector(sizeof(float), pExt->forge.Float, sFB.cols(), sFB.get_row(first_row++)); 726 } 727 728 // Update current RowID 729 nRowID = first_row; 730 } 731 }; 732 733 class LV2PathPort: public LV2Port 734 { 735 protected: 736 lv2_path_t sPath; 737 atomic_t nLastChange; 738 set_string(const char * string,size_t len,size_t flags)739 inline void set_string(const char *string, size_t len, size_t flags) 740 { 741 lsp_trace("submitting path to '%s' (length = %d), flags=0x%x", string, int(len), int(flags)); 742 sPath.submit(string, len, flags); 743 } 744 745 public: LV2PathPort(const port_t * meta,LV2Extensions * ext)746 explicit LV2PathPort(const port_t *meta, LV2Extensions *ext): LV2Port(meta, ext, true) 747 { 748 sPath.init(); 749 nLastChange = sPath.nChanges; 750 } 751 752 public: getBuffer()753 virtual void *getBuffer() 754 { 755 return static_cast<path_t *>(&sPath); 756 } 757 save()758 virtual void save() 759 { 760 const char *path = sPath.sPath; 761 762 lsp_trace("save port id=%s, urid=%d (%s), value=%s", pMetadata->id, urid, get_uri(), path); 763 764 if (::strlen(path) > 0) 765 { 766 char *mapped = NULL; 767 768 // We need to translate absolute path to relative path? 769 if ((pExt->mapPath != NULL) && (::strstr(path, LSP_BUILTIN_PREFIX) != path)) 770 { 771 mapped = pExt->mapPath->abstract_path(pExt->mapPath->handle, path); 772 if (mapped != NULL) 773 { 774 lsp_trace("mapped path: %s -> %s", path, mapped); 775 path = mapped; 776 } 777 } 778 779 // Store the actual value of the path 780 pExt->store_value(urid, pExt->uridPathType, path, ::strlen(path) + sizeof(char)); 781 782 if (mapped != NULL) 783 ::free(mapped); 784 } 785 } 786 tx_request()787 void tx_request() 788 { 789 lsp_trace("tx_request"); 790 atomic_add(&sPath.nChanges, 1); 791 } 792 restore()793 virtual void restore() 794 { 795 lsp_trace("restore port id=%s, urid=%d (%s)", pMetadata->id, urid, get_uri()); 796 size_t count = 0; 797 uint32_t type = -1; 798 799 const char *path = reinterpret_cast<const char *>(pExt->retrieve_value(urid, &type, &count)); 800 char *mapped = NULL; 801 if (path != NULL) 802 { 803 if (type == pExt->forge.URID) 804 { 805 const LV2_URID *urid = reinterpret_cast<const LV2_URID *>(path); 806 path = pExt->unmap_urid(*urid); 807 if (path != NULL) 808 count = ::strnlen(path, PATH_MAX-1); 809 } 810 else if ((type != pExt->uridPathType) && (type != pExt->forge.String)) 811 { 812 if (path != NULL) 813 lsp_trace("Invalid type: %d = %s", int(type), pExt->unmap_urid(type)); 814 path = NULL; 815 } 816 } 817 818 if ((path != NULL) && (count > 0)) 819 { 820 // Save path as temporary variable 821 char tmp_path[PATH_MAX]; 822 ::strncpy(tmp_path, path, count); 823 tmp_path[count] = '\0'; 824 path = tmp_path; 825 826 // We need to translate relative path to absolute path? 827 if ((pExt->mapPath != NULL) && (::strstr(path, LSP_BUILTIN_PREFIX) != path)) 828 { 829 mapped = pExt->mapPath->absolute_path(pExt->mapPath->handle, path); 830 if (mapped != NULL) 831 { 832 lsp_trace("unmapped path: %s -> %s", path, mapped); 833 path = mapped; 834 count = ::strnlen(path, PATH_MAX-1); 835 } 836 } 837 838 // Restore the actual value of the path 839 set_string(path, count, PF_STATE_IMPORT); 840 } 841 else 842 set_string("", 0, PF_STATE_IMPORT); 843 tx_request(); 844 845 if (mapped != NULL) 846 ::free(mapped); 847 } 848 tx_pending()849 virtual bool tx_pending() 850 { 851 return sPath.nChanges != nLastChange; 852 } 853 reset_tx_pending()854 void reset_tx_pending() 855 { 856 lsp_trace("reset_tx_pending"); 857 nLastChange = sPath.nChanges; 858 } 859 serialize()860 virtual void serialize() 861 { 862 pExt->forge_path(sPath.get_path()); 863 reset_tx_pending(); 864 } 865 deserialize(const void * data,size_t flags)866 virtual bool deserialize(const void *data, size_t flags) 867 { 868 const LV2_Atom *atom = static_cast<const LV2_Atom *>(data); 869 if (atom->type != pExt->uridPathType) 870 return false; 871 872 set_string(reinterpret_cast<const char *>(atom + 1), atom->size, flags); 873 return true; 874 } 875 get_type_urid()876 virtual LV2_URID get_type_urid() { return pExt->uridPathType; } 877 pre_process(size_t samples)878 virtual bool pre_process(size_t samples) 879 { 880 return sPath.pending(); 881 } 882 }; 883 884 class LV2MidiPort: public LV2Port 885 { 886 protected: 887 midi_t sQueue; 888 889 public: LV2MidiPort(const port_t * meta,LV2Extensions * ext)890 explicit LV2MidiPort(const port_t *meta, LV2Extensions *ext): LV2Port(meta, ext, false) 891 { 892 sQueue.clear(); 893 } 894 895 public: getBuffer()896 virtual void *getBuffer() 897 { 898 return &sQueue; 899 } 900 }; 901 902 class LV2OscPort: public LV2Port 903 { 904 protected: 905 osc_buffer_t *pFB; 906 907 public: LV2OscPort(const port_t * meta,LV2Extensions * ext)908 explicit LV2OscPort(const port_t *meta, LV2Extensions *ext) : LV2Port(meta, ext, false) 909 { 910 pFB = NULL; 911 } 912 ~LV2OscPort()913 virtual ~LV2OscPort() 914 { 915 } 916 917 public: getBuffer()918 virtual void *getBuffer() 919 { 920 return pFB; 921 } 922 init()923 virtual int init() 924 { 925 pFB = osc_buffer_t::create(OSC_BUFFER_MAX); 926 return (pFB == NULL) ? STATUS_NO_MEM : STATUS_OK; 927 } 928 destroy()929 virtual void destroy() 930 { 931 if (pFB != NULL) 932 { 933 osc_buffer_t::destroy(pFB); 934 pFB = NULL; 935 } 936 } 937 }; 938 939 } 940 941 942 #endif /* CONTAINER_LV2_PORTS_H_ */ 943