1 //===================================================================
2 //  MusE
3 //  Linux Music Editor
4 //
5 //  vst_native.cpp
6 //  (C) Copyright 2012-2013 Tim E. Real (terminator356 on users dot sourceforge dot net)
7 //
8 //  This program is free software; you can redistribute it and/or
9 //  modify it under the terms of the GNU General Public License
10 //  as published by the Free Software Foundation; version 2 of
11 //  the License, or (at your option) any later version.
12 //
13 //  This program 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 General Public License for more details.
17 //
18 //  You should have received a copy of the GNU General Public License
19 //  along with this program; if not, write to the Free Software
20 //  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
21 //
22 //===================================================================
23 
24 #include "config.h"
25 
26 #ifdef VST_NATIVE_SUPPORT
27 
28 #include <QDir>
29 #include <QMenu>
30 
31 #include <stdlib.h>
32 #include <assert.h>
33 #include <stdio.h>
34 #include <dlfcn.h>
35 #include "muse_math.h"
36 #include <set>
37 #include <string>
38 #include <jack/jack.h>
39 #include <sstream>
40 
41 #include "globals.h"
42 #include "gconfig.h"
43 #include "audio.h"
44 #include "synth.h"
45 #include "jackaudio.h"
46 #include "midi_consts.h"
47 #include "xml.h"
48 #include "plugin.h"
49 #include "popupmenu.h"
50 #include "pos.h"
51 #include "tempo.h"
52 #include "sync.h"
53 #include "sig.h"
54 #include "minstrument.h"
55 
56 #include "vst_native.h"
57 #include "pluglist.h"
58 
59 #define OLD_PLUGIN_ENTRY_POINT "main"
60 #define NEW_PLUGIN_ENTRY_POINT "VSTPluginMain"
61 
62 // Enable debugging messages
63 //#define VST_NATIVE_DEBUG
64 //#define VST_NATIVE_DEBUG_PROCESS
65 
66 namespace MusECore {
67 
68 extern JackAudioDevice* jackAudio;
69 
70 static VstIntPtr currentPluginId = 0;
71 static sem_t _vstIdLock;
72 
73 //-----------------------------------------------------------------------------------------
74 //   vstHostCallback
75 //   This must be a function, it cannot be a class method so we dispatch to various objects from here.
76 //-----------------------------------------------------------------------------------------
77 
vstNativeHostCallback(AEffect * effect,VstInt32 opcode,VstInt32 index,VstIntPtr value,void * ptr,float opt)78 VstIntPtr VSTCALLBACK vstNativeHostCallback(AEffect* effect, VstInt32 opcode, VstInt32 index, VstIntPtr value, void* ptr, float opt)
79 {
80       // Is this callback for an actual instance? Hand-off to the instance if so.
81       //VSTPlugin* plugin;
82       if(effect && effect->user)
83       {
84         VstNativeSynthOrPlugin *userData = (VstNativeSynthOrPlugin*)(effect->user);
85         //return ((VstNativeSynthIF*)plugin)->hostCallback(opcode, index, value, ptr, opt);
86         return VstNativeSynth::pluginHostCallback(userData, opcode, index, value, ptr, opt);
87 
88       }
89 
90       // No instance found. So we are just scanning for plugins...
91 
92 #ifdef VST_NATIVE_DEBUG
93       fprintf(stderr, "vstNativeHostCallback eff:%p opcode:%ld\n", effect, opcode);
94 #endif
95 
96       switch (opcode) {
97             case audioMasterAutomate:
98                   // index, value, returns 0
99                   return 0;
100 
101             case audioMasterVersion:
102                   // vst version, currently 2 (0 for older)
103                   return 2300;
104 
105             case audioMasterCurrentId:
106                   // returns the unique id of a plug that's currently
107                   // loading
108                   return currentPluginId;
109 
110             case audioMasterIdle:
111                   // call application idle routine (this will
112                   // call effEditIdle for all open editors too)
113                   return 0;
114 
115             case audioMasterGetTime:
116                   // returns const VstTimeInfo* (or 0 if not supported)
117                   // <value> should contain a mask indicating which fields are required
118                   // (see valid masks above), as some items may require extensive
119                   // conversions
120                   return 0;
121 
122             case audioMasterProcessEvents:
123                   // VstEvents* in <ptr>
124                   return 0;
125 
126             case audioMasterIOChanged:
127                    // numInputs and/or numOutputs has changed
128                   return 0;
129 
130             case audioMasterSizeWindow:
131                   // index: width, value: height
132                   return 0;
133 
134             case audioMasterGetSampleRate:
135                   return MusEGlobal::sampleRate;
136 
137             case audioMasterGetBlockSize:
138                   return MusEGlobal::segmentSize;
139 
140             case audioMasterGetInputLatency:
141                   return 0;
142 
143             case audioMasterGetOutputLatency:
144                   return 0;
145 
146             case audioMasterGetCurrentProcessLevel:
147                   // returns: 0: not supported,
148                   // 1: currently in user thread (gui)
149                   // 2: currently in audio thread (where process is called)
150                   // 3: currently in 'sequencer' thread (midi, timer etc)
151                   // 4: currently offline processing and thus in user thread
152                   // other: not defined, but probably pre-empting user thread.
153                   return 0;
154 
155             case audioMasterGetAutomationState:
156                   // returns 0: not supported, 1: off, 2:read, 3:write, 4:read/write
157                   // offline
158                   return 0;
159 
160             case audioMasterOfflineStart:
161             case audioMasterOfflineRead:
162                    // ptr points to offline structure, see below. return 0: error, 1 ok
163                   return 0;
164 
165             case audioMasterOfflineWrite:
166                   // same as read
167                   return 0;
168 
169             case audioMasterOfflineGetCurrentPass:
170             case audioMasterOfflineGetCurrentMetaPass:
171                   return 0;
172 
173             case audioMasterGetVendorString:
174                   // fills <ptr> with a string identifying the vendor (max 64 char)
175                   strcpy ((char*) ptr, "MusE");
176                   return 1;
177 
178             case audioMasterGetProductString:
179                   // fills <ptr> with a string with product name (max 64 char)
180                   strcpy ((char*) ptr, "NativeVST");
181                   return 1;
182 
183             case audioMasterGetVendorVersion:
184                   // returns vendor-specific version
185                   return 2000;
186 
187             case audioMasterVendorSpecific:
188                   // no definition, vendor specific handling
189                   return 0;
190 
191             case audioMasterCanDo:
192                   // string in ptr, see below
193                   return 0;
194 
195             case audioMasterGetLanguage:
196                   // see enum
197                   return kVstLangEnglish;
198 
199             case audioMasterGetDirectory:
200                   // get plug directory, FSSpec on MAC, else char*
201                   return 0;
202 
203             case audioMasterUpdateDisplay:
204                   // something has changed, update 'multi-fx' display
205                   return 0;
206 
207             case audioMasterBeginEdit:
208                   // begin of automation session (when mouse down), parameter index in <index>
209                   return 0;
210 
211             case audioMasterEndEdit:
212                   // end of automation session (when mouse up),     parameter index in <index>
213                   return 0;
214 
215             case audioMasterOpenFileSelector:
216                   // open a fileselector window with VstFileSelect* in <ptr>
217                   return 0;
218 
219             case audioMasterCloseFileSelector:
220                   return 0;
221 
222 #ifdef VST_FORCE_DEPRECATED
223 #ifndef VST_2_4_EXTENSIONS // deprecated in 2.4
224 
225             case audioMasterGetSpeakerArrangement:
226                   // (long)input in <value>, output in <ptr>
227                   return 0;
228 
229             case audioMasterPinConnected:
230                   // inquire if an input or output is being connected;
231                   // index enumerates input or output counting from zero:
232                   // value is 0 for input and != 0 otherwise. note: the
233                   // return value is 0 for <true> such that older versions
234                   // will always return true.
235                   //return 1;
236                   return 0;
237 
238             // VST 2.0 opcodes...
239             case audioMasterWantMidi:
240                   // <value> is a filter which is currently ignored
241                   return 0;
242 
243             case audioMasterSetTime:
244                   // VstTimenfo* in <ptr>, filter in <value>, not supported
245                   return 0;
246 
247             case audioMasterTempoAt:
248                   // returns tempo (in bpm * 10000) at sample frame location passed in <value>
249                   return 0;  // TODO:
250 
251             case audioMasterGetNumAutomatableParameters:
252                   return 0;
253 
254             case audioMasterGetParameterQuantization:
255                      // returns the integer value for +1.0 representation,
256                    // or 1 if full single float precision is maintained
257                      // in automation. parameter index in <value> (-1: all, any)
258                   //return 0;
259                   return 1;
260 
261             case audioMasterNeedIdle:
262                    // plug needs idle calls (outside its editor window)
263                   return 0;
264 
265             case audioMasterGetPreviousPlug:
266                    // input pin in <value> (-1: first to come), returns cEffect*
267                   return 0;
268 
269             case audioMasterGetNextPlug:
270                    // output pin in <value> (-1: first to come), returns cEffect*
271                   return 0;
272 
273             case audioMasterWillReplaceOrAccumulate:
274                    // returns: 0: not supported, 1: replace, 2: accumulate
275                   //return 0;
276                   return 1;
277 
278             case audioMasterSetOutputSampleRate:
279                   // for variable i/o, sample rate in <opt>
280                   return 0;
281 
282             case audioMasterSetIcon:
283                   // void* in <ptr>, format not defined yet
284                   return 0;
285 
286             case audioMasterOpenWindow:
287                   // returns platform specific ptr
288                   return 0;
289 
290             case audioMasterCloseWindow:
291                   // close window, platform specific handle in <ptr>
292                   return 0;
293 #endif
294 #endif
295 
296             default:
297                   break;
298             }
299 
300       if(MusEGlobal::debugMsg)
301         fprintf(stderr, "  unknown opcode\n");
302 
303       return 0;
304       }
305 
306 //---------------------------------------------------------
307 //   initVST_Native
308 //---------------------------------------------------------
309 
initVST_Native()310 void initVST_Native()
311 {
312 #ifdef VST_NATIVE_SUPPORT
313   #ifdef VST_VESTIGE_SUPPORT
314     printf("Initializing Native VST support. Using VESTIGE compatibility implementation.\n");
315   #else
316     printf("Initializing Native VST support. Using Steinberg VSTSDK.\n");
317   #endif
318 #endif
319   sem_init(&_vstIdLock, 0, 1);
320 
321   const char* message = "scanVstNativeLib: ";
322   const MusEPlugin::PluginScanList& scan_list = MusEPlugin::pluginList;
323   for(MusEPlugin::ciPluginScanList isl = scan_list.begin(); isl != scan_list.end(); ++isl)
324   {
325     const MusEPlugin::PluginScanInfoRef inforef = *isl;
326     const MusEPlugin::PluginScanInfoStruct& info = inforef->info();
327     switch(info._type)
328     {
329       case MusEPlugin::PluginScanInfoStruct::PluginTypeLinuxVST:
330       {
331 #ifdef VST_NATIVE_SUPPORT
332         if(MusEGlobal::loadNativeVST)
333         {
334           const QString inf_cbname = PLUGIN_GET_QSTRING(info._completeBaseName);
335           const QString inf_name   = PLUGIN_GET_QSTRING(info._name);
336           const QString inf_uri    = PLUGIN_GET_QSTRING(info._uri);
337           const Plugin* plug_found = MusEGlobal::plugins.find(
338             inf_cbname,
339             inf_uri,
340             inf_name);
341           const Synth* synth_found = MusEGlobal::synthis.find(
342             inf_cbname,
343             inf_uri,
344             inf_name);
345 
346           if(plug_found)
347           {
348             fprintf(stderr, "Ignoring LinuxVST effect name:%s uri:%s path:%s duplicate of path:%s\n",
349                     PLUGIN_GET_CSTRING(info._name),
350                     PLUGIN_GET_CSTRING(info._uri),
351                     PLUGIN_GET_CSTRING(info.filePath()),
352                     plug_found->filePath().toLatin1().constData());
353           }
354           if(synth_found)
355           {
356             fprintf(stderr, "Ignoring LinuxVST synth name:%s uri:%s path:%s duplicate of path:%s\n",
357                     PLUGIN_GET_CSTRING(info._name),
358                     PLUGIN_GET_CSTRING(info._uri),
359                     PLUGIN_GET_CSTRING(info.filePath()),
360                     synth_found->filePath().toLatin1().constData());
361           }
362 
363           const bool is_effect = info._class & MusEPlugin::PluginScanInfoStruct::PluginClassEffect;
364           const bool is_synth  = info._class & MusEPlugin::PluginScanInfoStruct::PluginClassInstrument;
365 
366           const bool add_plug  = (is_effect || is_synth) &&
367                                  info._inports > 0 && info._outports > 0 &&
368                                  !plug_found;
369 
370           // For now we allow effects as a synth track. Until we allow programs (and midi) in the effect rack.
371           const bool add_synth = (is_synth || is_effect) && !synth_found;
372 
373           if(add_plug || add_synth)
374           {
375             VstNativeSynth* new_synth = new VstNativeSynth(info);
376 
377             if(add_synth)
378             {
379               if(MusEGlobal::debugMsg)
380                 fprintf(stderr, "scanVstNativeLib: adding vst synth plugin:%s name:%s effectName:%s vendorString:%s productString:%s vstver:%d\n",
381                         PLUGIN_GET_CSTRING(info.filePath()),
382                         PLUGIN_GET_CSTRING(info._completeBaseName),
383                         PLUGIN_GET_CSTRING(info._name),
384                         PLUGIN_GET_CSTRING(info._maker),
385                         PLUGIN_GET_CSTRING(info._description),
386                         info._apiVersionMajor
387                         );
388 
389               MusEGlobal::synthis.push_back(new_synth);
390             }
391 
392             if(add_plug)
393             {
394               if(MusEGlobal::debugMsg)
395                 info.dump(message);
396               MusEGlobal::plugins.push_back( new VstNativePluginWrapper(new_synth, info._requiredFeatures) );
397             }
398           }
399         }
400 #endif
401       }
402       break;
403 
404       case MusEPlugin::PluginScanInfoStruct::PluginTypeLADSPA:
405       case MusEPlugin::PluginScanInfoStruct::PluginTypeDSSIVST:
406       case MusEPlugin::PluginScanInfoStruct::PluginTypeDSSI:
407       case MusEPlugin::PluginScanInfoStruct::PluginTypeVST:
408       case MusEPlugin::PluginScanInfoStruct::PluginTypeLV2:
409       case MusEPlugin::PluginScanInfoStruct::PluginTypeMESS:
410       case MusEPlugin::PluginScanInfoStruct::PluginTypeUnknown:
411       case MusEPlugin::PluginScanInfoStruct::PluginTypeNone:
412       case MusEPlugin::PluginScanInfoStruct::PluginTypeAll:
413       break;
414     }
415   }
416 }
417 
418 
419 //---------------------------------------------------------
420 //   VstNativeSynth
421 //---------------------------------------------------------
422 
VstNativeSynth(const QFileInfo & fi,const QString & uri,AEffect * plugin,const QString & label,const QString & desc,const QString & maker,const QString & ver,VstIntPtr id,void * dlHandle,bool isSynth,PluginFeatures_t reqFeatures)423 VstNativeSynth::VstNativeSynth(const QFileInfo& fi, const QString& uri, AEffect* plugin,
424                                const QString& label, const QString& desc, const QString& maker, const QString& ver,
425                                VstIntPtr id, void *dlHandle, bool isSynth, PluginFeatures_t reqFeatures)
426   : Synth(fi, uri, label, desc, maker, ver, reqFeatures)
427 {
428   _handle = dlHandle;
429   _id = id;
430   _hasGui = plugin->flags & effFlagsHasEditor;
431   _inports = plugin->numInputs;
432   _outports = plugin->numOutputs;
433   _controlInPorts = plugin->numParams;
434 //#ifndef VST_VESTIGE_SUPPORT
435   _hasChunks = plugin->flags & 32 /*effFlagsProgramChunks*/;
436 //#else
437  // _hasChunks = false;
438 //#endif
439 
440   _flags = 0;
441   _vst_version = 0;
442   _vst_version = plugin->dispatcher(plugin, effGetVstVersion, 0, 0, NULL, 0.0f);
443   // "2 = VST2.x, older versions return 0". Observed 2400 on all the ones tested so far.
444   if(_vst_version >= 2)
445   {
446     if(plugin->dispatcher(plugin, effCanDo, 0, 0, (void*)"receiveVstEvents", 0.0f) > 0)
447       _flags |= canReceiveVstEvents;
448     if(plugin->dispatcher(plugin, effCanDo, 0, 0, (void*)"sendVstEvents", 0.0f) > 0)
449       _flags |= canSendVstEvents;
450     if(plugin->dispatcher(plugin, effCanDo, 0, 0, (void*)"sendVstMidiEvent", 0.0f) > 0)
451       _flags |= canSendVstMidiEvents;
452     if(plugin->dispatcher(plugin, effCanDo, 0, 0, (void*)"sendVstTimeInfo", 0.0f) > 0)
453       _flags |= canSendVstTimeInfo;
454     if(plugin->dispatcher(plugin, effCanDo, 0, 0, (void*)"receiveVstMidiEvent", 0.0f) > 0)
455       _flags |= canReceiveVstMidiEvents;
456     if(plugin->dispatcher(plugin, effCanDo, 0, 0, (void*)"receiveVstTimeInfo", 0.0f) > 0)
457       _flags |= canReceiveVstTimeInfo;
458     if(plugin->dispatcher(plugin, effCanDo, 0, 0, (void*)"offline", 0.0f) > 0)
459       _flags |=canProcessVstOffline;
460     if(plugin->dispatcher(plugin, effCanDo, 0, 0, (void*)"plugAsChannelInsert", 0.0f) > 0)
461       _flags |= canUseVstAsInsert;
462     if(plugin->dispatcher(plugin, effCanDo, 0, 0, (void*)"plugAsSend", 0.0f) > 0)
463       _flags |= canUseVstAsSend;
464     if(plugin->dispatcher(plugin, effCanDo, 0, 0, (void*)"mixDryWet", 0.0f) > 0)
465       _flags |= canMixVstDryWet;
466     if(plugin->dispatcher(plugin, effCanDo, 0, 0, (void*)"midiProgramNames", 0.0f) > 0)
467       _flags |= canVstMidiProgramNames;
468   }
469   _isSynth = isSynth;
470 }
471 
VstNativeSynth(const MusEPlugin::PluginScanInfoStruct & info)472 VstNativeSynth::VstNativeSynth(const MusEPlugin::PluginScanInfoStruct& info)
473   : Synth(PLUGIN_GET_QSTRING(info.filePath()),
474           PLUGIN_GET_QSTRING(info._uri),
475           PLUGIN_GET_QSTRING(info._label),
476           PLUGIN_GET_QSTRING(info._description),
477           PLUGIN_GET_QSTRING(info._maker),
478           PLUGIN_GET_QSTRING(info._version),
479           info._requiredFeatures)
480 {
481 //   _handle = dlHandle;
482   _handle = NULL;
483   _id = info._subID;
484   _hasGui = info._pluginFlags & MusEPlugin::PluginScanInfoStruct::HasGui;
485   _inports = info._inports;
486   _outports = info._outports;
487   _controlInPorts = info._controlInPorts;
488 
489 //#ifndef VST_VESTIGE_SUPPORT
490   _hasChunks = info._pluginFlags & MusEPlugin::PluginScanInfoStruct::HasChunks;
491 //#else
492  // _hasChunks = false;
493 //#endif
494 
495   _vst_version = info._apiVersionMajor;
496   _flags = info._vstPluginFlags;
497   _isSynth = info._class & MusEPlugin::PluginScanInfoStruct::PluginClassInstrument;
498 }
499 
500 //---------------------------------------------------------
501 //   incInstances
502 //---------------------------------------------------------
503 
incInstances(int val)504 void VstNativeSynth::incInstances(int val)
505 {
506   _instances += val;
507   if(_instances == 0)
508   {
509     if(_handle && _id == 0)
510     {
511       #ifdef VST_NATIVE_DEBUG
512       fprintf(stderr, "VstNativeSynth::incInstances no more instances, closing library\n");
513       #endif
514 
515       dlclose(_handle);
516       _handle = NULL;
517     }
518     iIdx.clear();
519     oIdx.clear();
520     rpIdx.clear();
521     midiCtl2PortMap.clear();
522     port2MidiCtlMap.clear();
523   }
524 }
525 
526 //---------------------------------------------------------
527 //   instantiate
528 //---------------------------------------------------------
529 
instantiate(void * userData)530 AEffect* VstNativeSynth::instantiate(void* userData)
531 {
532   int inst_num = _instances;
533   inst_num++;
534   QString n;
535   n.setNum(inst_num);
536   QString instanceName = baseName() + "-" + n;
537   QByteArray ba = info.filePath().toLatin1();
538   const char* path = ba.constData();
539   void* hnd = _handle;
540   //int vst_version;
541 
542   if(hnd == NULL)
543   {
544     hnd = dlopen(path, RTLD_NOW);
545     if(hnd == NULL)
546     {
547       fprintf(stderr, "dlopen(%s) failed: %s\n", path, dlerror());
548       return NULL;
549     }
550   }
551 
552   AEffect *(*getInstance)(audioMasterCallback);
553   getInstance = (AEffect*(*)(audioMasterCallback))dlsym(hnd, NEW_PLUGIN_ENTRY_POINT);
554   if(!getInstance)
555   {
556     if(MusEGlobal::debugMsg)
557     {
558       fprintf(stderr, "VST 2.4 entrypoint \"" NEW_PLUGIN_ENTRY_POINT "\" not found in library %s, looking for \""
559                       OLD_PLUGIN_ENTRY_POINT "\"\n", path);
560     }
561 
562     getInstance = (AEffect*(*)(audioMasterCallback))dlsym(hnd, OLD_PLUGIN_ENTRY_POINT);
563     if(!getInstance)
564     {
565       fprintf(stderr, "ERROR: VST entrypoints \"" NEW_PLUGIN_ENTRY_POINT "\" or \""
566                       OLD_PLUGIN_ENTRY_POINT "\" not found in library\n");
567       dlclose(hnd);
568       return NULL;
569     }
570     else if(MusEGlobal::debugMsg)
571     {
572       fprintf(stderr, "VST entrypoint \"" OLD_PLUGIN_ENTRY_POINT "\" found\n");
573     }
574   }
575   else if(MusEGlobal::debugMsg)
576   {
577     fprintf(stderr, "VST entrypoint \"" NEW_PLUGIN_ENTRY_POINT "\" found\n");
578   }
579 
580 
581   sem_wait(&_vstIdLock);
582 
583   currentPluginId = _id;
584 
585   AEffect *plugin = getInstance(vstNativeHostCallback);
586 
587   sem_post(&_vstIdLock);
588   if(!plugin)
589   {
590     fprintf(stderr, "ERROR: Failed to instantiate plugin in VST library \"%s\"\n", path);
591     if(_id == 0)
592       dlclose(hnd);
593     return NULL;
594   }
595   else if(MusEGlobal::debugMsg)
596     fprintf(stderr, "plugin instantiated\n");
597 
598   if(plugin->magic != kEffectMagic)
599   {
600     fprintf(stderr, "Not a VST plugin in library \"%s\"\n", path);
601     if(_id == 0)
602       dlclose(hnd);
603     return NULL;
604   }
605   else if(MusEGlobal::debugMsg)
606     fprintf(stderr, "plugin is a VST\n");
607 
608   if(!(plugin->flags & effFlagsHasEditor))
609   {
610     if(MusEGlobal::debugMsg)
611       fprintf(stderr, "Plugin has no GUI\n");
612   }
613   else if(MusEGlobal::debugMsg)
614     fprintf(stderr, "Plugin has a GUI\n");
615 
616   if(!(plugin->flags & effFlagsCanReplacing))
617     fprintf(stderr, "Plugin does not support processReplacing\n");
618   else if(MusEGlobal::debugMsg)
619     fprintf(stderr, "Plugin supports processReplacing\n");
620 
621   plugin->user = userData;
622 
623   // "2 = VST2.x, older versions return 0". Observed 2400 on all the ones tested so far.
624   //vst_version = plugin->dispatcher(plugin, effGetVstVersion, 0, 0, NULL, 0.0f);
625   /*if(!((plugin->flags & effFlagsIsSynth) || (vst_version >= 2 && plugin->dispatcher(plugin, effCanDo, 0, 0,(void*) "receiveVstEvents", 0.0f) > 0)))
626   {
627     if(MusEGlobal::debugMsg)
628       fprintf(stderr, "Plugin is not a synth\n");
629     goto _error;
630   }*/
631 
632 
633   ++_instances;
634   _handle = hnd;
635 
636   return plugin;
637 /*
638 _error:
639   //plugin->dispatcher(plugin, effMainsChanged, 0, 0, NULL, 0);
640   plugin->dispatcher(plugin, effClose, 0, 0, NULL, 0);
641   if(_id == 0)
642     dlclose(hnd);
643   return NULL;
644   */
645 }
646 
647 //---------------------------------------------------------
648 //   openPlugin
649 //   static
650 //---------------------------------------------------------
651 
openPlugin(AEffect * plugin)652 bool VstNativeSynth::openPlugin(AEffect* plugin)
653 {
654   plugin->dispatcher(plugin, effOpen, 0, 0, NULL, 0);
655 
656   // work around to get airwave to work (author contacted so maybe another solution will
657   // reveal itself)
658   plugin->dispatcher(plugin, effSetSampleRate, 0, 0, NULL, MusEGlobal::sampleRate);
659   plugin->dispatcher(plugin, effSetBlockSize, 0, MusEGlobal::segmentSize, NULL, 0.0f);
660   plugin->dispatcher(plugin, effMainsChanged, 0, 1, NULL, 0.0f);
661 
662   //plugin->dispatcher(plugin, effSetProgram, 0, 0, NULL, 0.0f); // REMOVE Tim. Or keep?
663   return true;
664 }
665 
666 //---------------------------------------------------------
667 //   createSIF
668 //---------------------------------------------------------
669 
createSIF(SynthI * s)670 SynthIF* VstNativeSynth::createSIF(SynthI* s)
671       {
672       VstNativeSynthIF* sif = new VstNativeSynthIF(s);
673       sif->init(this);
674       return sif;
675       }
676 
677 //---------------------------------------------------------
678 //   VstNativeSynthIF
679 //---------------------------------------------------------
680 
VstNativeSynthIF(SynthI * s)681 VstNativeSynthIF::VstNativeSynthIF(SynthI* s) : SynthIF(s)
682 {
683       _guiVisible = false;
684       _gw = NULL;
685       _synth = NULL;
686       _plugin = NULL;
687       _active = false;
688       _editor = NULL;
689       _inProcess = false;
690        _controls = NULL;
691 //       controlsOut = 0;
692       _audioInBuffers = NULL;
693       _audioInSilenceBuf = NULL;
694       _audioOutBuffers = NULL;
695       userData.pstate = 0;
696       userData.sif = this;
697 }
698 
~VstNativeSynthIF()699 VstNativeSynthIF::~VstNativeSynthIF()
700 {
701   // Just in case it wasn't removed or deactivate3 wasn't called etc...
702   if(_plugin)
703     fprintf(stderr, "ERROR: ~VstNativeSynthIF: _plugin is not NULL!\n");
704 
705   if(_audioOutBuffers)
706   {
707     unsigned long op = _synth->outPorts();
708     for(unsigned long i = 0; i < op; ++i)
709     {
710       if(_audioOutBuffers[i])
711         free(_audioOutBuffers[i]);
712     }
713     delete[] _audioOutBuffers;
714   }
715 
716   if(_audioInBuffers)
717   {
718     unsigned long ip = _synth->inPorts();
719     for(unsigned long i = 0; i < ip; ++i)
720     {
721       if(_audioInBuffers[i])
722         free(_audioInBuffers[i]);
723     }
724     delete[] _audioInBuffers;
725   }
726 
727   if(_audioInSilenceBuf)
728     free(_audioInSilenceBuf);
729 
730   if(_controls)
731     delete[] _controls;
732 
733   if(_gw)
734     delete[] _gw;
735 }
736 
737 //---------------------------------------------------------
738 //   init
739 //---------------------------------------------------------
740 
init(Synth * s)741 bool VstNativeSynthIF::init(Synth* s)
742       {
743       _synth = (VstNativeSynth*)s;
744       _plugin = _synth->instantiate(&userData);
745       if(!_plugin)
746         return false;
747 
748       if(!_synth->openPlugin(_plugin))
749         return false;
750 
751       queryPrograms();
752 
753       unsigned long outports = _synth->outPorts();
754       if(outports != 0)
755       {
756         _audioOutBuffers = new float*[outports];
757         for(unsigned long k = 0; k < outports; ++k)
758         {
759 #ifdef _WIN32
760           _audioOutBuffers[k] = (float *) _aligned_malloc(16, sizeof(float *) * MusEGlobal::segmentSize);
761           if(_audioOutBuffers[k] == NULL)
762           {
763              fprintf(stderr, "ERROR: VstNativeSynthIF::init: _aligned_malloc returned error: NULL. Aborting!\n");
764              abort();
765           }
766 #else
767           int rv = posix_memalign((void**)&_audioOutBuffers[k], 16, sizeof(float) * MusEGlobal::segmentSize);
768           if(rv != 0)
769           {
770             fprintf(stderr, "ERROR: VstNativeSynthIF::init: posix_memalign returned error:%d. Aborting!\n", rv);
771             abort();
772           }
773 #endif
774           if(MusEGlobal::config.useDenormalBias)
775           {
776             for(unsigned q = 0; q < MusEGlobal::segmentSize; ++q)
777               _audioOutBuffers[k][q] = MusEGlobal::denormalBias;
778           }
779           else
780             memset(_audioOutBuffers[k], 0, sizeof(float) * MusEGlobal::segmentSize);
781         }
782       }
783 
784       unsigned long inports = _synth->inPorts();
785       if(inports != 0)
786       {
787         _audioInBuffers = new float*[inports];
788         for(unsigned long k = 0; k < inports; ++k)
789         {
790 #ifdef _WIN32
791           _audioInBuffers[k] = (float *) _aligned_malloc(16, sizeof(float *) * MusEGlobal::segmentSize);
792           if(_audioInBuffers[k] == NULL)
793           {
794              fprintf(stderr, "ERROR: VstNativeSynthIF::init: _aligned_malloc returned error: NULL. Aborting!\n");
795              abort();
796           }
797 #else
798           int rv = posix_memalign((void**)&_audioInBuffers[k], 16, sizeof(float) * MusEGlobal::segmentSize);
799           if(rv != 0)
800           {
801             fprintf(stderr, "ERROR: VstNativeSynthIF::init: posix_memalign returned error:%d. Aborting!\n", rv);
802             abort();
803           }
804 #endif
805           if(MusEGlobal::config.useDenormalBias)
806           {
807             for(unsigned q = 0; q < MusEGlobal::segmentSize; ++q)
808               _audioInBuffers[k][q] = MusEGlobal::denormalBias;
809           }
810           else
811             memset(_audioInBuffers[k], 0, sizeof(float) * MusEGlobal::segmentSize);
812         }
813 
814 #ifdef _WIN32
815         _audioInSilenceBuf = (float *) _aligned_malloc(16, sizeof(float *) * MusEGlobal::segmentSize);
816         if(_audioInSilenceBuf == NULL)
817         {
818            fprintf(stderr, "ERROR: VstNativeSynthIF::init: _aligned_malloc returned error: NULL. Aborting!\n");
819            abort();
820         }
821 #else
822         int rv = posix_memalign((void**)&_audioInSilenceBuf, 16, sizeof(float) * MusEGlobal::segmentSize);
823         if(rv != 0)
824         {
825           fprintf(stderr, "ERROR: VstNativeSynthIF::init: posix_memalign returned error:%d. Aborting!\n", rv);
826           abort();
827         }
828 #endif
829         if(MusEGlobal::config.useDenormalBias)
830         {
831           for(unsigned q = 0; q < MusEGlobal::segmentSize; ++q)
832             _audioInSilenceBuf[q] = MusEGlobal::denormalBias;
833         }
834         else
835           memset(_audioInSilenceBuf, 0, sizeof(float) * MusEGlobal::segmentSize);
836       }
837 
838       _controls = NULL;
839       _gw = NULL;
840       unsigned long controlPorts = _synth->inControls();
841       if(controlPorts != 0)
842       {
843         _controls = new Port[controlPorts];
844         _gw       = new VstNativeGuiWidgets[controlPorts];
845       }
846 
847       for(unsigned long i = 0; i < controlPorts; ++i)
848       {
849         _gw[i].pressed = false;
850 
851         _controls[i].idx = i;
852         //float val;  // TODO
853         //ladspaDefaultValue(ld, k, &val);   // FIXME TODO
854         float val = _plugin->getParameter(_plugin, i);  // TODO
855         _controls[i].val    = val;
856         _controls[i].tmpVal = val;
857         _controls[i].enCtrl  = true;
858 
859         // Support a special block for synth ladspa controllers.
860         // Put the ID at a special block after plugins (far after).
861         int id = genACnum(MusECore::MAX_PLUGINS, i);
862         const char* param_name = paramName(i);
863 
864         // TODO FIXME!
865         ///float min, max;
866         ///ladspaControlRange(ld, k, &min, &max);
867         float min = 0.0, max = 1.0;
868 
869         CtrlList* cl;
870         CtrlListList* cll = track()->controller();
871         iCtrlList icl = cll->find(id);
872         if (icl == cll->end())
873         {
874           cl = new CtrlList(id);
875           cll->add(cl);
876           cl->setCurVal(_controls[i].val);
877           //cl->setCurVal(_plugin->getParameter(_plugin, i));
878         }
879         else
880         {
881           cl = icl->second;
882           _controls[i].val = cl->curVal();
883 
884           if(dispatch(26 /*effCanBeAutomated*/, i, 0, NULL, 0.0f) == 1)
885           {
886             double v = cl->curVal();
887             if(v != _plugin->getParameter(_plugin, i))
888               _plugin->setParameter(_plugin, i, v);
889           }
890 
891   #ifdef VST_NATIVE_DEBUG
892           else
893             fprintf(stderr, "VstNativeSynthIF::init %s parameter:%lu cannot be automated\n", name().toLatin1().constData(), i);
894   #endif
895         }
896 
897         cl->setRange(min, max);
898         cl->setName(QString(param_name));
899         //cl->setValueType(ladspaCtrlValueType(ld, k));
900         cl->setValueType(ctrlValueType(i));
901         //cl->setMode(ladspaCtrlMode(ld, k));
902         cl->setMode(ctrlMode(i));
903       }
904 
905       activate();
906       return true;
907       }
908 
909 //---------------------------------------------------------
910 //   resizeEditor
911 //---------------------------------------------------------
912 
resizeEditor(MusEGui::VstNativeEditor * editor,int w,int h)913 bool VstNativeSynth::resizeEditor(MusEGui::VstNativeEditor *editor, int w, int h)
914 {
915     if(!editor || w <= 0 || h <= 0)
916         return false;
917 
918     if (editor->fixScaling() && editor->devicePixelRatio() >= 1.0) {
919         w = qRound((qreal)w / editor->devicePixelRatio());
920         h = qRound((qreal)h / editor->devicePixelRatio());
921     }
922 
923     editor->setFixedSize(w, h);
924     return true;
925 }
926 
927 //---------------------------------------------------------
928 //   vstconfWrite
929 //---------------------------------------------------------
930 
vstconfWrite(AEffect * plugin,const QString & name,int level,Xml & xml)931 void VstNativeSynth::vstconfWrite(AEffect *plugin, const QString& name, int level, Xml &xml)
932 {
933    if(hasChunks())
934    {
935       //---------------------------------------------
936       // dump current state of synth
937       //---------------------------------------------
938       fprintf(stderr, "%s: commencing chunk data dump, plugin api version=%d\n",
939               name.toLatin1().constData(), vstVersion());
940       unsigned long len = 0;
941       void* p = 0;
942       len = plugin->dispatcher(plugin, 23 /* effGetChunk */, 0, 0, &p, 0.0);
943 
944       if (len)
945       {
946          QByteArray arrOut = QByteArray::fromRawData((char *)p, len);
947 
948          // Weee! Compression!
949          QByteArray outEnc64 = qCompress(arrOut).toBase64();
950 
951          QString customData(outEnc64);
952          for (int pos=0; pos < customData.size(); pos+=150)
953          {
954             customData.insert(pos++,'\n'); // add newlines for readability
955          }
956          xml.strTag(level, "customData", customData);
957       }
958    }
959 }
960 
961 //---------------------------------------------------------
962 //   vstconfSet
963 //---------------------------------------------------------
964 
vstconfSet(AEffect * plugin,const std::vector<QString> & customParams)965 void VstNativeSynth::vstconfSet(AEffect *plugin, const std::vector<QString> &customParams)
966 {
967    if(customParams.size() == 0)
968       return;
969 
970    if(!hasChunks())
971    {
972       return;
973    }
974 
975    for(size_t i = 0; i < customParams.size(); i++)
976    {
977       QString param = customParams [i];
978       param.remove('\n'); // remove all linebreaks that may have been added to prettyprint the songs file
979       QByteArray paramIn;
980       paramIn.append(param.toUtf8());
981       // Try to uncompress the data.
982       QByteArray dec64 = qUncompress(QByteArray::fromBase64(paramIn));
983       // Failed? Try uncompressed.
984       if(dec64.isEmpty())
985         dec64 = QByteArray::fromBase64(paramIn);
986 
987       plugin->dispatcher(plugin, 24 /* effSetChunk */, 0, dec64.size(), (void*)dec64.data(), 0.0); // index 0: is bank 1: is program
988       break; //one customData tag includes all data in base64
989    }
990 }
991 
992 //---------------------------------------------------------
993 //   hostCallback
994 //---------------------------------------------------------
995 
pluginHostCallback(VstNativeSynthOrPlugin * userData,VstInt32 opcode,VstInt32 index,VstIntPtr value,void * ptr,float opt)996 VstIntPtr VstNativeSynth::pluginHostCallback(VstNativeSynthOrPlugin *userData, VstInt32 opcode, VstInt32 index, VstIntPtr value, void* ptr, float opt)
997 {
998    static VstTimeInfo _timeInfo;
999 
1000 #ifdef VST_NATIVE_DEBUG
1001    if(opcode != audioMasterGetTime)
1002       fprintf(stderr, "VstNativeSynthIF::hostCallback %s opcode:%ld\n", name().toLatin1().constData(), opcode);
1003 #endif
1004 
1005    switch (opcode) {
1006    case audioMasterAutomate:
1007       // index, value, returns 0
1008       ///_plugin->setParameter (_plugin, index, opt);
1009       VstNativeSynth::guiControlChanged(userData, index, opt);
1010       return 0;
1011 
1012    case audioMasterVersion:
1013       // vst version, currently 2 (0 for older)
1014       return 2300;
1015 
1016    case audioMasterCurrentId:
1017    {
1018       // returns the unique id of a plug that's currently
1019       // loading
1020       ///return 0;
1021       AEffect *vstPlug = 0;
1022       if(userData->sif)
1023          vstPlug = userData->sif->_plugin;
1024       else if(userData->pstate)
1025          vstPlug = userData->pstate->plugin;
1026       return vstPlug->uniqueID;
1027    }
1028 
1029    case audioMasterIdle:
1030       // call application idle routine (this will
1031       // call effEditIdle for all open editors too)
1032       //_plugin->updateParamValues(false);
1033       //_plugin->dispatcher(_plugin, effEditIdle, 0, 0, NULL, 0.0f);
1034       ///idleEditor();  // REMOVE Tim. Or keep.
1035       return 0;
1036 
1037    case audioMasterGetTime:
1038    {
1039       // returns const VstTimeInfo* (or 0 if not supported)
1040       // <value> should contain a mask indicating which fields are required
1041       // (see valid masks above), as some items may require extensive
1042       // conversions
1043 
1044       // FIXME TODO: Optimizations: This may be called many times in one process call
1045       //              due to our multi-run slices. Some of the (costly) info will be redundant.
1046       //             So try to add some flag to try to only call some or all of this once per cycle.
1047 
1048 #ifdef VST_NATIVE_DEBUG
1049       fprintf(stderr, "VstNativeSynthIF::hostCallback master time: valid: nanos:%d ppqpos:%d tempo:%d bars:%d cyclepos:%d sig:%d smpte:%d clock:%d\n",
1050               (bool)(value & kVstNanosValid),
1051               (bool)(value & kVstPpqPosValid),
1052               (bool)(value & kVstTempoValid),
1053               (bool)(value & kVstBarsValid),
1054               (bool)(value & kVstCyclePosValid),
1055               (bool)(value & kVstTimeSigValid),
1056               (bool)(value & kVstSmpteValid),
1057               (bool)(value & kVstClockValid));
1058 #endif
1059       memset(&_timeInfo, 0, sizeof(_timeInfo));
1060 
1061       unsigned int curr_frame = MusEGlobal::audio->pos().frame();
1062       _timeInfo.samplePos = (double)curr_frame;
1063       _timeInfo.sampleRate = (double)MusEGlobal::sampleRate;
1064       _timeInfo.flags = 0;
1065 
1066       Pos p(MusEGlobal::extSyncFlag ? MusEGlobal::audio->tickPos() : curr_frame, MusEGlobal::extSyncFlag ? true : false);
1067 
1068       if(value & kVstBarsValid)
1069       {
1070          int p_bar, p_beat, p_tick;
1071          p.mbt(&p_bar, &p_beat, &p_tick);
1072          _timeInfo.barStartPos = (double)Pos(p_bar, 0, 0).tick() / (double)MusEGlobal::config.division;
1073          _timeInfo.flags |= kVstBarsValid;
1074       }
1075 
1076       if(value & kVstTimeSigValid)
1077       {
1078          int z, n;
1079          MusEGlobal::sigmap.timesig(p.tick(), z, n);
1080 
1081 #ifndef VST_VESTIGE_SUPPORT
1082          _timeInfo.timeSigNumerator = (long)z;
1083          _timeInfo.timeSigDenominator = (long)n;
1084 #else
1085          _timeInfo.timeSigNumerator = z;
1086          _timeInfo.timeSigDenominator = n;
1087 #endif
1088          _timeInfo.flags |= kVstTimeSigValid;
1089       }
1090 
1091       if(value & kVstPpqPosValid)
1092       {
1093          _timeInfo.ppqPos = (double)MusEGlobal::audio->tickPos() / (double)MusEGlobal::config.division;
1094          _timeInfo.flags |= kVstPpqPosValid;
1095       }
1096 
1097       if(value & kVstTempoValid)
1098       {
1099          double tempo = MusEGlobal::tempomap.tempo(p.tick());
1100          _timeInfo.tempo = ((double)MusEGlobal::tempomap.globalTempo() * 600000.0) / tempo;
1101          _timeInfo.flags |= kVstTempoValid;
1102       }
1103 
1104 #ifdef VST_NATIVE_DEBUG
1105       fprintf(stderr, "VstNativeSynthIF::hostCallback master time: sample pos:%f samplerate:%f sig num:%ld den:%ld tempo:%f\n",
1106               _timeInfo.samplePos, _timeInfo.sampleRate, _timeInfo.timeSigNumerator, _timeInfo.timeSigDenominator, _timeInfo.tempo);
1107 #endif
1108 
1109       if(MusEGlobal::audio->isPlaying())
1110          _timeInfo.flags |= (kVstTransportPlaying | kVstTransportChanged);
1111       // TODO
1112       //if(MusEGlobal::audio->isRecording())
1113       //  _timeInfo.flags |= (kVstTransportRecording | kVstTransportChanged);
1114 
1115 #ifdef _WIN32
1116       return *((long*)(&_timeInfo));
1117 #else
1118       return (long)&_timeInfo;
1119 #endif
1120    }
1121 
1122    case audioMasterProcessEvents:
1123    {
1124      // VstEvents* in <ptr>
1125      VstEvents* ve = (VstEvents*)ptr;
1126      int num_ev = ve->numEvents;
1127 #ifdef VST_NATIVE_DEBUG
1128      fprintf(stderr, "VstNativeSynthIF::hostCallback audioMasterProcessEvents: numEvents:%d\n", num_ev);
1129 #endif
1130      for(int i = 0; i < num_ev; ++i)
1131      {
1132        // Due to incomplete vestige midi type support, cast as VstMidiEvent first in order to get the type.
1133        VstMidiEvent* vme = (VstMidiEvent*)ve->events[i];
1134        switch(vme->type)
1135        {
1136          // Is it really a midi event?
1137          case kVstMidiType:
1138          {
1139 #ifdef VST_NATIVE_DEBUG
1140            fprintf(stderr, "  kVstMidiType: deltaFrames:%d midiData[0]:%u [1]:%u [2]:%u\n",
1141                    vme->deltaFrames,
1142                    (unsigned char)vme->midiData[0], (unsigned char)vme->midiData[1], (unsigned char)vme->midiData[2]);
1143 #endif
1144            if(userData->sif)
1145              userData->sif->eventReceived(vme);
1146            //else if(userData->pstate) // TODO Plugin midi
1147              //  vstPlug = userData->pstate->plugin;
1148          }
1149          break;
1150 
1151 #ifndef VST_VESTIGE_SUPPORT
1152          case kVstSysExType:
1153          break;
1154 #endif
1155 
1156          default:
1157 #ifdef VST_NATIVE_DEBUG
1158            fprintf(stderr, "  unknown event type:%d\n", vme->type);
1159 #endif
1160          break;
1161        }
1162      }
1163      //return 0;  // TODO:
1164      return 1; // Supported and processed.
1165    }
1166 
1167    case audioMasterIOChanged:
1168       // numInputs and/or numOutputs has changed
1169       return 0;
1170 
1171    case audioMasterSizeWindow:
1172    {
1173       // index: width, value: height
1174       MusEGui::VstNativeEditor *editor = userData->sif ? userData->sif->_editor : userData->pstate->editor;
1175       if(VstNativeSynth::resizeEditor(editor, int(index), int(value)))
1176             return 1; // supported.
1177       return 0;
1178    }
1179 
1180    case audioMasterGetSampleRate:
1181       //return 0;
1182       return MusEGlobal::sampleRate;
1183 
1184    case audioMasterGetBlockSize:
1185       //return 0;
1186       return MusEGlobal::segmentSize;
1187 
1188    case audioMasterGetInputLatency:
1189       return 0;
1190 
1191    case audioMasterGetOutputLatency:
1192       return 0;
1193 
1194    case audioMasterGetCurrentProcessLevel:
1195    {
1196       // returns: 0: not supported,
1197       // 1: currently in user thread (gui)
1198       // 2: currently in audio thread (where process is called)
1199       // 3: currently in 'sequencer' thread (midi, timer etc)
1200       // 4: currently offline processing and thus in user thread
1201       // other: not defined, but probably pre-empting user thread.
1202       bool inProcessNow = userData->sif ? userData->sif->_inProcess : userData->pstate->inProcess;
1203       if(inProcessNow)
1204          return 2;
1205       else
1206          return 1;
1207    }
1208 
1209    case audioMasterGetAutomationState:
1210       // returns 0: not supported, 1: off, 2:read, 3:write, 4:read/write
1211       // offline
1212       return 1;   // TODO:
1213 
1214    case audioMasterOfflineStart:
1215    case audioMasterOfflineRead:
1216       // ptr points to offline structure, see below. return 0: error, 1 ok
1217       return 0;
1218 
1219    case audioMasterOfflineWrite:
1220       // same as read
1221       return 0;
1222 
1223    case audioMasterOfflineGetCurrentPass:
1224    case audioMasterOfflineGetCurrentMetaPass:
1225       return 0;
1226 
1227    case audioMasterGetVendorString:
1228       // fills <ptr> with a string identifying the vendor (max 64 char)
1229       strcpy ((char*) ptr, "MusE");
1230       return 1;
1231 
1232    case audioMasterGetProductString:
1233       // fills <ptr> with a string with product name (max 64 char)
1234       strcpy ((char*) ptr, "MusE Sequencer");
1235       return 1;
1236 
1237    case audioMasterGetVendorVersion:
1238       // returns vendor-specific version
1239       return 2000;
1240 
1241    case audioMasterVendorSpecific:
1242       // no definition, vendor specific handling
1243       return 0;
1244 
1245    case audioMasterCanDo:
1246       // string in ptr, see below
1247       if(!strcmp((char*)ptr, "sendVstEvents") ||
1248             !strcmp((char*)ptr, "receiveVstMidiEvent") ||
1249             !strcmp((char*)ptr, "sendVstMidiEvent") ||
1250             !strcmp((char*)ptr, "sendVstTimeInfo") ||
1251             !strcmp((char*)ptr, "sizeWindow") ||
1252             !strcmp((char*)ptr, "supplyIdle"))
1253          return 1;
1254 
1255 #if 0 //ifndef VST_VESTIGE_SUPPORT
1256       else
1257          if(!strcmp((char*)ptr, "openFileSelector") ||
1258                !strcmp((char*)ptr, "closeFileSelector"))
1259             return 1;
1260 #endif
1261       return 0;
1262 
1263    case audioMasterGetLanguage:
1264       // see enum
1265       //return 0;
1266       return kVstLangEnglish;
1267 
1268    case audioMasterGetDirectory:
1269       // get plug directory, FSSpec on MAC, else char*
1270       return 0;
1271 
1272    case audioMasterUpdateDisplay:
1273    {
1274       // something has changed, update 'multi-fx' display
1275 
1276       //_plugin->updateParamValues(false);
1277       //QApplication::processEvents();     // REMOVE Tim. Or keep. Commented in QTractor.
1278       AEffect *vstPlug = 0;
1279       if(userData->sif)
1280          vstPlug = userData->sif->_plugin;
1281       else if(userData->pstate)
1282          vstPlug = userData->pstate->plugin;
1283 
1284       vstPlug->dispatcher(vstPlug, effEditIdle, 0, 0, NULL, 0.0f);  // ?
1285 
1286       return 0;
1287    }
1288 
1289    case audioMasterBeginEdit:
1290       // begin of automation session (when mouse down), parameter index in <index>
1291       VstNativeSynth::guiAutomationBegin(userData, index);
1292       return 1;
1293 
1294    case audioMasterEndEdit:
1295       // end of automation session (when mouse up),     parameter index in <index>
1296       VstNativeSynth::guiAutomationEnd(userData, index);
1297       return 1;
1298 
1299 #if 0 //ifndef VST_VESTIGE_SUPPORT
1300    case audioMasterOpenFileSelector:
1301       // open a fileselector window with VstFileSelect* in <ptr>
1302       return 0;
1303 
1304    case audioMasterCloseFileSelector:
1305       return 0;
1306 #endif
1307 
1308 #ifdef VST_FORCE_DEPRECATED
1309 #ifndef VST_2_4_EXTENSIONS // deprecated in 2.4
1310 
1311    case audioMasterGetSpeakerArrangement:
1312       // (long)input in <value>, output in <ptr>
1313       return 0;
1314 
1315    case audioMasterPinConnected:
1316       // inquire if an input or output is being connected;
1317       // index enumerates input or output counting from zero:
1318       // value is 0 for input and != 0 otherwise. note: the
1319       // return value is 0 for <true> such that older versions
1320       // will always return true.
1321       //return 1;
1322       return 0;
1323 
1324       // VST 2.0 opcodes...
1325    case audioMasterWantMidi:
1326       // <value> is a filter which is currently ignored
1327       return 0;
1328 
1329    case audioMasterSetTime:
1330       // VstTimenfo* in <ptr>, filter in <value>, not supported
1331       return 0;
1332 
1333    case audioMasterTempoAt:
1334       // returns tempo (in bpm * 10000) at sample frame location passed in <value>
1335       return 0;  // TODO:
1336 
1337    case audioMasterGetNumAutomatableParameters:
1338       return 0;
1339 
1340    case audioMasterGetParameterQuantization:
1341       // returns the integer value for +1.0 representation,
1342       // or 1 if full single float precision is maintained
1343       // in automation. parameter index in <value> (-1: all, any)
1344       //return 0;
1345       return 1;
1346 
1347    case audioMasterNeedIdle:
1348       // plug needs idle calls (outside its editor window)
1349       return 0;
1350 
1351    case audioMasterGetPreviousPlug:
1352       // input pin in <value> (-1: first to come), returns cEffect*
1353       return 0;
1354 
1355    case audioMasterGetNextPlug:
1356       // output pin in <value> (-1: first to come), returns cEffect*
1357       return 0;
1358 
1359    case audioMasterWillReplaceOrAccumulate:
1360       // returns: 0: not supported, 1: replace, 2: accumulate
1361       //return 0;
1362       return 1;
1363 
1364    case audioMasterSetOutputSampleRate:
1365       // for variable i/o, sample rate in <opt>
1366       return 0;
1367 
1368    case audioMasterSetIcon:
1369       // void* in <ptr>, format not defined yet
1370       return 0;
1371 
1372    case audioMasterOpenWindow:
1373       // returns platform specific ptr
1374       return 0;
1375 
1376    case audioMasterCloseWindow:
1377       // close window, platform specific handle in <ptr>
1378       return 0;
1379 #endif
1380 #endif
1381 
1382 
1383    default:
1384       break;
1385    }
1386    return 0;
1387 }
1388 
1389 //---------------------------------------------------------
1390 //   idleEditor
1391 //---------------------------------------------------------
1392 
idleEditor()1393 void VstNativeSynthIF::idleEditor()
1394 {
1395 #ifdef VST_NATIVE_DEBUG
1396   fprintf(stderr, "VstNativeSynthIF::idleEditor %p\n", this);
1397 #endif
1398 
1399   // REMOVE Tim. Or keep.
1400   //_plugin->dispatcher(_plugin, effEditIdle, 0, 0, NULL, 0.0f);
1401   //if(_editor)
1402   //  _editor->update();
1403 }
1404 
1405 //---------------------------------------------------------
1406 //   guiHeartBeat
1407 //---------------------------------------------------------
1408 
guiHeartBeat()1409 void VstNativeSynthIF::guiHeartBeat()
1410 {
1411 #ifdef VST_NATIVE_DEBUG
1412   fprintf(stderr, "VstNativeSynthIF::guiHeartBeat %p\n", this);
1413 #endif
1414 
1415   // REMOVE Tim. Or keep.
1416   if(_plugin && _active)
1417   {
1418 //#ifdef VST_FORCE_DEPRECATED   // REMOVE Tim. Or keep
1419     //_plugin->dispatcher(_plugin, effIdle, 0, 0, NULL, 0.0f);
1420 //#endif
1421      if(_guiVisible)
1422      {
1423        _plugin->dispatcher(_plugin, effEditIdle, 0, 0, NULL, 0.0f);
1424        if(_editor)
1425          _editor->update();
1426      }
1427   }
1428 }
1429 
1430 //---------------------------------------------------------
1431 //   nativeGuiVisible
1432 //---------------------------------------------------------
1433 
nativeGuiVisible() const1434 bool VstNativeSynthIF::nativeGuiVisible() const
1435       {
1436       return _guiVisible;
1437       }
1438 
1439 //---------------------------------------------------------
1440 //   showGui
1441 //---------------------------------------------------------
1442 
showNativeGui(bool v)1443 void VstNativeSynthIF::showNativeGui(bool v)
1444       {
1445       if(!(_plugin->flags & effFlagsHasEditor)) // || v == nativeGuiVisible())
1446             return;
1447       if(v)
1448       {
1449         if(_editor)
1450         {
1451           if(!_editor->isVisible())
1452             _editor->show();
1453           _editor->raise();
1454           _editor->activateWindow();
1455         }
1456         else
1457         {
1458           Qt::WindowFlags wflags(Qt::Window
1459                   | Qt::CustomizeWindowHint
1460                   | Qt::WindowTitleHint
1461                   | Qt::WindowSystemMenuHint
1462                   | Qt::WindowMinMaxButtonsHint
1463                   | Qt::WindowCloseButtonHint);
1464           _editor = new MusEGui::VstNativeEditor(nullptr, wflags);
1465           _editor->open(this, nullptr);
1466         }
1467       }
1468       else
1469       {
1470         if(_editor)
1471         {
1472           _editor->close();
1473           //_editor = NULL;  // No - done in editorDeleted.
1474         }
1475       }
1476       _guiVisible = v;
1477 }
1478 
1479 //---------------------------------------------------------
1480 //   editorOpened
1481 //---------------------------------------------------------
1482 
getNativeGeometry(int * x,int * y,int * w,int * h) const1483 void VstNativeSynthIF::getNativeGeometry(int*x, int*y, int*w, int*h) const
1484 {
1485   if(!_editor)
1486   {
1487     *x=0;*y=0;*w=0;*h=0;
1488     return;
1489   }
1490 
1491   *x = _editor->x();
1492   *y = _editor->y();
1493   *w = _editor->width();
1494   *h = _editor->height();
1495 }
1496 
1497 //---------------------------------------------------------
1498 //   editorOpened
1499 //---------------------------------------------------------
1500 
setNativeGeometry(int x,int y,int w,int h)1501 void VstNativeSynthIF::setNativeGeometry(int x, int y, int w, int h)
1502 {
1503   if(!_editor)
1504     return;
1505 
1506   _editor->setGeometry(x, y, w, h);
1507 }
1508 
1509 //---------------------------------------------------------
1510 //   editorOpened
1511 //---------------------------------------------------------
1512 
editorOpened()1513 void VstNativeSynthIF::editorOpened()
1514 {
1515   _guiVisible = true;
1516 }
1517 
1518 //---------------------------------------------------------
1519 //   editorClosed
1520 //---------------------------------------------------------
1521 
editorClosed()1522 void VstNativeSynthIF::editorClosed()
1523 {
1524   _guiVisible = false;
1525 }
1526 
1527 //---------------------------------------------------------
1528 //   editorDeleted
1529 //---------------------------------------------------------
1530 
editorDeleted()1531 void VstNativeSynthIF::editorDeleted()
1532 {
1533   _editor = NULL;
1534 }
1535 
1536 //---------------------------------------------------------
1537 //   receiveEvent
1538 //---------------------------------------------------------
1539 
receiveEvent()1540 MidiPlayEvent VstNativeSynthIF::receiveEvent()
1541       {
1542       return MidiPlayEvent();
1543       }
1544 
1545 //---------------------------------------------------------
1546 //   eventReceived
1547 //---------------------------------------------------------
1548 
eventReceived(VstMidiEvent * ev)1549 void VstNativeSynthIF::eventReceived(VstMidiEvent* ev)
1550       {
1551       const int port = synti->midiPort();
1552 
1553       MidiRecordEvent event;
1554       event.setB(0);
1555       //event.setPort(_port);
1556       event.setPort(port);
1557 
1558       // NOTE: From muse_qt4_evolution. Not done here in Muse-2 (yet).
1559       // move all events 2*MusEGlobal::segmentSize into the future to get
1560       // jitterfree playback
1561       //
1562       //  cycle   n-1         n          n+1
1563       //          -+----------+----------+----------+-
1564       //               ^          ^          ^
1565       //               catch      process    play
1566       //
1567 
1568       // These Jack events arrived in the previous period, and it may not have been at the audio position before this one (after a seek).
1569       // This is how our ALSA driver works, events there are timestamped asynchronous of any process, referenced to the CURRENT audio
1570       //  position, so that by the time of the NEXT process, THOSE events have also occurred in the previous period.
1571       // So, technically this is correct. What MATTERS is how we adjust the times for storage, and/or simultaneous playback in THIS period,
1572       //  and TEST: we'll need to make sure any non-contiguous previous period is handled correctly by process - will it work OK as is?
1573       // If ALSA works OK than this should too...
1574       event.setTime(MusEGlobal::audio->pos().frame() + ev->deltaFrames);
1575       event.setTick(MusEGlobal::lastExtMidiSyncTick);
1576 
1577 //       event.setChannel(*(ev->buffer) & 0xf);
1578 //       int type = *(ev->buffer) & 0xf0;
1579 //       int a    = *(ev->buffer + 1) & 0x7f;
1580 //       int b    = *(ev->buffer + 2) & 0x7f;
1581       event.setChannel(ev->midiData[0] & 0xf);
1582       int type = ev->midiData[0] & 0xf0;
1583       int a    = ev->midiData[1] & 0x7f;
1584       int b    = ev->midiData[2] & 0x7f;
1585       event.setType(type);
1586 
1587       switch(type) {
1588             case ME_NOTEON:
1589                  // REMOVE Tim. Noteoff. Added.
1590                  // Convert zero-velocity note ons to note offs as per midi spec.
1591                  if(b == 0)
1592                    event.setType(ME_NOTEOFF);
1593                  // Fall through.
1594 
1595             case ME_NOTEOFF:
1596             case ME_CONTROLLER:
1597             case ME_POLYAFTER:
1598                   //event.setA(*(ev->buffer + 1));
1599                   //event.setB(*(ev->buffer + 2));
1600                   event.setA(ev->midiData[1]);
1601                   event.setB(ev->midiData[2]);
1602                   break;
1603             case ME_PROGRAM:
1604             case ME_AFTERTOUCH:
1605                   //event.setA(*(ev->buffer + 1));
1606                   event.setA(ev->midiData[1]);
1607                   break;
1608 
1609             case ME_PITCHBEND:
1610                   event.setA(((b << 7) + a) - 8192);
1611                   break;
1612 
1613             case ME_SYSEX:
1614                   {
1615                     //int type = *(ev->buffer) & 0xff;
1616                     int type = ev->midiData[0] & 0xff;
1617                     switch(type)
1618                     {
1619 // TODO: Sysex NOT supported with Vestige !
1620 //                           case ME_SYSEX:
1621 //
1622 //                                 // TODO: Deal with large sysex, which are broken up into chunks!
1623 //                                 // For now, do not accept if the last byte is not EOX, meaning it's a chunk with more chunks to follow.
1624 //                                 if(*(((unsigned char*)ev->buffer) + ev->size - 1) != ME_SYSEX_END)
1625 //                                 {
1626 //                                   if(MusEGlobal::debugMsg)
1627 //                                     printf("VstNativeSynthIF::eventReceived sysex chunks not supported!\n");
1628 //                                   return;
1629 //                                 }
1630 //
1631 //                                 //event.setTime(0);      // mark as used
1632 //                                 event.setType(ME_SYSEX);
1633 //                                 event.setData((unsigned char*)(ev->buffer + 1), ev->size - 2);
1634 //                                 break;
1635                           case ME_MTC_QUARTER:
1636                                 //if(_port != -1)
1637                                 if(port != -1)
1638                                 {
1639                                   //MusEGlobal::midiSyncContainer.mtcInputQuarter(_port, *(ev->buffer + 1));
1640                                   MusEGlobal::midiSyncContainer.mtcInputQuarter(port, ev->midiData[1]);
1641                                 }
1642                                 return;
1643                           case ME_SONGPOS:
1644                                 //if(_port != -1)
1645                                 if(port != -1)
1646                                 {
1647                                   //MusEGlobal::midiSyncContainer.setSongPosition(_port, *(ev->buffer + 1) | (*(ev->buffer + 2) << 7 )); // LSB then MSB
1648                                   MusEGlobal::midiSyncContainer.setSongPosition(port, ev->midiData[1] | (ev->midiData[2] << 7 )); // LSB then MSB
1649                                 }
1650                                 return;
1651                           //case ME_SONGSEL:
1652                           //case ME_TUNE_REQ:
1653                           //case ME_SENSE:
1654                           //      return;
1655 
1656 // TODO: Hm, need the last frame time... Isn't that the same as audio->pos().frame() like above?
1657 //                           case ME_CLOCK:
1658 //                                     const jack_nframes_t abs_ft = jack_last_frame_time(jc) - MusEGlobal::segmentSize + ev->time;
1659 //                                     midiClockInput(abs_ft);
1660 //                                 return;
1661 //                           case ME_TICK:
1662 //                           case ME_START:
1663 //                           case ME_CONTINUE:
1664 //                           case ME_STOP:
1665 //                           {
1666 //                                 if(MusEGlobal::audioDevice && MusEGlobal::audioDevice->deviceType() == JACK_MIDI && _port != -1)
1667 //                                 {
1668 //                                   MusECore::JackAudioDevice* jad = static_cast<MusECore::JackAudioDevice*>(MusEGlobal::audioDevice);
1669 //                                   jack_client_t* jc = jad->jackClient();
1670 //                                   if(jc)
1671 //                                   {
1672 //                                     jack_nframes_t abs_ft = jack_last_frame_time(jc)  + ev->time;
1673 //                                     double abs_ev_t = double(jack_frames_to_time(jc, abs_ft)) / 1000000.0;
1674 //                                     MusEGlobal::midiSyncContainer.realtimeSystemInput(_port, type, abs_ev_t);
1675 //                                   }
1676 //                                 }
1677 //                                 return;
1678 //                           }
1679 
1680                           //case ME_SYSEX_END:
1681                                 //break;
1682                           //      return;
1683                           default:
1684                                 if(MusEGlobal::debugMsg)
1685                                   printf("VstNativeSynthIF::eventReceived unsupported system event 0x%02x\n", type);
1686                                 return;
1687                     }
1688                   }
1689                   //return;
1690                   break;
1691             default:
1692               if(MusEGlobal::debugMsg)
1693                 printf("VstNativeSynthIF::eventReceived unknown event 0x%02x\n", type);
1694                 //printf("VstNativeSynthIF::eventReceived unknown event 0x%02x size:%d buf:0x%02x 0x%02x 0x%02x ...0x%02x\n", type, ev->size, *(ev->buffer), *(ev->buffer + 1), *(ev->buffer + 2), *(ev->buffer + (ev->size - 1)));
1695               return;
1696             }
1697 
1698       #ifdef VST_NATIVE_DEBUG
1699       printf("VstNativeSynthIF::eventReceived time:%d type:%d ch:%d A:%d B:%d\n", event.time(), event.type(), event.channel(), event.dataA(), event.dataB());
1700       #endif
1701 
1702       // Let recordEvent handle it from here, with timestamps, filtering, gui triggering etc.
1703       synti->recordEvent(event);
1704       }
1705 
1706 //---------------------------------------------------------
1707 //   hasGui
1708 //---------------------------------------------------------
1709 
hasNativeGui() const1710 bool VstNativeSynthIF::hasNativeGui() const
1711       {
1712       return _plugin->flags & effFlagsHasEditor;
1713       }
1714 
1715 //---------------------------------------------------------
1716 //   channels
1717 //---------------------------------------------------------
1718 
channels() const1719 int VstNativeSynthIF::channels() const
1720       {
1721       return _plugin->numOutputs > MusECore::MAX_CHANNELS ? MusECore::MAX_CHANNELS : _plugin->numOutputs ;
1722       }
1723 
totalOutChannels() const1724 int VstNativeSynthIF::totalOutChannels() const
1725       {
1726       return _plugin->numOutputs;
1727       }
1728 
totalInChannels() const1729 int VstNativeSynthIF::totalInChannels() const
1730       {
1731       return _plugin->numInputs;
1732       }
1733 
1734 //---------------------------------------------------------
1735 //   deactivate3
1736 //---------------------------------------------------------
1737 
deactivate3()1738 void VstNativeSynthIF::deactivate3()
1739       {
1740       if(_editor)
1741       {
1742         delete _editor;
1743         _editor = NULL;
1744         _guiVisible = false;
1745       }
1746 
1747       deactivate();
1748       if (_plugin) {
1749             _plugin->dispatcher (_plugin, effClose, 0, 0, NULL, 0);
1750             _plugin = NULL;
1751             }
1752       }
1753 
1754 //---------------------------------------------------------
1755 //   queryPrograms
1756 //---------------------------------------------------------
1757 
queryPrograms()1758 void VstNativeSynthIF::queryPrograms()
1759 {
1760       char buf[256];
1761       programs.clear();
1762       int num_progs = _plugin->numPrograms;
1763       int iOldIndex = dispatch(effGetProgram, 0, 0, NULL, 0.0f);
1764       bool need_restore = false;
1765       for(int prog = 0; prog < num_progs; ++prog)
1766       {
1767         buf[0] = 0;
1768 
1769 //#ifndef VST_VESTIGE_SUPPORT
1770         // value = category. -1 = regular linear.
1771         if(dispatch(effGetProgramNameIndexed, prog, -1, buf, 0.0f) == 0)
1772         {
1773 //#endif
1774           dispatch(effSetProgram, 0, prog, NULL, 0.0f);
1775           dispatch(effGetProgramName, 0, 0, buf, 0.0f);
1776           need_restore = true;
1777 //#ifndef VST_VESTIGE_SUPPORT
1778         }
1779 //#endif
1780 
1781         int bankH = (prog >> 14) & 0x7f;
1782         int bankL = (prog >> 7) & 0x7f;
1783         int patch = prog & 0x7f;
1784         VST_Program p;
1785         p.name    = QString(buf);
1786         //p.program = prog & 0x7f;
1787         //p.bank    = prog << 7;
1788         p.program = (bankH << 16) | (bankL << 8) | patch;
1789         programs.push_back(p);
1790       }
1791 
1792       // Restore current program.
1793       if(need_restore) // && num_progs > 0)
1794       {
1795         dispatch(effSetProgram, 0, iOldIndex, NULL, 0.0f);
1796         fprintf(stderr, "FIXME: VstNativeSynthIF::queryPrograms(): effGetProgramNameIndexed returned 0. Used ugly effSetProgram/effGetProgramName instead\n");
1797       }
1798 }
1799 
1800 //---------------------------------------------------------
1801 //   doSelectProgram
1802 //---------------------------------------------------------
1803 
doSelectProgram(int bankH,int bankL,int prog)1804 void VstNativeSynthIF::doSelectProgram(int bankH, int bankL, int prog)
1805 {
1806   if(!_plugin)
1807     return;
1808 
1809 #ifdef VST_NATIVE_DEBUG
1810   fprintf(stderr, "VstNativeSynthIF::doSelectProgram bankH:%d bankL:%d prog:%d\n", bankH, bankL, prog);
1811 #endif
1812 
1813 //    // Only if there's something to change...
1814 //    if(bankH >= 128 && bankL >= 128 && prog >= 128)
1815 //      return;
1816 
1817   if(bankH > 127) // Map "dont care" to 0
1818     bankH = 0;
1819   if(bankL > 127)
1820     bankL = 0;
1821   if(prog > 127)
1822     prog = 0;
1823 
1824   int p = (bankH << 14) | (bankL << 7) | prog;
1825 
1826   if(p >= _plugin->numPrograms)
1827   {
1828     fprintf(stderr, "VstNativeSynthIF::doSelectProgram program:%d out of range\n", p);
1829     return;
1830   }
1831 
1832   //for (unsigned short i = 0; i < instances(); ++i)
1833   //{
1834     // "host calls this before a new program (effSetProgram) is loaded"
1835 #ifndef VST_VESTIGE_SUPPORT
1836     //if(dispatch(effBeginSetProgram, 0, 0, NULL, 0.0f) == 1)  // TESTED: Usually it did not acknowledge. So IGNORE it.
1837     dispatch(effBeginSetProgram, 0, 0, NULL, 0.0f);
1838     //{
1839 #endif
1840       dispatch(effSetProgram, 0, p, NULL, 0.0f);
1841       //dispatch(effSetProgram, 0, prog, NULL, 0.0f);
1842       // "host calls this after the new program (effSetProgram) has been loaded"
1843 #ifndef VST_VESTIGE_SUPPORT
1844       dispatch(effEndSetProgram, 0, 0, NULL, 0.0f);
1845     //}
1846     //else
1847     //  fprintf(stderr, "VstNativeSynthIF::doSelectProgram bankH:%d bankL:%d prog:%d Effect did not acknowledge effBeginSetProgram\n", bankH, bankL, prog);
1848 #endif
1849   //}
1850 
1851   // TODO: Is this true of VSTs? See the similar section in dssihost.cpp  // REMOVE Tim.
1852   //   "A plugin is permitted to re-write the values of its input control ports when select_program is called.
1853   //    The host should re-read the input control port values and update its own records appropriately.
1854   //    (This is the only circumstance in which a DSSI plugin is allowed to modify its own input ports.)"   From dssi.h
1855   // Need to update the automation value, otherwise it overwrites later with the last automation value.
1856   if(id() != -1)
1857   {
1858     const unsigned long sic = _synth->inControls();
1859     for(unsigned long k = 0; k < sic; ++k)
1860     {
1861       // We're in the audio thread context: no need to send a message, just modify directly.
1862       //synti->setPluginCtrlVal(genACnum(id(), k), _controls[k].val);
1863       //synti->setPluginCtrlVal(genACnum(id(), k), _plugin->getParameter(_plugin, k));
1864       const float v = _plugin->getParameter(_plugin, k);
1865       _controls[k].val = v;
1866       synti->setPluginCtrlVal(genACnum(id(), k), v);
1867     }
1868   }
1869 
1870 //   // Reset parameters default value...   // TODO ?
1871 //   AEffect *pVstEffect = vst_effect(0);
1872 //   if (pVstEffect) {
1873 //           const qtractorPlugin::Params& params = qtractorPlugin::params();
1874 //           qtractorPlugin::Params::ConstIterator param = params.constBegin();
1875 //           for ( ; param != params.constEnd(); ++param) {
1876 //                   qtractorPluginParam *pParam = param.value();
1877 //                   float *pfValue = pParam->subject()->data();
1878 //                   *pfValue = pVstEffect->getParameter(pVstEffect, pParam->index());
1879 //                   pParam->setDefaultValue(*pfValue);
1880 //           }
1881 //   }
1882 
1883 }
1884 
1885 //---------------------------------------------------------
1886 //   getPatchName
1887 //---------------------------------------------------------
1888 
getPatchName(int,int prog,bool) const1889 QString VstNativeSynthIF::getPatchName(int /*chan*/, int prog, bool /*drum*/) const
1890 {
1891   unsigned long program = prog & 0xff;
1892   unsigned long lbank   = (prog >> 8) & 0xff;
1893   unsigned long hbank   = (prog >> 16) & 0xff;
1894   if (program > 127)  // Map "dont care" to 0
1895         program = 0;
1896   if (lbank > 127)
1897         lbank = 0;
1898   if (hbank > 127)
1899         hbank = 0;
1900   unsigned long p = (hbank << 16) | (lbank << 8) | program;
1901   unsigned long vp          = (hbank << 14) | (lbank << 7) | program;
1902   //if((int)vp < _plugin->numPrograms)
1903   if(vp < programs.size())
1904   {
1905     for(std::vector<VST_Program>::const_iterator i = programs.begin(); i != programs.end(); ++i)
1906     {
1907       if(i->program == p)
1908         return i->name;
1909     }
1910   }
1911   return "?";
1912 }
1913 
1914 //---------------------------------------------------------
1915 //   populatePatchPopup
1916 //---------------------------------------------------------
1917 
populatePatchPopup(MusEGui::PopupMenu * menu,int,bool)1918 void VstNativeSynthIF::populatePatchPopup(MusEGui::PopupMenu* menu, int /*chan*/, bool /*drum*/)
1919 {
1920   // The plugin can change the programs, patches etc.
1921   // So make sure we're up to date by calling queryPrograms.
1922   queryPrograms();
1923 
1924   menu->clear();
1925 
1926   for (std::vector<VST_Program>::const_iterator i = programs.begin(); i != programs.end(); ++i)
1927        {
1928         //int bank = i->bank;
1929         int prog = i->program;
1930         //int id   = (bank << 7) + prog;
1931 
1932         const int hb   = (prog >> 16) & 0xff;
1933         const int lb   = (prog >> 8) & 0xff;
1934         const int pr = prog & 0xff;
1935         const bool vhb = hb != 0xff;
1936         const bool vlb = lb != 0xff;
1937         const bool vpr = pr != 0xff;
1938         QString astr;
1939         if(vhb || vlb || vpr) {
1940           if(vhb)
1941             astr += QString::number(hb + 1) + QString(":");
1942           if(vlb)
1943             astr += QString::number(lb + 1) + QString(":");
1944           else if(vhb)
1945             astr += QString("--:");
1946           if(vpr)
1947             astr += QString::number(pr + 1);
1948           else if(vhb && vlb)
1949             astr += QString("--");
1950           astr += QString(" ");
1951         }
1952         astr += i->name;
1953 
1954         QAction *act = menu->addAction(astr);
1955         //act->setData(id);
1956         act->setData(prog);
1957         }
1958 
1959 }
1960 
1961 //---------------------------------------------------------
1962 //   getParameter
1963 //---------------------------------------------------------
1964 
getParameter(unsigned long idx) const1965 double VstNativeSynthIF::getParameter(unsigned long idx) const
1966       {
1967       if(idx >= _synth->inControls())
1968       {
1969         fprintf(stderr, "VstNativeSynthIF::getParameter param number %lu out of range of ports:%lu\n", idx, _synth->inControls());
1970         return 0.0;
1971       }
1972 
1973       return _plugin->getParameter(_plugin, idx);
1974       }
1975 
1976 //---------------------------------------------------------
1977 //   setParameter
1978 //---------------------------------------------------------
1979 
setParameter(unsigned long idx,double value)1980 void VstNativeSynthIF::setParameter(unsigned long idx, double value)
1981       {
1982       addScheduledControlEvent(idx, value, MusEGlobal::audio->curFrame());
1983       }
1984 
1985 //---------------------------------------------------------
1986 //   guiAutomationBegin
1987 //---------------------------------------------------------
1988 
guiAutomationBegin(VstNativeSynthOrPlugin * userData,unsigned long param_idx)1989 void VstNativeSynth::guiAutomationBegin(VstNativeSynthOrPlugin *userData, unsigned long param_idx)
1990 {
1991    //_gw[param_idx].pressed = true; //not used
1992    AudioTrack* t = userData->sif ? userData->sif->track() : userData->pstate->pluginI->track();
1993    int plug_id = userData->sif ? userData->sif->id() : userData->pstate->pluginI->id();
1994    if(t && plug_id != -1)
1995    {
1996       plug_id = genACnum(plug_id, param_idx);
1997 
1998       //if(params[param].type == GuiParam::GUI_SLIDER)
1999       //{
2000       //double val = ((Slider*)params[param].actuator)->value();
2001       float val = userData->sif ? userData->sif->param(param_idx) : userData->pstate->pluginI->param(param_idx);
2002       // FIXME TODO:
2003       //if (LADSPA_IS_HINT_LOGARITHMIC(params[param].hint))
2004       //      val = pow(10.0, val/20.0);
2005       //else if (LADSPA_IS_HINT_INTEGER(params[param].hint))
2006       //      val = rint(val);
2007       //plugin->setParam(param, val);
2008       //((DoubleLabel*)params[param].label)->setValue(val);
2009 
2010       //if(t)
2011       //{
2012       t->startAutoRecord(plug_id, val);
2013       t->setPluginCtrlVal(plug_id, val);
2014       //}
2015       //}
2016       //   else if(params[param].type == GuiParam::GUI_SWITCH)
2017       //   {
2018       //     float val = (float)((CheckBox*)params[param].actuator)->isChecked();
2019       //     plugin->setParam(param, val);
2020       //
2021       //     //if(t)
2022       //     //{
2023       //       t->startAutoRecord(plug_id, val);
2024       //       t->setPluginCtrlVal(plug_id, val);
2025       //     //}
2026       //   }
2027    }
2028    if(userData->sif)
2029    {
2030       userData->sif->enableController(param_idx, false);
2031    }
2032    else
2033    {
2034       userData->pstate->pluginI->enableController(param_idx, false);
2035    }
2036 }
2037 
2038 //---------------------------------------------------------
2039 //   guiAutomationEnd
2040 //---------------------------------------------------------
2041 
guiAutomationEnd(VstNativeSynthOrPlugin * userData,unsigned long param_idx)2042 void VstNativeSynth::guiAutomationEnd(VstNativeSynthOrPlugin *userData, unsigned long param_idx)
2043 {
2044    AutomationType at = AUTO_OFF;
2045    AudioTrack* t = userData->sif ? userData->sif->track() : userData->pstate->pluginI->track();
2046    int plug_id = userData->sif ? userData->sif->id() : userData->pstate->pluginI->id();
2047    if(t)
2048       at = t->automationType();
2049 
2050    if(t && plug_id != -1)
2051    {
2052       plug_id = genACnum(plug_id, param_idx);
2053 
2054       //if(params[param].type == GuiParam::GUI_SLIDER)
2055       //{
2056       //double val = ((Slider*)params[param].actuator)->value();
2057       float val = userData->sif ? userData->sif->param(param_idx) : userData->pstate->pluginI->param(param_idx);
2058       // FIXME TODO:
2059       //if (LADSPA_IS_HINT_LOGARITHMIC(params[param].hint))
2060       //      val = pow(10.0, val/20.0);
2061       //else if (LADSPA_IS_HINT_INTEGER(params[param].hint))
2062       //      val = rint(val);
2063       t->stopAutoRecord(plug_id, val);
2064       //}
2065    }
2066 
2067    // Special for switch - don't enable controller until transport stopped.
2068    if ((at == AUTO_OFF) ||
2069        (at == AUTO_TOUCH)) // && (params[param].type != GuiParam::GUI_SWITCH ||  // FIXME TODO
2070       //   !MusEGlobal::audio->isPlaying()) ) )
2071    {
2072       if(userData->sif)
2073       {
2074          userData->sif->enableController(param_idx, true);
2075       }
2076       else
2077       {
2078          userData->pstate->pluginI->enableController(param_idx, true);
2079       }
2080    }
2081 
2082    //_gw[param_idx].pressed = false; //not used
2083 }
2084 
2085 //---------------------------------------------------------
2086 //   guiControlChanged
2087 //---------------------------------------------------------
2088 
guiControlChanged(VstNativeSynthOrPlugin * userData,unsigned long param_idx,float value)2089 int VstNativeSynth::guiControlChanged(VstNativeSynthOrPlugin *userData, unsigned long param_idx, float value)
2090 {
2091    VstNativeSynth *synth = userData->sif ? userData->sif->_synth : userData->pstate->pluginWrapper->_synth;
2092 #ifdef VST_NATIVE_DEBUG
2093    fprintf(stderr, "VstNativeSynth::guiControlChanged received oscControl port:%lu val:%f\n", param_idx, value);
2094 #endif
2095 
2096    if(param_idx >= synth->inControls())
2097    {
2098       fprintf(stderr, "VstNativeSynth::guiControlChanged: port number:%lu is out of range of index list size:%lu\n", param_idx, synth->inControls());
2099       return 0;
2100    }
2101 
2102    // Record automation:
2103    // Take care of this immediately rather than in the fifo processing.
2104    int plugId = userData->sif ? userData->sif->id() : userData->pstate->pluginI->id();
2105    if(plugId != -1)
2106    {
2107       unsigned long pid = genACnum(plugId, param_idx);
2108       if(userData->sif)
2109       {
2110          userData->sif->synti->recordAutomation(pid, value);
2111       }
2112       else
2113       {
2114          userData->pstate->pluginI->track()->recordAutomation(pid, value);
2115       }
2116    }
2117 
2118    // Schedules a timed control change:
2119    ControlEvent ce;
2120    ce.unique = false; // Not used for native vst.
2121    ce.fromGui = true; // It came from the plugin's own GUI.
2122    ce.idx = param_idx;
2123    ce.value = value;
2124    // Don't use timestamp(), because it's circular, which is making it impossible to deal
2125    // with 'modulo' events which slip in 'under the wire' before processing the ring buffers.
2126    ce.frame = MusEGlobal::audio->curFrame();
2127 
2128    ControlFifo &cfifo = userData->sif ? userData->sif->_controlFifo : userData->pstate->pluginI->_controlFifo;
2129 
2130    if(cfifo.put(ce))
2131       fprintf(stderr, "VstNativeSynthIF::guiControlChanged: fifo overflow: in control number:%lu\n", param_idx);
2132 
2133    if(userData->sif)
2134    {
2135       userData->sif->enableController(param_idx, false);
2136    }
2137    else
2138    {
2139       userData->pstate->pluginI->enableController(param_idx, false);
2140    }
2141 
2142    return 0;
2143 }
2144 
2145 //---------------------------------------------------------
2146 //   write
2147 //---------------------------------------------------------
2148 
write(int level,Xml & xml) const2149 void VstNativeSynthIF::write(int level, Xml& xml) const
2150 {
2151 //#ifndef VST_VESTIGE_SUPPORT
2152   _synth->vstconfWrite(_plugin, name(), level, xml);
2153 //#else
2154 //  fprintf(stderr, "support for vst chunks not compiled in!\n");
2155 //#endif
2156 
2157   //---------------------------------------------
2158   // dump current state of synth
2159   //---------------------------------------------
2160 
2161   int params = _plugin->numParams;
2162   for (int i = 0; i < params; ++i)
2163     xml.doubleTag(level, "param", _plugin->getParameter(_plugin, i));
2164 }
2165 
2166 //---------------------------------------------------------
2167 //   setCustomData
2168 //---------------------------------------------------------
2169 
setCustomData(const std::vector<QString> & customParams)2170 void VstNativeSynthIF::setCustomData(const std::vector< QString > &customParams)
2171 {
2172   _synth->vstconfSet(_plugin, customParams);
2173 }
2174 
2175 //---------------------------------------------------------
2176 //   getData
2177 //---------------------------------------------------------
2178 
setVstEvent(VstMidiEvent * event,int a,int b,int c,int d)2179 void VstNativeSynthIF::setVstEvent(VstMidiEvent* event, int a, int b, int c, int d)
2180 {
2181   event->type         = kVstMidiType;
2182   event->byteSize     = 24;
2183   event->deltaFrames  = 0;
2184   event->flags        = 0;
2185   event->detune       = 0;
2186   event->noteLength   = 0;
2187   event->noteOffset   = 0;
2188   event->reserved1    = 0;
2189   event->reserved2    = 0;
2190   event->noteOffVelocity = 0;
2191   event->midiData[0]  = a;
2192   event->midiData[1]  = b;
2193   event->midiData[2]  = c;
2194   event->midiData[3]  = d;
2195 }
2196 
2197 //---------------------------------------------------------
2198 //   getData
2199 //---------------------------------------------------------
2200 
processEvent(const MidiPlayEvent & e,VstMidiEvent * event)2201 bool VstNativeSynthIF::processEvent(const MidiPlayEvent& e, VstMidiEvent* event)
2202 {
2203   int type = e.type();
2204   int chn = e.channel();
2205   int a   = e.dataA();
2206   int b   = e.dataB();
2207 
2208   #ifdef VST_NATIVE_DEBUG
2209   fprintf(stderr, "VstNativeSynthIF::processEvent midi event type:%d chn:%d a:%d b:%d\n", type, chn, a, b);
2210   #endif
2211 
2212   // REMOVE Tim. Noteoff. Added.
2213   const MidiInstrument::NoteOffMode nom = synti->noteOffMode();
2214 
2215   switch(type)
2216   {
2217     case ME_NOTEON:
2218       #ifdef VST_NATIVE_DEBUG
2219       fprintf(stderr, "VstNativeSynthIF::processEvent midi event is ME_NOTEON\n");
2220       #endif
2221 
2222       // REMOVE Tim. Noteoff. Added.
2223       if(b == 0)
2224       {
2225         // Handle zero-velocity note ons. Technically this is an error because internal midi paths
2226         //  are now all 'note-off' without zero-vel note ons - they're converted to note offs.
2227         // Nothing should be setting a Note type Event's on velocity to zero.
2228         // But just in case... If we get this warning, it means there is still code to change.
2229         fprintf(stderr, "VstNativeSynthIF::processEvent: Warning: Zero-vel note on: time:%d type:%d (ME_NOTEON) ch:%d A:%d B:%d\n", e.time(), e.type(), chn, a, b);
2230         switch(nom)
2231         {
2232           // Instrument uses note offs. Convert to zero-vel note off.
2233           case MidiInstrument::NoteOffAll:
2234             //if(MusEGlobal::midiOutputTrace)
2235             //  fprintf(stderr, "MidiOut: VST_Native: Following event will be converted to zero-velocity note off:\n");
2236             setVstEvent(event, (ME_NOTEOFF | chn) & 0xff, a & 0x7f, 0);
2237           break;
2238 
2239           // Instrument uses no note offs at all. Send as-is.
2240           case MidiInstrument::NoteOffNone:
2241           // Instrument converts all note offs to zero-vel note ons. Send as-is.
2242           case MidiInstrument::NoteOffConvertToZVNoteOn:
2243             setVstEvent(event, (type | chn) & 0xff, a & 0x7f, b & 0x7f);
2244           break;
2245         }
2246       }
2247       else
2248 
2249         setVstEvent(event, (type | chn) & 0xff, a & 0x7f, b & 0x7f);
2250 
2251     break;
2252     case ME_NOTEOFF:
2253       #ifdef VST_NATIVE_DEBUG
2254       fprintf(stderr, "VstNativeSynthIF::processEvent midi event is ME_NOTEOFF\n");
2255       #endif
2256 
2257       // REMOVE Tim. Noteoff. Changed.
2258 //       setVstEvent(event, (type | chn) & 0xff, a & 0x7f, 0);
2259       switch(nom)
2260       {
2261         // Instrument uses note offs. Send as-is.
2262         case MidiInstrument::NoteOffAll:
2263           setVstEvent(event, (type | chn) & 0xff, a & 0x7f, b);
2264         break;
2265 
2266         // Instrument uses no note offs at all. Send nothing. Eat up the event - return false.
2267         case MidiInstrument::NoteOffNone:
2268           return false;
2269 
2270         // Instrument converts all note offs to zero-vel note ons. Convert to zero-vel note on.
2271         case MidiInstrument::NoteOffConvertToZVNoteOn:
2272           //if(MusEGlobal::midiOutputTrace)
2273           //  fprintf(stderr, "MidiOut: VST_Native: Following event will be converted to zero-velocity note on:\n");
2274           setVstEvent(event, (ME_NOTEON | chn) & 0xff, a & 0x7f, 0);
2275         break;
2276       }
2277 
2278     break;
2279     // Synths are not allowed to receive ME_PROGRAM, CTRL_HBANK, or CTRL_LBANK alone anymore.
2280     case ME_PROGRAM:
2281     {
2282       #ifdef VST_NATIVE_DEBUG
2283       fprintf(stderr, "VstNativeSynthIF::processEvent midi event is ME_PROGRAM\n");
2284       #endif
2285 
2286       int hb, lb;
2287       synti->currentProg(chn, NULL, &lb, &hb);
2288       synti->setCurrentProg(chn, a & 0xff, lb, hb);
2289       doSelectProgram(hb, lb, a);
2290       return false;  // Event pointer not filled. Return false.
2291     }
2292     break;
2293     case ME_CONTROLLER:
2294     {
2295       #ifdef VST_NATIVE_DEBUG
2296       fprintf(stderr, "VstNativeSynthIF::processEvent midi event is ME_CONTROLLER\n");
2297       #endif
2298 
2299       // Our internal hwCtrl controllers support the 'unknown' value.
2300       // Don't send 'unknown' values to the driver. Ignore and return no error.
2301       if(b == CTRL_VAL_UNKNOWN)
2302         return false;
2303 
2304       if(a == CTRL_PROGRAM)
2305       {
2306         #ifdef VST_NATIVE_DEBUG
2307         fprintf(stderr, "VstNativeSynthIF::processEvent midi event is ME_CONTROLLER, dataA is CTRL_PROGRAM\n");
2308         #endif
2309 
2310         int bankH = (b >> 16) & 0xff;
2311         int bankL = (b >> 8) & 0xff;
2312         int prog = b & 0xff;
2313         synti->setCurrentProg(chn, prog, bankL, bankH);
2314         doSelectProgram(bankH, bankL, prog);
2315         return false; // Event pointer not filled. Return false.
2316       }
2317 
2318       if(a == CTRL_HBANK)
2319       {
2320         int lb, pr;
2321         synti->currentProg(chn, &pr, &lb, NULL);
2322         synti->setCurrentProg(chn, pr, lb, b & 0xff);
2323         doSelectProgram(b, lb, pr);
2324         // Event pointer not filled. Return false.
2325         return false;
2326       }
2327 
2328       if(a == CTRL_LBANK)
2329       {
2330         int hb, pr;
2331         synti->currentProg(chn, &pr, NULL, &hb);
2332         synti->setCurrentProg(chn, pr, b & 0xff, hb);
2333         doSelectProgram(hb, b, pr);
2334         // Event pointer not filled. Return false.
2335         return false;
2336       }
2337 
2338       if(a == CTRL_PITCH)
2339       {
2340         #ifdef VST_NATIVE_DEBUG
2341         fprintf(stderr, "VstNativeSynthIF::processEvent midi event is ME_CONTROLLER, dataA is CTRL_PITCH\n");
2342         #endif
2343         int v = b + 8192;
2344         setVstEvent(event, (ME_PITCHBEND | chn) & 0xff, v & 0x7f, (v >> 7) & 0x7f);
2345         return true;
2346       }
2347 
2348       if(a == CTRL_AFTERTOUCH)
2349       {
2350         #ifdef VST_NATIVE_DEBUG
2351         fprintf(stderr, "VstNativeSynthIF::processEvent midi event is ME_CONTROLLER, dataA is CTRL_AFTERTOUCH\n");
2352         #endif
2353         setVstEvent(event, (ME_AFTERTOUCH | chn) & 0xff, b & 0x7f);
2354         return true;
2355       }
2356 
2357       if((a | 0xff)  == CTRL_POLYAFTER)
2358       {
2359         #ifdef VST_NATIVE_DEBUG
2360         fprintf(stderr, "VstNativeSynthIF::processEvent midi event is ME_CONTROLLER, dataA is CTRL_POLYAFTER\n");
2361         #endif
2362         setVstEvent(event, (ME_POLYAFTER | chn) & 0xff, a & 0x7f, b & 0x7f);
2363         return true;
2364       }
2365 
2366       #ifdef VST_NATIVE_DEBUG
2367       fprintf(stderr, "VstNativeSynthIF::processEvent midi event is ME_CONTROLLER, dataA is:%d\n", a);
2368       #endif
2369 
2370       // Regular controller. Pass it on.
2371       setVstEvent(event, (type | chn) & 0xff, a & 0x7f, b & 0x7f);
2372 
2373       return true;
2374 
2375 // REMOVE Tim. Or keep. TODO For native vsts? Or not...
2376 //
2377 //       const LADSPA_Descriptor* ld = dssi->LADSPA_Plugin;
2378 //
2379 //       ciMidiCtl2LadspaPort ip = synth->midiCtl2PortMap.find(a);
2380 //       // Is it just a regular midi controller, not mapped to a LADSPA port (either by the plugin or by us)?
2381 //       // NOTE: There's no way to tell which of these controllers is supported by the plugin.
2382 //       // For example sustain footpedal or pitch bend may be supported, but not mapped to any LADSPA port.
2383 //       if(ip == synth->midiCtl2PortMap.end())
2384 //       {
2385 //         int ctlnum = a;
2386 //         if(midiControllerType(a) != MidiController::Controller7)
2387 //           return false;   // Event pointer not filled. Return false.
2388 //         else
2389 //         {
2390 //                 #ifdef VST_NATIVE_DEBUG
2391 //                 fprintf(stderr, "VstNativeSynthIF::processEvent non-ladspa midi event is Controller7. Current dataA:%d\n", a);
2392 //                 #endif
2393 //                 a &= 0x7f;
2394 //                 ctlnum = DSSI_CC_NUMBER(ctlnum);
2395 //         }
2396 //
2397 //         // Fill the event.
2398 //         #ifdef VST_NATIVE_DEBUG
2399 //        fprintf(stderr, "VstNativeSynthIF::processEvent non-ladspa filling midi event chn:%d dataA:%d dataB:%d\n", chn, a, b);
2400 //         #endif
2401 //         snd_seq_ev_clear(event);
2402 //         event->queue = SND_SEQ_QUEUE_DIRECT;
2403 //         snd_seq_ev_set_controller(event, chn, a, b);
2404 //         return true;
2405 //       }
2406 //
2407 //       unsigned long k = ip->second;
2408 //       unsigned long i = controls[k].idx;
2409 //       int ctlnum = DSSI_NONE;
2410 //       if(dssi->get_midi_controller_for_port)
2411 //         ctlnum = dssi->get_midi_controller_for_port(handle, i);
2412 //
2413 //       // No midi controller for the ladspa port? Send to ladspa control.
2414 //       if(ctlnum == DSSI_NONE)
2415 //       {
2416 //         // Sanity check.
2417 //         if(k > synth->_controlInPorts)
2418 //           return false;
2419 //
2420 //         // Simple but flawed solution: Start them at 0x60000 + 0x2000 = 0x62000. Max NRPN number is 0x3fff.
2421 //         ctlnum = k + (CTRL_NRPN14_OFFSET + 0x2000);
2422 //       }
2423 //       else
2424 //       {
2425 //         #ifdef VST_NATIVE_DEBUG
2426 //         fprintf(stderr, "VstNativeSynthIF::processEvent plugin requests DSSI-style ctlnum:%x(h) %d(d) be mapped to control port:%lu...\n", ctlnum, ctlnum, i);
2427 //         #endif
2428 //
2429 //         int c = ctlnum;
2430 //         // Can be both CC and NRPN! Prefer CC over NRPN.
2431 //         if(DSSI_IS_CC(ctlnum))
2432 //         {
2433 //           ctlnum = DSSI_CC_NUMBER(c);
2434 //
2435 //           #ifdef VST_NATIVE_DEBUG
2436 //           fprintf(stderr, "VstNativeSynthIF::processEvent is CC ctlnum:%d\n", ctlnum);
2437 //           #endif
2438 //
2439 //           #ifdef VST_NATIVE_DEBUG
2440 //           if(DSSI_IS_NRPN(ctlnum))
2441 //             fprintf(stderr, "VstNativeSynthIF::processEvent is also NRPN control. Using CC.\n");
2442 //           #endif
2443 //         }
2444 //         else
2445 //         if(DSSI_IS_NRPN(ctlnum))
2446 //         {
2447 //           ctlnum = DSSI_NRPN_NUMBER(c) + CTRL_NRPN14_OFFSET;
2448 //
2449 //           #ifdef VST_NATIVE_DEBUG
2450 //           fprintf(stderr, "VstNativeSynthIF::processEvent is NRPN ctlnum:%x(h) %d(d)\n", ctlnum, ctlnum);
2451 //           #endif
2452 //         }
2453 //
2454 //       }
2455 //
2456 //       float val = midi2LadspaValue(ld, i, ctlnum, b);
2457 //
2458 //       #ifdef VST_NATIVE_DEBUG
2459 //       fprintf(stderr, "VstNativeSynthIF::processEvent control port:%lu port:%lu dataA:%d Converting val from:%d to ladspa:%f\n", i, k, a, b, val);
2460 //       #endif
2461 //
2462 //       // Set the ladspa port value.
2463 //       controls[k].val = val;
2464 //
2465 //       // Need to update the automation value, otherwise it overwrites later with the last automation value.
2466 //       if(id() != -1)
2467 //         // We're in the audio thread context: no need to send a message, just modify directly.
2468 //         synti->setPluginCtrlVal(genACnum(id(), k), val);
2469 //
2470 //       // Since we absorbed the message as a ladspa control change, return false - the event is not filled.
2471 //       return false;
2472     }
2473     break;
2474     case ME_PITCHBEND:
2475     {
2476       int v = a + 8192;
2477       setVstEvent(event, (type | chn) & 0xff, v & 0x7f, (v >> 7) & 0x7f);
2478     }
2479     break;
2480     case ME_AFTERTOUCH:
2481       setVstEvent(event, (type | chn) & 0xff, a & 0x7f);
2482     break;
2483     case ME_POLYAFTER:
2484       setVstEvent(event, (type | chn) & 0xff, a & 0x7f, b & 0x7f);
2485     break;
2486     case ME_SYSEX:
2487       {
2488         #ifdef VST_NATIVE_DEBUG
2489         fprintf(stderr, "VstNativeSynthIF::processEvent midi event is ME_SYSEX\n");
2490         #endif
2491 
2492         const unsigned char* data = e.constData();
2493         if(e.len() >= 2)
2494         {
2495           if(data[0] == MUSE_SYNTH_SYSEX_MFG_ID)
2496           {
2497             if(data[1] == VST_NATIVE_SYNTH_UNIQUE_ID)
2498             {
2499               //if(e.len() >= 9)
2500               if(e.len() >= 10)
2501               {
2502 
2503                 //---------------------------------------------------------------------
2504                 // NOTICE: Obsolete. Replaced by customData block. Keep for old songs!
2505                 //         We should never arrive here with a newer song now.
2506                 //---------------------------------------------------------------------
2507                 if (QString((const char*)(data + 2)).startsWith("VSTSAVE"))
2508                 {
2509                   if(_synth->hasChunks())
2510                   {
2511 //#ifndef VST_VESTIGE_SUPPORT
2512                     int chunk_flags = data[9];
2513                     if(chunk_flags & VST_NATIVE_CHUNK_FLAG_COMPRESSED)
2514                       fprintf(stderr, "chunk flags:%x compressed chunks not supported yet.\n", chunk_flags);
2515                     else
2516                     {
2517                       fprintf(stderr, "%s: loading chunk from sysex!\n", name().toLatin1().constData());
2518                       // 10 = 2 bytes header + "VSTSAVE" + 1 byte flags (compression etc)
2519                       dispatch(24 /* effSetChunk */, 0, e.len()-10, (void*)(data+10), 0.0); // index 0: is bank 1: is program
2520                     }
2521 //#else
2522 //                    fprintf(stderr, "support for vst chunks not compiled in!\n");
2523 //#endif
2524                   }
2525                   // Event not filled.
2526                   return false;
2527                 }
2528               }
2529             }
2530           }
2531         }
2532         //else
2533         {
2534           // FIXME TODO: Sysex support.
2535           return false;
2536         }
2537       }
2538     break;
2539     default:
2540       if(MusEGlobal::debugMsg)
2541         fprintf(stderr, "VstNativeSynthIF::processEvent midi event unknown type:%d\n", e.type());
2542       // Event not filled.
2543       return false;
2544     break;
2545   }
2546 
2547   return true;
2548 }
2549 
2550 //---------------------------------------------------------
2551 //   getData
2552 //   If ports is 0, just process controllers only, not audio (do not 'run').
2553 //---------------------------------------------------------
2554 
getData(MidiPort *,unsigned pos,int ports,unsigned nframes,float ** buffer)2555 bool VstNativeSynthIF::getData(MidiPort* /*mp*/, unsigned pos, int ports, unsigned nframes, float** buffer)
2556 {
2557   const unsigned int syncFrame = MusEGlobal::audio->curSyncFrame();
2558 
2559   #ifdef VST_NATIVE_DEBUG_PROCESS
2560   fprintf(stderr, "VstNativeSynthIF::getData: pos:%u ports:%d nframes:%u syncFrame:%lu\n", pos, ports, nframes, syncFrame);
2561   #endif
2562 
2563   // All ports must be connected to something!
2564   const unsigned long in_ports = _synth->inPorts();
2565   const unsigned long out_ports = _synth->outPorts();
2566   const unsigned long nop = ((unsigned long) ports) > out_ports ? out_ports : ((unsigned long) ports);
2567 
2568   unsigned long sample = 0;
2569 
2570   // FIXME Better support for PluginPowerOf2BlockSize, by quantizing the control period times.
2571   //       For now we treat it like fixed size.
2572   const bool usefixedrate = (requiredFeatures() & (PluginFixedBlockSize | PluginPowerOf2BlockSize | PluginCoarseBlockSize));
2573 
2574   // For now, the fixed size is clamped to the audio buffer size.
2575   // TODO: We could later add slower processing over several cycles -
2576   //  so that users can select a small audio period but a larger control period.
2577   const unsigned long min_per = (usefixedrate || MusEGlobal::config.minControlProcessPeriod > nframes) ? nframes : MusEGlobal::config.minControlProcessPeriod;
2578   const unsigned long min_per_mask = min_per-1;   // min_per must be power of 2
2579 
2580   AudioTrack* atrack = track();
2581   const AutomationType at = atrack->automationType();
2582   const bool no_auto = !MusEGlobal::automation || at == AUTO_OFF;
2583   const unsigned long in_ctrls = _synth->inControls();
2584   CtrlListList* cll = atrack->controller();
2585   ciCtrlList icl_first;
2586   const int plug_id = id();
2587   if(plug_id != -1 && ports != 0)  // Don't bother if not 'running'.
2588     icl_first = cll->lower_bound(genACnum(plug_id, 0));
2589 
2590   // Inform the host callback we are in the audio thread.
2591   _inProcess = true;
2592 
2593   #ifdef VST_NATIVE_DEBUG_PROCESS
2594   fprintf(stderr, "VstNativeSynthIF::getData: Handling inputs...\n");
2595   #endif
2596 
2597   bool used_in_chan_array[in_ports]; // Don't bother initializing if not 'running'.
2598 
2599   // Don't bother if not 'running'.
2600   if(ports != 0)
2601   {
2602     // Initialize the array.
2603     for(unsigned long i = 0; i < in_ports; ++i)
2604       used_in_chan_array[i] = false;
2605 
2606     if(!atrack->noInRoute())
2607     {
2608       RouteList *irl = atrack->inRoutes();
2609       for(ciRoute i = irl->begin(); i != irl->end(); ++i)
2610       {
2611         if(i->track->isMidiTrack())
2612           continue;
2613         // Only this synth knows how many destination channels there are,
2614         //  while only the track knows how many source channels there are.
2615         // So take care of the destination channels here, and let the track handle the source channels.
2616         const int dst_ch = i->channel <= -1 ? 0 : i->channel;
2617         if((unsigned long)dst_ch >= in_ports)
2618           continue;
2619         const int dst_chs = i->channels <= -1 ? in_ports : i->channels;
2620         //const int total_ins = atrack->totalRoutableInputs(Route::TRACK_ROUTE);
2621         const int src_ch = i->remoteChannel <= -1 ? 0 : i->remoteChannel;
2622         const int src_chs = i->channels;
2623 
2624         int fin_dst_chs = dst_chs;
2625         if((unsigned long)(dst_ch + fin_dst_chs) > in_ports)
2626           fin_dst_chs = in_ports - dst_ch;
2627 
2628         static_cast<AudioTrack*>(i->track)->copyData(pos,
2629                                                      dst_ch, dst_chs, fin_dst_chs,
2630                                                      src_ch, src_chs,
2631                                                      nframes, &_audioInBuffers[0],
2632                                                      false, used_in_chan_array);
2633         const int nxt_ch = dst_ch + fin_dst_chs;
2634         for(int ch = dst_ch; ch < nxt_ch; ++ch)
2635           used_in_chan_array[ch] = true;
2636       }
2637     }
2638   }
2639 
2640   #ifdef VST_NATIVE_DEBUG_PROCESS
2641   fprintf(stderr, "VstNativeSynthIF::getData: Processing automation control values...\n");
2642   #endif
2643 
2644   int cur_slice = 0;
2645   while(sample < nframes)
2646   {
2647     unsigned long nsamp = nframes - sample;
2648     const unsigned long slice_frame = pos + sample;
2649 
2650     //
2651     // Process automation control values, while also determining the maximum acceptable
2652     //  size of this run. Further processing, from FIFOs for example, can lower the size
2653     //  from there, but this section determines where the next highest maximum frame
2654     //  absolutely needs to be for smooth playback of the controller value stream...
2655     //
2656     if(ports != 0)    // Don't bother if not 'running'.
2657     {
2658       ciCtrlList icl = icl_first;
2659       for(unsigned long k = 0; k < in_ctrls; ++k)
2660       {
2661         CtrlList* cl = (cll && plug_id != -1 && icl != cll->end()) ? icl->second : NULL;
2662         CtrlInterpolate& ci = _controls[k].interp;
2663         // Always refresh the interpolate struct at first, since things may have changed.
2664         // Or if the frame is outside of the interpolate range - and eStop is not true.  // FIXME TODO: Be sure these comparisons are correct.
2665         if(cur_slice == 0 || (!ci.eStop && MusEGlobal::audio->isPlaying() &&
2666             (slice_frame < (unsigned long)ci.sFrame || (ci.eFrameValid && slice_frame >= (unsigned long)ci.eFrame)) ) )
2667         {
2668           if(cl && plug_id != -1 && (unsigned long)cl->id() == genACnum(plug_id, k))
2669           {
2670             cl->getInterpolation(slice_frame, no_auto || !_controls[k].enCtrl, &ci);
2671             if(icl != cll->end())
2672               ++icl;
2673           }
2674           else
2675           {
2676             // No matching controller, or end. Just copy the current value into the interpolator.
2677             // Keep the current icl iterator, because since they are sorted by frames,
2678             //  if the IDs didn't match it means we can just let k catch up with icl.
2679             ci.sFrame   = 0;
2680             ci.eFrame   = 0;
2681             ci.eFrameValid = false;
2682             ci.sVal     = _controls[k].val;
2683             ci.eVal     = ci.sVal;
2684             ci.doInterp = false;
2685             ci.eStop    = false;
2686           }
2687         }
2688         else
2689         {
2690           if(ci.eStop && ci.eFrameValid && slice_frame >= (unsigned long)ci.eFrame)  // FIXME TODO: Get that comparison right.
2691           {
2692             // Clear the stop condition and set up the interp struct appropriately as an endless value.
2693             ci.sFrame   = 0; //ci->eFrame;
2694             ci.eFrame   = 0;
2695             ci.eFrameValid = false;
2696             ci.sVal     = ci.eVal;
2697             ci.doInterp = false;
2698             ci.eStop    = false;
2699           }
2700           if(cl && cll && icl != cll->end())
2701             ++icl;
2702         }
2703 
2704         if(!usefixedrate && MusEGlobal::audio->isPlaying())
2705         {
2706           unsigned long samps = nsamp;
2707           if(ci.eFrameValid)
2708             samps = (unsigned long)ci.eFrame - slice_frame;
2709 
2710           if(!ci.doInterp && samps > min_per)
2711           {
2712             samps &= ~min_per_mask;
2713             if((samps & min_per_mask) != 0)
2714               samps += min_per;
2715           }
2716           else
2717             samps = min_per;
2718 
2719           if(samps < nsamp)
2720             nsamp = samps;
2721 
2722         }
2723 
2724         float new_val;
2725         if(ci.doInterp && cl)
2726           new_val = cl->interpolate(MusEGlobal::audio->isPlaying() ? slice_frame : pos, ci);
2727         else
2728           new_val = ci.sVal;
2729         if(_controls[k].val != new_val)
2730         {
2731           _controls[k].val = new_val;
2732           if(dispatch(26 /*effCanBeAutomated*/, k, 0, NULL, 0.0f) == 1)
2733           {
2734             if(_plugin->getParameter(_plugin, k) != new_val)
2735               _plugin->setParameter(_plugin, k, new_val);
2736           }
2737   #ifdef VST_NATIVE_DEBUG
2738           else
2739             fprintf(stderr, "VstNativeSynthIF::getData %s parameter:%lu cannot be automated\n", name().toLatin1().constData(), k);
2740   #endif
2741         }
2742 
2743 #ifdef VST_NATIVE_DEBUG_PROCESS
2744         fprintf(stderr, "VstNativeSynthIF::getData k:%lu sample:%lu frame:%lu ci.eFrame:%d nsamp:%lu \n", k, sample, frame, ci.eFrame, nsamp);
2745 #endif
2746 
2747       }
2748     }
2749 
2750 #ifdef VST_NATIVE_DEBUG_PROCESS
2751       fprintf(stderr, "VstNativeSynthIF::getData sample:%lu nsamp:%lu\n", sample, nsamp);
2752 #endif
2753 
2754     bool found = false;
2755     unsigned long frame = 0;
2756     unsigned long index = 0;
2757     unsigned long evframe;
2758     // Get all control ring buffer items valid for this time period...
2759     while(!_controlFifo.isEmpty())
2760     {
2761       const ControlEvent& v = _controlFifo.peek();
2762       // The events happened in the last period or even before that. Shift into this period with + n. This will sync with audio.
2763       // If the events happened even before current frame - n, make sure they are counted immediately as zero-frame.
2764       evframe = (syncFrame > v.frame + nframes) ? 0 : v.frame - syncFrame + nframes;
2765 
2766       #ifdef VST_NATIVE_DEBUG
2767       fprintf(stderr, "VstNativeSynthIF::getData found:%d evframe:%lu frame:%lu  event frame:%lu idx:%lu val:%f unique:%d\n",
2768           found, evframe, frame, v.frame, v.idx, v.value, v.unique);
2769       #endif
2770 
2771       // Protection. Observed this condition. Why? Supposed to be linear timestamps.
2772       if(found && evframe < frame)
2773       {
2774         fprintf(stderr,
2775           "VstNativeSynthIF::getData *** Error: Event out of order: evframe:%lu < frame:%lu idx:%lu val:%f unique:%d syncFrame:%u nframes:%u v.frame:%lu\n",
2776           evframe, frame, v.idx, v.value, v.unique, syncFrame, nframes, v.frame);
2777 
2778         // No choice but to ignore it.
2779         _controlFifo.remove();               // Done with the ring buffer's item. Remove it.
2780         continue;
2781       }
2782 
2783       if(evframe >= nframes                                                         // Next events are for a later period.
2784           || (!usefixedrate && !found && !v.unique && (evframe - sample >= nsamp))  // Next events are for a later run in this period. (Autom took prio.)
2785           || (found && !v.unique && (evframe - sample >= min_per))                  // Eat up events within minimum slice - they're too close.
2786           || (usefixedrate && found && v.unique && v.idx == index))                 // Fixed rate and must reply to all.
2787         break;
2788 
2789       if(v.idx >= in_ctrls) // Sanity check.
2790       {
2791         _controlFifo.remove();               // Done with the ring buffer's item. Remove it.
2792         break;
2793       }
2794 
2795       found = true;
2796       frame = evframe;
2797       index = v.idx;
2798 
2799       if(ports == 0)                     // Don't bother if not 'running'.
2800       {
2801         _controls[v.idx].val = v.value;   // Might as well at least update these.
2802 // #ifndef VST_VESTIGE_SUPPORT
2803 //         if(dispatch(effCanBeAutomated, v.idx, 0, NULL, 0.0f) == 1)
2804 //         {
2805 // #endif
2806 //           if(v.value != _plugin->getParameter(_plugin, v.idx))
2807 //             _plugin->setParameter(_plugin, v.idx, v.value);
2808 // #ifndef VST_VESTIGE_SUPPORT
2809 //         }
2810 //   #ifdef VST_NATIVE_DEBUG
2811 //         else
2812 //           fprintf(stderr, "VstNativeSynthIF::getData %s parameter:%lu cannot be automated\n", name().toLatin1().constData(), v.idx);
2813 //   #endif
2814 // #endif
2815       }
2816       else
2817       {
2818         CtrlInterpolate* ci = &_controls[v.idx].interp;
2819         // Tell it to stop the current ramp at this frame, when it does stop, set this value:
2820         ci->eFrame = frame;
2821         ci->eFrameValid = true;
2822         ci->eVal   = v.value;
2823         ci->eStop  = true;
2824       }
2825 
2826       // Need to update the automation value, otherwise it overwrites later with the last automation value.
2827       if(plug_id != -1)
2828         synti->setPluginCtrlVal(genACnum(plug_id, v.idx), v.value);
2829 
2830       _controlFifo.remove();               // Done with the ring buffer's item. Remove it.
2831     }
2832 
2833     if(found && !usefixedrate)  // If a control FIFO item was found, takes priority over automation controller stream.
2834       nsamp = frame - sample;
2835 
2836     if(sample + nsamp > nframes)         // Safety check.
2837       nsamp = nframes - sample;
2838 
2839     // TODO: Don't allow zero-length runs. This could/should be checked in the control loop instead.
2840     // Note this means it is still possible to get stuck in the top loop (at least for a while).
2841     if(nsamp != 0)
2842     {
2843       unsigned long nevents = 0;
2844       // Get the state of the stop flag.
2845       const bool do_stop = synti->stopFlag();
2846 
2847       MidiPlayEvent buf_ev;
2848 
2849       // Transfer the user lock-free buffer events to the user sorted multi-set.
2850       // False = don't use the size snapshot, but update it.
2851       const unsigned int usr_buf_sz = synti->eventBuffers(MidiDevice::UserBuffer)->getSize(false);
2852       for(unsigned int i = 0; i < usr_buf_sz; ++i)
2853       {
2854         if(synti->eventBuffers(MidiDevice::UserBuffer)->get(buf_ev))
2855           synti->_outUserEvents.insert(buf_ev);
2856       }
2857 
2858       // Transfer the playback lock-free buffer events to the playback sorted multi-set.
2859       const unsigned int pb_buf_sz = synti->eventBuffers(MidiDevice::PlaybackBuffer)->getSize(false);
2860       for(unsigned int i = 0; i < pb_buf_sz; ++i)
2861       {
2862         // Are we stopping? Just remove the item.
2863         if(do_stop)
2864           synti->eventBuffers(MidiDevice::PlaybackBuffer)->remove();
2865         // Otherwise get the item.
2866         else if(synti->eventBuffers(MidiDevice::PlaybackBuffer)->get(buf_ev))
2867           synti->_outPlaybackEvents.insert(buf_ev);
2868       }
2869 
2870       // Are we stopping?
2871       if(do_stop)
2872       {
2873         // Transport has stopped, purge ALL further scheduled playback events now.
2874         synti->_outPlaybackEvents.clear();
2875         // Reset the flag.
2876         synti->setStopFlag(false);
2877       }
2878 
2879       // Count how many events we need.
2880       for(ciMPEvent impe = synti->_outPlaybackEvents.begin(); impe != synti->_outPlaybackEvents.end(); ++impe)
2881       {
2882         const MidiPlayEvent& e = *impe;
2883         if(e.time() >= (syncFrame + sample + nsamp))
2884           break;
2885         ++nevents;
2886       }
2887       for(ciMPEvent impe = synti->_outUserEvents.begin(); impe != synti->_outUserEvents.end(); ++impe)
2888       {
2889         const MidiPlayEvent& e = *impe;
2890         if(e.time() >= (syncFrame + sample + nsamp))
2891           break;
2892         ++nevents;
2893       }
2894 
2895       VstMidiEvent events[nevents];
2896       char evbuf[sizeof(VstMidiEvent*) * nevents + sizeof(VstEvents)];
2897       VstEvents *vst_events = (VstEvents*)evbuf;
2898       vst_events->numEvents = 0;
2899       vst_events->reserved  = 0;
2900 
2901       iMPEvent impe_pb = synti->_outPlaybackEvents.begin();
2902       iMPEvent impe_us = synti->_outUserEvents.begin();
2903       bool using_pb;
2904 
2905       unsigned long event_counter = 0;
2906       while(1)
2907       {
2908         if(impe_pb != synti->_outPlaybackEvents.end() && impe_us != synti->_outUserEvents.end())
2909           using_pb = *impe_pb < *impe_us;
2910         else if(impe_pb != synti->_outPlaybackEvents.end())
2911           using_pb = true;
2912         else if(impe_us != synti->_outUserEvents.end())
2913           using_pb = false;
2914         else break;
2915 
2916         const MidiPlayEvent& e = using_pb ? *impe_pb : *impe_us;
2917 
2918         #ifdef VST_NATIVE_DEBUG
2919         fprintf(stderr, "VstNativeSynthIF::getData eventFifos event time:%d\n", e.time());
2920         #endif
2921 
2922         // Event is for future?
2923         if(e.time() >= (sample + nsamp + syncFrame))
2924           break;
2925 
2926         if(ports != 0)  // Don't bother if not 'running'.
2927         {
2928           // Returns false if the event was not filled. It was handled, but some other way.
2929           if(processEvent(e, &events[event_counter]))
2930           {
2931             // Time-stamp the event.
2932             unsigned int ft = (e.time() < syncFrame) ? 0 : e.time() - syncFrame;
2933             ft = (ft < sample) ? 0 : ft - sample;
2934 
2935             if(ft >= nsamp)
2936             {
2937                 fprintf(stderr, "VstNativeSynthIF::getData: eventFifos event time:%d out of range. pos:%d syncFrame:%u ft:%u sample:%lu nsamp:%lu\n",
2938                         e.time(), pos, syncFrame, ft, sample, nsamp);
2939                 ft = nsamp - 1;
2940             }
2941             vst_events->events[event_counter] = (VstEvent*)&events[event_counter];
2942             events[event_counter].deltaFrames = ft;
2943 
2944             ++event_counter;
2945           }
2946         }
2947         // Done with ring buffer's event. Remove it.
2948         // C++11.
2949         if(using_pb)
2950           impe_pb = synti->_outPlaybackEvents.erase(impe_pb);
2951         else
2952           impe_us = synti->_outUserEvents.erase(impe_us);
2953       }
2954 
2955       if(event_counter < nevents)
2956         nevents = event_counter;
2957 
2958       #ifdef VST_NATIVE_DEBUG_PROCESS
2959       fprintf(stderr, "VstNativeSynthIF::getData: Connecting and running. sample:%lu nsamp:%lu nevents:%lu\n", sample, nsamp, nevents);
2960       #endif
2961 
2962       if(ports != 0)  // Don't bother if not 'running'.
2963       {
2964         // Set the events pointer.
2965         if(nevents > 0)
2966         {
2967           vst_events->numEvents = nevents;
2968           dispatch(effProcessEvents, 0, 0, vst_events, 0.0f);
2969         }
2970 
2971         float* in_bufs[in_ports];
2972         float* out_bufs[out_ports];
2973 
2974         // Connect the given buffers directly to the ports, up to a max of synth ports.
2975         for(unsigned long k = 0; k < nop; ++k)
2976           out_bufs[k] = buffer[k] + sample;
2977         // Connect the remaining ports to some local buffers (not used yet).
2978         for(unsigned long k = nop; k < out_ports; ++k)
2979           out_bufs[k] = _audioOutBuffers[k] + sample;
2980         // Connect all inputs either to some local buffers, or a silence buffer.
2981         for(unsigned long k = 0; k < in_ports; ++k)
2982         {
2983           if(used_in_chan_array[k])
2984             in_bufs[k] = _audioInBuffers[k] + sample;
2985           else
2986             in_bufs[k] = _audioInSilenceBuf + sample;
2987         }
2988 
2989         // Run the synth for a period of time. This processes events and gets/fills our local buffers...
2990         if((_plugin->flags & effFlagsCanReplacing) && _plugin->processReplacing)
2991         {
2992           _plugin->processReplacing(_plugin, in_bufs, out_bufs, nsamp);
2993         }
2994       }
2995 
2996       sample += nsamp;
2997     }
2998 
2999     ++cur_slice; // Slice is done. Moving on to any next slice now...
3000   }
3001 
3002   // Inform the host callback we will be no longer in the audio thread.
3003   _inProcess = false;
3004 
3005   return true;
3006 }
3007 
3008 //--------------------------------
3009 // Methods for PluginIBase:
3010 //--------------------------------
3011 
pluginID()3012 unsigned long VstNativeSynthIF::pluginID()                        { return (_plugin) ? _plugin->uniqueID : 0; }
id()3013 int VstNativeSynthIF::id()                                        { return MusECore::MAX_PLUGINS; } // Set for special block reserved for synth.
pluginLabel() const3014 QString VstNativeSynthIF::pluginLabel() const                     { return _synth ? QString(_synth->name()) : QString(); } // FIXME Maybe wrong
lib() const3015 QString VstNativeSynthIF::lib() const                             { return _synth ? _synth->completeBaseName() : QString(); }
uri() const3016 QString VstNativeSynthIF::uri() const                             { return _synth ? _synth->uri() : QString(); }
dirPath() const3017 QString VstNativeSynthIF::dirPath() const                         { return _synth ? _synth->absolutePath() : QString(); }
fileName() const3018 QString VstNativeSynthIF::fileName() const                        { return _synth ? _synth->fileName() : QString(); }
enableController(unsigned long i,bool v)3019 void VstNativeSynthIF::enableController(unsigned long i, bool v)  { _controls[i].enCtrl = v; }
controllerEnabled(unsigned long i) const3020 bool VstNativeSynthIF::controllerEnabled(unsigned long i) const   { return _controls[i].enCtrl;}
enableAllControllers(bool v)3021 void VstNativeSynthIF::enableAllControllers(bool v)
3022 {
3023   if(!_synth)
3024     return;
3025   const unsigned long sic = _synth->inControls();
3026   for(unsigned long i = 0; i < sic; ++i)
3027     _controls[i].enCtrl = v;
3028 }
updateControllers()3029 void VstNativeSynthIF::updateControllers() { }
activate()3030 void VstNativeSynthIF::activate()
3031 {
3032   // Set some default properties
3033   dispatch(effSetSampleRate, 0, 0, NULL, MusEGlobal::sampleRate);
3034   dispatch(effSetBlockSize, 0, MusEGlobal::segmentSize, NULL, 0.0f);
3035   //for (unsigned short i = 0; i < instances(); ++i) {
3036   //        dispatch(i, effMainsChanged, 0, 1, NULL, 0.0f);
3037   dispatch(effMainsChanged, 0, 1, NULL, 0.0f);
3038 #ifndef VST_VESTIGE_SUPPORT
3039   //dispatch(i, effStartProcess, 0, 0, NULL, 0.0f);
3040   dispatch(effStartProcess, 0, 0, NULL, 0.0f);
3041 #endif
3042   //}
3043 
3044 // REMOVE Tim. Or keep? From PluginI::activate().
3045 //   if (initControlValues) {
3046 //         for (unsigned long i = 0; i < controlPorts; ++i) {
3047 //               controls[i].val = controls[i].tmpVal;
3048 //               }
3049 //         }
3050 //   else {
3051 //         // get initial control values from plugin
3052 //         for (unsigned long i = 0; i < controlPorts; ++i) {
3053 //               controls[i].tmpVal = controls[i].val;
3054 //               }
3055 //         }
3056   _active = true;
3057 }
deactivate()3058 void VstNativeSynthIF::deactivate()
3059 {
3060   _active = false;
3061   //for (unsigned short i = 0; i < instances(); ++i) {
3062 #ifndef VST_VESTIGE_SUPPORT
3063   //dispatch(i, effStopProcess, 0, 0, NULL, 0.0f);
3064   dispatch(effStopProcess, 0, 0, NULL, 0.0f);
3065 #endif
3066   //dispatch(i, effMainsChanged, 0, 0, NULL, 0.0f);
3067   dispatch(effMainsChanged, 0, 0, NULL, 0.0f);
3068   //}
3069 }
3070 
parameters() const3071 unsigned long VstNativeSynthIF::parameters() const                { return _synth ? _synth->inControls() : 0; }
parametersOut() const3072 unsigned long VstNativeSynthIF::parametersOut() const             { return 0; }
setParam(unsigned long i,double val)3073 void VstNativeSynthIF::setParam(unsigned long i, double val)       { setParameter(i, val); }
param(unsigned long i) const3074 double VstNativeSynthIF::param(unsigned long i) const              { return getParameter(i); }
paramOut(unsigned long) const3075 double VstNativeSynthIF::paramOut(unsigned long) const            { return 0.0; }
paramName(unsigned long i)3076 const char* VstNativeSynthIF::paramName(unsigned long i)
3077 {
3078   if(!_plugin)
3079     return 0;
3080   static char buf[256];
3081   buf[0] = 0;
3082   dispatch(effGetParamName, i, 0, buf, 0);
3083   return buf;
3084 }
3085 
paramOutName(unsigned long)3086 const char* VstNativeSynthIF::paramOutName(unsigned long)       { return 0; }
range(unsigned long)3087 LADSPA_PortRangeHint VstNativeSynthIF::range(unsigned long /*i*/)
3088 {
3089   LADSPA_PortRangeHint h;
3090   // FIXME TODO:
3091   h.HintDescriptor = 0;
3092   h.LowerBound = 0.0;
3093   h.UpperBound = 1.0;
3094   return h;
3095 }
rangeOut(unsigned long)3096 LADSPA_PortRangeHint VstNativeSynthIF::rangeOut(unsigned long)
3097 {
3098   // There are no output controls.
3099   LADSPA_PortRangeHint h;
3100   h.HintDescriptor = 0;
3101   h.LowerBound = 0.0;
3102   h.UpperBound = 1.0;
3103   return h;
3104 }
3105 // FIXME TODO:
ctrlValueType(unsigned long) const3106 CtrlValueType VstNativeSynthIF::ctrlValueType(unsigned long /*i*/) const { return VAL_LINEAR; }
ctrlMode(unsigned long) const3107 CtrlList::Mode VstNativeSynthIF::ctrlMode(unsigned long /*i*/) const     { return CtrlList::INTERPOLATE; }
3108 
VstNativePluginWrapper(VstNativeSynth * s,PluginFeatures_t reqFeatures)3109 VstNativePluginWrapper::VstNativePluginWrapper(VstNativeSynth *s, PluginFeatures_t reqFeatures)
3110 {
3111    _synth = s;
3112 
3113    _requiredFeatures = reqFeatures;
3114 
3115    _fakeLd.Label = strdup(_synth->name().toUtf8().constData());
3116    _fakeLd.Name = strdup(_synth->name().toUtf8().constData());
3117    _fakeLd.UniqueID = _synth->_id;
3118    _fakeLd.Maker = strdup(_synth->maker().toUtf8().constData());
3119    _fakeLd.Copyright = strdup(_synth->version().toUtf8().constData());
3120    _isVstNativePlugin = true;
3121    _isVstNativeSynth = s->isSynth();
3122    int numPorts = _synth->inPorts()
3123                   + _synth->outPorts()
3124                   + _synth->inControls();
3125    _fakeLd.PortCount = numPorts;
3126    _fakePds = new LADSPA_PortDescriptor [numPorts];
3127    memset(_fakePds, 0, sizeof(int) * numPorts);
3128 
3129    for(size_t i = 0; i < _synth->inPorts(); i++)
3130    {
3131       _fakePds [i] = LADSPA_PORT_INPUT | LADSPA_PORT_AUDIO;
3132    }
3133 
3134    for(size_t i = 0; i < _synth->outPorts(); i++)
3135    {
3136       _fakePds [i + _synth->inPorts()] = LADSPA_PORT_OUTPUT | LADSPA_PORT_AUDIO;
3137    }
3138 
3139    for(size_t i = 0; i < _synth->inControls(); i++)
3140    {
3141       _fakePds [i + _synth->inPorts() + _synth->outPorts()] = LADSPA_PORT_INPUT | LADSPA_PORT_CONTROL;
3142    }
3143 
3144 
3145    _fakeLd.PortNames = NULL;
3146    _fakeLd.PortRangeHints = NULL;
3147    _fakeLd.PortDescriptors = _fakePds;
3148    _fakeLd.Properties = 0;
3149    plugin = &_fakeLd;
3150    _isDssi = false;
3151    _isDssiSynth = false;
3152    _isLV2Plugin = false;
3153    _isLV2Synth = false;
3154 
3155 #ifdef DSSI_SUPPORT
3156    dssi_descr = NULL;
3157 #endif
3158 
3159    fi = _synth->info;
3160    _uri = _synth->uri();
3161    ladspa = NULL;
3162    _handle = 0;
3163    _references = 0;
3164    _instNo     = 0;
3165    _label = _synth->name();
3166    _name = _synth->description();
3167    _uniqueID = plugin->UniqueID;
3168    _maker = _synth->maker();
3169    _copyright = _synth->version();
3170 
3171    _portCount = plugin->PortCount;
3172 
3173    _inports = 0;
3174    _outports = 0;
3175    _controlInPorts = 0;
3176    _controlOutPorts = 0;
3177 
3178    for(unsigned long k = 0; k < _portCount; ++k)
3179    {
3180       LADSPA_PortDescriptor pd = plugin->PortDescriptors[k];
3181 
3182       if(pd & LADSPA_PORT_AUDIO)
3183       {
3184          if(pd & LADSPA_PORT_INPUT)
3185          {
3186             ++_inports;
3187          }
3188          else if(pd & LADSPA_PORT_OUTPUT)
3189          {
3190             ++_outports;
3191          }
3192       }
3193       else if(pd & LADSPA_PORT_CONTROL)
3194       {
3195          if(pd & LADSPA_PORT_INPUT)
3196          {
3197             ++_controlInPorts;
3198          }
3199          else if(pd & LADSPA_PORT_OUTPUT)
3200          {
3201             ++_controlOutPorts;
3202          }
3203       }
3204    }
3205 }
3206 
~VstNativePluginWrapper()3207 VstNativePluginWrapper::~VstNativePluginWrapper()
3208 {
3209    free((void*)_fakeLd.Label);
3210    free((void*)_fakeLd.Name);
3211    free((void*)_fakeLd.Maker);
3212    free((void*)_fakeLd.Copyright);
3213    delete [] _fakePds;
3214 }
3215 
instantiate(PluginI * pluginI)3216 LADSPA_Handle VstNativePluginWrapper::instantiate(PluginI *pluginI)
3217 {
3218    VstNativePluginWrapper_State *state = new VstNativePluginWrapper_State;
3219    if(!state)
3220    {
3221       abort();
3222    }
3223    state->plugin = _synth->instantiate(&state->userData);
3224    if(!state->plugin)
3225    {
3226       delete state;
3227       return 0;
3228    }
3229 
3230    if(!_synth->openPlugin(state->plugin))
3231    {
3232       delete state;
3233       return 0;
3234    }
3235 
3236    state->pluginI = pluginI;
3237    state->pluginWrapper = this;
3238    state->inPorts.resize(_inports);
3239    state->outPorts.resize(_outports);
3240    state->inControlPorts.resize(_controlInPorts);
3241    state->inControlLastValues.resize(_controlInPorts);
3242    bool refillDefCtrls = false;
3243    if(inControlDefaults.size() == 0)
3244    {
3245       refillDefCtrls = true;
3246       inControlDefaults.resize(_controlInPorts);
3247       portNames.resize(_inports + _outports + _controlInPorts);
3248    }
3249    memset(&state->inPorts [0], 0, _inports * sizeof(float *));
3250    memset(&state->outPorts [0], 0, _outports * sizeof(float *));
3251    memset(&state->inControlPorts [0], 0, _controlInPorts * sizeof(float *));
3252 
3253    if(refillDefCtrls)
3254    {
3255       for(size_t i = 0; i < _controlInPorts; i++)
3256       {
3257          if(state->plugin->getParameter)
3258          {
3259             state->inControlLastValues [i] = inControlDefaults [i] = state->plugin->getParameter(state->plugin, i);
3260          }
3261       }
3262 
3263 
3264       for(size_t i = 0; i < portNames.size(); i++)
3265       {
3266          if(i < _inports)
3267          {
3268             std::stringstream ss;
3269             ss << "input" << i;
3270             portNames [i] = ss.str();
3271          }
3272          else if(i < _inports + _outports)
3273          {
3274             std::stringstream ss;
3275             ss << "output" << (i - _inports);
3276             portNames [i] = ss.str();
3277          }
3278          else if(i < _inports + _outports + _controlInPorts)
3279          {
3280             char buf[256];
3281             memset(buf, 0, sizeof(buf));
3282             dispatch(state, effGetParamName, i - _inports - _outports, 0, buf, 0);
3283             if(strlen(buf) > 0)
3284             {
3285                portNames [i] = buf;
3286             }
3287             else
3288             {
3289                std::stringstream ss;
3290                ss << "control" << (i - _inports - _outports);
3291                portNames [i] = ss.str();
3292             }
3293          }
3294       }
3295    }
3296 
3297    QObject::connect(MusEGlobal::heartBeatTimer, SIGNAL(timeout()), state, SLOT(heartBeat()));
3298 
3299    return(LADSPA_Handle)state;
3300 
3301 }
3302 
incReferences(int ref)3303 int VstNativePluginWrapper::incReferences(int ref)
3304 {
3305    _synth->incInstances(ref);
3306    return _synth->instances();
3307 }
3308 
activate(LADSPA_Handle handle)3309 void VstNativePluginWrapper::activate(LADSPA_Handle handle)
3310 {
3311    VstNativePluginWrapper_State *state = (VstNativePluginWrapper_State *)handle;
3312    // Set some default properties
3313    dispatch(state, effSetSampleRate, 0, 0, NULL, MusEGlobal::sampleRate);
3314    dispatch(state, effSetBlockSize, 0, MusEGlobal::segmentSize, NULL, 0.0f);
3315    //for (unsigned short i = 0; i < instances(); ++i) {
3316    //        dispatch(i, effMainsChanged, 0, 1, NULL, 0.0f);
3317    dispatch(state, effMainsChanged, 0, 1, NULL, 0.0f);
3318    dispatch(state, 71 /*effStartProcess*/, 0, 0, NULL, 0.0f);
3319 
3320    if(state->plugin->getParameter)
3321    {
3322       for(size_t i = 0; i < _controlInPorts; i++)
3323       {
3324          state->pluginI->controls [i].val = state->pluginI->controls [i].tmpVal = inControlDefaults [i];
3325       }
3326    }
3327    state->active = true;
3328 }
3329 
deactivate(LADSPA_Handle handle)3330 void VstNativePluginWrapper::deactivate(LADSPA_Handle handle)
3331 {
3332    VstNativePluginWrapper_State *state = (VstNativePluginWrapper_State *)handle;
3333    if(!state)
3334    {
3335       return;
3336    }
3337    state->active = false;
3338    dispatch(state, 72 /*effStopProcess*/, 0, 0, NULL, 0.0f);
3339    dispatch(state, effMainsChanged, 0, 0, NULL, 0.0f);
3340 }
3341 
cleanup(LADSPA_Handle handle)3342 void VstNativePluginWrapper::cleanup(LADSPA_Handle handle)
3343 {
3344    VstNativePluginWrapper_State *state = (VstNativePluginWrapper_State *)handle;
3345    if(!state)
3346    {
3347       return;
3348    }
3349    if(state->editor)
3350    {
3351      state->editor->close();
3352      state->editor = NULL;
3353      state->guiVisible = false;
3354    }
3355 
3356    if (state->plugin)
3357    {
3358       dispatch(state, effClose, 0, 0, NULL, 0);
3359       state->plugin = 0;
3360    }
3361 
3362    delete state;
3363 }
3364 
connectPort(LADSPA_Handle handle,unsigned long port,float * value)3365 void VstNativePluginWrapper::connectPort(LADSPA_Handle handle, unsigned long port, float *value)
3366 {
3367    VstNativePluginWrapper_State *state = (VstNativePluginWrapper_State *)handle;
3368    if(port < _inports)
3369    {
3370       state->inPorts [port] = value;
3371    }
3372    else if(port < _inports + _outports)
3373    {
3374       state->outPorts [port - _inports] = value;
3375    }
3376    else if(port < _inports + _outports + _controlInPorts)
3377    {
3378       state->inControlPorts [port - _inports - _outports] = value;
3379    }
3380 
3381 }
3382 
apply(LADSPA_Handle handle,unsigned long n,float)3383 void VstNativePluginWrapper::apply(LADSPA_Handle handle, unsigned long n, float /*latency_corr*/)
3384 {
3385    VstNativePluginWrapper_State *state = (VstNativePluginWrapper_State *)handle;
3386    state->inProcess = true;
3387    if(state->pluginI->controls)
3388    {
3389       for(size_t i = 0; i < _controlInPorts; i++)
3390       {
3391          if(state->pluginI->controls [i].val == state->inControlLastValues [i])
3392          {
3393             continue;
3394          }
3395          state->inControlLastValues [i] = state->pluginI->controls [i].val;
3396          if(dispatch(state, 26 /*effCanBeAutomated*/, i, 0, NULL, 0.0f) == 1)
3397          {
3398             if(state->plugin->getParameter && state->plugin->setParameter)
3399             {
3400                if(state->plugin->getParameter(state->plugin, i) != state->inControlLastValues [i])
3401                   state->plugin->setParameter(state->plugin, i, state->inControlLastValues [i]);
3402             }
3403          }
3404 
3405       }
3406    }
3407    if((state->plugin->flags & effFlagsCanReplacing) && state->plugin->processReplacing)
3408    {
3409      state->plugin->processReplacing(state->plugin, &state->inPorts [0], &state->outPorts [0], n);
3410    }
3411    else if(state->plugin->process)
3412    {
3413       state->plugin->process(state->plugin, &state->inPorts [0], &state->outPorts [0], n);
3414    }
3415    state->inProcess = false;
3416 
3417 }
3418 
portd(unsigned long k) const3419 LADSPA_PortDescriptor VstNativePluginWrapper::portd(unsigned long k) const
3420 {
3421    return _fakeLd.PortDescriptors[k];
3422 }
3423 
range(unsigned long)3424 LADSPA_PortRangeHint VstNativePluginWrapper::range(unsigned long)
3425 {
3426    LADSPA_PortRangeHint hint;
3427    hint.HintDescriptor = 0;
3428    hint.LowerBound = 0.0f;
3429    hint.UpperBound = 1.0f;
3430 
3431    hint.HintDescriptor |= LADSPA_HINT_BOUNDED_BELOW;
3432    hint.HintDescriptor |= LADSPA_HINT_BOUNDED_ABOVE;
3433 
3434    return hint;
3435 }
3436 
range(unsigned long,float * min,float * max) const3437 void VstNativePluginWrapper::range(unsigned long, float *min, float *max) const
3438 {
3439    *min = 0.0f;
3440    *max = 1.0f;
3441 }
3442 
defaultValue(unsigned long port) const3443 double VstNativePluginWrapper::defaultValue(unsigned long port) const
3444 {
3445    return inControlDefaults [port];
3446 }
3447 
portName(unsigned long port)3448 const char *VstNativePluginWrapper::portName(unsigned long port)
3449 {
3450    return portNames [port].c_str();
3451 }
3452 
ctrlValueType(unsigned long) const3453 CtrlValueType VstNativePluginWrapper::ctrlValueType(unsigned long) const
3454 {
3455    return VAL_LINEAR;
3456 }
3457 
ctrlMode(unsigned long) const3458 CtrlList::Mode VstNativePluginWrapper::ctrlMode(unsigned long) const
3459 {
3460    return CtrlList::INTERPOLATE;
3461 }
3462 
hasNativeGui() const3463 bool VstNativePluginWrapper::hasNativeGui() const
3464 {
3465    return _synth->_hasGui;
3466 }
3467 
showNativeGui(PluginI * p,bool bShow)3468 void VstNativePluginWrapper::showNativeGui(PluginI *p, bool bShow)
3469 {
3470    assert(p->instances > 0);
3471    VstNativePluginWrapper_State *state = (VstNativePluginWrapper_State *)p->handle [0];
3472    if(!hasNativeGui())
3473       return;
3474    if(bShow)
3475    {
3476       if(state->editor)
3477       {
3478          if(!state->editor->isVisible())
3479             state->editor->show();
3480          state->editor->raise();
3481          state->editor->activateWindow();
3482       }
3483       else
3484       {
3485          Qt::WindowFlags wflags(Qt::Window
3486                                   | Qt::CustomizeWindowHint
3487                                   | Qt::WindowTitleHint
3488                                   | Qt::WindowSystemMenuHint
3489                                   | Qt::WindowMinMaxButtonsHint
3490                                   | Qt::WindowCloseButtonHint);
3491          state->editor = new MusEGui::VstNativeEditor(NULL, wflags);
3492          state->editor->open(0, state);
3493       }
3494    }
3495    else
3496    {
3497       if(state->editor)
3498       {
3499          state->editor->close();
3500          //_editor = NULL;  // No - done in editorDeleted.
3501       }
3502    }
3503    state->guiVisible = bShow;
3504 }
3505 
nativeGuiVisible(const PluginI * p) const3506 bool VstNativePluginWrapper::nativeGuiVisible(const PluginI *p) const
3507 {
3508    assert(p->instances > 0);
3509    VstNativePluginWrapper_State *state = (VstNativePluginWrapper_State *)p->handle [0];
3510    return state->guiVisible;
3511 }
3512 
writeConfiguration(LADSPA_Handle handle,int level,Xml & xml)3513 void VstNativePluginWrapper::writeConfiguration(LADSPA_Handle handle, int level, Xml &xml)
3514 {
3515    VstNativePluginWrapper_State *state = (VstNativePluginWrapper_State *)handle;
3516    _synth->vstconfWrite(state->plugin, name(), level, xml); // index 0: is bank 1: is program
3517 }
3518 
setCustomData(LADSPA_Handle handle,const std::vector<QString> & customParams)3519 void VstNativePluginWrapper::setCustomData(LADSPA_Handle handle, const std::vector<QString> &customParams)
3520 {
3521    VstNativePluginWrapper_State *state = (VstNativePluginWrapper_State *)handle;
3522   _synth->vstconfSet(state->plugin, customParams);
3523 }
3524 
heartBeat()3525 void VstNativePluginWrapper_State::heartBeat()
3526 {
3527    if(plugin && active)
3528    {
3529       if(guiVisible)
3530       {
3531         plugin->dispatcher(plugin, effEditIdle, 0, 0, NULL, 0.0f);
3532         if(editor)
3533           editor->update();
3534       }
3535    }
3536 
3537 }
3538 
3539 } // namespace MusECore
3540 
3541 #else  // VST_NATIVE_SUPPORT
3542 namespace MusECore {
initVST_Native()3543 void initVST_Native() {}
3544 } // namespace MusECore
3545 #endif
3546 
3547