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