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_VST_PORTS_H_
23 #define CONTAINER_VST_PORTS_H_
24 
25 namespace lsp
26 {
27     // Specify port classes
28     class VSTPort: public IPort
29     {
30         protected:
31             AEffect                *pEffect;
32             audioMasterCallback     hCallback;
33             ssize_t                 nID;
34 
35         protected:
from_vst(float value)36             float from_vst(float value)
37             {
38 //                lsp_trace("input = %.3f", value);
39                 // Set value as integer or normalized
40                 if (pMetadata->unit == U_BOOL)
41                     value = (value >= 0.5f) ? 1.0f : 0.0f;
42 //                else if (pMetadata->unit == U_ENUM) { /* nothing */ }
43 //                else if (pMetadata->unit == U_SAMPLES)
44 //                    value = truncf(value);
45                 else
46                 {
47 //                    if (pMetadata->flags & F_INT)
48 //                        value = truncf(value);
49 //                    else
50 //                    {
51                         float min = 0.0f, max = 1.0f;
52                         get_port_parameters(pMetadata, &min, &max, NULL);
53                         value = min + value * (max - min);
54 //                    }
55                      if ((pMetadata->flags & F_INT) || (pMetadata->unit == U_ENUM) || (pMetadata->unit == U_SAMPLES))
56                          value  = truncf(value);
57                 }
58 
59 //                lsp_trace("result = %.3f", value);
60                 return value;
61             }
62 
to_vst(float value)63             float to_vst(float value)
64             {
65 //                lsp_trace("input = %.3f", value);
66                 // Set value as integer or normalized
67                 if (pMetadata->unit == U_BOOL) // { /* nothing */ }
68                     value = (value >= 0.5f) ? 1.0f : 0.0f;
69 //                else if (pMetadata->unit == U_ENUM) { /* nothing */ }
70 //                else if (pMetadata->unit == U_SAMPLES) { /* nothing */ }
71                 else
72                 {
73                     if ((pMetadata->flags & F_INT) || (pMetadata->unit == U_ENUM) || (pMetadata->unit == U_SAMPLES))
74                         value  = truncf(value);
75 
76 //                    if (pMetadata->flags & F_INT) { /* nothing */ }
77 //                    else
78 //                    {
79                         // Normalize value
80                         float min = 0.0f, max = 1.0f;
81                         get_port_parameters(pMetadata, &min, &max, NULL);
82                         value = (max != min) ? (value - min) / (max - min) : 0.0f;
83 //                    }
84                 }
85 
86 //                lsp_trace("result = %.3f", value);
87                 return value;
88             }
89 
90         public:
VSTPort(const port_t * meta,AEffect * effect,audioMasterCallback callback)91             explicit VSTPort(const port_t *meta, AEffect *effect, audioMasterCallback callback): IPort(meta)
92             {
93                 pEffect         = effect;
94                 hCallback       = callback;
95                 nID             = -1;
96             }
~VSTPort()97             virtual ~VSTPort()
98             {
99                 pEffect         = NULL;
100                 hCallback       = NULL;
101                 nID             = -1;
102             }
103 
104         public:
getEffect()105             inline AEffect                 *getEffect()         { return pEffect;               };
getCallback()106             inline audioMasterCallback      getCallback()       { return hCallback;             };
getID()107             inline ssize_t                  getID() const       { return nID;                   };
setID(ssize_t id)108             inline void                     setID(ssize_t id)   { nID = id;                     };
109 
masterCallback(VstInt32 opcode,VstInt32 index,VstIntPtr value,void * ptr,float opt)110             inline VstIntPtr                masterCallback(VstInt32 opcode, VstInt32 index, VstIntPtr value, void* ptr, float opt)
111             {
112                 return hCallback(pEffect, opcode, index, value, ptr, opt);
113             }
114 
writeValue(float value)115             virtual void writeValue(float value)    {};
116 
serializable()117             virtual bool serializable() const { return false; }
118 
119             /** Serialize the state of the port to the chunk
120              *
121              * @param chunk chunk to perform serialization
122              */
serialize(vst_chunk_t * chunk)123             virtual void serialize(vst_chunk_t *chunk) {}
124 
125             /** Deserialize the state of the port from the chunk (legacy version)
126              *
127              * @param data data buffer
128              * @param length length of the buffer in bytes
129              * @return number of bytes deserialized or error
130              */
deserialize_v1(const void * data,size_t length)131             virtual ssize_t deserialize_v1(const void *data, size_t length)
132             {
133                 return -1;
134             }
135 
136             /**
137              * Deserialize the state of the port from the chunk data, data pointer should
138              * be updated
139              * @param data chunk data
140              * @param limit the data size
141              * @return true on success
142              */
deserialize_v2(const uint8_t * data,size_t size)143             virtual bool deserialize_v2(const uint8_t *data, size_t size)
144             {
145                 return true;
146             }
147     };
148 
149     class VSTPortGroup: public VSTPort
150     {
151         private:
152             float                   nCurrRow;
153             size_t                  nCols;
154             size_t                  nRows;
155             volatile vst_serial_t   nSID; // Serial ID of the parameter
156 
157         public:
VSTPortGroup(const port_t * meta,AEffect * effect,audioMasterCallback callback)158             explicit VSTPortGroup(const port_t *meta, AEffect *effect, audioMasterCallback callback) : VSTPort(meta, effect, callback)
159             {
160                 nCurrRow            = meta->start;
161                 nCols               = port_list_size(meta->members);
162                 nRows               = list_size(meta->items);
163                 nSID                = 0;
164             }
165 
~VSTPortGroup()166             virtual ~VSTPortGroup()
167             {
168                 nCurrRow            = 0;
169                 nCols               = 0;
170                 nRows               = 0;
171                 nSID                = 0;
172             }
173 
174         public:
setValue(float value)175             virtual void setValue(float value)
176             {
177                 int32_t v   = value;
178                 if ((v >= 0) && (v < ssize_t(nRows)))
179                     nCurrRow        = v;
180             }
181 
getValue()182             virtual float getValue()
183             {
184                 return nCurrRow;
185             }
186 
getSID()187             inline vst_serial_t getSID()
188             {
189                 return nSID;
190             }
191 
serializable()192             virtual bool serializable() const { return true; }
193 
serialize(vst_chunk_t * chunk)194             virtual void serialize(vst_chunk_t *chunk)
195             {
196                 int32_t v = CPU_TO_BE(int32_t(nCurrRow));
197                 chunk->write(&v, sizeof(v));
198             }
199 
deserialize_v1(const void * data,size_t length)200             virtual ssize_t deserialize_v1(const void *data, size_t length)
201             {
202                 if (length < sizeof(int32_t))
203                     return -1;
204                 int32_t value   = BE_TO_CPU(*(reinterpret_cast<const int32_t *>(data)));
205                 if ((value >= 0) && (value < ssize_t(nRows)))
206                 {
207                     nCurrRow        = value;
208                     ++nSID;
209                 }
210                 return sizeof(int32_t);
211             }
212 
deserialize_v2(const uint8_t * data,size_t size)213             virtual bool deserialize_v2(const uint8_t *data, size_t size)
214             {
215                 if (size < sizeof(int32_t))
216                     return false;
217 
218                 int32_t v       = BE_TO_CPU(*(reinterpret_cast<const int32_t *>(data)));
219                 if ((v >= 0) && (v < ssize_t(nRows)))
220                 {
221                     nCurrRow        = v;
222                     ++nSID;
223                 }
224 
225                 return true;
226             }
227 
228         public:
rows()229             inline size_t rows() const      { return nRows; }
cols()230             inline size_t cols() const      { return nCols; }
curr_row()231             inline size_t curr_row() const  { return nCurrRow; }
232     };
233 
234     class VSTAudioPort: public VSTPort
235     {
236         private:
237             float          *pBuffer;
238             float          *pSanitized;
239             size_t          nBufSize;
240 
241         public:
VSTAudioPort(const port_t * meta,AEffect * effect,audioMasterCallback callback)242             explicit VSTAudioPort(const port_t *meta, AEffect *effect, audioMasterCallback callback) : VSTPort(meta, effect, callback)
243             {
244                 pBuffer     = NULL;
245                 pSanitized  = NULL;
246                 nBufSize    = 0;
247             }
248 
~VSTAudioPort()249             virtual ~VSTAudioPort()
250             {
251                 pBuffer     = NULL;
252 
253                 if (pSanitized != NULL)
254                 {
255                     ::free(pSanitized);
256                     pSanitized  = NULL;
257                     nBufSize    = 0;
258                 }
259             };
260 
261         public:
getBuffer()262             virtual void *getBuffer() { return pBuffer; };
263 
bind(float * data,size_t samples)264             void bind(float *data, size_t samples)
265             {
266                 pBuffer     = data;
267                 if (pSanitized == NULL)
268                     return;
269 
270                 // Perform sanitize() if possible
271                 if (samples <= nBufSize)
272                 {
273                     dsp::sanitize2(pSanitized, reinterpret_cast<float *>(pBuffer), samples);
274                     pBuffer = pSanitized;
275                 }
276                 else
277                 {
278                     lsp_warn("Could not sanitize buffer data for port %s, not enough buffer size (required: %d, actual: %d)",
279                             pMetadata->id, int(samples), int(nBufSize));
280                 }
281             };
282 
set_blk_size(size_t size)283             void set_blk_size(size_t size)
284             {
285                 if (!IS_IN_PORT(pMetadata))
286                     return;
287                 if (nBufSize == size)
288                     return;
289 
290                 float *buf  = reinterpret_cast<float *>(::realloc(pSanitized, sizeof(float) * size));
291                 if (buf == NULL)
292                 {
293                     ::free(pSanitized);
294                     pSanitized = NULL;
295                     return;
296                 }
297 
298                 nBufSize    = size;
299                 pSanitized  = buf;
300                 dsp::fill_zero(pSanitized, nBufSize);
301             }
302     };
303 
304     class VSTParameterPort: public VSTPort
305     {
306         private:
307             float       fValue;         // The internal value
308             float       fVstPrev;       // Previous value in VST standard notation
309             float       fVstValue;      // Current value in VST standard notation
310             volatile vst_serial_t nSID; // Serial ID of the parameter
311 
312         public:
VSTParameterPort(const port_t * meta,AEffect * effect,audioMasterCallback callback)313             explicit VSTParameterPort(const port_t *meta, AEffect *effect, audioMasterCallback callback) : VSTPort(meta, effect, callback)
314             {
315                 fValue      = meta->start;
316                 fVstPrev    = to_vst(meta->start);
317                 fVstValue   = fVstPrev;
318                 nSID        = 0;
319             }
320 
~VSTParameterPort()321             virtual ~VSTParameterPort()
322             {
323                 fValue      = pMetadata->start;
324                 fVstPrev    = 0.0f;
325                 fVstValue   = 0.0f;
326                 nSID        = 0;
327             }
328 
329         public:
getValue()330             virtual float getValue()
331             {
332                 return fValue;
333             }
334 
setValue(float value)335             virtual void setValue(float value)
336             {
337                 fValue      = limit_value(pMetadata, value);
338                 fVstValue   = to_vst(fValue);
339             }
340 
pre_process(size_t samples)341             virtual bool pre_process(size_t samples)
342             {
343                 if (fVstValue == fVstPrev)
344                     return false;
345                 fVstPrev = fVstValue;
346                 return true;
347             }
348 
writeValue(float value)349             virtual void writeValue(float value)
350             {
351                 setValue(value);
352                 if ((nID >= 0) && (pEffect != NULL) && (hCallback != NULL))
353                 {
354                     lsp_trace("hCallback=%p, pEffect=%p, operation=%d, id=%d, value=%.5f, vst_value=%.5f",
355                             hCallback, pEffect, int(audioMasterAutomate), int(nID), value, fVstValue);
356                     hCallback(pEffect, audioMasterAutomate, nID, 0, NULL, fVstValue);
357                 }
358             }
359 
setVstValue(float value)360             void setVstValue(float value)
361             {
362                 if (fVstValue == value)
363                     return;
364                 fValue          = limit_value(pMetadata, from_vst(value));
365                 fVstValue       = value;
366                 nSID            ++;
367             }
368 
getVstValue()369             inline float getVstValue()
370             {
371                 return fVstValue;
372             }
373 
getSID()374             inline vst_serial_t getSID()
375             {
376                 return nSID;
377             }
378 
serializable()379             virtual bool serializable() const { return true; }
380 
serialize(vst_chunk_t * chunk)381             virtual void serialize(vst_chunk_t *chunk)
382             {
383                 float v = CPU_TO_BE(fValue);
384                 chunk->write(&v, sizeof(v));
385             }
386 
deserialize_v1(const void * data,size_t length)387             virtual ssize_t deserialize_v1(const void *data, size_t length)
388             {
389                 if (length < sizeof(float))
390                     return -1;
391                 float value     = BE_TO_CPU(*(reinterpret_cast<const float *>(data)));
392                 writeValue(value);
393                 ++nSID;
394                 return sizeof(float);
395             }
396 
deserialize_v2(const uint8_t * data,size_t size)397             virtual bool deserialize_v2(const uint8_t *data, size_t size)
398             {
399                 if (size < sizeof(float))
400                     return false;
401 
402                 float v         = BE_TO_CPU(*(reinterpret_cast<const float *>(data)));
403                 writeValue(v);
404                 ++nSID;
405                 return true;
406             }
407     };
408 
409     class VSTMeterPort: public VSTPort
410     {
411         public:
412             float   fValue;
413             bool    bForce;
414 
415         public:
VSTMeterPort(const port_t * meta,AEffect * effect,audioMasterCallback callback)416             explicit VSTMeterPort(const port_t *meta, AEffect *effect, audioMasterCallback callback) : VSTPort(meta, effect, callback)
417             {
418                 fValue      = meta->start;
419                 bForce      = true;
420             }
421 
~VSTMeterPort()422             virtual ~VSTMeterPort()
423             {
424                 fValue      = pMetadata->start;
425             }
426 
427         public:
428             // Native Interface
getValue()429             virtual float getValue()
430             {
431                 return fValue;
432             }
433 
setValue(float value)434             virtual void setValue(float value)
435             {
436                 value       = limit_value(pMetadata, value);
437 
438                 if (pMetadata->flags & F_PEAK)
439                 {
440                     if ((bForce) || (fabs(fValue) < fabs(value)))
441                     {
442                         fValue  = value;
443                         bForce  = false;
444                     }
445                 }
446                 else
447                     fValue = value;
448             }
449 
syncValue()450             float syncValue()
451             {
452                 float value = fValue;
453                 bForce      = true;
454                 return value;
455             }
456     };
457 
458     class VSTMeshPort: public VSTPort
459     {
460         private:
461             mesh_t     *pMesh;
462 
463         public:
VSTMeshPort(const port_t * meta,AEffect * effect,audioMasterCallback callback)464             explicit VSTMeshPort(const port_t *meta, AEffect *effect, audioMasterCallback callback) : VSTPort(meta, effect, callback)
465             {
466                 pMesh   = vst_create_mesh(meta);
467             }
468 
~VSTMeshPort()469             virtual ~VSTMeshPort()
470             {
471                 vst_destroy_mesh(pMesh);
472                 pMesh = NULL;
473             }
474 
475         public:
getBuffer()476             virtual void *getBuffer()
477             {
478                 return pMesh;
479             }
480     };
481 
482     class VSTStreamPort: public VSTPort
483     {
484         private:
485             stream_t       *pStream;
486 
487         public:
VSTStreamPort(const port_t * meta,AEffect * effect,audioMasterCallback callback)488             explicit VSTStreamPort(const port_t *meta, AEffect *effect, audioMasterCallback callback) : VSTPort(meta, effect, callback)
489             {
490                 pStream     = stream_t::create(pMetadata->min, pMetadata->max, pMetadata->start);
491             }
492 
~VSTStreamPort()493             virtual ~VSTStreamPort()
494             {
495                 if (pStream != NULL)
496                 {
497                     stream_t::destroy(pStream);
498                     pStream     = NULL;
499                 }
500             }
501 
502         public:
getBuffer()503             virtual void *getBuffer()
504             {
505                 return pStream;
506             }
507     };
508 
509     class VSTFrameBufferPort: public VSTPort
510     {
511         private:
512             frame_buffer_t     sFB;
513 
514         public:
VSTFrameBufferPort(const port_t * meta,AEffect * effect,audioMasterCallback callback)515             explicit VSTFrameBufferPort(const port_t *meta, AEffect *effect, audioMasterCallback callback) : VSTPort(meta, effect, callback)
516             {
517                 sFB.init(pMetadata->start, pMetadata->step);
518             }
519 
~VSTFrameBufferPort()520             virtual ~VSTFrameBufferPort()
521             {
522                 sFB.destroy();
523             }
524 
525         public:
getBuffer()526             virtual void *getBuffer()
527             {
528                 return &sFB;
529             }
530 
destroy()531             virtual void destroy()
532             {
533                 sFB.destroy();
534             }
535     };
536 
537     class VSTMidiInputPort: public VSTPort
538     {
539         private:
540             midi_t      sQueue;         // MIDI event buffer
541 
542         public:
VSTMidiInputPort(const port_t * meta,AEffect * effect,audioMasterCallback callback)543             explicit VSTMidiInputPort(const port_t *meta, AEffect *effect, audioMasterCallback callback) : VSTPort(meta, effect, callback)
544             {
545                 sQueue.clear();
546             }
547 
~VSTMidiInputPort()548             virtual ~VSTMidiInputPort()
549             {
550             }
551 
552         public:
getBuffer()553             virtual void *getBuffer()
554             {
555                 return &sQueue;
556             }
557 
post_process(size_t samples)558             virtual void post_process(size_t samples)
559             {
560                 sQueue.clear();
561             }
562 
563         public:
deserialize(const VstEvents * e)564             void deserialize(const VstEvents *e)
565             {
566                 size_t count    = e->numEvents;
567                 for (size_t i=0; i<count; ++i)
568                 {
569                     // Get event and check type
570                     const VstEvent *ve      = e->events[i];
571                     if (ve->type != kVstMidiType)
572                         continue;
573 
574                     // Cast to VST MIDI event
575                     const VstMidiEvent *vme     = reinterpret_cast<const VstMidiEvent *>(ve);
576                     const uint8_t *bytes        = reinterpret_cast<const uint8_t *>(vme->midiData);
577 
578                     // Decode MIDI event
579                     midi::event_t me;
580                     if (midi::decode(&me, bytes) <= 0)
581                         return;
582 
583                     // Put the event to the queue
584                     me.timestamp      = vme->deltaFrames;
585 
586                     // Debug
587                     #ifdef LSP_TRACE
588                         #define TRACE_KEY(x)    case midi::MIDI_MSG_ ## x: evt_type = #x; break;
589                         lsp_trace("midi dump: %02x %02x %02x", int(bytes[0]) & 0xff, int(bytes[1]) & 0xff, int(bytes[2]) & 0xff);
590 
591                         char tmp_evt_type[32];
592                         const char *evt_type = NULL;
593                         switch (me.type)
594                         {
595                             TRACE_KEY(NOTE_OFF)
596                             TRACE_KEY(NOTE_ON)
597                             TRACE_KEY(NOTE_PRESSURE)
598                             TRACE_KEY(NOTE_CONTROLLER)
599                             TRACE_KEY(PROGRAM_CHANGE)
600                             TRACE_KEY(CHANNEL_PRESSURE)
601                             TRACE_KEY(PITCH_BEND)
602                             TRACE_KEY(SYSTEM_EXCLUSIVE)
603                             TRACE_KEY(MTC_QUARTER)
604                             TRACE_KEY(SONG_POS)
605                             TRACE_KEY(SONG_SELECT)
606                             TRACE_KEY(TUNE_REQUEST)
607                             TRACE_KEY(END_EXCLUSIVE)
608                             TRACE_KEY(CLOCK)
609                             TRACE_KEY(START)
610                             TRACE_KEY(CONTINUE)
611                             TRACE_KEY(STOP)
612                             TRACE_KEY(ACTIVE_SENSING)
613                             TRACE_KEY(RESET)
614                             default:
615                                 snprintf(tmp_evt_type, sizeof(tmp_evt_type), "UNKNOWN(0x%02x)", int(me.type));
616                                 evt_type = tmp_evt_type;
617                                 break;
618                         }
619 
620                         lsp_trace("MIDI Event: type=%s, timestamp=%ld", evt_type, (long)(me.timestamp));
621 
622                         #undef TRACE_KEY
623 
624                     #endif /* LSP_TRACE */
625 
626                     // Add event to the queue
627                     if (!sQueue.push(me))
628                         lsp_error("MIDI event queue overflow");
629                 }
630 
631                 // We don't know anything about ordering of events, reorder them chronologically
632                 sQueue.sort();
633             }
634     };
635 
636     class VSTMidiOutputPort: public VSTPort
637     {
638         private:
639             midi_t          sQueue;                     // MIDI event buffer
640             VstEvents      *pEvents;                    // Root pointer to VST MIDI events
641             VstMidiEvent    vEvents[MIDI_EVENTS_MAX];   // Buffer for VST MIDI events
642 
643         public:
VSTMidiOutputPort(const port_t * meta,AEffect * effect,audioMasterCallback callback)644             explicit VSTMidiOutputPort(const port_t *meta, AEffect *effect, audioMasterCallback callback) : VSTPort(meta, effect, callback)
645             {
646                 sQueue.clear();
647 
648                 // Allocate buffer for VST MIDI events
649                 size_t evt_size = ALIGN_SIZE(sizeof(VstEvents) + MIDI_EVENTS_MAX * sizeof(VstMidiEvent *), DEFAULT_ALIGN);
650                 pEvents         = reinterpret_cast<VstEvents *>(new uint8_t[evt_size]);
651             }
652 
~VSTMidiOutputPort()653             virtual ~VSTMidiOutputPort()
654             {
655             }
656 
657         public:
getBuffer()658             virtual void *getBuffer()
659             {
660                 return &sQueue;
661             }
662 
post_process(size_t samples)663             virtual void post_process(size_t samples)
664             {
665                 // Check that there are pending MIDI events
666                 if (sQueue.nEvents <= 0)
667                     return;
668 
669                 // We don't know anything about ordering of events, reorder them chronologically
670                 sQueue.sort();
671 
672                 // Translate events
673                 pEvents->numEvents  = 0;
674 
675                 for (size_t i=0; i<sQueue.nEvents; ++i)
676                 {
677                     const midi::event_t    *me  = &sQueue.vEvents[i];
678                     VstMidiEvent           *dst = &vEvents[pEvents->numEvents];
679 
680                     // Debug
681                     #ifdef LSP_TRACE
682                         #define TRACE_KEY(x)    case midi::MIDI_MSG_ ## x: evt_type = #x; break;
683 
684                         char tmp_evt_type[32];
685                         const char *evt_type = NULL;
686                         switch (me->type)
687                         {
688                             TRACE_KEY(NOTE_OFF)
689                             TRACE_KEY(NOTE_ON)
690                             TRACE_KEY(NOTE_PRESSURE)
691                             TRACE_KEY(NOTE_CONTROLLER)
692                             TRACE_KEY(PROGRAM_CHANGE)
693                             TRACE_KEY(CHANNEL_PRESSURE)
694                             TRACE_KEY(PITCH_BEND)
695                             TRACE_KEY(SYSTEM_EXCLUSIVE)
696                             TRACE_KEY(MTC_QUARTER)
697                             TRACE_KEY(SONG_POS)
698                             TRACE_KEY(SONG_SELECT)
699                             TRACE_KEY(TUNE_REQUEST)
700                             TRACE_KEY(END_EXCLUSIVE)
701                             TRACE_KEY(CLOCK)
702                             TRACE_KEY(START)
703                             TRACE_KEY(CONTINUE)
704                             TRACE_KEY(STOP)
705                             TRACE_KEY(ACTIVE_SENSING)
706                             TRACE_KEY(RESET)
707                             default:
708                                 snprintf(tmp_evt_type, sizeof(tmp_evt_type), "UNKNOWN(0x%02x)", int(me->type));
709                                 evt_type = tmp_evt_type;
710                                 break;
711                         }
712 
713                         lsp_trace("MIDI Event: type=%s, timestamp=%ld", evt_type, (long)(me->timestamp));
714 
715                         #undef TRACE_KEY
716 
717                     #endif /* LSP_TRACE */
718 
719                     ssize_t bytes = midi::encode(reinterpret_cast<uint8_t *>(dst->midiData), me);
720                     if (bytes <= 0)
721                     {
722                         lsp_error("Tried to serialize invalid MIDI event");
723                         continue;
724                     }
725 
726                     dst->type           = kVstMidiType;
727                     dst->byteSize       = sizeof(VstMidiEvent);
728                     dst->deltaFrames    = me->timestamp;
729                     dst->flags          = (me->type >= midi::MIDI_MSG_CLOCK) ? kVstMidiEventIsRealtime : 0;
730                     dst->noteLength     = 0;
731                     dst->noteOffset     = 0;
732                     dst->detune         = 0;
733                     dst->noteOffVelocity= (me->type == midi::MIDI_MSG_NOTE_OFF) ? me->note.velocity : 0;
734 
735                     lsp_trace("midi dump: %02x %02x %02x",
736                         int(dst->midiData[0]) & 0xff, int(dst->midiData[1]) & 0xff, int(dst->midiData[2]) & 0xff);
737 
738                     // Add pointer to the VST event to the VST eventn list
739                     pEvents->events[pEvents->numEvents++]       = reinterpret_cast<VstEvent *>(dst);
740                 }
741 
742                 // Call host to process MIDI events if they are
743                 if (pEvents->numEvents > 0)
744                 {
745                     masterCallback(audioMasterProcessEvents, 0, 0, pEvents, 0.0f);
746                     pEvents->numEvents      = 0;
747                 }
748 
749                 sQueue.clear();
750             }
751     };
752 
753     class VSTPathPort: public VSTPort
754     {
755         private:
756             vst_path_t     sPath;
757 
758         public:
VSTPathPort(const port_t * meta,AEffect * effect,audioMasterCallback callback)759             explicit VSTPathPort(const port_t *meta, AEffect *effect, audioMasterCallback callback) : VSTPort(meta, effect, callback)
760             {
761                 sPath.init();
762             }
763 
~VSTPathPort()764             virtual ~VSTPathPort()
765             {
766             }
767 
768         public:
getBuffer()769             virtual void *getBuffer()
770             {
771                 return static_cast<path_t *>(&sPath);
772             }
773 
pre_process(size_t samples)774             virtual bool pre_process(size_t samples)
775             {
776                 return sPath.pending();
777             }
778 
sizeof_state()779             size_t sizeof_state()
780             {
781                 size_t bytes    = strlen(sPath.sPath);
782                 if (bytes >= 0x7fff)
783                     bytes           = 0x7fff;
784                 if (bytes > 0x7f)
785                     bytes          += 2;
786                 else
787                     bytes          += 1;
788 
789                 return bytes;
790             }
791 
serialize(vst_chunk_t * chunk)792             virtual void serialize(vst_chunk_t *chunk)
793             {
794                 chunk->write_string(sPath.sPath);
795             }
796 
deserialize_v1(const void * data,size_t length)797             virtual ssize_t deserialize_v1(const void *data, size_t length)
798             {
799                 const uint8_t  *ptr     = reinterpret_cast<const uint8_t *>(data);
800                 const uint8_t  *tail    = ptr + length;
801                 if (ptr >= tail)
802                     return -1;
803 
804                 // Read length of string
805                 size_t bytes        = *(ptr++);
806                 if (bytes & 0x80)
807                 {
808                     if (ptr >= tail)
809                         return -1;
810 
811                     bytes       = ((bytes << 8) | (*(ptr++))) & 0x7fff;
812                 }
813 
814                 // Read string
815                 tail           -= bytes;
816                 if (ptr > tail)
817                     return -1;
818 
819                 // Submit data
820                 sPath.submit(reinterpret_cast<const char *>(ptr), bytes, false, PF_STATE_RESTORE);
821                 ptr            += bytes;
822                 return ptr - reinterpret_cast<const uint8_t *>(data);
823             }
824 
deserialize_v2(const uint8_t * data,size_t size)825             virtual bool deserialize_v2(const uint8_t *data, size_t size)
826             {
827                 const char *str = reinterpret_cast<const char *>(data);
828                 size_t len  = ::strnlen(str, size) + 1;
829                 if (len > size)
830                     return false;
831 
832                 sPath.submit(str, len, false, PF_STATE_RESTORE);
833                 return true;
834             }
835 
serializable()836             virtual bool serializable() const { return true; }
837     };
838 
839     class VSTOscPort: public VSTPort
840     {
841         private:
842             osc_buffer_t     *pFB;
843 
844         public:
VSTOscPort(const port_t * meta,AEffect * effect,audioMasterCallback callback)845             explicit VSTOscPort(const port_t *meta, AEffect *effect, audioMasterCallback callback) : VSTPort(meta, effect, callback)
846             {
847                 pFB     = NULL;
848             }
849 
~VSTOscPort()850             virtual ~VSTOscPort()
851             {
852             }
853 
854         public:
getBuffer()855             virtual void *getBuffer()
856             {
857                 return pFB;
858             }
859 
init()860             virtual int init()
861             {
862                 pFB = osc_buffer_t::create(OSC_BUFFER_MAX);
863                 return (pFB == NULL) ? STATUS_NO_MEM : STATUS_OK;
864             }
865 
destroy()866             virtual void destroy()
867             {
868                 if (pFB != NULL)
869                 {
870                     osc_buffer_t::destroy(pFB);
871                     pFB     = NULL;
872                 }
873             }
874     };
875 }
876 
877 
878 #endif /* CONTAINER_VST_PORTS_H_ */
879