1 /*
2     InterChange.cpp - General communications
3 
4     Copyright 2016-2019, Will Godfrey & others
5     Copyright 2020-2020, Kristian Amlie, Will Godfrey, & others
6     Copyright 2021, Will Godfrey, Rainer Hans Liffers, & others
7 
8     This file is part of yoshimi, which is free software: you can redistribute
9     it and/or modify it under the terms of the GNU Library General Public
10     License as published by the Free Software Foundation; either version 2 of
11     the License, or (at your option) any later version.
12 
13     yoshimi is distributed in the hope that it will be useful, but WITHOUT ANY
14     WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15     FOR A PARTICULAR PURPOSE.   See the GNU General Public License (version 2 or
16     later) for more details.
17 
18     You should have received a copy of the GNU General Public License along with
19     yoshimi; if not, write to the Free Software Foundation, Inc., 51 Franklin
20     Street, Fifth Floor, Boston, MA  02110-1301, USA.
21 
22 */
23 
24 #include <iostream>
25 #include <string>
26 #include <algorithm>
27 #include <cfloat>
28 #include <bitset>
29 #include <unistd.h>
30 #include <thread>
31 
32 #include "Interface/InterChange.h"
33 #include "Interface/Data2Text.h"
34 #include "Interface/TextLists.h"
35 #include "Misc/FileMgrFuncs.h"
36 #include "Misc/NumericFuncs.h"
37 #include "Misc/FormatFuncs.h"
38 #include "Misc/Microtonal.h"
39 #include "Misc/SynthEngine.h"
40 #include "Misc/Part.h"
41 #include "Misc/TextMsgBuffer.h"
42 #include "Params/Controller.h"
43 #include "Params/ADnoteParameters.h"
44 #include "Params/SUBnoteParameters.h"
45 #include "Params/PADnoteParameters.h"
46 #include "Params/LFOParams.h"
47 #include "Params/FilterParams.h"
48 #include "Params/EnvelopeParams.h"
49 #include "Effects/EffectMgr.h"
50 #include "Synth/Resonance.h"
51 #include "Synth/OscilGen.h"
52 #ifdef GUI_FLTK
53     #include "MasterUI.h"
54 #endif
55 
56 using file::localPath;
57 using file::findFile;
58 using file::isRegularFile;
59 using file::createDir;
60 using file::listDir;
61 using file::isDirectory;
62 using file::setExtension;
63 using file::findLeafName;
64 using file::createEmptyFile;
65 using file::deleteFile;
66 using file::loadText;
67 using file::saveText;
68 
69 using func::bitSet;
70 using func::bitClear;
71 using func::nearestPowerOf2;
72 
73 using func::asString;
74 
75 extern void mainRegisterAudioPort(SynthEngine *s, int portnum);
76 extern SynthEngine *firstSynth;
77 
78 int startInstance = 0;
79 
InterChange(SynthEngine * _synth)80 InterChange::InterChange(SynthEngine *_synth) :
81     synth(_synth),
82 #ifndef YOSHIMI_LV2_PLUGIN
83     fromCLI(),
84 #endif
85     decodeLoopback(),
86 #ifdef GUI_FLTK
87     fromGUI(),
88     toGUI(),
89 #endif
90     fromMIDI(),
91     returnsBuffer(),
92     syncWrite(false),
93     lowPrioWrite(false),
94     tick(0),
95     sortResultsThreadHandle(0),
96     swapRoot1(UNUSED),
97     swapBank1(UNUSED),
98     swapInstrument1(UNUSED),
99     searchInst(0),
100     searchBank(0),
101     searchRoot(0)
102 {
103     ;
104 }
105 
106 
Init()107 bool InterChange::Init()
108 {
109 #ifndef YOSHIMI_LV2_PLUGIN
110     fromCLI.init ();
111 #endif
112     decodeLoopback.init ();
113 #ifdef GUI_FLTK
114     fromGUI.init ();
115     toGUI.init ();
116 #endif
117     fromMIDI.init ();
118     returnsBuffer.init ();
119     muteQueue.init ();
120     if (!synth->getRuntime().startThread(&sortResultsThreadHandle, _sortResultsThread, this, false, 0, "CLI"))
121     {
122         synth->getRuntime().Log("Failed to start CLI resolve thread");
123         return false;
124     }
125     else
126     {
127         searchInst = searchBank = searchRoot = 0;
128         return true;
129     }
130 }
131 
132 
_sortResultsThread(void * arg)133 void *InterChange::_sortResultsThread(void *arg)
134 {
135     return static_cast<InterChange*>(arg)->sortResultsThread();
136 }
137 
138 
sortResultsThread(void)139 void *InterChange::sortResultsThread(void)
140 {
141     while (synth->getRuntime().runSynth)
142     {
143         /*
144          * To maintain portability we synthesise a very simple low accuracy
145          * timer based on the loop time of this function. As it makes no system
146          * calls apart from usleep() it is lightweight and should have no thread
147          * safety issues. It is used mostly for low priority timeouts.
148          */
149         ++ tick;
150 
151         /*if (!(tick & 8191))
152         {
153             if (tick & 16383)
154                 std::cout << "Tick" << std::endl;
155             else
156                 std::cout << "Tock" << std::endl;
157         }*/
158 
159         CommandBlock getData;
160 
161         /* It is possible that several operations initiated from
162          * different sources complete within the same period
163          * (especially with large buffer sizes) so this small
164          * ring buffer ensures they can all clear together.
165          */
166         while (synth->audioOut.load() == _SYS_::mute::Active)
167         {
168             //std::cout << "here fetching" << std:: endl;
169             if (muteQueue.read(getData.bytes))
170                 indirectTransfers(&getData);
171             else
172                 synth->audioOut.store(_SYS_::mute::Complete);
173         }
174 
175         while (decodeLoopback.read(getData.bytes))
176         {
177             if (getData.data.part == TOPLEVEL::section::midiLearn)
178                 synth->midilearn.generalOperations(&getData);
179             else if (getData.data.source >= TOPLEVEL::action::lowPrio)
180                 indirectTransfers(&getData);
181             else
182                 resolveReplies(&getData);
183         }
184             usleep(80); // actually gives around 120 uS
185     }
186     return NULL;
187 }
188 
189 
~InterChange()190 InterChange::~InterChange()
191 {
192     if (sortResultsThreadHandle)
193         pthread_join(sortResultsThreadHandle, 0);
194 }
195 
196 
muteQueueWrite(CommandBlock * getData)197 void InterChange::muteQueueWrite(CommandBlock *getData)
198 {
199     if (!muteQueue.write(getData->bytes))
200     {
201         std::cout << "failed to write to muteQueue" << std::endl;
202         return;
203     }
204     if (synth->audioOut.load() == _SYS_::mute::Idle)
205     {
206         //std::cout << "here pending" << std:: endl;
207         synth->audioOut.store(_SYS_::mute::Pending);
208     }
209 }
210 
211 
findHtmlManual(void)212 std::string InterChange::findHtmlManual(void)
213 {
214     string namestring = "doc/yoshimi/yoshimi_user_guide/files/yoshimi_user_guide_version";
215     string namelist = "";
216     if (isRegularFile("/usr/share/" + namestring))
217         namelist += ("/usr/share/" + namestring + "\n");
218     if (isRegularFile("/usr/local/share/" + namestring))
219         namelist += ("/usr/local/share/" + namestring + "\n");
220     if (namelist.empty())
221     {
222         if(!file::cmd2string("find /home/ -type f -name 'yoshimi_user_guide_version' 2>/dev/null", namelist))
223             return "";
224     }
225     //std::cout << namelist << std::endl;
226 
227     size_t next = 0;
228     size_t lastversion = 0;
229     string found = "";
230     string name = "";
231     while (next != string::npos)
232     {
233         next = namelist.find("\n");
234         if (next != string::npos)
235         {
236             name = namelist.substr(0, next);
237 
238             // check it's there and the most recent
239             size_t current = isRegularFile(name);
240             if (current > lastversion)
241             {
242                 lastversion = current;
243                 found = name;
244             }
245             namelist = namelist.substr( next +1);
246         }
247     }
248     return found;
249 }
250 
251 
manualSearch(std::string dir2search,std::string path2match)252 std::string InterChange::manualSearch(std::string dir2search, std::string path2match)
253 {
254     std::list<string> wanted;
255     listDir(&wanted, dir2search);
256     if (wanted.empty())
257     return "";
258     wanted.sort();
259 
260     std::string path = "";
261     std::list<string>::reverse_iterator itr = wanted.rbegin();
262     while (itr != wanted.rend())
263     {
264         std::string tmp = *itr;
265         // some installs have a missing third digit so we trap it
266         if (tmp.find(path2match) != std::string::npos && tmp.rfind("2.0.pdf") == std::string::npos)
267         {
268             path = tmp;
269             itr = wanted.rend();
270         }
271         else
272             ++itr;
273     }
274     return path;
275 }
276 
277 
indirectTransfers(CommandBlock * getData,bool noForward)278 void InterChange::indirectTransfers(CommandBlock *getData, bool noForward)
279 {
280     int value = lrint(getData->data.value);
281     unsigned char type = getData->data.type;
282     unsigned char control = getData->data.control;
283     unsigned char switchNum = getData->data.part;
284     unsigned char kititem = getData->data.kit;
285     unsigned char engine = getData->data.engine;
286     unsigned char insert = getData->data.insert;
287     //unsigned char parameter = getData->data.parameter;
288     //unsigned char miscmsg = getData->data.miscmsg;
289 
290     while (syncWrite)
291         usleep(10);
292     bool write = (type & TOPLEVEL::type::Write);
293     if (write)
294         lowPrioWrite = true;
295     bool guiTo = false;
296     (void) guiTo; // suppress warning when headless build
297     unsigned char newMsg = false;//NO_MSG;
298 
299     if (switchNum == TOPLEVEL::section::main && control == MAIN::control::loadFileFromList)
300     {
301         int result = synth->LoadNumbered(kititem, engine);
302         if (result > NO_MSG)
303             getData->data.miscmsg = result & NO_MSG;
304         else
305         {
306             getData->data.miscmsg = result;
307             switch (kititem) // group
308             {
309                 case TOPLEVEL::XML::Instrument:
310                 {
311                     control = MAIN::control::loadInstrumentByName;
312                     getData->data.kit = insert;
313                     break;
314                 }
315                 case TOPLEVEL::XML::Patch:
316                 {
317                     control = MAIN::control::loadNamedPatchset;
318                     break;
319                 }
320                 case TOPLEVEL::XML::Scale:
321                 {
322                     control = MAIN::control::loadNamedScale;
323                     break;
324                 }
325                 case TOPLEVEL::XML::State:
326                 {
327                     control = MAIN::control::loadNamedState;
328                     break;
329                 }
330                 case TOPLEVEL::XML::Vector:
331                 {
332                     control = MAIN::control::loadNamedVector;
333                     break;
334                 }
335                 case TOPLEVEL::XML::MLearn:
336                 { // this is a bit messy MIDI learn is an edge case
337                     getData->data.control = MIDILEARN::control::loadList;
338                     synth->midilearn.generalOperations(getData);
339                     lowPrioWrite = false;
340                     return;
341                     break;
342                 }
343             }
344             getData->data.control = control;
345         }
346     }
347 
348     std::string text;
349     if (getData->data.miscmsg != NO_MSG)
350     {
351         text = textMsgBuffer.fetch(getData->data.miscmsg);
352         getData->data.miscmsg = NO_MSG; // this may be reset later
353     }
354     else
355         text = "";
356 
357     if (control == TOPLEVEL::control::textMessage)
358         switchNum = TOPLEVEL::section::message; // this is a bit hacky :(
359 
360     switch(switchNum)
361     {
362         case TOPLEVEL::section::vector:
363             value = indirectVector(getData, synth, newMsg, guiTo, text);
364             break;
365         case TOPLEVEL::section::midiLearn:
366             if (control == MIDILEARN::control::findSize)
367                 value = synth->midilearn.findSize();
368             // very naughty! should do better
369             break;
370         case TOPLEVEL::section::midiIn: // program / bank / root
371             value = indirectMidi(getData, synth, newMsg, guiTo, text);
372             break;
373         case TOPLEVEL::section::scales:
374             value = indirectScales(getData, synth, newMsg, guiTo, text);
375             break;
376 
377         case TOPLEVEL::section::main:
378             value = indirectMain(getData, synth, newMsg, guiTo, text);
379             break;
380 
381         case TOPLEVEL::section::bank: // instrument / bank
382             value = indirectBank(getData, synth, newMsg, guiTo, text);
383             break;
384 
385         case TOPLEVEL::section::config:
386             value = indirectConfig(getData, synth, newMsg, guiTo, text);
387             break;
388 
389         case TOPLEVEL::section::message:
390             newMsg = true;
391             getData->data.source &= ~TOPLEVEL::action::lowPrio;
392             break;
393         default:
394             if (switchNum < NUM_MIDI_PARTS)
395             {
396                 value = indirectPart(getData, synth, newMsg, guiTo, text);
397             }
398             break;
399     }
400 
401      // CLI message text has to be set here.
402     if (!synth->fileCompatible)
403         text += "\nIncompatible file from ZynAddSubFX 3.x";
404 
405     if (newMsg)
406         value = textMsgBuffer.push(text);
407     // TODO need to improve message handling for multiple receivers
408 
409     getData->data.value = float(value);
410     if (write)
411         lowPrioWrite = false;
412     if (noForward)
413         return;
414 
415 
416     if (getData->data.source < TOPLEVEL::action::lowPrio)
417     {
418 #ifdef GUI_FLTK
419         if (text != "" && synth->getRuntime().showGui && (write || guiTo))
420         {
421             getData->data.miscmsg = textMsgBuffer.push(text); // pass it on to GUI
422         }
423 #endif
424         bool ok = returnsBuffer.write(getData->bytes);
425 #ifdef GUI_FLTK
426         if (synth->getRuntime().showGui)
427         {
428             if (switchNum == TOPLEVEL::section::scales && control == SCALES::control::importScl)
429             {   // loading a tuning includes a name and comment!
430                 getData->data.control = SCALES::control::name;
431                 getData->data.miscmsg = textMsgBuffer.push(synth->microtonal.Pname);
432                 returnsBuffer.write(getData->bytes);
433                 getData->data.control = SCALES::control::comment;
434                 getData->data.miscmsg = textMsgBuffer.push(synth->microtonal.Pcomment);
435                 ok &= returnsBuffer.write(getData->bytes);
436             }
437             if (switchNum == TOPLEVEL::section::main && control == MAIN::control::loadNamedState)
438                 synth->midilearn.updateGui();
439                 /*
440                  * This needs improving. We should only set it
441                  * when the state file contains a learn list.
442                  */
443         }
444 #endif
445         if (!ok)
446             synth->getRuntime().Log("Unable to  write to returnsBuffer buffer");
447 
448         // cancelling and GUI report must be set after action completed.
449         if (!synth->fileCompatible)
450         {
451             synth->fileCompatible = true;
452 #ifdef GUI_FLTK
453             if (synth->getRuntime().showGui &&
454                (getData->data.source & TOPLEVEL::action::noAction) == TOPLEVEL::action::fromGUI)
455             {
456                 getData->data.control = TOPLEVEL::control::textMessage;
457                 getData->data.miscmsg = textMsgBuffer.push("File from ZynAddSubFX 3.0 or later has parameter types changed incompatibly with earlier versions, and with Yoshimi. It may not perform correctly.");
458                 returnsBuffer.write(getData->bytes);
459             }
460 #endif
461         }
462     }
463     else // don't leave this hanging
464     {
465         synth->fileCompatible = true;
466         std::cout << "No indirect return" << std::endl;
467     }
468 }
469 
470 
indirectVector(CommandBlock * getData,SynthEngine * synth,unsigned char & newMsg,bool & guiTo,std::string & text)471 int InterChange::indirectVector(CommandBlock *getData, SynthEngine *synth, unsigned char &newMsg, bool &guiTo, std::string &text)
472 {
473     bool write = (getData->data.type & TOPLEVEL::type::Write);
474     int value = getData->data.value;
475     int control = getData->data.control;
476     int insert = getData->data.insert;
477 
478     switch(control)
479     {
480         case VECTOR::control::name:
481             if (write)
482                 synth->getRuntime().vectordata.Name[insert] = text;
483             else
484                 text = synth->getRuntime().vectordata.Name[insert];
485             newMsg = true;
486             getData->data.source &= ~TOPLEVEL::action::lowPrio;
487             guiTo = true;
488             break;
489     }
490 
491     return value;
492 }
493 
494 
indirectMidi(CommandBlock * getData,SynthEngine * synth,unsigned char & newMsg,bool & guiTo,std::string & text)495 int InterChange::indirectMidi(CommandBlock *getData, SynthEngine *synth, unsigned char &newMsg, bool &guiTo, std::string &text)
496 {
497     int value = getData->data.value;
498     int control = getData->data.control;
499     int msgID;
500     if (control == MIDI::control::instrument)
501     {
502         msgID = synth->setProgramFromBank(getData);
503         getData->data.control = MAIN::control::loadInstrumentFromBank;
504         getData->data.part = TOPLEVEL::section::main;
505         // moved to 'main' for return updates.
506         if (msgID > NO_MSG)
507             text = " FAILED " + text;
508         else
509             text = "ed ";
510     }
511     else
512     {
513         msgID = synth->setRootBank(getData->data.insert, getData->data.engine);
514         if (msgID > NO_MSG)
515             text = "FAILED " + text;
516         else
517             text = "";
518     }
519     text += textMsgBuffer.fetch(msgID & NO_MSG);
520     newMsg = true;
521     getData->data.source = TOPLEVEL::action::toAll;
522     // everyone will want to know about these!
523     guiTo = true;
524     return value;
525 }
526 
527 
indirectScales(CommandBlock * getData,SynthEngine * synth,unsigned char & newMsg,bool & guiTo,std::string & text)528 int InterChange::indirectScales(CommandBlock *getData, SynthEngine *synth, unsigned char &newMsg, bool &guiTo, std::string &text)
529 {
530     bool write = (getData->data.type & TOPLEVEL::type::Write);
531     int value = getData->data.value;
532     int control = getData->data.control;
533 
534     switch(control)
535     {
536         case SCALES::control::tuning:
537             text = formatScales(text);
538             value = synth->microtonal.texttotunings(text.c_str());
539             if (value > 0)
540                 synth->setAllPartMaps();
541             break;
542         case SCALES::control::keyboardMap:
543             text = formatScales(text);
544             value = synth->microtonal.texttomapping(text.c_str());
545             if (value > 0)
546                 synth->setAllPartMaps();
547             break;
548 
549         case SCALES::control::importScl:
550             value = synth->microtonal.loadscl(setExtension(text,EXTEN::scalaTuning));
551             if (value > 0)
552             {
553                 text = "";
554                 char *buf = new char[100];
555                 for (int i = 0; i < value; ++ i)
556                 {
557                     synth->microtonal.tuningtoline(i, buf, 100);
558                     if (i > 0)
559                         text += "\n";
560                     text += std::string(buf);
561                 }
562                 delete [] buf;
563             }
564             break;
565         case SCALES::control::importKbm:
566             value = synth->microtonal.loadkbm(setExtension(text,EXTEN::scalaKeymap));
567             if (value > 0)
568             {
569                 text = "";
570                 int map;
571                 for (int i = 0; i < value; ++ i)
572                 {
573                     if (i > 0)
574                         text += "\n";
575                     map = synth->microtonal.Pmapping[i];
576                     if (map == -1)
577                         text += 'x';
578                     else
579                         text += std::to_string(map);
580                 }
581                 getData->data.kit = synth->microtonal.PrefNote;
582                 getData->data.engine = synth->microtonal.Pfirstkey;
583                 getData->data.insert = synth->microtonal.Pmiddlenote;
584                 getData->data.parameter |= synth->microtonal.Plastkey; // need to keep top bit
585                 synth->setAllPartMaps();
586             }
587             break;
588 
589         case SCALES::control::name:
590             if (write)
591             {
592                 synth->microtonal.Pname = text;
593             }
594             else
595                 text = synth->microtonal.Pname;
596             newMsg = true;
597             break;
598         case SCALES::control::comment:
599             if (write)
600                 synth->microtonal.Pcomment = text;
601             else
602                 text = synth->microtonal.Pcomment;
603             newMsg = true;
604             break;
605     }
606     getData->data.source &= ~TOPLEVEL::action::lowPrio;
607     guiTo = true;
608     return value;
609 }
610 
611 
indirectMain(CommandBlock * getData,SynthEngine * synth,unsigned char & newMsg,bool & guiTo,std::string & text)612 int InterChange::indirectMain(CommandBlock *getData, SynthEngine *synth, unsigned char &newMsg, bool &guiTo, std::string &text)
613 {
614     bool write = (getData->data.type & TOPLEVEL::type::Write);
615     int value = getData->data.value;
616     int control = getData->data.control;
617     int kititem = getData->data.kit;
618     int insert = getData->data.insert;
619     switch (control)
620     {
621         case MAIN::control::detune:
622         {
623             if (write)
624             {
625                 synth->microtonal.Pglobalfinedetune = value;
626                 synth->setAllPartMaps();
627             }
628             else
629                 value = synth->microtonal.Pglobalfinedetune;
630             break;
631         }
632         case MAIN::control::keyShift:
633         {
634             if (write)
635             {
636                 synth->setPkeyshift(value + 64);
637                 synth->setAllPartMaps();
638             }
639             else
640                 value = synth->Pkeyshift - 64;
641             break;
642         }
643 
644         case MAIN::control::exportBank:
645         {
646             if (kititem == UNUSED)
647                 kititem = synth->getRuntime().currentRoot;
648             text = synth->bank.exportBank(text, kititem, value);
649             newMsg = true;
650             break;
651         }
652         case MAIN::control::importBank:
653         {
654             if (kititem == UNUSED)
655                 kititem = synth->getRuntime().currentRoot;
656             text = synth->bank.importBank(text, kititem, value);
657             newMsg = true;
658             break;
659         }
660         case MAIN::control::deleteBank:
661         {
662             text = synth->bank.removebank(value, kititem);
663             newMsg = true;
664             break;
665         }
666         case MAIN::control::loadInstrumentFromBank:
667         {
668             unsigned int result = synth->setProgramFromBank(getData);
669             text = textMsgBuffer.fetch(result & NO_MSG);
670             if (result < 0x1000)
671             {
672                 if (synth->getRuntime().bankHighlight)
673                     synth->getRuntime().lastBankPart = (value << 15) | (synth->getRuntime().currentBank << 8) | synth->getRuntime().currentRoot;
674                 else
675                     synth->getRuntime().lastBankPart = UNUSED;
676                 text = "ed " + text;
677             }
678             else
679                 text = " FAILED " + text;
680             newMsg = true;
681             break;
682         }
683 
684         case MAIN::control::loadInstrumentByName:
685         {
686             getData->data.miscmsg = textMsgBuffer.push(text);
687             unsigned int result = synth->setProgramByName(getData);
688             text = textMsgBuffer.fetch(result & NO_MSG);
689             synth->getRuntime().lastBankPart = UNUSED;
690             if (result < 0x1000)
691                 text = "ed " + text;
692             else
693                 text = " FAILED " + text;
694             newMsg = true;
695             break;
696         }
697 
698         case MAIN::control::saveNamedInstrument:
699         {
700             bool ok = true;
701             int saveType = synth->getRuntime().instrumentFormat;
702             // This is both. Below we send them individually.
703 
704             if (saveType & 2) // Yoshimi format
705                 ok = synth->part[value]->saveXML(text, true);
706             if (ok && (saveType & 1)) // legacy
707                 ok = synth->part[value]->saveXML(text, false);
708 
709             if (ok)
710             {
711                 synth->getRuntime().sessionSeen[TOPLEVEL::XML::Instrument] = true;
712                 synth->addHistory(setExtension(text, EXTEN::zynInst), TOPLEVEL::XML::Instrument);
713                 synth->part[value]->PyoshiType = (saveType & 2);
714                 text = "d " + text;
715             }
716             else
717                 text = " FAILED " + text;
718             newMsg = true;
719             break;
720         }
721         case MAIN::control::loadNamedPatchset:
722             vectorClear(NUM_MIDI_CHANNELS);
723             if (synth->loadPatchSetAndUpdate(text))
724             {
725                 synth->addHistory(setExtension(text, EXTEN::patchset), TOPLEVEL::XML::Patch);
726                 text = "ed " + text;
727             }
728             else
729                 text = " FAILED " + text;
730             synth->getRuntime().lastBankPart = UNUSED;
731             newMsg = true;
732             break;
733         case MAIN::control::saveNamedPatchset:
734             if (synth->savePatchesXML(text))
735             {
736                 synth->addHistory(setExtension(text, EXTEN::patchset), TOPLEVEL::XML::Patch);
737                 text = "d " + text;
738             }
739             else
740                 text = " FAILED " + text;
741             newMsg = true;
742             break;
743         case MAIN::control::loadNamedVector:
744         {
745             int tmp = synth->loadVectorAndUpdate(insert, text);
746             if (tmp < NO_MSG)
747             {
748                 getData->data.insert = tmp;
749                 synth->addHistory(setExtension(text, EXTEN::vector), TOPLEVEL::XML::Vector);
750                 text = "ed " + text + " to chan " + std::to_string(int(tmp + 1));
751             }
752             else
753                 text = " FAILED " + text;
754             synth->getRuntime().lastBankPart = UNUSED;
755             newMsg = true;
756             break;
757         }
758         case MAIN::control::saveNamedVector:
759         {
760             std::string oldname = synth->getRuntime().vectordata.Name[insert];
761             int pos = oldname.find("No Name");
762             if (pos >=0 && pos < 2)
763                 synth->getRuntime().vectordata.Name[insert] = findLeafName(text);
764             int tmp = synth->saveVector(insert, text, true);
765             if (tmp == NO_MSG)
766             {
767                 synth->addHistory(setExtension(text, EXTEN::vector), TOPLEVEL::XML::Vector);
768                 text = "d " + text;
769             }
770             else
771             {
772                 string name = textMsgBuffer.fetch(tmp);
773                 if (name != "FAIL")
774                     text = " " + name;
775                 else
776                     text = " FAILED " + text;
777             }
778             newMsg = true;
779             break;
780         }
781        case MAIN::control::loadNamedScale:
782            if (synth->loadMicrotonal(text))
783            {
784                 synth->addHistory(setExtension(text, EXTEN::scale), TOPLEVEL::XML::Scale);
785                 text = "ed " + text;
786             }
787             else
788                 text = " FAILED " + text;
789             newMsg = true;
790             break;
791         case MAIN::control::saveNamedScale:
792             if (synth->saveMicrotonal(text))
793             {
794                 synth->addHistory(setExtension(text, EXTEN::scale), TOPLEVEL::XML::Scale);
795                 text = "d " + text;
796             }
797             else
798                 text = " FAILED " + text;
799             newMsg = true;
800             break;
801         case MAIN::control::loadNamedState:
802             vectorClear(NUM_MIDI_CHANNELS);
803             if (synth->loadStateAndUpdate(text))
804             {
805                 text = setExtension(text, EXTEN::state);
806                 string name = file::configDir() + "/yoshimi";
807                 name += ("-" + to_string(synth->getUniqueId()));
808                 name += ".state";
809                 if ((text != name)) // never include default state
810                     synth->addHistory(text, TOPLEVEL::XML::State);
811                 text = "ed " + text;
812             }
813             else
814                 text = " FAILED " + text;
815             synth->getRuntime().lastBankPart = UNUSED;
816             newMsg = true;
817             break;
818         case MAIN::control::saveNamedState:
819         {
820             string filename = setExtension(text, EXTEN::state);
821             if (synth->saveState(filename))
822             {
823                 string name = file::configDir() + "/yoshimi";
824                 name += ("-" + to_string(synth->getUniqueId()));
825                 name += ".state";
826                 if ((text != name)) // never include default state
827                     synth->addHistory(filename, TOPLEVEL::XML::State);
828                 text = "d " + text;
829             }
830             else
831                 text = " FAILED " + text;
832             newMsg = true;
833             break;
834         }
835         case MAIN::control::readLastSeen:
836             break; // do nothing here
837         case MAIN::control::loadFileFromList:
838             break; // do nothing here
839 
840         case MAIN::control::defaultPart: // clear part
841             if (write)
842             {
843                 doClearPart(value);
844                 synth->getRuntime().sessionSeen[TOPLEVEL::XML::Instrument] = false;
845                 getData->data.source &= ~TOPLEVEL::action::lowPrio;
846             }
847             break;
848 
849         case MAIN::control::exportPadSynthSamples:
850         {
851             unsigned char partnum = insert;
852             synth->partonoffWrite(partnum, -1);
853             setpadparams(partnum, kititem);
854             if (synth->part[partnum]->kit[kititem].padpars->export2wav(text))
855             {
856                 synth->addHistory(text, TOPLEVEL::XML::PadSample);
857                 text = "d " + text;
858             }
859             else
860                 text = " FAILED some samples " + text;
861             newMsg = true;
862             break;
863         }
864         case MAIN::control::masterReset:
865             synth->resetAll(0);
866             break;
867         case MAIN::control::masterResetAndMlearn:
868             synth->resetAll(1);
869             break;
870         case MAIN::control::openManual: // display user guide
871         {
872             // first try html version
873             text = "";
874             getData->data.control = TOPLEVEL::control::textMessage;
875             string found  = findHtmlManual();
876             if (!found.empty())
877             {
878 
879                 size_t pos = found.rfind("files/yoshimi_user_guide_version");
880                 found = found.substr(0, pos);
881                 file::cmd2string("xdg-open " + found + "index.html &");
882             }
883             else
884                 text = "Can't find manual :(";
885 
886             if (found.empty())
887             {    // fall back to older PDF version
888                 std::string manfile = synth->manualname();
889                 std::string stub = manfile.substr(0, manfile.rfind("-"));
890 
891                 std::string path = "";
892                 std::string lastdir = "";
893                 std::string search = "/usr/share/doc/yoshimi";
894                 path = manualSearch(search, stub);
895                 //std::cout << "name1 " << path << std::endl;
896                 found = path;
897                 lastdir = search;
898 
899                 search = "/usr/local/share/doc/yoshimi";
900                 path = manualSearch(search, stub);
901                 //std::cout << "name2 " << path << std::endl;
902                 if (path >= found)
903                 {
904                     found = path;
905                     lastdir = search;
906                 }
907 
908                 search = localPath();
909                 if (!search.empty())
910                 {
911                     path = manualSearch(search, stub);
912                     //std::cout << "name3 " << path << std::endl;
913                     if (path >= found)
914                     {
915                         found = path;
916                         lastdir = search;
917                     }
918                 }
919 
920                 if (found.empty())
921                 {
922                     getData->data.miscmsg = textMsgBuffer.push("Can't find PDF manual :(");
923                     returnsBuffer.write(getData->bytes);
924                 }
925                 else
926                 {
927                     if (found.substr(0, found.rfind(".")) != manfile)
928                     getData->data.miscmsg = textMsgBuffer.push("Can't find last PDF. Looking for older one");
929                     returnsBuffer.write(getData->bytes);
930                 }
931                 std::string command = "xdg-open " + lastdir + "/" + found + "&";
932                 if (!file::cmd2string(command))
933                 {
934                     getData->data.miscmsg = textMsgBuffer.push("Can't find PDF reader :(");
935                     returnsBuffer.write(getData->bytes);
936                     found = "";
937                 }
938             }
939             if (!found.empty())
940             {
941                 text = "";
942                 getData->data.miscmsg = NO_MSG;
943                 returnsBuffer.write(getData->bytes);
944             }
945             newMsg = true;
946             break;
947 
948         }
949         case MAIN::control::startInstance:
950             if (synth == firstSynth)
951             {
952                 if (value > 0 && value < 32)
953                     startInstance = value | 0x80;
954                 else
955                     startInstance = 0x81; // next available
956                 while (startInstance > 0x80)
957                     usleep(1000);
958                 value = startInstance; // actual instance found
959                 startInstance = 0; // just to be sure
960             }
961             break;
962         case MAIN::control::stopInstance:
963             text = std::to_string(value) + " ";
964             if (value < 0 || value >= 32)
965                 text += "Out of range";
966             else
967             {
968                 SynthEngine *toClose = firstSynth->getSynthFromId(value);
969                 if (toClose == firstSynth && value > 0)
970                     text += "Can't find";
971                 else
972                 {
973                     toClose->getRuntime().runSynth = false;
974                     text += "Closed";
975                 }
976             }
977             newMsg = true;
978             break;
979 
980         case MAIN::control::stopSound:
981 #ifdef REPORT_NOTES_ON_OFF
982             // note test
983             synth->getRuntime().Log("note on sent " + std::to_string(synth->getRuntime().noteOnSent));
984             synth->getRuntime().Log("note on seen " + std::to_string(synth->getRuntime().noteOnSeen));
985             synth->getRuntime().Log("note off sent " + std::to_string(synth->getRuntime().noteOffSent));
986             synth->getRuntime().Log("note off seen " + std::to_string(synth->getRuntime().noteOffSeen));
987             synth->getRuntime().Log("notes hanging sent " + std::to_string(synth->getRuntime().noteOnSent - synth->getRuntime().noteOffSent));
988             synth->getRuntime().Log("notes hanging seen " + std::to_string(synth->getRuntime().noteOnSeen - synth->getRuntime().noteOffSeen));
989 #endif
990             synth->ShutUp();
991             break;
992     }
993     getData->data.source &= ~TOPLEVEL::action::lowPrio;
994     if (control != MAIN::control::startInstance && control != MAIN::control::stopInstance)
995         guiTo = true;
996     return value;
997 }
998 
999 
1000 
indirectBank(CommandBlock * getData,SynthEngine * synth,unsigned char & newMsg,bool & guiTo,std::string & text)1001 int InterChange::indirectBank(CommandBlock *getData, SynthEngine *synth, unsigned char &newMsg, bool &guiTo, std::string &text)
1002 {
1003     bool write = (getData->data.type & TOPLEVEL::type::Write);
1004     int value = getData->data.value;
1005     int control = getData->data.control;
1006     int kititem = getData->data.kit;
1007     int engine = getData->data.engine;
1008     int insert = getData->data.insert;
1009     int parameter = getData->data.parameter;
1010     switch (control)
1011     {
1012         case BANK::control::renameInstrument:
1013         {
1014             if (kititem == UNUSED)
1015             {
1016                 kititem = synth->getRuntime().currentBank;
1017                 getData->data.kit = kititem;
1018             }
1019             if (engine == UNUSED)
1020             {
1021                 engine = synth->getRuntime().currentRoot;
1022                 getData->data.engine = engine;
1023             }
1024             int msgID = synth->bank.setInstrumentName(text, insert, kititem, engine);
1025             if (msgID > NO_MSG)
1026                 text = " FAILED ";
1027             else
1028                 text = " ";
1029             text += textMsgBuffer.fetch(msgID & NO_MSG);
1030             synth->getRuntime().lastBankPart = UNUSED;
1031             newMsg = true;
1032             break;
1033         }
1034         case BANK::control::saveInstrument:
1035         {
1036             if (kititem == UNUSED)
1037             {
1038                 kititem = synth->getRuntime().currentBank;
1039                 getData->data.kit = kititem;
1040             }
1041             if (engine == UNUSED)
1042             {
1043                 engine = synth->getRuntime().currentRoot;
1044                 getData->data.engine = engine;
1045             }
1046             if (parameter == UNUSED)
1047             {
1048                 parameter = synth->getRuntime().currentPart;
1049                 getData->data.parameter = parameter;
1050             }
1051             text = synth->part[parameter]->Pname;
1052             if (text == DEFAULT_NAME)
1053                 text = "FAILED Can't save default instrument type";
1054             else if (!synth->bank.savetoslot(engine, kititem, insert, parameter))
1055                 text = "FAILED Could not save " + text + " to " + to_string(insert + 1);
1056             else
1057             { // 0x80 on engine indicates it is a save not a load
1058                 if (synth->getRuntime().bankHighlight)
1059                     synth->getRuntime().lastBankPart = (insert << 15) | (kititem << 8) | engine | 0x80;
1060                 text = "" + to_string(insert + 1) +". " + text;
1061             }
1062             newMsg = true;
1063             break;
1064         }
1065         case BANK::control::deleteInstrument:
1066         {
1067             text  = synth->bank.clearslot(value, synth->getRuntime().currentRoot,  synth->getRuntime().currentBank);
1068             synth->getRuntime().lastBankPart = UNUSED;
1069             newMsg = true;
1070             break;
1071         }
1072 
1073         case BANK::control::selectFirstInstrumentToSwap:
1074         {
1075             if (kititem == UNUSED)
1076             {
1077                 kititem = synth->getRuntime().currentBank;
1078                 getData->data.kit = kititem;
1079             }
1080             if (engine == UNUSED)
1081             {
1082                 engine = synth->getRuntime().currentRoot;
1083                 getData->data.engine = engine;
1084             }
1085             swapInstrument1 = insert;
1086             swapBank1 = kititem;
1087             swapRoot1 = engine;
1088             break;
1089         }
1090         case BANK::control::selectSecondInstrumentAndSwap:
1091         {
1092             if (kititem == UNUSED)
1093             {
1094                 kititem = synth->getRuntime().currentBank;
1095                 getData->data.kit = kititem;
1096             }
1097             if (engine == UNUSED)
1098             {
1099                 engine = synth->getRuntime().currentRoot;
1100                 getData->data.engine = engine;
1101             }
1102             text = synth->bank.swapslot(swapInstrument1, insert, swapBank1, kititem, swapRoot1, engine);
1103             swapInstrument1 = UNUSED;
1104             swapBank1 = UNUSED;
1105             swapRoot1 = UNUSED;
1106             synth->getRuntime().lastBankPart = UNUSED;
1107             newMsg = true;
1108             guiTo = true;
1109             break;
1110         }
1111         case BANK::control::selectBank:
1112             if (engine == UNUSED)
1113                 engine = getData->data.engine = synth->getRuntime().currentRoot;
1114             if (write)
1115             {
1116                 text = textMsgBuffer.fetch(synth->setRootBank(engine, value) & NO_MSG);
1117 
1118             }
1119             else
1120             {
1121                 int tmp = synth->getRuntime().currentBank;
1122                 text = "Current: " +(to_string(tmp)) + " " + synth->bank.getBankName(tmp, getData->data.engine);
1123             }
1124             newMsg = true;
1125             break;
1126         case BANK::control::renameBank:
1127             if (engine == UNUSED)
1128                 engine = getData->data.engine = synth->getRuntime().currentRoot;
1129             if (write)
1130             {
1131                 int tmp = synth->bank.changeBankName(getData->data.engine, value, text);
1132                 text = textMsgBuffer.fetch(tmp & NO_MSG);
1133                 if (tmp > NO_MSG)
1134                     text = "FAILED: " + text;
1135                 guiTo = true;
1136             }
1137             else
1138             {
1139                 text = " Name: " + synth->bank.getBankName(value, getData->data.engine);
1140             }
1141             newMsg = true;
1142             break;
1143         case BANK::control::createBank:
1144             {
1145                 bool isOK = true;
1146                 int newbank = kititem;
1147                 int rootID = engine;
1148                 if (rootID == UNUSED)
1149                     rootID = synth->getRuntime().currentRoot;
1150                 if (newbank == UNUSED)
1151                 {
1152                     isOK = false;
1153                     newbank = 5; // offset to avoid zero for as long as possible
1154                     for (int i = 0; i < MAX_BANKS_IN_ROOT; ++i)
1155                     {
1156                         newbank = (newbank + 5) & 0x7f;
1157                         if (synth->getBankRef().getBankName(newbank, rootID).empty())
1158                         {
1159                             isOK = true;
1160                             break;
1161                         }
1162                     }
1163                     if (!isOK)
1164                         text = "FAILED: Root " + to_string(rootID) + " has no space";
1165                 }
1166                 if (isOK)
1167                 {
1168                     string trytext = synth->bank.getBankName(newbank, rootID);
1169                     if (!trytext.empty())
1170                     {
1171                         text = "FAILED: ID " + to_string(newbank) + " already contains " + trytext;
1172                         isOK = false;
1173                     }
1174 
1175                     if (isOK && !synth->getBankRef().newIDbank(text, newbank))
1176                     {
1177                         text = "FAILED Could not create bank " + text + " for ID " + asString(newbank);
1178                         isOK = false;
1179                     }
1180                 }
1181                 if (isOK)
1182                     text = "Created " + text + " at ID " + to_string(newbank) + " in root " + to_string(rootID);
1183                 newMsg = true;
1184                 guiTo = true;
1185             }
1186             break;
1187 
1188         case BANK::control::deleteBank:
1189             break; // not yet!
1190 
1191         case BANK::control::findBankSize:
1192             if (engine == UNUSED)
1193                 engine = synth->getRuntime().currentRoot;
1194             if (synth->bank.getBankName(kititem, engine).empty())
1195                 value = UNUSED;
1196             else
1197                 value = synth->bank.getBankSize(kititem, engine);
1198             break;
1199 
1200         case BANK::control::selectFirstBankToSwap:
1201             if (engine == UNUSED)
1202             {
1203                 engine = synth->getRuntime().currentRoot;
1204                 getData->data.engine = engine;
1205             }
1206             swapBank1 = kititem;
1207             swapRoot1 = engine;
1208             break;
1209         case BANK::control::selectSecondBankAndSwap:
1210             if (engine == UNUSED)
1211             {
1212                 engine = synth->getRuntime().currentRoot;
1213                 getData->data.engine = engine;
1214             }
1215             text = synth->bank.swapbanks(swapBank1, kititem, swapRoot1, engine);
1216             swapBank1 = UNUSED;
1217             swapRoot1 = UNUSED;
1218             newMsg = true;
1219             guiTo = true;
1220             break;
1221 
1222         case BANK::control::selectRoot:
1223             if (write)
1224             {
1225                 int msgID = synth->setRootBank(value, UNUSED);
1226                 if (msgID < NO_MSG)
1227                     synth->saveBanks(); // do we need this when only selecting?
1228                 text = textMsgBuffer.fetch(msgID & NO_MSG);
1229             }
1230             else
1231             {
1232                 int tmp = synth->getRuntime().currentRoot;
1233                 text = "Current Root: " +(to_string(tmp)) + " " + synth->bank.getRootPath(tmp);
1234             }
1235             newMsg = true;
1236             break;
1237         case BANK::control::changeRootId:
1238             if (engine == UNUSED)
1239                 getData->data.engine = synth->getRuntime().currentRoot;
1240             synth->bank.changeRootID(getData->data.engine, value);
1241             synth->saveBanks();
1242             break;
1243         case BANK::addNamedRoot:
1244             if (write) // not realistically readable
1245             {
1246                 if (kititem != UNUSED)
1247                 {
1248                     kititem = synth->getBankRef().generateSingleRoot(text, false);
1249                     getData->data.kit = kititem;
1250                     synth->getBankRef().installNewRoot(kititem, text);
1251                     synth->saveBanks();
1252                 }
1253                 else
1254                 {
1255                     size_t found = synth->getBankRef().addRootDir(text);
1256                     if (found)
1257                     {
1258                         synth->getBankRef().installNewRoot(found, text);
1259                         synth->saveBanks();
1260                     }
1261                     else
1262                     {
1263                         value = UNUSED;
1264                         text = "Can't find path " + text;
1265                     }
1266                 }
1267                 newMsg = true;
1268             }
1269             break;
1270         case BANK::deselectRoot:
1271             if (write) // not realistically readable
1272             {
1273                 if (synth->getBankRef().removeRoot(kititem))
1274                     value = UNUSED;
1275                 synth->saveBanks();
1276             }
1277             break;
1278 
1279         case BANK::control::refreshDefaults:
1280             if (value)
1281                 synth->bank.checkLocalBanks();
1282             synth->getRuntime().banksChecked = true;
1283         break;
1284     }
1285     getData->data.source &= ~TOPLEVEL::action::lowPrio;
1286     return value;
1287 }
1288 
1289 
indirectConfig(CommandBlock * getData,SynthEngine * synth,unsigned char & newMsg,bool & guiTo,std::string & text)1290 int InterChange::indirectConfig(CommandBlock *getData, SynthEngine *synth, unsigned char &newMsg, bool &guiTo, std::string &text)
1291 {
1292     bool write = (getData->data.type & TOPLEVEL::type::Write);
1293     int value = getData->data.value;
1294     int control = getData->data.control;
1295     int kititem = getData->data.kit;
1296     switch (control)
1297     {
1298         case CONFIG::control::jackMidiSource:
1299             if (write)
1300             {
1301                 synth->getRuntime().jackMidiDevice = text;
1302                 synth->getRuntime().configChanged = true;
1303             }
1304             else
1305                 text = synth->getRuntime().jackMidiDevice;
1306             newMsg = true;
1307             break;
1308         case CONFIG::control::jackServer:
1309             if (write)
1310             {
1311                 synth->getRuntime().jackServer = text;
1312                 synth->getRuntime().configChanged = true;
1313             }
1314             else
1315                 text = synth->getRuntime().jackServer;
1316             newMsg = true;
1317             break;
1318         case CONFIG::control::alsaMidiSource:
1319             if (write)
1320             {
1321                 synth->getRuntime().alsaMidiDevice = text;
1322                 synth->getRuntime().configChanged = true;
1323             }
1324             else
1325                 text = synth->getRuntime().alsaMidiDevice;
1326             newMsg = true;
1327             break;
1328         case CONFIG::control::alsaAudioDevice:
1329             if (write)
1330             {
1331                 synth->getRuntime().alsaAudioDevice = text;
1332                 synth->getRuntime().configChanged = true;
1333             }
1334             else
1335                 text = synth->getRuntime().alsaAudioDevice;
1336             newMsg = true;
1337             break;
1338         case CONFIG::control::addPresetRootDir:
1339         {
1340             bool isOK = false;
1341             if (isDirectory(text))
1342                 isOK= true;
1343             else
1344             {
1345                 if (createDir(text))
1346                 {
1347                     text = " FAILED could not create " + text;
1348                 }
1349                 else
1350                     isOK = true;
1351             }
1352             if (isOK)
1353             {
1354                 int i = 0;
1355                 while (!firstSynth->getRuntime().presetsDirlist[i].empty())
1356                     ++i;
1357                 if (i > (MAX_PRESETS - 2))
1358                     text = " FAILED preset list full";
1359                 else
1360                 {
1361                     firstSynth->getRuntime().presetsDirlist[i] = text;
1362                     text = "ed " + text;
1363                 }
1364             }
1365             newMsg = true;
1366             synth->getRuntime().configChanged = true;
1367             break;
1368         }
1369         case CONFIG::control::removePresetRootDir:
1370         {
1371             int i = value;
1372             text = firstSynth->getRuntime().presetsDirlist[i];
1373             while (!firstSynth->getRuntime().presetsDirlist[i + 1].empty())
1374             {
1375                 firstSynth->getRuntime().presetsDirlist[i] = firstSynth->getRuntime().presetsDirlist[i + 1];
1376                 ++i;
1377             }
1378             firstSynth->getRuntime().presetsDirlist[i] = "";
1379             synth->getRuntime().currentPreset = 0;
1380             newMsg = true;
1381             synth->getRuntime().configChanged = true;
1382             break;
1383         }
1384         case CONFIG::control::currentPresetRoot:
1385         {
1386             if (write)
1387             {
1388                 synth->getRuntime().currentPreset = value;
1389                 synth->getRuntime().configChanged = true;
1390             }
1391             else
1392                 value = synth->getRuntime().currentPreset = value;
1393             text = firstSynth->getRuntime().presetsDirlist[value];
1394             newMsg = true;
1395             break;
1396         }
1397         case CONFIG::control::saveCurrentConfig:
1398             if (write)
1399             {
1400                 text = synth->getRuntime().ConfigFile;
1401                 if (synth->getRuntime().saveConfig())
1402                     text = "d " + text;
1403                 else
1404                     text = " FAILED " + text;
1405             }
1406             else
1407                 text = "READ";
1408             newMsg = true;
1409             getData->data.miscmsg = textMsgBuffer.push(text); // slightly odd case
1410             break;
1411         case CONFIG::control::historyLock:
1412         {
1413             if (write)
1414             {
1415                 synth->setHistoryLock(kititem, value);
1416                 synth->getRuntime().configChanged = true;
1417             }
1418             else
1419                 value = synth->getHistoryLock(kititem);
1420             break;
1421         }
1422     }
1423     if ((getData->data.source & TOPLEVEL::action::noAction) != TOPLEVEL::action::fromGUI)
1424         guiTo = true;
1425     getData->data.source &= ~TOPLEVEL::action::lowPrio;
1426     return value;
1427 }
1428 
1429 
indirectPart(CommandBlock * getData,SynthEngine * synth,unsigned char & newMsg,bool & guiTo,std::string & text)1430 int InterChange::indirectPart(CommandBlock *getData, SynthEngine *synth, unsigned char &newMsg, bool &guiTo, std::string &text)
1431 {
1432     bool write = (getData->data.type & TOPLEVEL::type::Write);
1433     int value = getData->data.value;
1434     int control = getData->data.control;
1435     int npart = getData->data.part;
1436     int kititem = getData->data.kit;
1437     int parameter = getData->data.parameter;
1438 
1439     Part *part = synth->part[npart];
1440 
1441     switch(control)
1442     {
1443         case PART::control::keyShift:
1444         {
1445             if (write)
1446             {
1447                 part->Pkeyshift = value + 64;
1448                 synth->setPartMap(npart);
1449             }
1450             else
1451                 value = part->Pkeyshift - 64;
1452             getData->data.source &= ~TOPLEVEL::action::lowPrio;
1453         }
1454         break;
1455         case PART::control::enableKitLine:
1456             if (write)
1457             {
1458                 part->setkititemstatus(kititem, value);
1459                 synth->partonoffWrite(npart, 2);
1460                 getData->data.source &= ~TOPLEVEL::action::lowPrio;
1461             }
1462         break;
1463 
1464         case PART::control::enablePad:
1465             if (write)
1466             {
1467                 int temp = kititem;
1468                 if (temp >= NUM_KIT_ITEMS)
1469                     temp = 0;
1470                 setpadparams(npart, temp);
1471                 getData->data.source &= ~TOPLEVEL::action::lowPrio;
1472             }
1473             break;
1474         case PART::control::padsynthParameters:
1475             if (write)
1476             {
1477                 setpadparams(npart, kititem);
1478                 getData->data.source &= ~TOPLEVEL::action::lowPrio;
1479             }
1480             else
1481                 value = part->kit[kititem].padpars->Papplied;
1482             break;
1483 
1484         case PART::control::audioDestination:
1485             if (npart < synth->getRuntime().NumAvailableParts)
1486             {
1487                 if (value & 2)
1488                 {
1489                     mainRegisterAudioPort(synth, npart);
1490                 }
1491                 getData->data.source &= ~TOPLEVEL::action::lowPrio;
1492             }
1493             break;
1494         case PART::control::instrumentCopyright:
1495             if (write)
1496             {
1497                 part->info.Pauthor = text;
1498                 guiTo = true;
1499             }
1500             else
1501                 text = part->info.Pauthor;
1502             getData->data.source &= ~TOPLEVEL::action::lowPrio;
1503             newMsg = true;
1504             break;
1505         case PART::control::instrumentComments:
1506             if (write)
1507             {
1508                 part->info.Pcomments = text;
1509                 guiTo = true;
1510             }
1511             else
1512                 text = part->info.Pcomments;
1513             getData->data.source &= ~TOPLEVEL::action::lowPrio;
1514             newMsg = true;
1515             break;
1516         case PART::control::instrumentName: // part or kit item names
1517             if (kititem == UNUSED)
1518             {
1519                 if (write)
1520                 {
1521                     part->Pname = text;
1522                     if (part->Poriginal.empty())
1523                         part->Poriginal = text;
1524                     guiTo = true;
1525                 }
1526                 else
1527                 {
1528                     text = part->Pname;
1529                 }
1530             }
1531             else if (part->Pkitmode)
1532             {
1533                 if (kititem >= NUM_KIT_ITEMS)
1534                     text = " FAILED out of range";
1535                 else
1536                 {
1537                     if (write)
1538                     {
1539                         part->kit[kititem].Pname = text;
1540                         guiTo = true;
1541                     }
1542                     else
1543                     {
1544                         text = part->kit[kititem].Pname;
1545                     }
1546                 }
1547             }
1548             else
1549                 text = " FAILED Not in kit mode";
1550             getData->data.source &= ~TOPLEVEL::action::lowPrio;
1551             newMsg = true;
1552             break;
1553         case PART::control::instrumentType:
1554             if (write)
1555             {
1556                 part->info.Ptype = value;
1557                 guiTo = true;
1558             }
1559             else
1560                 value = part->info.Ptype;
1561             getData->data.source &= ~TOPLEVEL::action::lowPrio;
1562             break;
1563         case PART::control::defaultInstrumentCopyright:
1564             std::string name = file::configDir() + "/copyright.txt";
1565             if (parameter == 0) // load
1566             {
1567                 text = loadText(name); // TODO provide failure warning
1568                 text = func::formatTextLines(text, 54);
1569                 part->info.Pauthor = text;
1570                 guiTo = true;
1571             }
1572             else
1573             {
1574                 text = part->info.Pauthor;
1575                 saveText(text, name);
1576             }
1577             getData->data.source &= ~TOPLEVEL::action::lowPrio;
1578             newMsg = true;
1579             break;
1580     }
1581     return value;
1582 }
1583 
formatScales(std::string text)1584 std::string InterChange::formatScales(std::string text)
1585 {
1586     text.erase(remove(text.begin(), text.end(), ' '), text.end());
1587     std::string delimiters = ",";
1588     size_t current;
1589     size_t next = -1;
1590     size_t found;
1591     std::string word;
1592     std::string newtext = "";
1593     do
1594     {
1595         current = next + 1;
1596         next = text.find_first_of(delimiters, current );
1597         word = text.substr(current, next - current );
1598 
1599         found = word.find('.');
1600         if (found != string::npos)
1601         {
1602             if (found < 4)
1603             {
1604                 std::string tmp (4 - found, '0'); // leading zeros
1605                 word = tmp + word;
1606             }
1607             found = word.size();
1608             if (found < 11)
1609             {
1610                 std::string tmp  (11 - found, '0'); // trailing zeros
1611                 word += tmp;
1612             }
1613         }
1614         newtext += word;
1615         if (next != string::npos)
1616             newtext += "\n";
1617     }
1618     while (next != string::npos);
1619     return newtext;
1620 }
1621 
1622 
readAllData(CommandBlock * getData)1623 float InterChange::readAllData(CommandBlock *getData)
1624 {
1625     if (getData->data.type & TOPLEVEL::type::Limits) // these are static
1626     {
1627         /*
1628          * commandtype limits values
1629          * 0    adjusted input value
1630          * 1    min
1631          * 2    max
1632          * 3    default
1633          *
1634          * tryData.data.type will be updated:
1635          * bit 5 set    MIDI-learnable
1636          * bit 7 set    Is an integer value
1637          */
1638         getData->data.type -= TOPLEVEL::type::Limits;
1639         float value = returnLimits(getData);
1640         synth->getRuntime().finishedCLI = true;
1641         return value;
1642     }
1643 
1644     // these are not!
1645 
1646     /*
1647      * VU always responds even when loading a *huge*
1648      * PadSynth instrument. This is safe because the part
1649      * being changed is disabled, so won't be seen.
1650      *
1651      * Other reads will be blocked.
1652      * This needs improving.
1653      */
1654     CommandBlock tryData;
1655     unsigned char control = getData->data.control;
1656     if (getData->data.part == TOPLEVEL::section::main && (control >= MAIN::control::readPartPeak && control <= MAIN::control::readMainLRrms))
1657     {
1658         commandSendReal(getData);
1659         synth->fetchMeterData();
1660         return getData->data.value;
1661     }
1662     int npart = getData->data.part;
1663     bool indirect = ((getData->data.source & TOPLEVEL::action::muteAndLoop) == TOPLEVEL::action::lowPrio);
1664     if (npart < NUM_MIDI_PARTS && synth->part[npart]->busy)
1665     {
1666         getData->data.control = PART::control::partBusy; // part busy message
1667         getData->data.kit = UNUSED;
1668         getData->data.engine = UNUSED;
1669         getData->data.insert = UNUSED;
1670     }
1671     reTry:
1672     memcpy(tryData.bytes, getData->bytes, sizeof(tryData));
1673     while (syncWrite || lowPrioWrite)
1674         usleep(10);
1675     if (indirect)
1676     {
1677         /*
1678          * This still isn't quite right there is a very
1679          * remote chance of getting garbled text :(
1680          */
1681         indirectTransfers(&tryData, true);
1682         synth->getRuntime().finishedCLI = true;
1683         return tryData.data.value;
1684     }
1685     else
1686         commandSendReal(&tryData);
1687     if (syncWrite || lowPrioWrite)
1688         goto reTry; // it may have changed mid-process
1689 
1690     if ((tryData.data.source & TOPLEVEL::action::noAction) == TOPLEVEL::action::fromCLI)
1691         resolveReplies(&tryData);
1692 
1693 
1694     synth->getRuntime().finishedCLI = true; // in case it misses lines above
1695     return tryData.data.value;
1696 }
1697 
1698 
resolveReplies(CommandBlock * getData)1699 void InterChange::resolveReplies(CommandBlock *getData)
1700 {
1701     if (false)
1702     {
1703         std::cout << "\nType " << int(getData->data.type) << " Action " << int(getData->data.source) << " Control " << int(getData->data.control) << " Value " << getData->data.value
1704         << "\nPart " << int(getData->data.part) << " Kit " << int(getData->data.kit) << " Engine " << int(getData->data.engine)
1705         << "\nInsert " << int(getData->data.insert) << " Parameter " << int(getData->data.parameter) << " Offset " << int(getData->data.offset)
1706         << "\nMiscMsg " << int(getData->data.miscmsg) << " Spare1 " << int(getData->data.spare1) << " Spare0 " << int(getData->data.spare0) << std::endl;
1707     }
1708     unsigned char source = getData->data.source & TOPLEVEL::action::noAction;
1709     // making sure there are no stray top bits.
1710     if (source == TOPLEVEL::action::noAction)
1711     {
1712         // in case it was originally called from CLI
1713         synth->getRuntime().finishedCLI = true;
1714         return; // no further action
1715     }
1716 
1717     if (getData->data.type & TOPLEVEL::type::LearnRequest)
1718     {
1719         synth->midilearn.setTransferBlock(getData);
1720         return;
1721     }
1722 
1723     if (source != TOPLEVEL::action::fromMIDI)
1724         synth->getRuntime().Log(resolveAll(synth, getData, _SYS_::LogNotSerious));
1725 
1726     if (source == TOPLEVEL::action::fromCLI)
1727         synth->getRuntime().finishedCLI = true;
1728 }
1729 
1730 
1731 // This is only used when no valid banks can be found
generateSpecialInstrument(int npart,std::string name)1732 void InterChange::generateSpecialInstrument(int npart, std::string name)
1733 {
1734     synth->part[npart]->Pname = name;
1735     Part *part;
1736     part = synth->part[npart];
1737     part->partefx[0]->changeeffect(1);
1738     part->kit[0].Padenabled = false;
1739     part->kit[0].Psubenabled = true;
1740 
1741     SUBnoteParameters *pars;
1742     pars = part->kit[0].subpars;
1743     pars->Phmag[1] = 75;
1744     pars->Phmag[2] = 40;
1745     pars->Pbandwidth = 60;
1746 }
1747 
1748 
mediate()1749 void InterChange::mediate()
1750 {
1751     CommandBlock getData;
1752     getData.data.control = UNUSED; // No other data element could be read uninitialised
1753     syncWrite = true;
1754     bool more;
1755     do
1756     {
1757         more = false;
1758 #ifndef YOSHIMI_LV2_PLUGIN
1759         if (fromCLI.read(getData.bytes))
1760         {
1761             more = true;
1762             if (getData.data.part != TOPLEVEL::section::midiLearn) // Not special midi-learn message
1763                 commandSend(&getData);
1764             returns(&getData);
1765         }
1766 #endif
1767 #ifdef GUI_FLTK
1768         if (synth->getRuntime().showGui
1769             && fromGUI.read(getData.bytes))
1770         {
1771             more = true;
1772             if (getData.data.part != TOPLEVEL::section::midiLearn) // Not special midi-learn message
1773                 commandSend(&getData);
1774             returns(&getData);
1775         }
1776 #endif
1777         if (fromMIDI.read(getData.bytes))
1778         {
1779             more = true;
1780             if (getData.data.part != TOPLEVEL::section::midiLearn)
1781                 // Normal MIDI message, not special midi-learn message
1782             {
1783                 historyActionCheck(&getData);
1784                 commandSend(&getData);
1785                 returns(&getData);
1786             }
1787 #ifdef GUI_FLTK
1788             else if (synth->getRuntime().showGui
1789                     && getData.data.control == MIDILEARN::control::reportActivity)
1790                 toGUI.write(getData.bytes);
1791 #endif
1792         }
1793         else if (getData.data.control == TOPLEVEL::section::midiLearn)
1794         {
1795 //  we are looking at the MIDI learn control type that any section *except* MIDI can send.
1796             synth->mididecode.midiProcess(getData.data.kit, getData.data.engine, getData.data.insert, false);
1797         }
1798         if (returnsBuffer.read(getData.bytes))
1799         {
1800             returns(&getData);
1801             more = true;
1802         }
1803 
1804          // temporary fix block
1805          // TODO find a better place to put this out of the main process!
1806 
1807         int effpar = synth->getRuntime().effectChange;
1808         if (effpar > 0xffff)
1809         {
1810 #ifdef GUI_FLTK
1811             if (synth->getRuntime().showGui)
1812             {
1813                 CommandBlock effData;
1814                 memset(&effData.bytes, 255, sizeof(effData));
1815                 unsigned char npart = effpar & 0xff;
1816                 unsigned char effnum = (effpar >> 8) & 0xff;
1817                 unsigned char efftype;
1818                 if (npart < NUM_MIDI_PARTS)
1819                 {
1820                     efftype = synth->part[npart]->partefx[effnum]->geteffect();
1821                     effData.data.control = PART::control::effectType;
1822                 }
1823                 else
1824                 {
1825                     effData.data.control = EFFECT::sysIns::effectType;
1826                     if (npart == TOPLEVEL::section::systemEffects)
1827                         efftype = synth->sysefx[effnum]->geteffect();
1828                     else
1829                         efftype = synth->insefx[effnum]->geteffect();
1830                 }
1831                 effData.data.source = TOPLEVEL::action::fromGUI | TOPLEVEL::action::forceUpdate;
1832                 effData.data.type = TOPLEVEL::type::Write;
1833                 effData.data.value = efftype;
1834                 effData.data.part = npart;
1835                 effData.data.engine = effnum;
1836                 toGUI.write(effData.bytes);
1837             }
1838 #endif
1839             synth->getRuntime().effectChange = UNUSED;
1840         } // end of temporary fix
1841 
1842     }
1843     while (more && synth->getRuntime().runSynth);
1844     syncWrite = false;
1845 }
1846 
1847 
1848 /*
1849  * Currently this is only used by MIDI NRPNs but eventually
1850  * be used as a unified way of catching all list loads.
1851  */
historyActionCheck(CommandBlock * getData)1852 void InterChange::historyActionCheck(CommandBlock *getData)
1853 {
1854     if (getData->data.part != TOPLEVEL::section::main || getData->data.control != MAIN::control::loadFileFromList)
1855         return;
1856     getData->data.type |= TOPLEVEL::type::Write; // just to be sure
1857     switch (getData->data.kit)
1858     {
1859         case TOPLEVEL::XML::Instrument:
1860             getData->data.source |= TOPLEVEL::action::lowPrio;
1861             synth->partonoffWrite((getData->data.insert << 4), -1);
1862             break;
1863         case TOPLEVEL::XML::Patch:
1864             getData->data.source |= TOPLEVEL::action::muteAndLoop;
1865             break;
1866         case TOPLEVEL::XML::Scale:
1867             getData->data.source |= TOPLEVEL::action::lowPrio;
1868             break;
1869         case TOPLEVEL::XML::State:
1870             getData->data.source |= TOPLEVEL::action::muteAndLoop;
1871             break;
1872         case TOPLEVEL::XML::Vector:
1873             getData->data.source |= TOPLEVEL::action::muteAndLoop;
1874             break;
1875     }
1876 }
1877 
1878 
returns(CommandBlock * getData)1879 void InterChange::returns(CommandBlock *getData)
1880 {
1881     synth->getRuntime().finishedCLI = true; // belt and braces :)
1882     if ((getData->data.source & TOPLEVEL::action::noAction) == TOPLEVEL::action::noAction)
1883         return; // no further action
1884 
1885     if (getData->data.source < TOPLEVEL::action::lowPrio)
1886     { // currently only used by gui. this may change!
1887 #ifdef GUI_FLTK
1888         if (synth->getRuntime().showGui)
1889         {
1890             unsigned char type = getData->data.type; // back from synth
1891             int tmp = (getData->data.source & TOPLEVEL::action::noAction);
1892             if (getData->data.source & TOPLEVEL::action::forceUpdate)
1893                 tmp = TOPLEVEL::action::toAll;
1894 
1895             if ((type & TOPLEVEL::type::Write) && tmp != TOPLEVEL::action::fromGUI)
1896                 toGUI.write(getData->bytes);
1897         }
1898 #endif
1899     }
1900     if (!decodeLoopback.write(getData->bytes))
1901         synth->getRuntime().Log("Unable to write to decodeLoopback buffer");
1902 }
1903 
1904 
setpadparams(int npart,int kititem)1905 void InterChange::setpadparams(int npart, int kititem)
1906 {
1907     synth->part[npart]->busy = true;
1908     if (synth->part[npart]->kit[kititem].padpars != NULL)
1909         synth->part[npart]->kit[kititem].padpars->applyparameters();
1910     synth->part[npart]->busy = false;
1911     synth->partonoffWrite(npart, 2);
1912 }
1913 
1914 
doClearPart(int npart)1915 void InterChange::doClearPart(int npart)
1916 {
1917     synth->part[npart]->defaultsinstrument();
1918     synth->part[npart]->cleanup();
1919     synth->getRuntime().currentPart = npart;
1920     synth->partonoffWrite(npart, 2);
1921 }
1922 
commandSend(CommandBlock * getData)1923 bool InterChange::commandSend(CommandBlock *getData)
1924 {
1925     bool isChanged = commandSendReal(getData);
1926     bool isWrite = (getData->data.type & TOPLEVEL::type::Write) > 0;
1927     if (isWrite && isChanged) //write command
1928     {
1929         synth->setNeedsSaving(true);
1930         unsigned char control = getData->data.control;
1931         unsigned char npart = getData->data.part;
1932         unsigned char insert = getData->data.insert;
1933         if (npart < NUM_MIDI_PARTS && (insert != UNUSED || (control != PART::control::enable && control != PART::control::instrumentName)))
1934         {
1935             if (synth->part[npart]->Pname == DEFAULT_NAME)
1936             {
1937                 synth->part[npart]->Pname = UNTITLED;
1938                 getData->data.source |= TOPLEVEL::action::forceUpdate;
1939             }
1940         }
1941     }
1942     return isChanged;
1943 }
1944 
1945 
commandSendReal(CommandBlock * getData)1946 bool InterChange::commandSendReal(CommandBlock *getData)
1947 {
1948     unsigned char npart = getData->data.part;
1949     if (npart == TOPLEVEL::section::midiIn) // music input takes priority!
1950     {
1951         commandMidi(getData);
1952         return false;
1953     }
1954     if (getData->data.control == TOPLEVEL::control::forceExit)
1955     {
1956         getData->data.source = TOPLEVEL::action::noAction;
1957         firstSynth->getRuntime().exitType = FORCED_EXIT;
1958         firstSynth->getRuntime().runSynth = false;
1959         return false;
1960     }
1961 
1962     if ((getData->data.source & TOPLEVEL::action::muteAndLoop) == TOPLEVEL::action::lowPrio)
1963         return true; // indirect transfer
1964 
1965     unsigned char type = getData->data.type;
1966     unsigned char control = getData->data.control;
1967     unsigned char kititem = getData->data.kit;
1968     unsigned char engine = getData->data.engine;
1969     unsigned char insert = getData->data.insert;
1970 
1971     bool isGui = ((getData->data.source & TOPLEVEL::action::noAction) == TOPLEVEL::action::fromGUI);
1972     char button = type & 3;
1973 
1974     if (!isGui && button == 1)
1975     {
1976         return false;
1977     }
1978 
1979     if (npart == TOPLEVEL::section::vector)
1980     {
1981         commandVector(getData);
1982         return true;
1983     }
1984     if (npart == TOPLEVEL::section::scales)
1985     {
1986         commandMicrotonal(getData);
1987         return true;
1988     }
1989     if (npart == TOPLEVEL::section::config)
1990     {
1991         commandConfig(getData);
1992         return true;
1993     }
1994     if (npart == TOPLEVEL::section::main)
1995     {
1996         commandMain(getData);
1997         return true;
1998     }
1999     if (npart == TOPLEVEL::section::bank)
2000     {
2001         commandBank(getData);
2002         return true;
2003     }
2004 
2005 
2006     if ((npart == TOPLEVEL::section::systemEffects || npart == TOPLEVEL::section::insertEffects) && kititem == UNUSED)
2007     {
2008         commandSysIns(getData);
2009         return true;
2010     }
2011     if (kititem >= EFFECT::type::none && kititem <= EFFECT::type::dynFilter)
2012     {
2013         commandEffects(getData);
2014         return true;
2015     }
2016 
2017     if (npart >= NUM_MIDI_PARTS)
2018     {
2019         return false; // invalid part number
2020     }
2021 
2022     if (kititem >= NUM_KIT_ITEMS && kititem != UNUSED)
2023     {
2024         return false; // invalid kit number
2025     }
2026 
2027     Part *part = synth->part[npart];
2028     if (part->busy && engine == PART::engine::padSynth)
2029     {
2030         getData->data.type &= ~TOPLEVEL::type::Write; // turn it into a read
2031         getData->data.control = PART::control::partBusy;
2032         getData->data.kit = UNUSED;
2033         getData->data.engine = UNUSED;
2034         getData->data.insert = UNUSED;
2035         return false;
2036     }
2037     if (control == PART::control::partBusy)
2038     {
2039         getData->data.value = part->busy;
2040         return false;
2041     }
2042     if (kititem == UNUSED || insert == TOPLEVEL::insert::kitGroup)
2043     {
2044         commandPart(getData);
2045         return true;
2046     }
2047 
2048     if (kititem > 0 && kititem != UNUSED)
2049     {
2050         if (part->Pkitmode == 0)
2051             return false;
2052         else if (!part->kit[kititem].Penabled)
2053             return false;
2054     }
2055 
2056     if (engine == PART::engine::addSynth)
2057         return processAdd(getData, synth);
2058 
2059     if (engine == PART::engine::subSynth)
2060         return processSub(getData, synth);
2061 
2062     if (engine == PART::engine::padSynth)
2063         return processPad(getData, synth);
2064 
2065     if (engine >= PART::engine::addVoice1)
2066     {
2067         if ((engine > PART::engine::addVoice8 && engine < PART::engine::addMod1) || engine > PART::engine::addMod8)
2068         {
2069             getData->data.source = TOPLEVEL::action::noAction;
2070             synth->getRuntime().Log("Invalid voice number");
2071             synth->getRuntime().finishedCLI = true;
2072             return false;
2073         }
2074         return processVoice(getData, synth);
2075     }
2076 
2077     getData->data.source = TOPLEVEL::action::noAction;
2078     synth->getRuntime().Log("Invalid engine number");
2079     synth->getRuntime().finishedCLI = true;
2080     return false;
2081 }
2082 
2083 
processAdd(CommandBlock * getData,SynthEngine * synth)2084 bool InterChange::processAdd(CommandBlock *getData, SynthEngine *synth)
2085 {
2086     Part *part = synth->part[getData->data.part];
2087     int kititem = getData->data.kit;
2088     switch(getData->data.insert)
2089     {
2090         case UNUSED:
2091             commandAdd(getData);
2092             part->kit[kititem].adpars->presetsUpdated();
2093             break;
2094         case TOPLEVEL::insert::LFOgroup:
2095             commandLFO(getData);
2096             break;
2097         case TOPLEVEL::insert::filterGroup:
2098             commandFilter(getData);
2099             break;
2100         case TOPLEVEL::insert::envelopeGroup:
2101         case TOPLEVEL::insert::envelopePoints:
2102         case TOPLEVEL::insert::envelopePointChange:
2103             commandEnvelope(getData);
2104             break;
2105         case TOPLEVEL::insert::resonanceGroup:
2106         case TOPLEVEL::insert::resonanceGraphInsert:
2107             commandResonance(getData, part->kit[kititem].adpars->GlobalPar.Reson);
2108             part->kit[kititem].adpars->presetsUpdated();
2109             break;
2110         }
2111     return true;
2112 }
2113 
2114 
processVoice(CommandBlock * getData,SynthEngine * synth)2115 bool InterChange::processVoice(CommandBlock *getData, SynthEngine *synth)
2116 {
2117     Part *part = synth->part[getData->data.part];
2118     int control = getData->data.control;
2119     int kititem = getData->data.kit;
2120     int engine = getData->data.engine;
2121     switch(getData->data.insert)
2122     {
2123         case UNUSED:
2124             commandAddVoice(getData);
2125             part->kit[kititem].adpars->presetsUpdated();
2126             break;
2127         case TOPLEVEL::insert::LFOgroup:
2128             commandLFO(getData);
2129             break;
2130         case TOPLEVEL::insert::filterGroup:
2131             commandFilter(getData);
2132             break;
2133         case TOPLEVEL::insert::envelopeGroup:
2134         case TOPLEVEL::insert::envelopePoints:
2135         case TOPLEVEL::insert::envelopePointChange:
2136             commandEnvelope(getData);
2137             break;
2138         case TOPLEVEL::insert::oscillatorGroup:
2139         case TOPLEVEL::insert::harmonicAmplitude:
2140         case TOPLEVEL::insert::harmonicPhaseBandwidth:
2141             if (engine >= PART::engine::addMod1)
2142             {
2143                 engine -= PART::engine::addMod1;
2144                 if (control != ADDVOICE::control::modulatorOscillatorSource)
2145                 {
2146                     int voicechange = part->kit[kititem].adpars->VoicePar[engine].PextFMoscil;
2147                     if (voicechange != -1)
2148                     {
2149                         engine = voicechange;
2150                         getData->data.engine = engine +  PART::addMod1;
2151                     }   // force it to external mod
2152                 }
2153 
2154                 commandOscillator(getData,  part->kit[kititem].adpars->VoicePar[engine].POscilFM);
2155             }
2156             else
2157             {
2158                 engine -= PART::engine::addVoice1;
2159                 if (control != PART::control::sustainPedalEnable) // how can this ever be true!!!
2160                 {
2161                     int voicechange = part->kit[kititem].adpars->VoicePar[engine].Pextoscil;
2162                     if (voicechange != -1)
2163                     {
2164                         engine = voicechange;
2165                         getData->data.engine = engine | PART::engine::addVoice1;
2166                     }   // force it to external voice
2167                 }
2168                 commandOscillator(getData,  part->kit[kititem].adpars->VoicePar[engine].POscil);
2169             }
2170             part->kit[kititem].adpars->presetsUpdated();
2171             break;
2172     }
2173     return true;
2174 }
2175 
2176 
processSub(CommandBlock * getData,SynthEngine * synth)2177 bool InterChange::processSub(CommandBlock *getData, SynthEngine *synth)
2178 {
2179     Part *part = synth->part[getData->data.part];
2180     int kititem = getData->data.kit;
2181     switch(getData->data.insert)
2182     {
2183         case UNUSED:
2184             commandSub(getData);
2185             part->kit[kititem].subpars->presetsUpdated();
2186             break;
2187         case TOPLEVEL::insert::harmonicAmplitude:
2188             commandSub(getData);
2189             part->kit[kititem].subpars->presetsUpdated();
2190             break;
2191         case TOPLEVEL::insert::harmonicPhaseBandwidth:
2192             commandSub(getData);
2193             part->kit[kititem].subpars->presetsUpdated();
2194             break;
2195         case TOPLEVEL::insert::filterGroup:
2196             commandFilter(getData);
2197             break;
2198         case TOPLEVEL::insert::envelopeGroup:
2199             commandEnvelope(getData);
2200             break;
2201         case TOPLEVEL::insert::envelopePoints:
2202             commandEnvelope(getData);
2203             break;
2204         case TOPLEVEL::insert::envelopePointChange:
2205             commandEnvelope(getData);
2206             break;
2207     }
2208     return true;
2209 }
2210 
2211 
processPad(CommandBlock * getData,SynthEngine * synth)2212 bool InterChange::processPad(CommandBlock *getData, SynthEngine *synth)
2213 {
2214     Part *part = synth->part[getData->data.part];
2215     int kititem = getData->data.kit;
2216     bool needApply = false;
2217     switch(getData->data.insert)
2218     {
2219         case UNUSED:
2220             commandPad(getData);
2221             part->kit[kititem].padpars->presetsUpdated();
2222             break;
2223         case TOPLEVEL::insert::LFOgroup:
2224             commandLFO(getData);
2225             break;
2226         case TOPLEVEL::insert::filterGroup:
2227             commandFilter(getData);
2228             break;
2229         case TOPLEVEL::insert::envelopeGroup:
2230             commandEnvelope(getData);
2231             break;
2232         case TOPLEVEL::insert::envelopePoints:
2233             commandEnvelope(getData);
2234             break;
2235         case TOPLEVEL::insert::envelopePointChange:
2236             commandEnvelope(getData);
2237             break;
2238         case TOPLEVEL::insert::oscillatorGroup:
2239             commandOscillator(getData,  part->kit[kititem].padpars->POscil);
2240             part->kit[kititem].padpars->presetsUpdated();
2241             needApply = true;
2242             break;
2243         case TOPLEVEL::insert::harmonicAmplitude:
2244             commandOscillator(getData,  part->kit[kititem].padpars->POscil);
2245             part->kit[kititem].padpars->presetsUpdated();
2246             needApply = true;
2247             break;
2248         case TOPLEVEL::insert::harmonicPhaseBandwidth:
2249             commandOscillator(getData,  part->kit[kititem].padpars->POscil);
2250             part->kit[kititem].padpars->presetsUpdated();
2251             needApply = true;
2252             break;
2253         case TOPLEVEL::insert::resonanceGroup:
2254             commandResonance(getData, part->kit[kititem].padpars->resonance);
2255             part->kit[kititem].padpars->presetsUpdated();
2256             needApply = true;
2257             break;
2258         case TOPLEVEL::insert::resonanceGraphInsert:
2259             commandResonance(getData, part->kit[kititem].padpars->resonance);
2260             part->kit[kititem].padpars->presetsUpdated();
2261             needApply = true;
2262             break;
2263     }
2264     if (needApply)
2265     {
2266         part->kit[kititem].padpars->Papplied = 0;
2267         getData->data.offset = 0;
2268     }
2269     return true;
2270 }
2271 
2272 
commandMidi(CommandBlock * getData)2273 void InterChange::commandMidi(CommandBlock *getData)
2274 {
2275     int value_int = lrint(getData->data.value);
2276     unsigned char control = getData->data.control;
2277     unsigned char chan = getData->data.kit;
2278     unsigned int char1 = getData->data.engine;
2279     unsigned char miscmsg = getData->data.miscmsg;
2280 
2281     //std::cout << "here MIDI " << control << "  " << value_int << "  " << int(chan) << "  " << int(char1) << std::endl;
2282 
2283     if (control == MIDI::control::controller && char1 >= 0x80)
2284         char1 |= 0x200; // for 'specials'
2285 
2286     switch(control)
2287     {
2288         case MIDI::control::noteOn:
2289             synth->NoteOn(chan, char1, value_int);
2290             synth->getRuntime().finishedCLI = true;
2291             getData->data.source = TOPLEVEL::action::noAction; // till we know what to do!
2292             break;
2293         case MIDI::control::noteOff:
2294             synth->NoteOff(chan, char1);
2295             synth->getRuntime().finishedCLI = true;
2296             getData->data.source = TOPLEVEL::action::noAction; // till we know what to do!
2297             break;
2298         case MIDI::control::controller:
2299             synth->SetController(chan, char1, value_int);
2300             break;
2301 
2302         case MIDI::control::instrument:
2303             getData->data.source |= TOPLEVEL::action::lowPrio;
2304             getData->data.part = TOPLEVEL::section::midiIn;
2305             synth->partonoffLock(chan & 0x3f, -1);
2306             synth->getRuntime().finishedCLI = true;
2307             break;
2308 
2309         case MIDI::control::bankChange:
2310             getData->data.source = TOPLEVEL::action::lowPrio;
2311             if ((value_int != UNUSED || miscmsg != NO_MSG) && chan < synth->getRuntime().NumAvailableParts)
2312             {
2313                 synth->partonoffLock(chan & 0x3f, -1);
2314                 synth->getRuntime().finishedCLI = true;
2315             }
2316             break;
2317     }
2318 }
2319 
2320 
vectorClear(int Nvector)2321 void InterChange::vectorClear(int Nvector)
2322 {
2323     int start;
2324     int end;
2325     if (Nvector >= NUM_MIDI_CHANNELS)
2326     {
2327         start = 0;
2328         end = NUM_MIDI_CHANNELS;
2329     }
2330     else
2331     {
2332         start = Nvector;
2333         end = Nvector + 1;
2334     }
2335     for (int ch = start; ch < end; ++ ch)
2336     {
2337         synth->getRuntime().vectordata.Xaxis[ch] = UNUSED;
2338         synth->getRuntime().vectordata.Yaxis[ch] = UNUSED;
2339         synth->getRuntime().vectordata.Xfeatures[ch] = 0;
2340         synth->getRuntime().vectordata.Yfeatures[ch] = 0;
2341         synth->getRuntime().vectordata.Enabled[ch] = false;
2342         synth->getRuntime().vectordata.Name[ch] = "No Name " + std::to_string(ch + 1);
2343     }
2344 }
2345 
2346 
commandVector(CommandBlock * getData)2347 void InterChange::commandVector(CommandBlock *getData)
2348 {
2349     int value = getData->data.value; // no floats here
2350     unsigned char type = getData->data.type;
2351     unsigned char control = getData->data.control;
2352     unsigned int chan = getData->data.insert;
2353     bool write = (type & TOPLEVEL::type::Write) > 0;
2354 
2355     unsigned int features = 0;
2356 
2357     if (control == VECTOR::control::erase)
2358     {
2359         vectorClear(chan);
2360         return;
2361     }
2362     if (write)
2363     {
2364         if (control >= VECTOR::control::Xfeature0 && control <= VECTOR::control::Xfeature3)
2365             features = synth->getRuntime().vectordata.Xfeatures[chan];
2366         else if (control >= VECTOR::control::Yfeature0 && control <= VECTOR::control::Yfeature3)
2367             features = synth->getRuntime().vectordata.Yfeatures[chan];
2368     }
2369 
2370     switch (control)
2371     {
2372         case 0:
2373             break;
2374         case 1:
2375             if (write)
2376             {
2377                 switch (value)
2378                 {
2379                     case 0:
2380                     case 1:
2381                     case 2: // local to source
2382                         break;
2383                     case 3:
2384                         synth->vectorSet(127, chan, 0);
2385                         break;
2386                     case 4:
2387                         for (int ch = 0; ch < NUM_MIDI_CHANNELS; ++ ch)
2388                             synth->vectorSet(127, ch, 0);
2389                         break;
2390                 }
2391             }
2392             break;
2393 
2394         case VECTOR::control::name:
2395             break; // handled elsewhere
2396 
2397         case VECTOR::control::Xcontroller: // also enable vector
2398             if (write)
2399             {
2400                 if (value >= 14)
2401                 {
2402                     if (!synth->vectorInit(0, chan, value))
2403                         synth->vectorSet(0, chan, value);
2404                     else
2405                         getData->data.value = 0;
2406                 }
2407             }
2408             else
2409             {
2410                 ;
2411             }
2412             break;
2413         case VECTOR::control::XleftInstrument:
2414             if (write)
2415                 synth->vectorSet(4, chan, value);
2416             else
2417             {
2418                 ;
2419             }
2420             break;
2421         case VECTOR::control::XrightInstrument:
2422             if (write)
2423                 synth->vectorSet(5, chan, value);
2424             else
2425             {
2426                 ;
2427             }
2428             break;
2429         case VECTOR::control::Xfeature0:
2430         case VECTOR::control::Yfeature0: // volume
2431             if (write)
2432                 if (value == 0)
2433                     bitClear(features, 0);
2434                 else
2435                     bitSet(features, 0);
2436             else
2437             {
2438                 ;
2439             }
2440             break;
2441         case VECTOR::control::Xfeature1:
2442         case VECTOR::control::Yfeature1: // panning
2443             if (write)
2444             {
2445                 bitClear(features, 1);
2446                 bitClear(features, 4);
2447                 if (value > 0)
2448                 {
2449                     bitSet(features, 1);
2450                     if (value == 2)
2451                         bitSet(features, 4);
2452                 }
2453             }
2454             else
2455             {
2456                 ;
2457             }
2458             break;
2459         case VECTOR::control::Xfeature2:
2460         case VECTOR::control::Yfeature2: // filter cutoff
2461             if (write)
2462             {
2463                 bitClear(features, 2);
2464                 bitClear(features, 5);
2465                 if (value > 0)
2466                 {
2467                     bitSet(features, 2);
2468                     if (value == 2)
2469                         bitSet(features, 5);
2470                 }
2471             }
2472             else
2473             {
2474                 ;
2475             }
2476             break;
2477         case VECTOR::control::Xfeature3:
2478         case VECTOR::control::Yfeature3: // modulation
2479             if (write)
2480             {
2481                 bitClear(features, 3);
2482                 bitClear(features, 6);
2483                 if (value > 0)
2484                 {
2485                     bitSet(features, 3);
2486                     if (value == 2)
2487                         bitSet(features, 6);
2488                 }
2489             }
2490             else
2491             {
2492                 ;
2493             }
2494             break;
2495 
2496         case VECTOR::control::Ycontroller: // also enable Y
2497             if (write)
2498             {
2499                 if (value >= 14)
2500                 {
2501                     if (!synth->vectorInit(1, chan, value))
2502                         synth->vectorSet(1, chan, value);
2503                     else
2504                         getData->data.value = 0;
2505                 }
2506             }
2507             else
2508             {
2509                 ;
2510             }
2511             break;
2512         case VECTOR::control::YupInstrument:
2513             if (write)
2514                 synth->vectorSet(6, chan, value);
2515             else
2516             {
2517                 ;
2518             }
2519             break;
2520         case VECTOR::control::YdownInstrument:
2521             if (write)
2522                 synth->vectorSet(7, chan, value);
2523             else
2524             {
2525                 ;
2526             }
2527             break;
2528     }
2529 
2530     if (write)
2531     {
2532         if (control >= VECTOR::control::Xfeature0 && control <= VECTOR::control::Xfeature3)
2533             synth->getRuntime().vectordata.Xfeatures[chan] = features;
2534         else if (control >= VECTOR::control::Yfeature0 && control <= VECTOR::control::Yfeature3)
2535             synth->getRuntime().vectordata.Yfeatures[chan] = features;
2536     }
2537 }
2538 
2539 
commandMicrotonal(CommandBlock * getData)2540 void InterChange::commandMicrotonal(CommandBlock *getData)
2541 {
2542     float value = getData->data.value;
2543     unsigned char type = getData->data.type;
2544     unsigned char control = getData->data.control;
2545 
2546     bool write = (type & TOPLEVEL::type::Write) > 0;
2547 
2548     int value_int = lrint(value);
2549     bool value_bool = _SYS_::F2B(value);
2550 
2551     switch (control)
2552     {
2553         case SCALES::control::refFrequency:
2554             if (write)
2555             {
2556                 if (value > 2000)
2557                     value = 2000;
2558                 else if (value < 1)
2559                     value = 1;
2560                 synth->microtonal.PrefFreq = value;
2561             }
2562             else
2563                 value = synth->microtonal.PrefFreq;
2564             getData->data.parameter = synth->microtonal.PrefNote;
2565             break;
2566 
2567         case SCALES::control::refNote:
2568             if (write)
2569                 synth->microtonal.PrefNote = value_int;
2570             else
2571                 value = synth->microtonal.PrefNote;
2572             break;
2573         case SCALES::control::invertScale:
2574             if (write)
2575                 synth->microtonal.Pinvertupdown = value_bool;
2576             else
2577                 value = synth->microtonal.Pinvertupdown;
2578             break;
2579         case SCALES::control::invertedScaleCenter:
2580             if (write)
2581                 synth->microtonal.Pinvertupdowncenter = value_int;
2582             else
2583                 value = synth->microtonal.Pinvertupdowncenter;
2584             break;
2585         case SCALES::control::scaleShift:
2586             if (write)
2587                 synth->microtonal.Pscaleshift = value_int + 64;
2588             else
2589                 value = synth->microtonal.Pscaleshift - 64;
2590             break;
2591 
2592         case SCALES::control::enableMicrotonal:
2593             if (write)
2594                 synth->microtonal.Penabled = value_bool;
2595             else
2596                 value = synth->microtonal.Penabled;
2597             break;
2598 
2599         case SCALES::control::enableKeyboardMap:
2600             if (write)
2601                 synth->microtonal.Pmappingenabled = value_bool;
2602             else
2603                value = synth->microtonal.Pmappingenabled;
2604             break;
2605         case SCALES::control::lowKey:
2606             if (write)
2607             {
2608                 if (value_int < 0)
2609                 {
2610                     value_int = 0;
2611                     getData->data.value = value_int;
2612                 }
2613                 else if (value_int >= synth->microtonal.Pmiddlenote)
2614                 {
2615                     value_int = synth->microtonal.Pmiddlenote - 1;
2616                     getData->data.value = value_int;
2617                 }
2618                 synth->microtonal.Pfirstkey = value_int;
2619             }
2620             else
2621                 value = synth->microtonal.Pfirstkey;
2622             break;
2623         case SCALES::control::middleKey:
2624             if (write)
2625             {
2626                 if (value_int <= synth->microtonal.Pfirstkey)
2627                 {
2628                     value_int = synth->microtonal.Pfirstkey + 1;
2629                     getData->data.value = value_int;
2630                 }
2631                 else if (value_int >= synth->microtonal.Plastkey)
2632                 {
2633                     value_int = synth->microtonal.Plastkey - 1;
2634                     getData->data.value = value_int;
2635                 }
2636                 synth->microtonal.Pmiddlenote = value_int;
2637             }
2638             else
2639                 value = synth->microtonal.Pmiddlenote;
2640             break;
2641         case SCALES::control::highKey:
2642             if (write)
2643             {
2644                 if (value_int <= synth->microtonal.Pmiddlenote)
2645                 {
2646                     value_int = synth->microtonal.Pmiddlenote + 1;
2647                     getData->data.value = value_int;
2648                 }
2649                 else if (value_int > 127)
2650                 {
2651                     value_int = 127;
2652                     getData->data.value = value_int;
2653                 }
2654                 synth->microtonal.Plastkey = value_int;
2655             }
2656             else
2657                 value = synth->microtonal.Plastkey;
2658             break;
2659 
2660         case SCALES::control::tuning:
2661             // done elsewhere
2662             break;
2663         case SCALES::control::keyboardMap:
2664             // done elsewhere
2665             break;
2666 
2667         case SCALES::control::importScl:
2668             // done elsewhere
2669             break;
2670         case SCALES::control::importKbm:
2671             // done elsewhere
2672             break;
2673 
2674         case SCALES::control::name:
2675             // done elsewhere
2676             break;
2677         case SCALES::control::comment:
2678             // done elsewhere
2679             break;
2680 
2681         case SCALES::control::retune:
2682             // done elsewhere
2683             break;
2684         case SCALES::control::clearAll: // Clear scales
2685             synth->microtonal.defaults();
2686             break;
2687     }
2688 
2689     if (!write)
2690         getData->data.value = value;
2691 }
2692 
2693 
commandConfig(CommandBlock * getData)2694 void InterChange::commandConfig(CommandBlock *getData)
2695 {
2696     float value = getData->data.value;
2697     unsigned char type = getData->data.type;
2698     unsigned char control = getData->data.control;
2699 
2700     bool write = (type & TOPLEVEL::type::Write) > 0;
2701 
2702     bool mightChange = true;
2703     int value_int = lrint(value);
2704     bool value_bool = _SYS_::F2B(value);
2705 
2706     switch (control)
2707     {
2708 // main
2709         case CONFIG::control::oscillatorSize:
2710             if (write)
2711             {
2712                 value = nearestPowerOf2(value_int, MIN_OSCIL_SIZE, MAX_OSCIL_SIZE);
2713                 getData->data.value = value;
2714                 synth->getRuntime().Oscilsize = value;
2715             }
2716             else
2717                 value = synth->getRuntime().Oscilsize;
2718             break;
2719         case CONFIG::control::bufferSize:
2720             if (write)
2721             {
2722                 value = nearestPowerOf2(value_int, MIN_BUFFER_SIZE, MAX_BUFFER_SIZE);
2723                 getData->data.value = value;
2724                 synth->getRuntime().Buffersize = value;
2725             }
2726             else
2727                 value = synth->getRuntime().Buffersize;
2728             break;
2729         case CONFIG::control::padSynthInterpolation:
2730             if (write)
2731                  synth->getRuntime().Interpolation = value_bool;
2732             else
2733                 value = synth->getRuntime().Interpolation;
2734             break;
2735         case CONFIG::control::virtualKeyboardLayout:
2736             if (write)
2737                  synth->getRuntime().VirKeybLayout = value_int;
2738             else
2739                 value = synth->getRuntime().VirKeybLayout;
2740             break;
2741         case CONFIG::control::XMLcompressionLevel:
2742             if (write)
2743                  synth->getRuntime().GzipCompression = value_int;
2744             else
2745                 value = synth->getRuntime().GzipCompression;
2746             break;
2747         case CONFIG::control::reportsDestination:
2748             if (write)
2749                  synth->getRuntime().toConsole = value_bool;
2750             else
2751                 value = synth->getRuntime().toConsole;
2752             break;
2753         case CONFIG::control::logTextSize:
2754             if (write)
2755                  synth->getRuntime().consoleTextSize = value_int;
2756             else
2757                 value = synth->getRuntime().consoleTextSize;
2758             break;
2759         case CONFIG::control::savedInstrumentFormat:
2760             if (write)
2761                  synth->getRuntime().instrumentFormat = value_int;
2762             else
2763                 value = synth->getRuntime().instrumentFormat;
2764             break;
2765 // switches
2766         case CONFIG::control::defaultStateStart:
2767             if (write)
2768                 synth->getRuntime().loadDefaultState = value_bool;
2769             else
2770                 value = synth->getRuntime().loadDefaultState;
2771             break;
2772         case CONFIG::control::hideNonFatalErrors:
2773             if (write)
2774                 synth->getRuntime().hideErrors = value_bool;
2775             else
2776                 value = synth->getRuntime().hideErrors;
2777             break;
2778         case CONFIG::control::showSplash:
2779             if (write)
2780                 synth->getRuntime().showSplash = value_bool;
2781             else
2782                 value = synth->getRuntime().showSplash;
2783             break;
2784         case CONFIG::control::logInstrumentLoadTimes:
2785             if (write)
2786                 synth->getRuntime().showTimes = value_bool;
2787             else
2788                 value = synth->getRuntime().showTimes;
2789             break;
2790         case CONFIG::control::logXMLheaders:
2791             if (write)
2792                 synth->getRuntime().logXMLheaders = value_bool;
2793             else
2794                 value = synth->getRuntime().logXMLheaders;
2795             break;
2796         case CONFIG::control::saveAllXMLdata:
2797             if (write)
2798                 synth->getRuntime().xmlmax = value_bool;
2799             else
2800                 value = synth->getRuntime().xmlmax;
2801             break;
2802         case CONFIG::control::enableGUI:
2803             if (write)
2804                 synth->getRuntime().showGui = value_bool;
2805             else
2806                 value = synth->getRuntime().showGui;
2807             break;
2808         case CONFIG::control::enableCLI:
2809             if (write)
2810                 synth->getRuntime().showCli = value_bool;
2811             else
2812                 value = synth->getRuntime().showCli;
2813             break;
2814         case CONFIG::control::enableAutoInstance:
2815             if (write)
2816                 synth->getRuntime().autoInstance = value_bool;
2817             else
2818                 value = synth->getRuntime().autoInstance;
2819             break;
2820         case CONFIG::control::enableSinglePath:
2821             if (write)
2822                 synth->getRuntime().singlePath = value;
2823             else
2824                 value = synth->getRuntime().singlePath;
2825             break;
2826         case CONFIG::control::enableHighlight:
2827             if (write)
2828                 synth->getRuntime().bankHighlight = value;
2829             else
2830                 value = synth->getRuntime().bankHighlight;
2831             break;
2832         case CONFIG::control::exposeStatus:
2833             if (write)
2834                 firstSynth->getRuntime().showCLIcontext = value_int;
2835             else
2836                 value = firstSynth->getRuntime().showCLIcontext;
2837             break;
2838 
2839         case CONFIG::control::readAudio:
2840             value = int(synth->getRuntime().audioEngine);
2841             break;
2842         case CONFIG::control::readMIDI:
2843             value = int(synth->getRuntime().midiEngine);
2844             break;
2845 // jack
2846         case CONFIG::control::jackMidiSource: // done elsewhere
2847             break;
2848         case CONFIG::control::jackPreferredMidi:
2849             if (write)
2850             {
2851                 if (value_bool)
2852                     synth->getRuntime().midiEngine = jack_midi;
2853                 else
2854                     synth->getRuntime().midiEngine = alsa_midi;
2855             }
2856             else
2857                 value = (synth->getRuntime().midiEngine == jack_midi);
2858             break;
2859         case CONFIG::control::jackServer: // done elsewhere
2860             break;
2861         case CONFIG::control::jackPreferredAudio:
2862             if (write)
2863             {
2864                 if (value_bool)
2865                     synth->getRuntime().audioEngine = jack_audio;
2866                 else
2867                     synth->getRuntime().audioEngine = alsa_audio;
2868             }
2869             else
2870                 value = (synth->getRuntime().audioEngine == jack_audio);
2871             break;
2872         case CONFIG::control::jackAutoConnectAudio:
2873             if (write)
2874             {
2875                 synth->getRuntime().connectJackaudio = value_bool;
2876                 synth->getRuntime().audioEngine = jack_audio;
2877             }
2878             else
2879                 value = synth->getRuntime().connectJackaudio;
2880             break;
2881 // alsa
2882         case CONFIG::control::alsaMidiSource: // done elsewhere
2883             break;
2884         case CONFIG::control::alsaPreferredMidi:
2885             if (write)
2886             {
2887                 if (value_bool)
2888                     synth->getRuntime().midiEngine = alsa_midi;
2889                 else
2890                     synth->getRuntime().midiEngine = jack_midi;
2891             }
2892             else
2893                 value = (synth->getRuntime().midiEngine == alsa_midi);
2894             break;
2895         case CONFIG::control::alsaMidiType:
2896             if (write)
2897                 synth->getRuntime().alsaMidiType = value_int;
2898             else
2899                 value = synth->getRuntime().alsaMidiType;
2900             break;
2901 
2902         case CONFIG::control::alsaAudioDevice: // done elsewhere
2903             break;
2904         case CONFIG::control::alsaPreferredAudio:
2905             if (write)
2906             {
2907                 if (value_bool)
2908                     synth->getRuntime().audioEngine = alsa_audio;
2909                 else
2910                     synth->getRuntime().audioEngine = jack_audio;
2911             }
2912             else
2913                 value = (synth->getRuntime().audioEngine == alsa_audio);
2914             break;
2915         case CONFIG::control::alsaSampleRate:
2916             if (write)
2917             {
2918                 switch(value_int)
2919                 {
2920                     case 0:
2921                         value = 192000;
2922                         break;
2923                     case 1:
2924                         value = 96000;
2925                         break;
2926                     case 2:
2927                         value = 48000;
2928                         break;
2929                     case 3:
2930                         value = 44100;
2931                         break;
2932                     default:
2933                         value = 44100;
2934                         break;
2935                 }
2936                 synth->getRuntime().Samplerate = value;
2937                 getData->data.value = value;
2938             }
2939             else
2940                 switch(synth->getRuntime().Samplerate)
2941                 {
2942                     case 192000:
2943                         value = 0;
2944                         break;
2945                     case 96000:
2946                         value = 1;
2947                         break;
2948                     case 48000:
2949                         value = 2;
2950                         break;
2951                     case 44100:
2952                         value = 3;
2953                         break;
2954                     default:
2955                         value = 3;
2956                         break;
2957                 }
2958             break;
2959 // midi
2960         case CONFIG::control::bankRootCC:
2961             if (write)
2962             {
2963                 if (value_int != 0 && value_int != 32)
2964                 {
2965                     value_int = 128;
2966                     getData->data.value = value_int;
2967                 }
2968                 synth->getRuntime().midi_bank_root = value_int;
2969             }
2970             else
2971                 value = synth->getRuntime().midi_bank_root;
2972             break;
2973 
2974         case CONFIG::control::bankCC:
2975             if (write)
2976             {
2977                 if (value_int != 0 && value_int != 32)
2978                 {
2979                     value_int = 128;
2980                     getData->data.value = value_int;
2981                 }
2982                 synth->getRuntime().midi_bank_C = value_int;
2983             }
2984             else
2985                 value = synth->getRuntime().midi_bank_C;
2986             break;
2987         case CONFIG::control::enableProgramChange:
2988             if (write)
2989                 synth->getRuntime().EnableProgChange = value_bool;
2990             else
2991                 value = synth->getRuntime().EnableProgChange;
2992             break;
2993         case CONFIG::control::extendedProgramChangeCC:
2994             if (write)
2995             {
2996                 if (value_int > 119)
2997                 {
2998                     value_int = 128;
2999                     getData->data.value = value_int;
3000                 }
3001                 synth->getRuntime().midi_upper_voice_C = value_int;
3002             }
3003             else
3004                 value = synth->getRuntime().midi_upper_voice_C;
3005             break;
3006         case CONFIG::control::ignoreResetAllCCs:
3007             if (write)
3008                 synth->getRuntime().ignoreResetCCs = value_bool;
3009             else
3010                 value = synth->getRuntime().ignoreResetCCs;
3011             break;
3012         case CONFIG::control::logIncomingCCs:
3013             if (write)
3014                 synth->getRuntime().monitorCCin = value_bool;
3015             else
3016                 value = synth->getRuntime().monitorCCin;
3017             break;
3018         case CONFIG::control::showLearnEditor:
3019             if (write)
3020                 synth->getRuntime().showLearnedCC = value_bool;
3021             else
3022                 value = synth->getRuntime().showLearnedCC;
3023             break;
3024         case CONFIG::control::enableNRPNs:
3025             if (write)
3026                 synth->getRuntime().enable_NRPN = value_bool;
3027             else
3028                 value = synth->getRuntime().enable_NRPN;
3029             break;
3030 // save config
3031         case CONFIG::control::saveCurrentConfig: //done elsewhere
3032             break;
3033         default:
3034             mightChange = false;
3035         break;
3036     }
3037     if (!write)
3038         getData->data.value = value;
3039     else if (mightChange)
3040         synth->getRuntime().configChanged = true;
3041 }
3042 
3043 
commandMain(CommandBlock * getData)3044 void InterChange::commandMain(CommandBlock *getData)
3045 {
3046     float value = getData->data.value;
3047     unsigned char type = getData->data.type;
3048     unsigned char action = getData->data.source;
3049     unsigned char control = getData->data.control;
3050     unsigned char kititem = getData->data.kit;
3051     unsigned char engine = getData->data.engine;
3052 
3053     bool write = (type & TOPLEVEL::type::Write) > 0;
3054     int value_int = lrint(value);
3055 
3056     switch (control)
3057     {
3058         case MAIN::control::volume:
3059             if (write)
3060                 synth->setPvolume(value);
3061             else
3062                 value = synth->Pvolume;
3063             break;
3064 
3065         case MAIN::control::partNumber:
3066             if (write)
3067                 synth->getRuntime().currentPart = value_int;
3068             else
3069                 value = synth->getRuntime().currentPart;
3070             break;
3071         case MAIN::control::availableParts:
3072             if ((write) && (value == 16 || value == 32 || value == 64))
3073                 synth->getRuntime().NumAvailableParts = value;
3074             else
3075                 value = synth->getRuntime().NumAvailableParts;
3076             break;
3077         case MAIN::control::panLawType:
3078             if (write)
3079                 synth->getRuntime().panLaw = value_int;
3080             else
3081                 value = synth->getRuntime().panLaw;
3082             break;
3083 
3084 
3085         case MAIN::control::detune: // done elsewhere
3086             break;
3087         case MAIN::control::keyShift: // done elsewhere
3088             break;
3089 
3090         case MAIN::control::mono:
3091             if (write)
3092                 synth->masterMono = value;
3093             else
3094                 value = synth->masterMono;
3095             break;
3096 
3097         case MAIN::control::reseed:
3098             synth->setReproducibleState(int(value));
3099             // std::cout << "rnd " << synth->randomINT() << std::endl;
3100             break;
3101 
3102         case MAIN::control::soloType:
3103             if (write && value_int <= MIDI::SoloType::Channel)
3104             {
3105                 synth->getRuntime().channelSwitchType = value_int;
3106                 synth->getRuntime().channelSwitchCC = 128;
3107                 synth->getRuntime().channelSwitchValue = 0;
3108                 switch (value_int)
3109                 {
3110                     case MIDI::SoloType::Disabled:
3111                         for (int i = 0; i < NUM_MIDI_PARTS; ++i)
3112                             synth->part[i]->Prcvchn = (i & (NUM_MIDI_CHANNELS - 1));
3113                         break;
3114 
3115                     case MIDI::SoloType::Row:
3116                         for (int i = 1; i < NUM_MIDI_CHANNELS; ++i)
3117                             synth->part[i]->Prcvchn = NUM_MIDI_CHANNELS;
3118                         synth->part[0]->Prcvchn = 0;
3119                         break;
3120 
3121                     case MIDI::SoloType::Column:
3122                         for (int i = 0; i < NUM_MIDI_PARTS; ++i)
3123                             synth->part[i]->Prcvchn = (i & (NUM_MIDI_CHANNELS - 1));
3124                         break;
3125 
3126                     case MIDI::SoloType::Loop:
3127                     case MIDI::SoloType::TwoWay:
3128                         for (int i = 0; i < NUM_MIDI_CHANNELS; ++i)
3129                             synth->part[i]->Prcvchn = NUM_MIDI_CHANNELS;
3130                         synth->part[0]->Prcvchn = 0;
3131                         break;
3132 
3133                     case MIDI::SoloType::Channel:
3134                         for (int p = 0; p < NUM_MIDI_PARTS; ++p)
3135                         {
3136                             if (synth->part[p]->Prcvchn >= NUM_MIDI_CHANNELS)
3137                                 synth->part[p]->Prcvchn = p &(NUM_MIDI_CHANNELS - 1);
3138                         }
3139                         break;
3140                 }
3141             }
3142             else
3143             {
3144                 write = false; // for an invalid write attempt
3145                 value = synth->getRuntime().channelSwitchType;
3146             }
3147             break;
3148         case MAIN::control::soloCC:
3149             if (write && synth->getRuntime().channelSwitchType > 0)
3150                 synth->getRuntime().channelSwitchCC = value_int;
3151             else
3152             {
3153                 write = false; // for an invalid write attempt
3154                 value = synth->getRuntime().channelSwitchCC;
3155             }
3156             break;
3157 
3158         case MAIN::control::loadInstrumentFromBank:
3159             synth->partonoffLock(kititem, -1);
3160             getData->data.source |= TOPLEVEL::action::lowPrio;
3161             break;
3162 
3163         case MAIN::control::loadInstrumentByName:
3164             synth->partonoffLock(kititem, -1);
3165             getData->data.source |= TOPLEVEL::action::lowPrio;
3166             break;
3167 
3168         case MAIN::control::loadNamedPatchset:
3169             if (write && ((action & TOPLEVEL::action::muteAndLoop) == TOPLEVEL::action::muteAndLoop))
3170             {
3171                 muteQueueWrite(getData);
3172                 getData->data.source = TOPLEVEL::action::noAction;
3173             }
3174             break;
3175 
3176         case MAIN::control::loadNamedVector:
3177             if (write && ((action & TOPLEVEL::action::muteAndLoop) == TOPLEVEL::action::muteAndLoop))
3178             {
3179                 muteQueueWrite(getData);
3180                 getData->data.source = TOPLEVEL::action::noAction;
3181             }
3182             break;
3183         case MAIN::control::saveNamedVector: // done elsewhere
3184             break;
3185         case MAIN::control::loadNamedScale: // done elsewhere
3186             break;
3187         case MAIN::control::saveNamedScale: // done elsewhere
3188             break;
3189         case MAIN::control::loadNamedState:
3190             if (write && ((action & TOPLEVEL::action::muteAndLoop) == TOPLEVEL::action::muteAndLoop))
3191             {
3192                 muteQueueWrite(getData);
3193                 getData->data.source = TOPLEVEL::action::noAction;
3194             }
3195             break;
3196         case MAIN::control::saveNamedState: // done elsewhere
3197             break;
3198         case MAIN::control::readLastSeen: // read only
3199             value = textMsgBuffer.push(synth->lastItemSeen(value));
3200             break;
3201         case MAIN::control::loadFileFromList:
3202             muteQueueWrite(getData);
3203             getData->data.source = TOPLEVEL::action::noAction;
3204             break;
3205 
3206         case MAIN::control::defaultPart: // doClearPart
3207             if (write)
3208             {
3209                 synth->partonoffWrite(value_int, -1);
3210                 getData->data.source = TOPLEVEL::action::lowPrio;
3211             }
3212             else
3213                 getData->data.source = TOPLEVEL::action::noAction;
3214             break;
3215 
3216         case MAIN::control::masterReset:
3217         case MAIN::control::masterResetAndMlearn:
3218             if (write && ((action & TOPLEVEL::action::muteAndLoop) == TOPLEVEL::action::muteAndLoop))
3219             {
3220                 muteQueueWrite(getData);
3221                 getData->data.source = TOPLEVEL::action::noAction;
3222             }
3223             break;
3224         case MAIN::control::startInstance: // done elsewhere
3225             break;
3226         case MAIN::control::stopInstance: // done elsewhere
3227             break;
3228         case MAIN::control::stopSound: // just stop
3229             if (write)
3230                 muteQueueWrite(getData);
3231             getData->data.source = TOPLEVEL::action::noAction;
3232             break;
3233 
3234         case MAIN::control::readPartPeak:
3235             if (!write && kititem < NUM_MIDI_PARTS)
3236             {
3237                 if (engine == 1)
3238                     value = synth->VUdata.values.partsR[kititem];
3239                 else
3240                     value = synth->VUdata.values.parts[kititem];
3241             }
3242             break;
3243         case MAIN::control::readMainLRpeak:
3244             if (!write)
3245             {
3246                 if (kititem == 1)
3247                     value = synth->VUdata.values.vuOutPeakR;
3248                 else
3249                     value = synth->VUdata.values.vuOutPeakL;
3250             }
3251             break;
3252         case MAIN::control::readMainLRrms:
3253             if (!write)
3254             {
3255                 if (kititem == 1)
3256                     value = synth->VUdata.values.vuRmsPeakR;
3257                 else
3258                     value = synth->VUdata.values.vuRmsPeakL;
3259             }
3260             break;
3261 
3262         case TOPLEVEL::control::textMessage:
3263             getData->data.source = TOPLEVEL::action::noAction;
3264             break;
3265     }
3266 
3267     if (!write)
3268         getData->data.value = value;
3269 }
3270 
3271 
commandBank(CommandBlock * getData)3272 void InterChange::commandBank(CommandBlock *getData)
3273 {
3274     int value_int = int(getData->data.value + 0.5f);
3275     unsigned char type = getData->data.type;
3276     unsigned char control = getData->data.control;
3277     unsigned char kititem = getData->data.kit;
3278     unsigned char engine = getData->data.engine;
3279     unsigned char parameter = getData->data.parameter;
3280 
3281     bool write = (type & TOPLEVEL::type::Write) > 0;
3282 
3283     switch (control)
3284     {
3285         case BANK::control::readInstrumentName:
3286         {
3287             if (kititem == UNUSED)
3288             {
3289                 kititem = synth->getRuntime().currentBank;
3290                 getData->data.kit = kititem;
3291             }
3292             if (engine == UNUSED)
3293             {
3294                 engine = synth->getRuntime().currentRoot;
3295                 getData->data.engine = engine;
3296             }
3297             textMsgBuffer.push(synth->getBankRef().getname(parameter, kititem, engine));
3298             break;
3299         }
3300         case BANK::control::findInstrumentName:
3301         {
3302             if (parameter == UNUSED) // return the name of a specific instrument.
3303                 textMsgBuffer.push(synth->getBankRef().getname(value_int, kititem, engine));
3304             else
3305             {
3306                 int offset = type_offset [parameter];
3307                 /*
3308                  * This version of the call is for building up lists of instruments that match the given type.
3309                  * It will find the next in the series until the entire bank structure has been scanned.
3310                  * It returns the terminator when this has been completed so the calling function knows the
3311                  * entire list has been scanned, and resets ready for a new set of calls.
3312                  */
3313 
3314                 if (offset == -1)
3315                 {
3316                     synth->getRuntime().Log("caught invalid instrument type (-1)");
3317                     textMsgBuffer.push("@end");
3318                 }
3319 
3320                 do {
3321                     do {
3322                         do {
3323                             if (synth->getBankRef().getType(searchInst, searchBank, searchRoot) == offset)
3324                             {
3325                                 textMsgBuffer.push(asString(searchRoot, 3) + ": " + asString(searchBank, 3) + ". " + asString(searchInst + 1, 3) + "  " + synth->getBankRef().getname(searchInst, searchBank, searchRoot));
3326                                 ++ searchInst;
3327                                 return;
3328                                 /*
3329                                  * notice this exit point!
3330                                  */
3331                             }
3332                             ++searchInst;
3333                         } while (searchInst < MAX_INSTRUMENTS_IN_BANK);
3334 
3335                         searchInst = 0;
3336                         ++searchBank;
3337                     } while (searchBank < MAX_BANKS_IN_ROOT);
3338                     searchBank = 0;
3339                     ++searchRoot;
3340                 } while (searchRoot < MAX_BANK_ROOT_DIRS);
3341                 searchRoot = 0;
3342                 textMsgBuffer.push("@end");
3343             }
3344             break;
3345         }
3346         case BANK::control::lastSeenInBank: // read only
3347             value_int = synth->getRuntime().lastBankPart;
3348             break;
3349         case BANK::control::selectBank: // done elsewhere for write
3350             value_int = synth->ReadBank();
3351             break;
3352         case BANK::control::selectRoot:
3353             value_int = synth->getRuntime().currentRoot; // currently read only
3354             break;
3355         default:
3356             getData->data.source = TOPLEVEL::action::noAction;
3357             break;
3358     }
3359 
3360     if (!write)
3361         getData->data.value = value_int;
3362 }
3363 
3364 
commandPart(CommandBlock * getData)3365 void InterChange::commandPart(CommandBlock *getData)
3366 {
3367     float value = getData->data.value;
3368     unsigned char type = getData->data.type;
3369     unsigned char control = getData->data.control;
3370     unsigned char npart = getData->data.part;
3371     unsigned char kititem = getData->data.kit;
3372     unsigned char engine = getData->data.engine;
3373     unsigned char insert = getData->data.insert;
3374 
3375     bool write = (type & TOPLEVEL::type::Write) > 0;
3376 
3377     bool kitType = (insert == TOPLEVEL::insert::kitGroup);
3378 
3379     if (kitType && kititem >= NUM_KIT_ITEMS)
3380     {
3381         getData->data.source = TOPLEVEL::action::noAction;
3382         synth->getRuntime().Log("Invalid kit number");
3383         return;
3384     }
3385     int value_int = lrint(value);
3386     char value_bool = _SYS_::F2B(value);
3387 
3388     Part *part;
3389     part = synth->part[npart];
3390     if (part->Pkitmode == 0)
3391     {
3392         kitType = false;
3393         if (control != PART::control::kitMode && kititem != UNUSED)
3394         {
3395             getData->data.source = TOPLEVEL::action::noAction;
3396             synth->getRuntime().Log("Not in kit mode");
3397         }
3398     }
3399     else if (control != PART::control::enableKitLine && !part->kit[kititem].Penabled && kititem < UNUSED)
3400     {
3401         getData->data.source = TOPLEVEL::action::noAction;
3402         synth->getRuntime().Log("Kit item " +  to_string(kititem + 1) + " not enabled");
3403         return;
3404     }
3405 
3406     unsigned char effNum = part->Peffnum;
3407     if (!kitType)
3408         kititem = 0;
3409 
3410     switch (control)
3411     {
3412         case PART::control::enable:
3413             if (write)
3414             {
3415                 if (value_bool && synth->getRuntime().currentPart != npart) // make it a part change
3416                 {
3417                     synth->partonoffWrite(npart, 1);
3418                     synth->getRuntime().currentPart = npart;
3419                     getData->data.value = npart;
3420                     getData->data.control = MAIN::control::partNumber;
3421                     getData->data.part = TOPLEVEL::section::main;
3422                 }
3423                 else
3424                     synth->partonoffWrite(npart, value_int);
3425             }
3426             else
3427                 value = synth->partonoffRead(npart);
3428             break;
3429         case PART::control::enableAdd:
3430             if (write)
3431                 part->kit[kititem].Padenabled = value_bool;
3432             else
3433                 value = part->kit[kititem].Padenabled;
3434             break;
3435         case PART::control::enableSub:
3436             if (write)
3437                 part->kit[kititem].Psubenabled = value_bool;
3438             else
3439                 value = part->kit[kititem].Psubenabled;
3440             break;
3441         case PART::control::enablePad:
3442             if (write)
3443             {
3444                 part->kit[kititem].Ppadenabled = value_bool;
3445                 if (!part->kit[kititem].padpars->Papplied)
3446                 {
3447                     synth->partonoffWrite(npart, -1);
3448                     getData->data.source = TOPLEVEL::action::lowPrio;
3449                 }
3450             }
3451             else
3452                 value = part->kit[kititem].Ppadenabled;
3453             break;
3454         case PART::control::enableKitLine:
3455             if (write)
3456             {
3457                 synth->partonoffWrite(npart, -1);
3458                 getData->data.source = TOPLEVEL::action::lowPrio;
3459             }
3460             else
3461                 value = part->kit[kititem].Penabled;
3462             break;
3463 
3464         case PART::control::volume:
3465             if (write)
3466                 part->setVolume(value);
3467             else
3468                 value = part->Pvolume;
3469             break;
3470         case PART::control::velocitySense:
3471             if (write)
3472                 part->Pvelsns = value;
3473             else
3474                 value = part->Pvelsns;
3475             break;
3476         case PART::control::panning:
3477             if (write)
3478                 part->SetController(MIDI::CC::panning, value);
3479             else
3480                 value = part->Ppanning;
3481             break;
3482         case PART::control::velocityOffset:
3483             if (write)
3484                 part->Pveloffs = value;
3485             else
3486                 value = part->Pveloffs;
3487             break;
3488         case PART::control::midiChannel:
3489             if (write)
3490                 part->Prcvchn = value_int;
3491             else
3492                 value = part->Prcvchn;
3493             break;
3494         case PART::control::keyMode:
3495             if (write)
3496                 synth->SetPartKeyMode(npart, value_int);
3497             else
3498                 value = (synth->ReadPartKeyMode(npart)) & 3; // clear out temporary legato
3499             break;
3500         case PART::control::channelATset:
3501             if (write)
3502             {
3503                 part->PchannelATchoice = value_int;
3504                 int tmp1, tmp2;
3505                 tmp1 = tmp2 = part->PkeyATchoice;
3506                 tmp1 &= ~value_int;
3507                 if (tmp1 != tmp2)
3508                 {
3509                     part->PkeyATchoice = tmp1; // can't have the same
3510                     getData->data.parameter = tmp1; // send possible correction
3511                 }
3512             }
3513             else
3514                 value = part->PchannelATchoice;
3515             break;
3516         case PART::control::keyATset:
3517             if (write)
3518             {
3519                 part->PkeyATchoice = value_int;
3520                 int tmp1, tmp2;
3521                 tmp1 = tmp2 = part->PchannelATchoice;
3522                 tmp1 &= ~value_int;
3523                 if (tmp1 != tmp2)
3524                 {
3525                     part->PchannelATchoice = tmp1; // can't have the same
3526                     getData->data.parameter = tmp1; // send possible correction
3527                 }
3528             }
3529             else
3530                 value = part->PkeyATchoice;
3531             break;
3532         case PART::control::portamento:
3533             if (write)
3534                 part->ctl->portamento.portamento = value_bool;
3535             else
3536                 value = part->ctl->portamento.portamento;
3537             break;
3538         case PART::control::kitItemMute:
3539             if (kitType)
3540             {
3541                 if (write)
3542                     part->kit[kititem].Pmuted = value_bool;
3543                 else
3544                     value = part->kit[kititem].Pmuted;
3545             }
3546             break;
3547 
3548         case PART::control::minNote: // always return actual value
3549             if (kitType)
3550             {
3551                 if (write)
3552                 {
3553                     if (value_int > part->kit[kititem].Pmaxkey)
3554                         part->kit[kititem].Pminkey = part->kit[kititem].Pmaxkey;
3555                     else
3556                         part->kit[kititem].Pminkey = value_int;
3557                 }
3558                 value = part->kit[kititem].Pminkey;
3559             }
3560             else
3561             {
3562                 if (write)
3563                 {
3564                     if (value_int > part->Pmaxkey)
3565                         part->Pminkey = part->Pmaxkey;
3566                     else
3567                         part->Pminkey = value_int;
3568                 }
3569                 value = part->Pminkey;
3570             }
3571             break;
3572         case PART::control::maxNote: // always return actual value
3573             if (kitType)
3574             {
3575                 if (write)
3576                 {
3577                     if (value_int < part->kit[kititem].Pminkey)
3578                         part->kit[kititem].Pmaxkey = part->kit[kititem].Pminkey;
3579                     else
3580                         part->kit[kititem].Pmaxkey = value_int;
3581                 }
3582                 value = part->kit[kititem].Pmaxkey;
3583             }
3584             else
3585             {
3586                 if (write)
3587                 {
3588                     if (value_int < part->Pminkey)
3589                         part->Pmaxkey = part->Pminkey;
3590                     else
3591                         part->Pmaxkey = value_int;
3592                 }
3593                 value = part->Pmaxkey;
3594             }
3595             break;
3596         case PART::control::minToLastKey: // always return actual value
3597             value_int = part->lastnote;
3598             if (kitType)
3599             {
3600                 if ((write) && value_int >= 0)
3601                 {
3602                     if (value_int > part->kit[kititem].Pmaxkey)
3603                         part->kit[kititem].Pminkey = part->kit[kititem].Pmaxkey;
3604                     else
3605                         part->kit[kititem].Pminkey = part->lastnote;
3606                 }
3607                 value = part->kit[kititem].Pminkey;
3608             }
3609             else
3610             {
3611                 if ((write) && part->lastnote >= 0)
3612                 {
3613                     if (value_int > part->Pmaxkey)
3614                         part->Pminkey = part->Pmaxkey;
3615                     else
3616                         part->Pminkey = part->lastnote;
3617                 }
3618                 value = part->Pminkey;
3619             }
3620             break;
3621         case PART::control::maxToLastKey: // always return actual value
3622             value_int = part->lastnote;
3623             if (kitType)
3624             {
3625                 if ((write) && part->lastnote >= 0)
3626                 {
3627                     if (value_int < part->kit[kititem].Pminkey)
3628                         part->kit[kititem].Pmaxkey = part->kit[kititem].Pminkey;
3629                     else
3630                         part->kit[kititem].Pmaxkey = part->lastnote;
3631                 }
3632                 value = part->kit[kititem].Pmaxkey;
3633             }
3634             else
3635             {
3636                 if ((write) && part->lastnote >= 0)
3637                 {
3638                     if (value_int < part->Pminkey)
3639                         part->Pmaxkey = part->Pminkey;
3640                     else
3641                         part->Pmaxkey = part->lastnote;
3642                 }
3643                 value = part->Pmaxkey;
3644             }
3645             break;
3646         case PART::control::resetMinMaxKey:
3647             if (kitType)
3648             {
3649                 if (write)
3650                 {
3651                     part->kit[kititem].Pminkey = 0;
3652                     part->kit[kititem].Pmaxkey = 127;
3653                 }
3654             }
3655             else
3656             {
3657                 if (write)
3658                 {
3659                     part->Pminkey = 0;
3660                     part->Pmaxkey = 127;
3661                 }
3662             }
3663             break;
3664 
3665         case PART::control::kitEffectNum:
3666             if (kitType)
3667             {
3668                 if (write)
3669                 {
3670                     if (value_int == 0 )
3671                         part->kit[kititem].Psendtoparteffect = 127;
3672                     else
3673                         part->kit[kititem].Psendtoparteffect = value_int - 1;
3674                 }
3675                 else
3676                     value = part->kit[kititem].Psendtoparteffect;
3677             }
3678             break;
3679 
3680         case PART::control::maxNotes:
3681             if (write)
3682             {
3683                 part->Pkeylimit = value_int;
3684                 if (part->Pkeymode == PART_NORMAL)
3685                     part->enforcekeylimit();
3686             }
3687             else
3688                 value = part->Pkeylimit;
3689             break;
3690         case PART::control::keyShift: // done elsewhere
3691             break;
3692 
3693         case PART::control::partToSystemEffect1:
3694             if (write)
3695                 synth->setPsysefxvol(npart,0, value);
3696             else
3697                 value = synth->Psysefxvol[0][npart];
3698             break;
3699         case PART::control::partToSystemEffect2:
3700             if (write)
3701                 synth->setPsysefxvol(npart,1, value);
3702             else
3703                 value = synth->Psysefxvol[1][npart];
3704             break;
3705         case PART::control::partToSystemEffect3:
3706             if (write)
3707                 synth->setPsysefxvol(npart,2, value);
3708             else
3709                 value = synth->Psysefxvol[2][npart];
3710             break;
3711         case PART::control::partToSystemEffect4:
3712             if (write)
3713                 synth->setPsysefxvol(npart,3, value);
3714             else
3715                 value = synth->Psysefxvol[3][npart];
3716             break;
3717 
3718         case PART::control::humanise:
3719             if (write)
3720                 part->Pfrand = value;
3721             else
3722                 value = part->Pfrand;
3723             break;
3724 
3725         case PART::control::humanvelocity:
3726             if (write)
3727                 part->Pvelrand = value;
3728             else
3729                 value = part->Pvelrand;
3730             break;
3731 
3732         case PART::control::drumMode:
3733             if (write)
3734             {
3735                 part->Pdrummode = value_bool;
3736                 synth->setPartMap(npart);
3737             }
3738             else
3739                 value = part->Pdrummode;
3740             break;
3741         case PART::control::kitMode:
3742             if (write)
3743             {
3744                 if (value == 3)
3745                 {
3746                     part->Pkitmode = 1;
3747                     part->Pkitfade = true;
3748                     value = 1; // just to be sure
3749                 }
3750                 else
3751                 {
3752                     part->Pkitfade = false;
3753                     part->Pkitmode = value_int;
3754                 }
3755             }
3756             else
3757             {
3758                 value = part->Pkitmode;
3759                 if (value == 1 && part->Pkitfade == true)
3760                     value = 3;
3761             }
3762             break;
3763 
3764         case PART::control::effectNumber:
3765             if (write)
3766             {
3767                 part->Peffnum = value_int;
3768                 getData->data.parameter = (part->partefx[value_int]->geteffectpar(-1) != 0);
3769                 getData->data.engine = value_int;
3770                 getData->data.source |= getData->data.source |= TOPLEVEL::action::forceUpdate;
3771                 // the line above is to show it's changed from preset values
3772 
3773             }
3774             else
3775                 value = part->Peffnum;
3776             break;
3777 
3778         case PART::control::effectType:
3779             if (write)
3780                 part->partefx[effNum]->changeeffect(value_int);
3781             else
3782                 value = part->partefx[effNum]->geteffect();
3783             getData->data.parameter = (part->partefx[effNum]->geteffectpar(-1) != 0);
3784             getData->data.offset = 0;
3785             break;
3786         case PART::control::effectDestination:
3787             if (write)
3788             {
3789                 part->Pefxroute[effNum] = value_int;
3790                 part->partefx[effNum]->setdryonly(value_int == 2);
3791             }
3792             else
3793                 value = part->Pefxroute[effNum];
3794             break;
3795         case PART::control::effectBypass:
3796         {
3797             int tmp = part->Peffnum;
3798             part->Peffnum = engine;
3799             if (write)
3800             {
3801                 bool newSwitch = value_bool;
3802                 bool oldSwitch = part->Pefxbypass[engine];
3803                 part->Pefxbypass[engine] = newSwitch;
3804                 if (newSwitch != oldSwitch)
3805                     part->partefx[engine]->cleanup();
3806             }
3807             else
3808                 value = part->Pefxbypass[engine];
3809             part->Peffnum = tmp; // leave it as it was before
3810             break;
3811         }
3812 
3813         case PART::control::audioDestination:
3814             if (synth->partonoffRead(npart) != 1)
3815             {
3816                 getData->data.value = part->Paudiodest; // specific for this control
3817                 return;
3818             }
3819             else if (write)
3820             {
3821                 if (npart < synth->getRuntime().NumAvailableParts)
3822                     synth->part[npart]->Paudiodest = value_int;
3823                 getData->data.source = TOPLEVEL::action::lowPrio;
3824             }
3825             else
3826                 value = part->Paudiodest;
3827             break;
3828 
3829         case PART::control::volumeRange: // start of controllers
3830             if (write)
3831                 part->ctl->setvolume(value_int); // not the *actual* volume
3832             else
3833                 value = part->ctl->volume.data;
3834             break;
3835         case PART::control::volumeEnable:
3836             if (write)
3837                 part->ctl->volume.receive = value_bool;
3838             else
3839                 value = part->ctl->volume.receive;
3840             break;
3841         case PART::control::panningWidth:
3842             if (write)
3843                 part->ctl->setPanDepth(value_int);
3844             else
3845                 value = part->ctl->panning.depth;
3846             break;
3847         case PART::control::modWheelDepth:
3848             if (write)
3849                 part->ctl->modwheel.depth = value;
3850             else
3851                 value = part->ctl->modwheel.depth;
3852             break;
3853         case PART::control::exponentialModWheel:
3854             if (write)
3855                 part->ctl->modwheel.exponential = value_bool;
3856             else
3857                 value = part->ctl->modwheel.exponential;
3858             break;
3859         case PART::control::bandwidthDepth:
3860             if (write)
3861                 part->ctl->bandwidth.depth = value;
3862             else
3863                 value = part->ctl->bandwidth.depth;
3864             break;
3865         case PART::control::exponentialBandwidth:
3866             if (write)
3867                 part->ctl->bandwidth.exponential = value_bool;
3868             else
3869                 value = part->ctl->bandwidth.exponential;
3870             break;
3871         case PART::control::expressionEnable:
3872             if (write)
3873                 part->ctl->expression.receive = value_bool;
3874             else
3875                 value = part->ctl->expression.receive;
3876             break;
3877         case PART::control::FMamplitudeEnable:
3878             if (write)
3879                 part->ctl->fmamp.receive = value_bool;
3880             else
3881                 value = part->ctl->fmamp.receive;
3882             break;
3883         case PART::control::sustainPedalEnable:
3884             if (write)
3885                 part->ctl->sustain.receive = value_bool;
3886             else
3887                 value = part->ctl->sustain.receive;
3888             break;
3889         case PART::control::pitchWheelRange:
3890             if (write)
3891                 part->ctl->pitchwheel.bendrange = value_int;
3892             else
3893                 value = part->ctl->pitchwheel.bendrange;
3894             break;
3895         case PART::control::filterQdepth:
3896             if (write)
3897                 part->ctl->filterq.depth = value;
3898             else
3899                 value = part->ctl->filterq.depth;
3900             break;
3901         case PART::control::filterCutoffDepth:
3902             if (write)
3903                 part->ctl->filtercutoff.depth = value;
3904             else
3905                 value = part->ctl->filtercutoff.depth;
3906             break;
3907         case PART::control::breathControlEnable:
3908             if (write)
3909                 if (value_bool)
3910                     part->PbreathControl = MIDI::CC::breath;
3911                 else
3912                     part->PbreathControl = 128; // impossible CC value
3913             else
3914                 value = part->PbreathControl;
3915             break;
3916 
3917         case PART::control::resonanceCenterFrequencyDepth:
3918             if (write)
3919                 part->ctl->resonancecenter.depth = value;
3920             else
3921                 value = part->ctl->resonancecenter.depth;
3922             break;
3923         case PART::control::resonanceBandwidthDepth:
3924             if (write)
3925                 part->ctl->resonancebandwidth.depth = value;
3926             else
3927                 value = part->ctl->resonancebandwidth.depth;
3928             break;
3929 
3930         case PART::control::portamentoTime:
3931             if (write)
3932                 part->ctl->portamento.time = value;
3933             else
3934                 value = part->ctl->portamento.time;
3935             break;
3936         case PART::control::portamentoTimeStretch:
3937             if (write)
3938                 part->ctl->portamento.updowntimestretch = value;
3939             else
3940                 value = part->ctl->portamento.updowntimestretch;
3941             break;
3942         case PART::control::portamentoThreshold:
3943             if (write)
3944                 part->ctl->portamento.pitchthresh = value;
3945             else
3946                 value = part->ctl->portamento.pitchthresh;
3947             break;
3948         case PART::control::portamentoThresholdType:
3949             if (write)
3950                 part->ctl->portamento.pitchthreshtype = value_int;
3951             else
3952                 value = part->ctl->portamento.pitchthreshtype;
3953             break;
3954         case PART::control::enableProportionalPortamento:
3955             if (write)
3956                 part->ctl->portamento.proportional = value_int;
3957             else
3958                 value = part->ctl->portamento.proportional;
3959             break;
3960         case PART::control::proportionalPortamentoRate:
3961             if (write)
3962                 part->ctl->portamento.propRate = value;
3963             else
3964                 value = part->ctl->portamento.propRate;
3965             break;
3966         case PART::control::proportionalPortamentoDepth:
3967             if (write)
3968                 part->ctl->portamento.propDepth = value;
3969             else
3970                 value = part->ctl->portamento.propDepth;
3971             break;
3972 
3973         case PART::control::receivePortamento: // end of controllers
3974             if (write)
3975                 part->ctl->portamento.receive = value_bool;
3976             else
3977                 value = part->ctl->portamento.receive;
3978             break;
3979 
3980         case PART::control::midiModWheel:
3981             if (write)
3982                 part->ctl->setmodwheel(value);
3983             else
3984                 value = part->ctl->modwheel.data;
3985             break;
3986         case PART::control::midiBreath:
3987             ; // not yet
3988             break;
3989         case PART::control::midiExpression:
3990             if (write)
3991                 part->SetController(MIDI::CC::expression, value);
3992             else
3993                 value = part->ctl->expression.data;
3994             break;
3995         case PART::control::midiSustain:
3996             if (write)
3997                 part->ctl->setsustain(value);
3998             else
3999                 value = part->ctl->sustain.data;
4000             break;
4001         case PART::control::midiPortamento:
4002             if (write)
4003                 part->ctl->setportamento(value);
4004             else
4005                 value = part->ctl->portamento.data;
4006             break;
4007         case PART::control::midiFilterQ:
4008             if (write)
4009                 part->ctl->setfilterq(value);
4010             else
4011                 value = part->ctl->filterq.data;
4012             break;
4013         case PART::control::midiFilterCutoff:
4014             if (write)
4015                 part->ctl->setfiltercutoff(value);
4016             else
4017                 value = part->ctl->filtercutoff.data;
4018             break;
4019         case PART::control::midiBandwidth:
4020             if (write)
4021                 part->ctl->setbandwidth(value);
4022             else
4023                 value = part->ctl->bandwidth.data;
4024             break;
4025 
4026         case PART::control::midiFMamp:
4027             if (write)
4028                 part->ctl->setfmamp(value);
4029             else
4030                 value = part->ctl->fmamp.data;
4031             break;
4032         case PART::control::midiResonanceCenter:
4033             if (write)
4034                 part->ctl->setresonancecenter(value);
4035             else
4036                 value = part->ctl->resonancecenter.data;
4037             break;
4038         case PART::control::midiResonanceBandwidth:
4039             if (write)
4040                 part->ctl->setresonancebw(value);
4041             else
4042                 value = part->ctl->resonancebandwidth.data;
4043             break;
4044 
4045         case PART::control::instrumentCopyright: // done elsewhere
4046             break;
4047         case PART::control::instrumentComments: // done elsewhere
4048             break;
4049         case PART::control::instrumentName: // done elsewhere
4050             break;
4051         case PART::control::instrumentType:// done elsewhere
4052             break;
4053         case PART::control::defaultInstrumentCopyright: // done elsewhere
4054             ;
4055         case PART::control::resetAllControllers:
4056             if (write)
4057                 part->SetController(0x79,0);
4058             break;
4059     }
4060 
4061     if (!write || control == PART::control::minToLastKey || control == PART::control::maxToLastKey)
4062         getData->data.value = value;
4063 }
4064 
4065 
commandAdd(CommandBlock * getData)4066 void InterChange::commandAdd(CommandBlock *getData)
4067 {
4068     float value = getData->data.value;
4069     unsigned char type = getData->data.type;
4070     unsigned char control = getData->data.control;
4071     unsigned char npart = getData->data.part;
4072     unsigned char kititem = getData->data.kit;
4073 
4074     bool write = (type & TOPLEVEL::type::Write) > 0;
4075 
4076     int value_int = lrint(value);
4077     char value_bool = _SYS_::F2B(value);
4078 
4079     Part *part;
4080     part = synth->part[npart];
4081     ADnoteParameters *pars;
4082     pars = part->kit[kititem].adpars;
4083 
4084     switch (control)
4085     {
4086         case ADDSYNTH::control::volume:
4087             if (write)
4088                 pars->GlobalPar.PVolume = value_int;
4089             else
4090                 value = pars->GlobalPar.PVolume;
4091             break;
4092         case ADDSYNTH::control::velocitySense:
4093             if (write)
4094                 pars->GlobalPar.PAmpVelocityScaleFunction = value_int;
4095             else
4096                 value = pars->GlobalPar.PAmpVelocityScaleFunction;
4097             break;
4098         case ADDSYNTH::control::panning:
4099             if (write)
4100                 pars->setGlobalPan(value_int, synth->getRuntime().panLaw);
4101             else
4102                 value = pars->GlobalPar.PPanning;
4103             break;
4104         case ADDSYNTH::control::enableRandomPan:
4105             if (write)
4106                 pars->GlobalPar.PRandom = value_int;
4107             else
4108                 value = pars->GlobalPar.PRandom;
4109             break;
4110         case ADDSYNTH::control::randomWidth:
4111             if (write)
4112                 pars->GlobalPar.PWidth = value_int;
4113             else
4114                 value = pars->GlobalPar.PWidth;
4115             break;
4116 
4117         case ADDSYNTH::control::detuneFrequency:
4118             if (write)
4119                 pars->GlobalPar.PDetune = value_int + 8192;
4120             else
4121                 value = pars->GlobalPar.PDetune - 8192;
4122             break;
4123 
4124         case ADDSYNTH::control::octave:
4125         {
4126             int k;
4127             if (write)
4128             {
4129                 k = value;
4130                 if (k < 0)
4131                     k += 16;
4132                 pars->GlobalPar.PCoarseDetune = k * 1024 + pars->GlobalPar.PCoarseDetune % 1024;
4133             }
4134             else
4135             {
4136                 k = pars->GlobalPar.PCoarseDetune / 1024;
4137                 if (k >= 8)
4138                     k -= 16;
4139                 value = k;
4140             }
4141             break;
4142         }
4143         case ADDSYNTH::control::detuneType:
4144             if (write)
4145             {
4146                 if (value_int < 1) // can't be default for addsynth
4147                 {
4148                     getData->data.value = 1;
4149                     value_int = 1;
4150                 }
4151                 pars->GlobalPar.PDetuneType = value_int;
4152             }
4153             else
4154             {
4155                 value = pars->GlobalPar.PDetuneType;
4156                 if (value < 1)
4157                     value = 1;
4158             }
4159             break;
4160         case ADDSYNTH::control::coarseDetune:
4161         {
4162             int k;
4163             if (write)
4164             {
4165                 k = value;
4166                 if (k < 0)
4167                     k += 1024;
4168                 pars->GlobalPar.PCoarseDetune = k + (pars->GlobalPar.PCoarseDetune / 1024) * 1024;
4169             }
4170             else
4171             {
4172                 k = pars->GlobalPar.PCoarseDetune % 1024;
4173                 if (k >= 512)
4174                     k -= 1024;
4175                 value = k;
4176             }
4177             break;
4178         }
4179         case ADDSYNTH::control::relativeBandwidth:
4180             if (write)
4181             {
4182                 pars->GlobalPar.PBandwidth = value_int;
4183                  pars->getBandwidthDetuneMultiplier();
4184             }
4185             else
4186                 value = pars->GlobalPar.PBandwidth;
4187             break;
4188 
4189         case ADDSYNTH::control::stereo:
4190             if (write)
4191                 pars->GlobalPar.PStereo = value_bool;
4192             else
4193                 value = pars->GlobalPar.PStereo;
4194             break;
4195         case ADDSYNTH::control::randomGroup:
4196             if (write)
4197                 pars->GlobalPar.Hrandgrouping = value_bool;
4198             else
4199                 value = pars->GlobalPar.Hrandgrouping;
4200             break;
4201 
4202         case ADDSYNTH::control::dePop:
4203             if (write)
4204                 pars->GlobalPar.Fadein_adjustment = value_int;
4205             else
4206                 value = pars->GlobalPar.Fadein_adjustment;
4207             break;
4208         case ADDSYNTH::control::punchStrength:
4209             if (write)
4210                 pars->GlobalPar.PPunchStrength = value_int;
4211             else
4212                 value = pars->GlobalPar.PPunchStrength;
4213             break;
4214         case ADDSYNTH::control::punchDuration:
4215             if (write)
4216                 pars->GlobalPar.PPunchTime = value_int;
4217             else
4218                 value = pars->GlobalPar.PPunchTime;
4219             break;
4220         case ADDSYNTH::control::punchStretch:
4221             if (write)
4222                 pars->GlobalPar.PPunchStretch = value_int;
4223             else
4224                 value = pars->GlobalPar.PPunchStretch;
4225             break;
4226         case ADDSYNTH::control::punchVelocity:
4227             if (write)
4228                 pars->GlobalPar.PPunchVelocitySensing = value_int;
4229             else
4230                 value = pars->GlobalPar.PPunchVelocitySensing;
4231             break;
4232     }
4233     if (!write)
4234         getData->data.value = value;
4235 }
4236 
4237 
commandAddVoice(CommandBlock * getData)4238 void InterChange::commandAddVoice(CommandBlock *getData)
4239 {
4240     float value = getData->data.value;
4241     unsigned char type = getData->data.type;
4242     unsigned char control = getData->data.control;
4243     unsigned char npart = getData->data.part;
4244     unsigned char kititem = getData->data.kit;
4245     unsigned char engine = getData->data.engine;
4246     int nvoice;
4247     if (engine >= PART::engine::addMod1)
4248         nvoice = engine - PART::engine::addMod1;
4249     else
4250         nvoice = engine - PART::engine::addVoice1;
4251 
4252     bool write = (type & TOPLEVEL::type::Write) > 0;
4253 
4254     int value_int = lrint(value);
4255     char value_bool = _SYS_::F2B(value);
4256 
4257     Part *part;
4258     part = synth->part[npart];
4259     ADnoteParameters *pars;
4260     pars = part->kit[kititem].adpars;
4261 
4262     switch (control)
4263     {
4264         case ADDVOICE::control::volume:
4265             if (write)
4266                 pars->VoicePar[nvoice].PVolume = value_int;
4267             else
4268                 value = pars->VoicePar[nvoice].PVolume;
4269             break;
4270         case ADDVOICE::control::velocitySense:
4271             if (write)
4272                 pars->VoicePar[nvoice].PAmpVelocityScaleFunction = value_int;
4273             else
4274                 value = pars->VoicePar[nvoice].PAmpVelocityScaleFunction;
4275             break;
4276         case ADDVOICE::control::panning:
4277             if (write)
4278                  pars->setVoicePan(nvoice, value_int, synth->getRuntime().panLaw);
4279             else
4280                 value = pars->VoicePar[nvoice].PPanning;
4281             break;
4282             case ADDVOICE::control::enableRandomPan:
4283                 if (write)
4284                     pars->VoicePar[nvoice].PRandom = value_int;
4285                 else
4286                     value = pars->VoicePar[nvoice].PRandom;
4287                 break;
4288             case ADDVOICE::control::randomWidth:
4289                 if (write)
4290                     pars->VoicePar[nvoice].PWidth = value_int;
4291                 else
4292                     value = pars->VoicePar[nvoice].PWidth;
4293                 break;
4294 
4295         case ADDVOICE::control::invertPhase:
4296             if (write)
4297                 pars->VoicePar[nvoice].PVolumeminus = value_bool;
4298             else
4299                 value = pars->VoicePar[nvoice].PVolumeminus;
4300             break;
4301         case ADDVOICE::control::enableAmplitudeEnvelope:
4302             if (write)
4303                 pars->VoicePar[nvoice].PAmpEnvelopeEnabled = value_bool;
4304             else
4305                 value = pars->VoicePar[nvoice].PAmpEnvelopeEnabled;
4306             break;
4307         case ADDVOICE::control::enableAmplitudeLFO:
4308             if (write)
4309                 pars->VoicePar[nvoice].PAmpLfoEnabled = value_bool;
4310             else
4311                 value = pars->VoicePar[nvoice].PAmpLfoEnabled;
4312             break;
4313 
4314         case ADDVOICE::control::modulatorType:
4315             if (write)
4316             {
4317                 pars->VoicePar[nvoice].PFMEnabled = value_int;
4318                 getData->data.value = value_int; // we have to do this otherwise GUI goes out of sync
4319             }
4320             else
4321                 value = pars->VoicePar[nvoice].PFMEnabled;
4322             break;
4323         case ADDVOICE::control::externalModulator:
4324             if (write)
4325                 pars->VoicePar[nvoice].PFMVoice = value_int;
4326             else
4327                 value = pars->VoicePar[nvoice].PFMVoice;
4328             break;
4329 
4330         case ADDVOICE::control::externalOscillator:
4331             if (write)
4332                 pars->VoicePar[nvoice].PVoice = value_int;
4333             else
4334                 value = pars->VoicePar[nvoice].PVoice;
4335             break;
4336 
4337         case ADDVOICE::control::detuneFrequency:
4338             if (write)
4339                 pars->VoicePar[nvoice].PDetune = value_int + 8192;
4340             else
4341                 value = pars->VoicePar[nvoice].PDetune-8192;
4342             break;
4343         case ADDVOICE::control::equalTemperVariation:
4344             if (write)
4345                 pars->VoicePar[nvoice].PfixedfreqET = value_int;
4346             else
4347                 value = pars->VoicePar[nvoice].PfixedfreqET;
4348             break;
4349         case ADDVOICE::control::baseFrequencyAs440Hz:
4350             if (write)
4351                  pars->VoicePar[nvoice].Pfixedfreq = value_bool;
4352             else
4353                 value = pars->VoicePar[nvoice].Pfixedfreq;
4354             break;
4355         case ADDVOICE::control::octave:
4356         {
4357             int k;
4358             if (write)
4359             {
4360                 k = value;
4361                 if (k < 0)
4362                     k += 16;
4363                 pars->VoicePar[nvoice].PCoarseDetune = k * 1024 + pars->VoicePar[nvoice].PCoarseDetune % 1024;
4364             }
4365             else
4366             {
4367                 k = pars->VoicePar[nvoice].PCoarseDetune / 1024;
4368                 if (k >= 8)
4369                     k -= 16;
4370                 value = k;
4371             }
4372             break;
4373         }
4374         case ADDVOICE::control::detuneType:
4375             if (write)
4376                 pars->VoicePar[nvoice].PDetuneType = value_int;
4377             else
4378                 value = pars->VoicePar[nvoice].PDetuneType;
4379             break;
4380         case ADDVOICE::control::coarseDetune:
4381         {
4382             int k;
4383             if (write)
4384             {
4385                 k = value;
4386                 if (k < 0)
4387                     k += 1024;
4388                 pars->VoicePar[nvoice].PCoarseDetune = k + (pars->VoicePar[nvoice].PCoarseDetune / 1024) * 1024;
4389             }
4390             else
4391             {
4392                 k = pars->VoicePar[nvoice].PCoarseDetune % 1024;
4393                 if (k >= 512)
4394                     k -= 1024;
4395                 value = k;
4396             }
4397             break;
4398         }
4399         case ADDVOICE::control::pitchBendAdjustment:
4400             if (write)
4401                 pars->VoicePar[nvoice].PBendAdjust = value_int;
4402             else
4403                 value = pars->VoicePar[nvoice].PBendAdjust;
4404             break;
4405         case ADDVOICE::control::pitchBendOffset:
4406             if (write)
4407                 pars->VoicePar[nvoice].POffsetHz = value_int;
4408             else
4409                 value = pars->VoicePar[nvoice].POffsetHz;
4410             break;
4411         case ADDVOICE::control::enableFrequencyEnvelope:
4412             if (write)
4413                 pars->VoicePar[nvoice].PFreqEnvelopeEnabled = value_int;
4414             else
4415                 value = pars->VoicePar[nvoice].PFreqEnvelopeEnabled;
4416             break;
4417         case ADDVOICE::control::enableFrequencyLFO:
4418             if (write)
4419                 pars->VoicePar[nvoice].PFreqLfoEnabled = value_int;
4420             else
4421                 value = pars->VoicePar[nvoice].PFreqLfoEnabled;
4422             break;
4423 
4424         case ADDVOICE::control::unisonFrequencySpread:
4425             if (write)
4426                 pars->VoicePar[nvoice].Unison_frequency_spread = value_int;
4427             else
4428                 value = pars->VoicePar[nvoice].Unison_frequency_spread;
4429             break;
4430         case ADDVOICE::control::unisonPhaseRandomise:
4431             if (write)
4432                 pars->VoicePar[nvoice].Unison_phase_randomness = value_int;
4433             else
4434                 value = pars->VoicePar[nvoice].Unison_phase_randomness;
4435             break;
4436         case ADDVOICE::control::unisonStereoSpread:
4437             if (write)
4438                 pars->VoicePar[nvoice].Unison_stereo_spread = value_int;
4439             else
4440                 value = pars->VoicePar[nvoice].Unison_stereo_spread;
4441             break;
4442         case ADDVOICE::control::unisonVibratoDepth:
4443             if (write)
4444                 pars->VoicePar[nvoice].Unison_vibratto = value_int;
4445             else
4446                 value = pars->VoicePar[nvoice].Unison_vibratto;
4447             break;
4448         case ADDVOICE::control::unisonVibratoSpeed:
4449             if (write)
4450                 pars->VoicePar[nvoice].Unison_vibratto_speed = value_int;
4451             else
4452                 value = pars->VoicePar[nvoice].Unison_vibratto_speed;
4453             break;
4454         case ADDVOICE::control::unisonSize:
4455             if (write)
4456             {
4457                 if (value < 2)
4458                     value = 2;
4459                 pars->VoicePar[nvoice].Unison_size = value_int;
4460             }
4461             else
4462                 value = pars->VoicePar[nvoice].Unison_size;
4463             break;
4464         case ADDVOICE::control::unisonPhaseInvert:
4465             if (write)
4466                 pars->VoicePar[nvoice].Unison_invert_phase = value_int;
4467             else
4468                 value = pars->VoicePar[nvoice].Unison_invert_phase;
4469             break;
4470         case ADDVOICE::control::enableUnison:
4471         {
4472             int k;
4473             if (write)
4474             {
4475                 k = value_bool + 1;
4476                 if (pars->VoicePar[nvoice].Unison_size < 2 || k == 1)
4477                     pars->VoicePar[nvoice].Unison_size = k;
4478             }
4479             else
4480                 value = (pars->VoicePar[nvoice].Unison_size > 1);
4481             break;
4482         }
4483 
4484         case ADDVOICE::control::bypassGlobalFilter:
4485             if (write)
4486                 pars->VoicePar[nvoice].Pfilterbypass = value_bool;
4487             else
4488                 value = pars->VoicePar[nvoice].Pfilterbypass;
4489             break;
4490         case ADDVOICE::control::enableFilter:
4491             if (write)
4492                  pars->VoicePar[nvoice].PFilterEnabled =  value_bool;
4493             else
4494                 value = pars->VoicePar[nvoice].PFilterEnabled;
4495             break;
4496         case ADDVOICE::control::enableFilterEnvelope:
4497             if (write)
4498                 pars->VoicePar[nvoice].PFilterEnvelopeEnabled= value_bool;
4499             else
4500                 value = pars->VoicePar[nvoice].PFilterEnvelopeEnabled;
4501             break;
4502         case ADDVOICE::control::enableFilterLFO:
4503             if (write)
4504                 pars->VoicePar[nvoice].PFilterLfoEnabled= value_bool;
4505             else
4506                 value = pars->VoicePar[nvoice].PFilterLfoEnabled;
4507             break;
4508 
4509         case ADDVOICE::control::modulatorAmplitude:
4510             if (write)
4511                 pars->VoicePar[nvoice].PFMVolume = value_int;
4512             else
4513                 value = pars->VoicePar[nvoice].PFMVolume;
4514             break;
4515         case ADDVOICE::control::modulatorVelocitySense:
4516             if (write)
4517                 pars->VoicePar[nvoice].PFMVelocityScaleFunction = value_int;
4518             else
4519                 value = pars->VoicePar[nvoice].PFMVelocityScaleFunction;
4520             break;
4521         case ADDVOICE::control::modulatorHFdamping:
4522             if (write)
4523                 pars->VoicePar[nvoice].PFMVolumeDamp = value_int + 64;
4524             else
4525                 value = pars->VoicePar[nvoice].PFMVolumeDamp - 64;
4526             break;
4527         case ADDVOICE::control::enableModulatorAmplitudeEnvelope:
4528             if (write)
4529                 pars->VoicePar[nvoice].PFMAmpEnvelopeEnabled = value_bool;
4530             else
4531                 value =  pars->VoicePar[nvoice].PFMAmpEnvelopeEnabled;
4532             break;
4533 
4534         case ADDVOICE::control::modulatorDetuneFrequency:
4535             if (write)
4536                 pars->VoicePar[nvoice].PFMDetune = value_int + 8192;
4537             else
4538                 value = pars->VoicePar[nvoice].PFMDetune - 8192;
4539             break;
4540         case ADDVOICE::control::modulatorDetuneFromBaseOsc:
4541             if (write)
4542                 pars->VoicePar[nvoice].PFMDetuneFromBaseOsc = value_bool;
4543             else
4544                 value = pars->VoicePar[nvoice].PFMDetuneFromBaseOsc;
4545             break;
4546         case ADDVOICE::control::modulatorFrequencyAs440Hz:
4547             if (write)
4548                 pars->VoicePar[nvoice].PFMFixedFreq = value_bool;
4549             else
4550                 value = pars->VoicePar[nvoice].PFMFixedFreq;
4551             break;
4552         case ADDVOICE::control::modulatorOctave:
4553         {
4554             int k;
4555             if (write)
4556             {
4557                 k = value_int;
4558                 if (k < 0)
4559                     k += 16;
4560                 pars->VoicePar[nvoice].PFMCoarseDetune = k * 1024 + pars->VoicePar[nvoice].PFMCoarseDetune % 1024;
4561             }
4562             else
4563             {
4564                 k = pars->VoicePar[nvoice].PFMCoarseDetune / 1024;
4565                 if (k >= 8)
4566                     k -= 16;
4567                 value = k;
4568             }
4569             break;
4570         }
4571         case ADDVOICE::control::modulatorDetuneType:
4572             if (write)
4573                 pars->VoicePar[nvoice].PFMDetuneType = value_int;
4574             else
4575                 value = pars->VoicePar[nvoice].PFMDetuneType;
4576             break;
4577         case ADDVOICE::control::modulatorCoarseDetune:
4578         {
4579             int k;
4580             if (write)
4581             {
4582                 int k = value_int;
4583                 if (k < 0)
4584                     k += 1024;
4585                 pars->VoicePar[nvoice].PFMCoarseDetune = k + (pars->VoicePar[nvoice].PFMCoarseDetune / 1024) * 1024;
4586             }
4587             else
4588             {
4589                 k = pars->VoicePar[nvoice].PFMCoarseDetune % 1024;
4590                 if (k >= 512)
4591                     k-= 1024;
4592                 value = k;
4593             }
4594             break;
4595         }
4596         case ADDVOICE::control::enableModulatorFrequencyEnvelope:
4597             if (write)
4598                 pars->VoicePar[nvoice].PFMFreqEnvelopeEnabled = value_int;
4599             else
4600                 value = pars->VoicePar[nvoice].PFMFreqEnvelopeEnabled;
4601             break;
4602 
4603         case ADDVOICE::control::modulatorOscillatorPhase:
4604             if (write)
4605                 pars->VoicePar[nvoice].PFMoscilphase = 64 - value_int;
4606             else
4607                 value = 64 - pars->VoicePar[nvoice].PFMoscilphase;
4608             break;
4609         case ADDVOICE::control::modulatorOscillatorSource:
4610             if (write)
4611                 pars->VoicePar[nvoice].PextFMoscil = value_int;
4612             else
4613                 value = pars->VoicePar[nvoice].PextFMoscil;
4614             break;
4615 
4616         case ADDVOICE::control::delay:
4617             if (write)
4618                 pars->VoicePar[nvoice].PDelay = value_int;
4619             else
4620                 value = pars->VoicePar[nvoice].PDelay;
4621             break;
4622         case ADDVOICE::control::enableVoice:
4623             if (write)
4624                 pars->VoicePar[nvoice].Enabled = value_bool;
4625             else
4626                 value = pars->VoicePar[nvoice].Enabled;
4627             break;
4628         case ADDVOICE::control::enableResonance:
4629             if (write)
4630                 pars->VoicePar[nvoice].Presonance = value_bool;
4631             else
4632                 value = pars->VoicePar[nvoice].Presonance;
4633             break;
4634         case ADDVOICE::control::voiceOscillatorPhase:
4635             if (write)
4636                 pars->VoicePar[nvoice].Poscilphase = 64 - value_int;
4637             else
4638                 value = 64 - pars->VoicePar[nvoice].Poscilphase;
4639             break;
4640         case ADDVOICE::control::voiceOscillatorSource:
4641             if (write)
4642                 pars->VoicePar[nvoice].Pextoscil = value_int;
4643             else
4644                 value = pars->VoicePar[nvoice].Pextoscil;
4645             break;
4646         case ADDVOICE::control::soundType:
4647             if (write)
4648                 pars->VoicePar[nvoice].Type = value_int;
4649             else
4650                 value = pars->VoicePar[nvoice].Type;
4651             break;
4652     }
4653 
4654     if (!write)
4655         getData->data.value = value;
4656 }
4657 
4658 
commandSub(CommandBlock * getData)4659 void InterChange::commandSub(CommandBlock *getData)
4660 {
4661     float value = getData->data.value;
4662     unsigned char type = getData->data.type;
4663     unsigned char control = getData->data.control;
4664     unsigned char npart = getData->data.part;
4665     unsigned char kititem = getData->data.kit;
4666     unsigned char insert = getData->data.insert & 0x1f; // ensure no stray filter
4667 
4668     bool write = (type & TOPLEVEL::type::Write) > 0;
4669 
4670     int value_int = lrint(value);
4671     char value_bool = _SYS_::F2B(value);
4672 
4673     Part *part;
4674     part = synth->part[npart];
4675     SUBnoteParameters *pars;
4676     pars = part->kit[kititem].subpars;
4677 
4678     if (insert == TOPLEVEL::insert::harmonicAmplitude || insert == TOPLEVEL::insert::harmonicPhaseBandwidth)
4679     {
4680         if (insert == TOPLEVEL::insert::harmonicAmplitude)
4681         {
4682             if (write)
4683                 pars->Phmag[control] = value;
4684             else
4685                 value = pars->Phmag[control];
4686         }
4687         else
4688         {
4689             if (write)
4690                 pars->Phrelbw[control] = value;
4691             else
4692                 value = pars->Phrelbw[control];
4693         }
4694 
4695         if (!write)
4696             getData->data.value = value;
4697         else
4698             pars->PfilterChanged[control] = insert;
4699         return;
4700     }
4701 
4702     switch (control)
4703     {
4704         case SUBSYNTH::control::volume:
4705             if (write)
4706                 pars->PVolume = value;
4707             else
4708                 value = pars->PVolume;
4709             break;
4710         case SUBSYNTH::control::velocitySense:
4711             if (write)
4712                 pars->PAmpVelocityScaleFunction = value;
4713             else
4714                 value = pars->PAmpVelocityScaleFunction;
4715             break;
4716         case SUBSYNTH::control::panning:
4717             if (write)
4718                 pars->setPan(value, synth->getRuntime().panLaw);
4719             else
4720                 value = pars->PPanning;
4721             break;
4722         case SUBSYNTH::control::enableRandomPan:
4723             if (write)
4724                 pars->PRandom = value_int;
4725             else
4726                 value = pars->PRandom;
4727             break;
4728         case SUBSYNTH::control::randomWidth:
4729             if (write)
4730                 pars->PWidth = value_int;
4731             else
4732                 value = pars->PWidth;
4733             break;
4734 
4735         case SUBSYNTH::control::bandwidth:
4736             if (write)
4737                 pars->Pbandwidth = value;
4738             else
4739                 value = pars->Pbandwidth;
4740             break;
4741         case SUBSYNTH::control::bandwidthScale:
4742             if (write)
4743                 pars->Pbwscale = value + 64;
4744             else
4745                 value = pars->Pbwscale - 64;
4746             break;
4747         case SUBSYNTH::control::enableBandwidthEnvelope:
4748             if (write)
4749                 pars->PBandWidthEnvelopeEnabled = value_bool;
4750             else
4751                 value = pars->PBandWidthEnvelopeEnabled;
4752             break;
4753 
4754         case SUBSYNTH::control::detuneFrequency:
4755             if (write)
4756                 pars->PDetune = value + 8192;
4757             else
4758                 value = pars->PDetune - 8192;
4759             break;
4760         case SUBSYNTH::control::equalTemperVariation:
4761             if (write)
4762                 pars->PfixedfreqET = value;
4763             else
4764                 value = pars->PfixedfreqET;
4765             break;
4766         case SUBSYNTH::control::baseFrequencyAs440Hz:
4767             if (write)
4768                 pars->Pfixedfreq = value_bool;
4769             else
4770                 value = pars->Pfixedfreq;
4771             break;
4772         case SUBSYNTH::control::octave:
4773         {
4774             int k;
4775             if (write)
4776             {
4777                 k = value;
4778                 if (k < 0)
4779                     k += 16;
4780                 pars->PCoarseDetune = k * 1024 + pars->PCoarseDetune % 1024;
4781             }
4782             else
4783             {
4784                 k = pars->PCoarseDetune / 1024;
4785                 if (k >= 8)
4786                     k -= 16;
4787                 value = k;
4788             }
4789             break;
4790         }
4791         case SUBSYNTH::control::detuneType:
4792             if (write)
4793             {
4794                 if (value_int < 1) // can't be default for subsynth
4795                 {
4796                     getData->data.value = 1;
4797                     value_int = 1;
4798                 }
4799                 pars->PDetuneType = value_int;
4800             }
4801             else
4802                 value = pars->PDetuneType;
4803             break;
4804         case SUBSYNTH::control::coarseDetune:
4805         {
4806             int k;
4807             if (write)
4808             {
4809                 k = value;
4810                 if (k < 0)
4811                     k += 1024;
4812                 pars->PCoarseDetune = k + (pars->PCoarseDetune / 1024) * 1024;
4813             }
4814             else
4815             {
4816                 k = pars->PCoarseDetune % 1024;
4817                 if (k >= 512)
4818                     k -= 1024;
4819                 value = k;
4820             }
4821             break;
4822         }
4823 
4824         case SUBSYNTH::control::pitchBendAdjustment:
4825             if (write)
4826                 pars->PBendAdjust = value;
4827             else
4828                 value = pars->PBendAdjust;
4829             break;
4830 
4831         case SUBSYNTH::control::pitchBendOffset:
4832             if (write)
4833                 pars->POffsetHz = value;
4834             else
4835                 value = pars->POffsetHz;
4836             break;
4837 
4838         case SUBSYNTH::control::enableFrequencyEnvelope:
4839             if (write)
4840                 pars->PFreqEnvelopeEnabled = value_bool;
4841             else
4842                 value = pars->PFreqEnvelopeEnabled;
4843             break;
4844 
4845         case SUBSYNTH::control::overtoneParameter1:
4846             if (write)
4847             {
4848                 pars->POvertoneSpread.par1 = value;
4849                 pars->updateFrequencyMultipliers();
4850             }
4851             else
4852                 value = pars->POvertoneSpread.par1;
4853             break;
4854         case SUBSYNTH::control::overtoneParameter2:
4855             if (write)
4856             {
4857                 pars->POvertoneSpread.par2 = value;
4858                 pars->updateFrequencyMultipliers();
4859             }
4860             else
4861                 value = pars->POvertoneSpread.par2;
4862             break;
4863         case SUBSYNTH::control::overtoneForceHarmonics:
4864             if (write)
4865             {
4866                 pars->POvertoneSpread.par3 = value;
4867                 pars->updateFrequencyMultipliers();
4868             }
4869             else
4870                 value = pars->POvertoneSpread.par3;
4871             break;
4872         case SUBSYNTH::control::overtonePosition:
4873             if (write)
4874             {
4875                 pars->POvertoneSpread.type =  value_int;
4876                 pars->updateFrequencyMultipliers();
4877             }
4878             else
4879                 value = pars->POvertoneSpread.type;
4880             break;
4881 
4882         case SUBSYNTH::control::enableFilter:
4883             if (write)
4884                 pars->PGlobalFilterEnabled = value_bool;
4885             else
4886                 value = pars->PGlobalFilterEnabled;
4887             break;
4888 
4889         case SUBSYNTH::control::filterStages:
4890             if (write)
4891                 pars->Pnumstages = value_int;
4892             else
4893                 value = pars->Pnumstages;
4894             break;
4895         case SUBSYNTH::control::magType:
4896             if (write)
4897                 pars->Phmagtype = value_int;
4898             else
4899                 value = pars->Phmagtype;
4900             break;
4901         case SUBSYNTH::control::startPosition:
4902             if (write)
4903                 pars->Pstart = value_int;
4904             else
4905                 value = pars->Pstart;
4906             break;
4907 
4908         case SUBSYNTH::control::clearHarmonics:
4909             if (write)
4910             {
4911                 for (int i = 0; i < MAX_SUB_HARMONICS; i++)
4912                 {
4913                     pars->Phmag[i] = 0;
4914                     pars->Phrelbw[i] = 64;
4915                 }
4916                 pars->Phmag[0] = 127;
4917             }
4918             break;
4919 
4920         case SUBSYNTH::control::stereo:
4921             if (write)
4922                 pars->Pstereo = value_bool;
4923             else
4924                 value = pars->Pstereo;
4925             break;
4926     }
4927 
4928     if (!write)
4929         getData->data.value = value;
4930 }
4931 
4932 
commandPad(CommandBlock * getData)4933 void InterChange::commandPad(CommandBlock *getData)
4934 {
4935     float value = getData->data.value;
4936     unsigned char type = getData->data.type;
4937     unsigned char control = getData->data.control;
4938     unsigned char npart = getData->data.part;
4939     unsigned char kititem = getData->data.kit;
4940 
4941     bool write = (type & TOPLEVEL::type::Write) > 0;
4942 
4943     int value_int = lrint(value);
4944     char value_bool = _SYS_::F2B(value);
4945 
4946     Part *part;
4947     part = synth->part[npart];
4948     PADnoteParameters *pars;
4949     pars = part->kit[kititem].padpars;
4950 
4951     switch (control)
4952     {
4953         case PADSYNTH::control::volume:
4954             if (write)
4955                 pars->PVolume = value;
4956             else
4957                 value = pars->PVolume;
4958             break;
4959         case PADSYNTH::control::velocitySense:
4960             if (write)
4961                 pars->PAmpVelocityScaleFunction = value;
4962             else
4963                 value = pars->PAmpVelocityScaleFunction;
4964             break;
4965         case PADSYNTH::control::panning:
4966             if (write)
4967                 pars->setPan(value, synth->getRuntime().panLaw);
4968             else
4969                 value = pars->PPanning;
4970             break;
4971         case PADSYNTH::control::enableRandomPan:
4972             if (write)
4973                 pars->PRandom = value_int;
4974             else
4975                 value = pars->PRandom;
4976             break;
4977         case PADSYNTH::control::randomWidth:
4978             if (write)
4979                 pars->PWidth = value_int;
4980             else
4981                 value = pars->PWidth;
4982             break;
4983 
4984         case PADSYNTH::control::bandwidth:
4985             if (write)
4986                 pars->setPbandwidth(value_int);
4987             else
4988                 value = pars->Pbandwidth;
4989             break;
4990         case PADSYNTH::control::bandwidthScale:
4991             if (write)
4992                 pars->Pbwscale = value_int;
4993             else
4994                 value = pars->Pbwscale;
4995             break;
4996         case PADSYNTH::control::spectrumMode:
4997             if (write)
4998                 pars->Pmode = value_int;
4999             else
5000                 value = pars->Pmode;
5001             break;
5002 
5003         case PADSYNTH::control::detuneFrequency:
5004             if (write)
5005                 pars->PDetune = value_int + 8192;
5006             else
5007                 value = pars->PDetune - 8192;
5008             break;
5009         case PADSYNTH::control::equalTemperVariation:
5010             if (write)
5011                 pars->PfixedfreqET = value_int;
5012             else
5013                 value = pars->PfixedfreqET;
5014             break;
5015         case PADSYNTH::control::baseFrequencyAs440Hz:
5016             if (write)
5017                 pars->Pfixedfreq = value_bool;
5018             else
5019                 value = pars->Pfixedfreq;
5020             break;
5021         case PADSYNTH::control::octave:
5022             if (write)
5023             {
5024                 int tmp = value;
5025                 if (tmp < 0)
5026                     tmp += 16;
5027                 pars->PCoarseDetune = tmp * 1024 + pars->PCoarseDetune % 1024;
5028             }
5029             else
5030             {
5031                 int tmp = pars->PCoarseDetune / 1024;
5032                 if (tmp >= 8)
5033                     tmp -= 16;
5034                 value = tmp;
5035             }
5036             break;
5037         case PADSYNTH::control::detuneType:
5038             if (write)
5039             {
5040                 if (value_int < 1) // can't be default for padsynth
5041                 {
5042                     getData->data.value = 1;
5043                     value_int = 1;
5044                 }
5045                  pars->PDetuneType = value_int;
5046             }
5047             else
5048                 value =  pars->PDetuneType;
5049             break;
5050         case PADSYNTH::control::coarseDetune:
5051             if (write)
5052             {
5053                 int tmp = value;
5054                 if (tmp < 0)
5055                     tmp += 1024;
5056                  pars->PCoarseDetune = tmp + (pars->PCoarseDetune / 1024) * 1024;
5057             }
5058             else
5059             {
5060                 int tmp = pars->PCoarseDetune % 1024;
5061                 if (tmp >= 512)
5062                     tmp -= 1024;
5063                 value = tmp;
5064             }
5065             break;
5066 
5067         case PADSYNTH::control::pitchBendAdjustment:
5068             if (write)
5069                 pars->PBendAdjust = value_int;
5070             else
5071                 value = pars->PBendAdjust;
5072             break;
5073         case PADSYNTH::control::pitchBendOffset:
5074             if (write)
5075                 pars->POffsetHz = value_int;
5076             else
5077                 value = pars->POffsetHz;
5078             break;
5079 
5080         case PADSYNTH::control::overtoneParameter1:
5081             if (write)
5082                 pars->Phrpos.par1 = value_int;
5083             else
5084                 value = pars->Phrpos.par1;
5085             break;
5086         case PADSYNTH::control::overtoneParameter2:
5087             if (write)
5088                 pars->Phrpos.par2 = value_int;
5089             else
5090                 value = pars->Phrpos.par2;
5091             break;
5092         case PADSYNTH::control::overtoneForceHarmonics:
5093             if (write)
5094                 pars->Phrpos.par3 = value_int;
5095             else
5096                 value = pars->Phrpos.par3;
5097             break;
5098         case PADSYNTH::control::overtonePosition:
5099             if (write)
5100                 pars->Phrpos.type = value_int;
5101             else
5102                 value = pars->Phrpos.type;
5103             break;
5104 
5105         case PADSYNTH::control::baseWidth:
5106             if (write)
5107                 pars->Php.base.par1 = value_int;
5108             else
5109                 value = pars->Php.base.par1;
5110             break;
5111         case PADSYNTH::control::frequencyMultiplier:
5112             if (write)
5113                 pars->Php.freqmult = value_int;
5114             else
5115                 value = pars->Php.freqmult;
5116             break;
5117         case PADSYNTH::control::modulatorStretch:
5118             if (write)
5119                 pars->Php.modulator.par1 = value_int;
5120             else
5121                 value = pars->Php.modulator.par1;
5122             break;
5123         case PADSYNTH::control::modulatorFrequency:
5124             if (write)
5125                 pars->Php.modulator.freq = value_int;
5126             else
5127                 value = pars->Php.modulator.freq;
5128             break;
5129         case PADSYNTH::control::size:
5130             if (write)
5131                 pars->Php.width = value_int;
5132             else
5133                 value = pars->Php.width;
5134             break;
5135         case PADSYNTH::control::baseType:
5136             if (write)
5137                 pars->Php.base.type = value;
5138             else
5139                 value = pars->Php.base.type;
5140             break;
5141         case PADSYNTH::control::harmonicSidebands:
5142             if (write)
5143                  pars->Php.onehalf = value;
5144             else
5145                 value = pars->Php.onehalf;
5146             break;
5147         case PADSYNTH::control::spectralWidth:
5148             if (write)
5149                 pars->Php.amp.par1 = value_int;
5150             else
5151                 value = pars->Php.amp.par1;
5152             break;
5153         case PADSYNTH::control::spectralAmplitude:
5154             if (write)
5155                 pars->Php.amp.par2 = value_int;
5156             else
5157                 value = pars->Php.amp.par2;
5158             break;
5159         case PADSYNTH::control::amplitudeMultiplier:
5160             if (write)
5161                 pars->Php.amp.type = value;
5162             else
5163                 value = pars->Php.amp.type;
5164             break;
5165         case PADSYNTH::control::amplitudeMode:
5166             if (write)
5167                 pars->Php.amp.mode = value;
5168             else
5169                 value = pars->Php.amp.mode;
5170             break;
5171         case PADSYNTH::control::autoscale:
5172             if (write)
5173                 pars->Php.autoscale = value_bool;
5174             else
5175                 value = pars->Php.autoscale;
5176             break;
5177 
5178         case PADSYNTH::control::harmonicBase:
5179             if (write)
5180                 pars->Pquality.basenote = value_int;
5181             else
5182                 value = pars->Pquality.basenote;
5183             break;
5184         case PADSYNTH::control::samplesPerOctave:
5185             if (write)
5186                 pars->Pquality.smpoct = value_int;
5187             else
5188                 value = pars->Pquality.smpoct;
5189             break;
5190         case PADSYNTH::control::numberOfOctaves:
5191             if (write)
5192                 pars->Pquality.oct = value_int;
5193             else
5194                 value = pars->Pquality.oct;
5195             break;
5196         case PADSYNTH::control::sampleSize:
5197             if (write)
5198                 pars->Pquality.samplesize = value_int;
5199             else
5200                 value = pars->Pquality.samplesize;
5201             break;
5202 
5203         case PADSYNTH::control::applyChanges:
5204             if (write && value >= 0.5f)
5205             { // this control is 'expensive' only used if necessary
5206                 if (!pars->Papplied)
5207                 {
5208                     synth->partonoffWrite(npart, -1);
5209                     getData->data.source = TOPLEVEL::action::lowPrio;
5210                     getData->data.value = 1;
5211                 }
5212                 else
5213                     getData->data.source = TOPLEVEL::action::noAction;
5214             }
5215             else
5216                 value = pars->Papplied;
5217             break;
5218 
5219         case PADSYNTH::control::stereo:
5220             if (write)
5221                 pars->PStereo = value_bool;
5222             else
5223                 value = pars->PStereo;
5224             break;
5225 
5226         case PADSYNTH::control::dePop:
5227             if (write)
5228                 pars->Fadein_adjustment = value_int;
5229             else
5230                 value = pars->Fadein_adjustment;
5231             break;
5232         case PADSYNTH::control::punchStrength:
5233             if (write)
5234                 pars->PPunchStrength = value_int;
5235             else
5236                 value = pars->PPunchStrength;
5237             break;
5238         case PADSYNTH::control::punchDuration:
5239             if (write)
5240                 pars->PPunchTime = value_int;
5241             else
5242                 value = pars->PPunchTime;
5243             break;
5244         case PADSYNTH::control::punchStretch:
5245             if (write)
5246                 pars->PPunchStretch = value_int;
5247             else
5248                 value = pars->PPunchStretch;
5249             break;
5250         case PADSYNTH::control::punchVelocity:
5251             if (write)
5252                 pars->PPunchVelocitySensing = value_int;
5253             else
5254                 value = pars->PPunchVelocitySensing;
5255             break;
5256     }
5257 
5258     if (control >= PADSYNTH::control::bandwidth && control < PADSYNTH::control::applyChanges)
5259     {
5260         pars->Papplied = 0;
5261         getData->data.offset = 0;
5262     }
5263     if (!write)
5264         getData->data.value = value;
5265 }
5266 
5267 
commandOscillator(CommandBlock * getData,OscilParameters * oscil)5268 void InterChange::commandOscillator(CommandBlock *getData, OscilParameters *oscil)
5269 {
5270     float value = getData->data.value;
5271     unsigned char type = getData->data.type;
5272     unsigned char control = getData->data.control;
5273     unsigned char insert = getData->data.insert;
5274 
5275     int value_int = lrint(value);
5276     bool value_bool = _SYS_::F2B(value);
5277     bool write = (type & TOPLEVEL::type::Write) > 0;
5278 
5279     if (insert == TOPLEVEL::insert::harmonicAmplitude)
5280     {
5281         if (write)
5282         {
5283             oscil->Phmag[control] = value_int;
5284             if (value_int == 64)
5285                 oscil->Phphase[control] = 64;
5286             oscil->presetsUpdated();
5287         }
5288         else
5289             getData->data.value = oscil->Phmag[control];
5290         return;
5291     }
5292     else if (insert == TOPLEVEL::insert::harmonicPhaseBandwidth)
5293     {
5294         if (write)
5295         {
5296             oscil->Phphase[control] = value_int;
5297             oscil->presetsUpdated();
5298         }
5299         else
5300             getData->data.value = oscil->Phphase[control];
5301         return;
5302     }
5303 
5304     switch (control)
5305     {
5306         case OSCILLATOR::control::phaseRandomness:
5307             if (write)
5308                 oscil->Prand = value_int + 64;
5309             else
5310                 value = oscil->Prand - 64;
5311             break;
5312         case OSCILLATOR::control::magType:
5313             if (write)
5314                 oscil->Phmagtype = value_int;
5315             else
5316                 value = oscil->Phmagtype;
5317             break;
5318         case OSCILLATOR::control::harmonicAmplitudeRandomness:
5319             if (write)
5320                 oscil->Pamprandpower = value_int;
5321             else
5322                 value = oscil->Pamprandpower;
5323             break;
5324         case OSCILLATOR::control::harmonicRandomnessType:
5325             if (write)
5326                 oscil->Pamprandtype = value_int;
5327             else
5328                 value = oscil->Pamprandtype;
5329             break;
5330 
5331         case OSCILLATOR::control::baseFunctionParameter:
5332             if (write)
5333                 oscil->Pbasefuncpar = value_int + 64;
5334             else
5335                 value = oscil->Pbasefuncpar - 64;
5336             break;
5337         case OSCILLATOR::control::baseFunctionType:
5338             if (write)
5339                 oscil->Pcurrentbasefunc = value_int;
5340             else
5341                 value = oscil->Pcurrentbasefunc;
5342             break;
5343         case OSCILLATOR::control::baseModulationParameter1:
5344             if (write)
5345                 oscil->Pbasefuncmodulationpar1 = value_int;
5346             else
5347                 value = oscil->Pbasefuncmodulationpar1;
5348             break;
5349         case OSCILLATOR::control::baseModulationParameter2:
5350             if (write)
5351                 oscil->Pbasefuncmodulationpar2 = value_int;
5352             else
5353                 value = oscil->Pbasefuncmodulationpar2;
5354             break;
5355         case OSCILLATOR::control::baseModulationParameter3:
5356             if (write)
5357                 oscil->Pbasefuncmodulationpar3 = value_int;
5358             else
5359                 value = oscil->Pbasefuncmodulationpar3;
5360             break;
5361         case OSCILLATOR::control::baseModulationType:
5362             if (write)
5363                 oscil->Pbasefuncmodulation = value_int;
5364             else
5365                 value = oscil->Pbasefuncmodulation;
5366             break;
5367 
5368         case OSCILLATOR::control::autoClear: // this is local to the GUI
5369             break;
5370         case OSCILLATOR::control::useAsBaseFunction:
5371             if (write)
5372             {
5373                 FFTwrapper fft(synth->oscilsize);
5374                 OscilGen gen(&fft, NULL, synth, oscil);
5375                 gen.useasbase();
5376                 if (value_bool)
5377                 {
5378                     for (int i = 0; i < MAX_AD_HARMONICS; ++ i)
5379                     {
5380                         oscil->Phmag[i] = 64;
5381                         oscil->Phphase[i] = 64;
5382                     }
5383                     oscil->Phmag[0] = 127;
5384                     oscil->Pharmonicshift = 0;
5385                     oscil->Pwaveshapingfunction = 0;
5386                     oscil->Pfiltertype = 0;
5387                     oscil->Psatype = 0;
5388                 }
5389                 oscil->presetsUpdated();
5390             }
5391             break;
5392 
5393         case OSCILLATOR::control::waveshapeParameter:
5394             if (write)
5395                 oscil->Pwaveshaping = value_int + 64;
5396             else
5397                 value = oscil->Pwaveshaping - 64;
5398             break;
5399         case OSCILLATOR::control::waveshapeType:
5400             if (write)
5401                 oscil->Pwaveshapingfunction = value_int;
5402             else
5403                 value = oscil->Pwaveshapingfunction;
5404             break;
5405 
5406         case OSCILLATOR::control::filterParameter1:
5407             if (write)
5408                 oscil->Pfilterpar1 = value_int;
5409             else
5410                 value = oscil->Pfilterpar1;
5411             break;
5412         case OSCILLATOR::control::filterParameter2:
5413             if (write)
5414                 oscil->Pfilterpar2 = value_int;
5415             else
5416                 value = oscil->Pfilterpar2;
5417             break;
5418         case OSCILLATOR::control::filterBeforeWaveshape:
5419             if (write)
5420                 oscil->Pfilterbeforews = value_bool;
5421             else
5422                 value = oscil->Pfilterbeforews;
5423             break;
5424         case OSCILLATOR::control::filterType:
5425             if (write)
5426                 oscil->Pfiltertype = value_int;
5427             else
5428                 value = oscil->Pfiltertype;
5429             break;
5430         case OSCILLATOR::control::modulationParameter1:
5431             if (write)
5432                 oscil->Pmodulationpar1 = value_int;
5433             else
5434                 value = oscil->Pmodulationpar1;
5435             break;
5436         case OSCILLATOR::control::modulationParameter2:
5437             if (write)
5438                 oscil->Pmodulationpar2 = value_int;
5439             else
5440                 value = oscil->Pmodulationpar2;
5441             break;
5442         case OSCILLATOR::control::modulationParameter3:
5443             if (write)
5444                 oscil->Pmodulationpar3 = value_int;
5445             else
5446                 value = oscil->Pmodulationpar3;
5447             break;
5448         case OSCILLATOR::control::modulationType:
5449             if (write)
5450                 oscil->Pmodulation = value_int;
5451             else
5452                 value = oscil->Pmodulation;
5453             break;
5454         case OSCILLATOR::control::spectrumAdjustParameter:
5455             if (write)
5456                 oscil->Psapar = value_int;
5457             else
5458                 value = oscil->Psapar;
5459             break;
5460         case OSCILLATOR::control::spectrumAdjustType:
5461             if (write)
5462                 oscil->Psatype = value_int;
5463             else
5464                 value = oscil->Psatype;
5465             break;
5466 
5467         case OSCILLATOR::control::harmonicShift:
5468             if (write)
5469                 oscil->Pharmonicshift = value_int;
5470             else
5471                 value = oscil->Pharmonicshift;
5472             break;
5473         case OSCILLATOR::control::clearHarmonicShift:
5474             if (write)
5475                 oscil->Pharmonicshift = 0;
5476             break;
5477         case OSCILLATOR::control::shiftBeforeWaveshapeAndFilter:
5478             if (write)
5479                 oscil->Pharmonicshiftfirst = value_bool;
5480             else
5481                 value = oscil->Pharmonicshiftfirst;
5482             break;
5483         case OSCILLATOR::control::adaptiveHarmonicsParameter:
5484             if (write)
5485                 oscil->Padaptiveharmonicspar = value_int;
5486             else
5487                 value = oscil->Padaptiveharmonicspar;
5488             break;
5489         case OSCILLATOR::control::adaptiveHarmonicsBase:
5490             if (write)
5491                 oscil->Padaptiveharmonicsbasefreq = value_int;
5492             else
5493                 value = oscil->Padaptiveharmonicsbasefreq;
5494             break;
5495         case OSCILLATOR::control::adaptiveHarmonicsPower:
5496             if (write)
5497                 oscil->Padaptiveharmonicspower = value_int;
5498             else
5499                 value = oscil->Padaptiveharmonicspower;
5500             break;
5501         case OSCILLATOR::control::adaptiveHarmonicsType:
5502             if (write)
5503                 oscil->Padaptiveharmonics = value_int;
5504             else
5505                 value = oscil->Padaptiveharmonics;
5506             break;
5507 
5508         case OSCILLATOR::control::clearHarmonics:
5509             if (write)
5510             {
5511                 for (int i = 0; i < MAX_AD_HARMONICS; ++ i)
5512                 {
5513                     oscil->Phmag[i]=64;
5514                     oscil->Phphase[i]=64;
5515                 }
5516                 oscil->Phmag[0]=127;
5517                 oscil->presetsUpdated();
5518             }
5519             break;
5520         case OSCILLATOR::control::convertToSine:
5521             if (write)
5522             {
5523                 FFTwrapper fft(synth->oscilsize);
5524                 OscilGen gen(&fft, NULL, synth, oscil);
5525                 gen.convert2sine();
5526                 oscil->presetsUpdated();
5527             }
5528             break;
5529     }
5530     if (!write)
5531         getData->data.value = value;
5532 }
5533 
5534 
commandResonance(CommandBlock * getData,Resonance * respar)5535 void InterChange::commandResonance(CommandBlock *getData, Resonance *respar)
5536 {
5537     float value = getData->data.value;
5538     unsigned char type = getData->data.type;
5539     unsigned char control = getData->data.control;
5540     unsigned char insert = getData->data.insert;
5541     unsigned char parameter = getData->data.parameter;
5542     int value_int = lrint(value);
5543     bool value_bool = _SYS_::F2B(value);
5544     bool write = (type & TOPLEVEL::type::Write) > 0;
5545 
5546     if (insert == TOPLEVEL::insert::resonanceGraphInsert)
5547     {
5548         if (write)
5549             respar->setpoint(parameter, value_int);
5550         else
5551             getData->data.value = respar->Prespoints[parameter];
5552         return;
5553     }
5554 
5555     switch (control)
5556     {
5557         case RESONANCE::control::maxDb:
5558             if (write)
5559                 respar->PmaxdB = value_int;
5560             else
5561                 value = respar->PmaxdB;
5562             break;
5563         case RESONANCE::control::centerFrequency:
5564             if (write)
5565                 respar->Pcenterfreq = value_int;
5566             else
5567                 value = respar->Pcenterfreq;
5568             break;
5569         case RESONANCE::control::octaves:
5570             if (write)
5571                 respar->Poctavesfreq = value_int;
5572             else
5573                 value = respar->Poctavesfreq;
5574             break;
5575 
5576         case RESONANCE::control::enableResonance:
5577             if (write)
5578                 respar->Penabled = value_bool;
5579             else
5580                 value = respar->Penabled;
5581             break;
5582 
5583         case RESONANCE::control::randomType:
5584             if (write)
5585                 respar->randomize(value_int);
5586             break;
5587 
5588         case RESONANCE::control::interpolatePeaks:
5589             if (write)
5590                 respar->interpolatepeaks(value_bool);
5591             break;
5592         case RESONANCE::control::protectFundamental:
5593             if (write)
5594                 respar->Pprotectthefundamental = value_bool;
5595             else
5596                 value = respar->Pprotectthefundamental;
5597             break;
5598 
5599         case RESONANCE::control::clearGraph:
5600             if (write)
5601                 for (int i = 0; i < MAX_RESONANCE_POINTS; ++ i)
5602                     respar->setpoint(i, 64);
5603             break;
5604         case RESONANCE::control::smoothGraph:
5605             if (write)
5606                 respar->smooth();
5607             break;
5608     }
5609     if (!write)
5610         getData->data.value = value;
5611 }
5612 
5613 
commandLFO(CommandBlock * getData)5614 void InterChange::commandLFO(CommandBlock *getData)
5615 {
5616     unsigned char npart = getData->data.part;
5617     unsigned char kititem = getData->data.kit;
5618     unsigned char engine = getData->data.engine;
5619     unsigned char insertParam = getData->data.parameter;
5620 
5621     Part *part;
5622     part = synth->part[npart];
5623 
5624     if (engine == PART::engine::addSynth)
5625     {
5626        switch (insertParam)
5627         {
5628            case TOPLEVEL::insertType::amplitude:
5629                 lfoReadWrite(getData, part->kit[kititem].adpars->GlobalPar.AmpLfo);
5630                 break;
5631             case TOPLEVEL::insertType::frequency:
5632                 lfoReadWrite(getData, part->kit[kititem].adpars->GlobalPar.FreqLfo);
5633                 break;
5634             case TOPLEVEL::insertType::filter:
5635                 lfoReadWrite(getData, part->kit[kititem].adpars->GlobalPar.FilterLfo);
5636                 break;
5637         }
5638     }
5639     else if (engine == PART::engine::padSynth)
5640     {
5641         switch (insertParam)
5642         {
5643             case TOPLEVEL::insertType::amplitude:
5644                 lfoReadWrite(getData, part->kit[kititem].padpars->AmpLfo);
5645                 break;
5646             case TOPLEVEL::insertType::frequency:
5647                 lfoReadWrite(getData, part->kit[kititem].padpars->FreqLfo);
5648                 break;
5649             case TOPLEVEL::insertType::filter:
5650                 lfoReadWrite(getData, part->kit[kititem].padpars->FilterLfo);
5651                 break;
5652         }
5653     }
5654     else if (engine >= PART::engine::addVoice1)
5655     {
5656         int nvoice = engine - PART::engine::addVoice1;
5657         switch (insertParam)
5658         {
5659             case TOPLEVEL::insertType::amplitude:
5660                 lfoReadWrite(getData, part->kit[kititem].adpars->VoicePar[nvoice].AmpLfo);
5661                 break;
5662             case TOPLEVEL::insertType::frequency:
5663                 lfoReadWrite(getData, part->kit[kititem].adpars->VoicePar[nvoice].FreqLfo);
5664                 break;
5665             case TOPLEVEL::insertType::filter:
5666                 lfoReadWrite(getData, part->kit[kititem].adpars->VoicePar[nvoice].FilterLfo);
5667                 break;
5668         }
5669     }
5670 }
5671 
5672 
lfoReadWrite(CommandBlock * getData,LFOParams * pars)5673 void InterChange::lfoReadWrite(CommandBlock *getData, LFOParams *pars)
5674 {
5675     bool write = (getData->data.type & TOPLEVEL::type::Write) > 0;
5676 
5677     float val = getData->data.value;
5678 
5679     switch (getData->data.control)
5680     {
5681         case LFOINSERT::control::speed:
5682             if(pars->Pbpm) // set a flag so CLI can read the status
5683                 getData->data.offset = 1;
5684             if (write)
5685                 pars->setPfreq(val * Fmul2I);
5686             else
5687                 val = float(pars->PfreqI) / float(Fmul2I);
5688             break;
5689         case LFOINSERT::control::depth:
5690             if (write)
5691                 pars->setPintensity(val);
5692             else
5693                 val = pars->Pintensity;
5694             break;
5695         case LFOINSERT::control::delay:
5696             if (write)
5697                 pars->setPdelay(val);
5698             else
5699                 val = pars->Pdelay;
5700             break;
5701         case LFOINSERT::control::start:
5702             if (write)
5703                 pars->setPstartphase(val);
5704             else
5705                 val = pars->Pstartphase;
5706             break;
5707         case LFOINSERT::control::amplitudeRandomness:
5708             if (write)
5709                 pars->setPrandomness(val);
5710             else
5711                 val = pars->Prandomness;
5712             break;
5713         case LFOINSERT::control::type:
5714             if (write)
5715                 pars->setPLFOtype(lrint(val));
5716             else
5717                 val = pars->PLFOtype;
5718             break;
5719         case LFOINSERT::control::continuous:
5720             if (write)
5721                 pars->setPcontinous(_SYS_::F2B(val));
5722             else
5723                 val = pars->Pcontinous;
5724             break;
5725         case LFOINSERT::control::bpm:
5726             if (write)
5727                 pars->setPbpm(_SYS_::F2B(val));
5728             else
5729                 val = pars->Pbpm;
5730             break;
5731         case LFOINSERT::control::frequencyRandomness:
5732             if (write)
5733                 pars->setPfreqrand(val);
5734             else
5735                 val = pars->Pfreqrand;
5736             break;
5737         case LFOINSERT::control::stretch:
5738             if (write)
5739                 pars->setPstretch(val);
5740             else
5741                 val = pars->Pstretch;
5742             break;
5743     }
5744 
5745     if (write)
5746         pars->presetsUpdated();
5747     else
5748         getData->data.value = val;
5749 }
5750 
5751 
commandFilter(CommandBlock * getData)5752 void InterChange::commandFilter(CommandBlock *getData)
5753 {
5754     unsigned char npart = getData->data.part;
5755     unsigned char kititem = getData->data.kit;
5756     unsigned char engine = getData->data.engine;
5757 
5758     Part *part;
5759     part = synth->part[npart];
5760 
5761     if (engine == PART::engine::addSynth)
5762     {
5763         filterReadWrite(getData, part->kit[kititem].adpars->GlobalPar.GlobalFilter
5764                     , &part->kit[kititem].adpars->GlobalPar.PFilterVelocityScale
5765                     , &part->kit[kititem].adpars->GlobalPar.PFilterVelocityScaleFunction);
5766     }
5767     else if (engine == PART::engine::subSynth)
5768     {
5769         filterReadWrite(getData, part->kit[kititem].subpars->GlobalFilter
5770                     , &part->kit[kititem].subpars->PGlobalFilterVelocityScale
5771                     , &part->kit[kititem].subpars->PGlobalFilterVelocityScaleFunction);
5772     }
5773     else if (engine == PART::engine::padSynth)
5774     {
5775         filterReadWrite(getData, part->kit[kititem].padpars->GlobalFilter
5776                     , &part->kit[kititem].padpars->PFilterVelocityScale
5777                     , &part->kit[kititem].padpars->PFilterVelocityScaleFunction);
5778     }
5779     else if (engine >= PART::engine::addVoice1)
5780     {
5781         int eng = engine - PART::engine::addVoice1;
5782         filterReadWrite(getData, part->kit[kititem].adpars->VoicePar[eng].VoiceFilter
5783                     , &part->kit[kititem].adpars->VoicePar[eng].PFilterVelocityScale
5784                     , &part->kit[kititem].adpars->VoicePar[eng].PFilterVelocityScaleFunction);
5785     }
5786 }
5787 
5788 
filterReadWrite(CommandBlock * getData,FilterParams * pars,unsigned char * velsnsamp,unsigned char * velsns)5789 void InterChange::filterReadWrite(CommandBlock *getData, FilterParams *pars, unsigned char *velsnsamp, unsigned char *velsns)
5790 {
5791     bool write = (getData->data.type & TOPLEVEL::type::Write) > 0;
5792 
5793     float val = getData->data.value;
5794     int value_int = lrint(val);
5795 
5796     int nseqpos = getData->data.parameter;
5797     int nformant = getData->data.parameter;
5798     int nvowel = getData->data.offset;
5799 
5800     switch (getData->data.control)
5801     {
5802         case FILTERINSERT::control::centerFrequency:
5803             if (write)
5804                 pars->Pfreq = val;
5805             else
5806                 val = pars->Pfreq;
5807             break;
5808         case FILTERINSERT::control::Q:
5809             if (write)
5810                 pars->Pq = val;
5811             else
5812                 val = pars->Pq;
5813             break;
5814         case FILTERINSERT::control::frequencyTracking:
5815             if (write)
5816                 pars->Pfreqtrack = val;
5817             else
5818                 val = pars->Pfreqtrack;
5819             break;
5820         case FILTERINSERT::control::velocitySensitivity:
5821             if (velsnsamp != NULL)
5822             {
5823                 if (write)
5824                     *velsnsamp = value_int;
5825                 else
5826                     val = *velsnsamp;
5827             }
5828             break;
5829         case FILTERINSERT::control::velocityCurve:
5830             if (velsns != NULL)
5831             {
5832                 if (write)
5833                     *velsns = value_int;
5834                 else
5835                     val = *velsns;
5836             }
5837             break;
5838         case FILTERINSERT::control::gain:
5839             if (write)
5840             {
5841                 pars->Pgain = val;
5842                 pars->changed = true;
5843             }
5844             else
5845                 val = pars->Pgain;
5846             break;
5847         case FILTERINSERT::control::stages:
5848             if (write)
5849             {
5850                 pars->Pstages = value_int;
5851                 pars->changed = true;
5852             }
5853             else
5854                 val = pars->Pstages;
5855             break;
5856         case FILTERINSERT::control::baseType:
5857             if (write)
5858             {
5859                 if (pars->Pcategory != value_int)
5860                 {
5861                     pars->Pgain = 64;
5862                     pars->Ptype = 0;
5863                     pars->changed = true;
5864                     pars->Pcategory = value_int;
5865                 }
5866             }
5867             else
5868                 val = pars->Pcategory;
5869             break;
5870         case FILTERINSERT::control::analogType:
5871         case FILTERINSERT::control::stateVariableType:
5872             if (write)
5873             {
5874                 pars->Ptype = value_int;
5875                 pars->changed = true;
5876             }
5877             else
5878                 val = pars->Ptype;
5879             break;
5880         case FILTERINSERT::control::frequencyTrackingRange:
5881             if (write)
5882             {
5883                 pars->Pfreqtrackoffset = (value_int != 0);
5884                 pars->changed = true;
5885             }
5886             else
5887                 val = pars->Pfreqtrackoffset;
5888             break;
5889 
5890         case FILTERINSERT::control::formantSlowness:
5891             if (write)
5892             {
5893                 pars->Pformantslowness = val;
5894                 pars->changed = true;
5895             }
5896             else
5897                 val = pars->Pformantslowness;
5898             break;
5899         case FILTERINSERT::control::formantClearness:
5900             if (write)
5901             {
5902                 pars->Pvowelclearness = val;
5903                 pars->changed = true;
5904             }
5905             else
5906                 val = pars->Pvowelclearness;
5907             break;
5908         case FILTERINSERT::control::formantFrequency:
5909             if (write)
5910             {
5911                 pars->Pvowels[nvowel].formants[nformant].freq = val;
5912                 pars->changed = true;
5913             }
5914             else
5915                 val = pars->Pvowels[nvowel].formants[nformant].freq;
5916             break;
5917         case FILTERINSERT::control::formantQ:
5918             if (write)
5919             {
5920                 pars->Pvowels[nvowel].formants[nformant].q = val;
5921                 pars->changed = true;
5922             }
5923             else
5924                 val = pars->Pvowels[nvowel].formants[nformant].q;
5925             break;
5926         case FILTERINSERT::control::formantAmplitude:
5927             if (write)
5928             {
5929                 pars->Pvowels[nvowel].formants[nformant].amp = val;
5930                 pars->changed = true;
5931             }
5932             else
5933                 val = pars->Pvowels[nvowel].formants[nformant].amp;
5934             break;
5935         case FILTERINSERT::control::formantStretch:
5936             if (write)
5937             {
5938                 pars->Psequencestretch = val;
5939                 pars->changed = true;
5940             }
5941             else
5942                 val = pars->Psequencestretch;
5943             break;
5944         case FILTERINSERT::control::formantCenter:
5945             if (write)
5946             {
5947                 pars->Pcenterfreq = val;
5948                 pars->changed = true;
5949             }
5950             else
5951                 val = pars->Pcenterfreq;
5952             break;
5953         case FILTERINSERT::control::formantOctave:
5954             if (write)
5955             {
5956                 pars->Poctavesfreq = val;
5957                 pars->changed = true;
5958             }
5959             else
5960                 val = pars->Poctavesfreq;
5961             break;
5962 
5963         case FILTERINSERT::control::numberOfFormants:
5964             if (write)
5965             {
5966                 pars->Pnumformants = value_int;
5967                 pars->changed = true;
5968             }
5969             else
5970                 val = pars->Pnumformants;
5971             break;
5972         case FILTERINSERT::control::vowelNumber: // this is local to the GUI
5973             break;
5974         case FILTERINSERT::control::formantNumber: // this is local to the GUI
5975             break;
5976         case FILTERINSERT::control::sequenceSize:
5977             if (write)
5978             {
5979                 pars->Psequencesize = value_int;
5980                 pars->changed = true;
5981             }
5982             else
5983                 val = pars->Psequencesize;
5984             break;
5985         case FILTERINSERT::control::sequencePosition:
5986             /*
5987              * this appears to be just setting the GUI
5988              * reference point yet sets pars changed.
5989              * why?
5990              */
5991             if (write)
5992                 pars->changed = true;
5993             else
5994             {
5995                 ;
5996             }
5997             break;
5998         case FILTERINSERT::control::vowelPositionInSequence:
5999             if (write)
6000             {
6001                 pars->Psequence[nseqpos].nvowel = value_int;
6002                 pars->changed = true;
6003             }
6004             else
6005                 val = pars->Psequence[nseqpos].nvowel;
6006             break;
6007         case FILTERINSERT::control::negateInput:
6008             if (write)
6009             {
6010                 pars->Psequencereversed = (value_int != 0);
6011                 pars->changed = true;
6012             }
6013             else
6014                 val = pars->Psequencereversed;
6015             break;
6016     }
6017 
6018     if (write)
6019         pars->presetsUpdated();
6020     else
6021         getData->data.value = val;
6022 }
6023 
6024 
commandEnvelope(CommandBlock * getData)6025 void InterChange::commandEnvelope(CommandBlock *getData)
6026 {
6027     unsigned char npart = getData->data.part;
6028     unsigned char kititem = getData->data.kit;
6029     unsigned char engine = getData->data.engine;
6030     unsigned char insertParam = getData->data.parameter;
6031 
6032     Part *part;
6033     part = synth->part[npart];
6034 
6035     std::string env;
6036     std::string name;
6037     if (engine == PART::engine::addSynth)
6038     {
6039         switch (insertParam)
6040         {
6041             case TOPLEVEL::insertType::amplitude:
6042                 envelopeReadWrite(getData, part->kit[kititem].adpars->GlobalPar.AmpEnvelope);
6043                 break;
6044             case TOPLEVEL::insertType::frequency:
6045                 envelopeReadWrite(getData, part->kit[kititem].adpars->GlobalPar.FreqEnvelope);
6046                 break;
6047             case TOPLEVEL::insertType::filter:
6048                 envelopeReadWrite(getData, part->kit[kititem].adpars->GlobalPar.FilterEnvelope);
6049                 break;
6050         }
6051     }
6052     else if (engine == PART::engine::subSynth)
6053     {
6054         switch (insertParam)
6055         {
6056             case TOPLEVEL::insertType::amplitude:
6057                 envelopeReadWrite(getData, part->kit[kititem].subpars->AmpEnvelope);
6058                 break;
6059             case TOPLEVEL::insertType::frequency:
6060                 envelopeReadWrite(getData, part->kit[kititem].subpars->FreqEnvelope);
6061                 break;
6062             case TOPLEVEL::insertType::filter:
6063                 envelopeReadWrite(getData, part->kit[kititem].subpars->GlobalFilterEnvelope);
6064                 break;
6065             case TOPLEVEL::insertType::bandwidth:
6066                 envelopeReadWrite(getData, part->kit[kititem].subpars->BandWidthEnvelope);
6067                 break;
6068         }
6069     }
6070     else if (engine == PART::engine::padSynth)
6071     {
6072         switch (insertParam)
6073         {
6074             case TOPLEVEL::insertType::amplitude:
6075                 envelopeReadWrite(getData, part->kit[kititem].padpars->AmpEnvelope);
6076                 break;
6077             case TOPLEVEL::insertType::frequency:
6078                 envelopeReadWrite(getData, part->kit[kititem].padpars->FreqEnvelope);
6079                 break;
6080             case TOPLEVEL::insertType::filter:
6081                 envelopeReadWrite(getData, part->kit[kititem].padpars->FilterEnvelope);
6082                 break;
6083         }
6084     }
6085 
6086     else if (engine >= PART::engine::addMod1)
6087     {
6088         int nvoice = engine - PART::engine::addMod1;
6089         switch (insertParam)
6090         {
6091             case TOPLEVEL::insertType::amplitude:
6092                 envelopeReadWrite(getData, part->kit[kititem].adpars->VoicePar[nvoice].FMAmpEnvelope);
6093                 break;
6094             case TOPLEVEL::insertType::frequency:
6095                 envelopeReadWrite(getData, part->kit[kititem].adpars->VoicePar[nvoice].FMFreqEnvelope);
6096                 break;
6097         }
6098     }
6099 
6100     else if (engine >= PART::engine::addVoice1)
6101     {
6102         int nvoice = engine - PART::engine::addVoice1;
6103         switch (insertParam)
6104         {
6105             case TOPLEVEL::insertType::amplitude:
6106                 envelopeReadWrite(getData, part->kit[kititem].adpars->VoicePar[nvoice].AmpEnvelope);
6107                 break;
6108             case TOPLEVEL::insertType::frequency:
6109                 envelopeReadWrite(getData, part->kit[kititem].adpars->VoicePar[nvoice].FreqEnvelope);
6110                 break;
6111             case TOPLEVEL::insertType::filter:
6112                 envelopeReadWrite(getData, part->kit[kititem].adpars->VoicePar[nvoice].FilterEnvelope);
6113                 break;
6114         }
6115     }
6116 }
6117 
6118 
envelopeReadWrite(CommandBlock * getData,EnvelopeParams * pars)6119 void InterChange::envelopeReadWrite(CommandBlock *getData, EnvelopeParams *pars)
6120 {
6121     int val = lrint(getData->data.value); // these are all integers or bool
6122     bool write = (getData->data.type & TOPLEVEL::type::Write) > 0;
6123 
6124     unsigned char point = getData->data.control;
6125     unsigned char insert = getData->data.insert;
6126     unsigned char Xincrement = getData->data.offset;
6127 
6128     int envpoints = pars->Penvpoints;
6129     bool isAddpoint = (Xincrement < UNUSED);
6130 
6131     if (insert == TOPLEVEL::insert::envelopePoints) // here be dragons :(
6132     {
6133         if (!pars->Pfreemode)
6134         {
6135             getData->data.value = UNUSED;
6136             getData->data.offset = UNUSED;
6137             return;
6138         }
6139 
6140         if (!write || point == 0 || point >= envpoints)
6141         {
6142             getData->data.value = UNUSED;
6143             getData->data.offset = envpoints;
6144             return;
6145         }
6146 
6147         if (isAddpoint)
6148         {
6149             if (envpoints < MAX_ENVELOPE_POINTS)
6150             {
6151                 pars->Penvpoints += 1;
6152                 for (int i = envpoints; i >= point; -- i)
6153                 {
6154                     pars->Penvdt[i + 1] = pars->Penvdt[i];
6155                     pars->Penvval[i + 1] = pars->Penvval[i];
6156                 }
6157 
6158                 if (point == 0)
6159                     pars->Penvdt[1] = 64;
6160 
6161                 if (point <= pars->Penvsustain)
6162                     ++ pars->Penvsustain;
6163 
6164                 pars->Penvdt[point] = Xincrement;
6165                 pars->Penvval[point] = val;
6166                 getData->data.value = val;
6167                 getData->data.offset = Xincrement;
6168                 pars->presetsUpdated();
6169             }
6170             else
6171                 getData->data.value = UNUSED;
6172             return;
6173         }
6174         else if (envpoints < 4)
6175         {
6176             getData->data.value = UNUSED;
6177             getData->data.offset = UNUSED;
6178             return; // can't have less than 4
6179         }
6180         else
6181         {
6182             envpoints -= 1;
6183             for (int i = point; i < envpoints; ++ i)
6184             {
6185                 pars->Penvdt[i] = pars->Penvdt[i + 1];
6186                 pars->Penvval[i] = pars->Penvval[i + 1];
6187             }
6188             if (point <= pars->Penvsustain)
6189                 -- pars->Penvsustain;
6190             pars->Penvpoints = envpoints;
6191             getData->data.value = envpoints;
6192             pars->presetsUpdated();
6193         }
6194         return;
6195     }
6196 
6197     if (insert == TOPLEVEL::insert::envelopePointChange)
6198     {
6199         if (!pars->Pfreemode || point >= envpoints)
6200         {
6201             getData->data.value = UNUSED;
6202             getData->data.offset = UNUSED;
6203             return;
6204         }
6205         if (write)
6206         {
6207             pars->Penvval[point] = val;
6208             if (point == 0)
6209                 Xincrement = 0;
6210             else
6211                 pars->Penvdt[point] = Xincrement;
6212             pars->presetsUpdated();
6213         }
6214         else
6215         {
6216             val = pars->Penvval[point];
6217             Xincrement = pars->Penvdt[point];
6218         }
6219         getData->data.value = val;
6220         getData->data.offset = Xincrement;
6221         return;
6222     }
6223 
6224     switch (getData->data.control)
6225     {
6226         case ENVELOPEINSERT::control::attackLevel:
6227             if (write)
6228                 pars->PA_val = val;
6229             else
6230                 val = pars->PA_val;
6231             break;
6232         case ENVELOPEINSERT::control::attackTime:
6233             if (write)
6234                 pars->PA_dt = val;
6235             else
6236                 val = pars->PA_dt;
6237             break;
6238         case ENVELOPEINSERT::control::decayLevel:
6239             if (write)
6240                 pars->PD_val = val;
6241             else
6242                 val = pars->PD_val;
6243             break;
6244         case ENVELOPEINSERT::control::decayTime:
6245             if (write)
6246                 pars->PD_dt = val;
6247             else
6248                 val = pars->PD_dt;
6249             break;
6250         case ENVELOPEINSERT::control::sustainLevel:
6251             if (write)
6252                 pars->PS_val = val;
6253             else
6254                 val = pars->PS_val;
6255             break;
6256         case ENVELOPEINSERT::control::releaseTime:
6257             if (write)
6258                 pars->PR_dt = val;
6259             else
6260                 val = pars->PR_dt;
6261             break;
6262         case ENVELOPEINSERT::control::releaseLevel:
6263             if (write)
6264                 pars->PR_val = val;
6265             else
6266                 val = pars->PR_val;
6267             break;
6268         case ENVELOPEINSERT::control::stretch:
6269             if (write)
6270                 pars->Penvstretch = val;
6271             else
6272                 val = pars->Penvstretch;
6273             break;
6274 
6275         case ENVELOPEINSERT::control::forcedRelease:
6276             if (write)
6277                 pars->Pforcedrelease = (val != 0);
6278             else
6279                 val = pars->Pforcedrelease;
6280             break;
6281         case ENVELOPEINSERT::control::linearEnvelope:
6282             if (write)
6283                 pars->Plinearenvelope = (val != 0);
6284             else
6285                 val = pars->Plinearenvelope;
6286             break;
6287 
6288         case ENVELOPEINSERT::control::edit:
6289             break;
6290 
6291         case ENVELOPEINSERT::control::enableFreeMode:
6292             if (write)
6293             {
6294                 if (val != 0)
6295                     pars->Pfreemode = 1;
6296                 else
6297                     pars->Pfreemode = 0;
6298             }
6299             else
6300                 val = pars->Pfreemode;
6301             break;
6302         case ENVELOPEINSERT::control::points:
6303             if (!pars->Pfreemode)
6304             {
6305                 val = UNUSED;
6306                 Xincrement = UNUSED;
6307             }
6308             else
6309             {
6310                 val = envpoints;
6311                 Xincrement = envpoints; // don't really need this now
6312             }
6313             break;
6314         case ENVELOPEINSERT::control::sustainPoint:
6315             if (write)
6316                 pars->Penvsustain = val;
6317             else
6318                 val = pars->Penvsustain;
6319             break;
6320     }
6321     if (write)
6322         pars->presetsUpdated();
6323     getData->data.value = val;
6324     getData->data.offset = Xincrement;
6325     return;
6326 }
6327 
6328 
commandSysIns(CommandBlock * getData)6329 void InterChange::commandSysIns(CommandBlock *getData)
6330 {
6331     float value = getData->data.value;
6332     unsigned char type = getData->data.type;
6333     unsigned char control = getData->data.control;
6334     unsigned char npart = getData->data.part;
6335     unsigned char effnum = getData->data.engine;
6336     unsigned char insert = getData->data.insert;
6337 
6338     bool write = (type & TOPLEVEL::type::Write) > 0;
6339     //std::cout << "Itype " << int(type) << "  val " << value << "  cont " << int(control) << "  part " << int(npart) << "  effnum " << int(effnum) << "  insert " << int(insert) << std::endl;
6340 
6341     int value_int = lrint(value);
6342     bool isSysEff = (npart == TOPLEVEL::section::systemEffects);
6343     if (isSysEff)
6344         effnum = synth->syseffnum;
6345     else
6346         effnum = synth->inseffnum;
6347 
6348     if (insert == UNUSED)
6349     {
6350         switch (control)
6351         {
6352             case EFFECT::sysIns::effectNumber:
6353                 if (write)
6354                 {
6355                     if (isSysEff)
6356                     {
6357                         synth->syseffnum = value_int;
6358                         getData->data.parameter = (synth->sysefx[value_int]->geteffectpar(-1) != 0);
6359                     }
6360                     else
6361                     {
6362                         synth->inseffnum = value_int;
6363                         getData->data.parameter = (synth->insefx[value_int]->geteffectpar(-1) != 0);
6364                     }
6365                     getData->data.source |= getData->data.source |= TOPLEVEL::action::forceUpdate;
6366                     // the line above is to show it's changed from preset values
6367                     getData->data.engine = value_int;
6368                 }
6369                 else
6370                 {
6371                     if (isSysEff)
6372                         value = synth->syseffnum;
6373                     else
6374                         value = synth->inseffnum;
6375                 }
6376                 break;
6377             case EFFECT::sysIns::effectType:
6378                 if (write)
6379                 {
6380                     if (isSysEff)
6381                     {
6382                         synth->sysefx[effnum]->changeeffect(value_int);
6383                         getData->data.parameter = (synth->sysefx[effnum]->geteffectpar(-1) != 0);
6384                     }
6385                     else
6386                     {
6387                         synth->insefx[effnum]->changeeffect(value_int);
6388                         getData->data.parameter = (synth->insefx[effnum]->geteffectpar(-1) != 0);
6389                     }
6390                     getData->data.offset = 0;
6391                 }
6392                 else
6393                 {
6394                     if (isSysEff)
6395                         value = synth->sysefx[effnum]->geteffect();
6396                     else
6397                         value = synth->insefx[effnum]->geteffect();
6398                 }
6399                 break;
6400             case EFFECT::sysIns::effectDestination: // insert only
6401                 if (write)
6402                 {
6403                     synth->Pinsparts[effnum] = value_int;
6404                     if (value_int == -1)
6405                         synth->insefx[effnum]->cleanup();
6406                 }
6407                 else
6408                     value = synth->Pinsparts[effnum];
6409                 break;
6410             case EFFECT::sysIns::effectEnable: // system only
6411                 if (write)
6412                 {
6413                     bool newSwitch = _SYS_::F2B(value);
6414                     bool oldSwitch = synth->syseffEnable[effnum];
6415                     synth->syseffEnable[effnum] = newSwitch;
6416                     if (newSwitch != oldSwitch)
6417                         synth->sysefx[effnum]->cleanup();
6418                 }
6419                 else
6420                     value = synth->syseffEnable[effnum];
6421                 break;
6422         }
6423     }
6424     else // system only
6425     {
6426         if (write)
6427             synth->setPsysefxsend(effnum, control, value);
6428         else
6429             value = synth->Psysefxsend[effnum][control];
6430     }
6431 
6432     if (!write)
6433         getData->data.value = value;
6434 }
6435 
6436 
commandEffects(CommandBlock * getData)6437 void InterChange::commandEffects(CommandBlock *getData)
6438 {
6439     float value = getData->data.value;
6440     int value_int = int(value + 0.5f);
6441     unsigned char type = getData->data.type;
6442     unsigned char control = getData->data.control;
6443     unsigned char npart = getData->data.part;
6444     unsigned char kititem = getData->data.kit;
6445     unsigned char effnum = getData->data.engine;
6446 
6447     bool write = (type & TOPLEVEL::type::Write) > 0;
6448     if (write)
6449     {
6450         getData->data.source |= getData->data.source |= TOPLEVEL::action::forceUpdate;
6451         // the line above is to show it's changed from preset values
6452     }
6453 
6454     EffectMgr *eff;
6455 
6456     if (npart == TOPLEVEL::section::systemEffects)
6457         eff = synth->sysefx[effnum];
6458 
6459     else if (npart == TOPLEVEL::section::insertEffects)
6460         eff = synth->insefx[effnum];
6461     else if (npart < NUM_MIDI_PARTS)
6462         eff = synth->part[npart]->partefx[effnum];
6463     else
6464         return; // invalid part number
6465     if (kititem > EFFECT::type::dynFilter)
6466         return; // invalid kit number
6467     if (control != PART::control::effectType && (kititem & 127) != eff->geteffect())
6468     {
6469         if ((getData->data.source & TOPLEVEL::action::noAction) != TOPLEVEL::action::fromMIDI)
6470             synth->getRuntime().Log("Not Available"); // TODO sort this better for CLI as well as MIDI
6471         getData->data.source = TOPLEVEL::action::noAction;
6472         return;
6473     }
6474 
6475     if (eff->geteffectpar(EFFECT::control::bpm) == 1)
6476         getData->data.offset = 1; // mark this for reporting in Data2Text
6477 
6478     if (kititem == EFFECT::type::dynFilter && getData->data.insert != UNUSED)
6479     {
6480         if (write)
6481             eff->seteffectpar(-1, true); // effect changed
6482         filterReadWrite(getData, eff->filterpars,NULL,NULL);
6483         return;
6484     }
6485     if (control >= EFFECT::control::changed)
6486     {
6487         if (!write)
6488         {
6489             value = eff->geteffectpar(-1);
6490             getData->data.value = value;
6491         }
6492         return; // specific for reading change status
6493     }
6494     if (write)
6495     {
6496         if (kititem == EFFECT::type::eq)
6497         /*
6498          * specific to EQ
6499          * Control 1 is not a saved parameter, but a band index.
6500          * Also, EQ does not have presets, and 16 is the control
6501          * for the band 1 frequency parameter
6502         */
6503         {
6504             if (control <= 1)
6505                 eff->seteffectpar(control, value_int);
6506             else
6507             {
6508                 eff->seteffectpar(control + (eff->geteffectpar(1) * 5), value_int);
6509                 getData->data.parameter = eff->geteffectpar(1);
6510             }
6511         }
6512         else
6513         {
6514             if (control == EFFECT::control::preset)
6515                 eff->changepreset(value_int);
6516             else
6517             {
6518                 eff->seteffectpar(control, value_int);
6519                 if (kititem == EFFECT::type::reverb && control == 10 && value_int == 2)
6520                     // bandwidth type update for GUI
6521                     getData->data.offset = eff->geteffectpar(12);
6522             }
6523         }
6524     }
6525     else
6526     {
6527         if (kititem == EFFECT::type::eq && control > 1) // specific to EQ
6528         {
6529             value = eff->geteffectpar(control + (eff->geteffectpar(1) * 5));
6530             getData->data.parameter = eff->geteffectpar(1);
6531         }
6532         else
6533         {
6534             if (control == EFFECT::control::preset)
6535                 value = eff->getpreset();
6536             else
6537                 value = eff->geteffectpar(control);
6538         }
6539     }
6540 
6541     if (!write)
6542         getData->data.value = value;
6543 }
6544 
6545 // tests and returns corrected values
testLimits(CommandBlock * getData)6546 void InterChange::testLimits(CommandBlock *getData)
6547 {
6548     float value = getData->data.value;
6549 
6550     int control = getData->data.control;
6551     /*
6552      * This is a special case as existing defined
6553      * midi CCs need to be checked.
6554      * I don't like special cases either :(
6555      */
6556     if (getData->data.part == TOPLEVEL::section::config
6557         && (control == CONFIG::control::bankRootCC
6558         || control == CONFIG::control::bankCC
6559         || control == CONFIG::control::extendedProgramChangeCC))
6560     {
6561         getData->data.miscmsg = NO_MSG; // just to be sure
6562         if (value > 119)
6563             return;
6564         std::string text;
6565         if (control == CONFIG::control::bankRootCC)
6566         {
6567             text = synth->getRuntime().masterCCtest(int(value));
6568             if (text != "")
6569                 getData->data.miscmsg = textMsgBuffer.push(text);
6570             return;
6571         }
6572         if (control == CONFIG::control::bankCC)
6573         {
6574             if (value != 0 && value != 32)
6575                 return;
6576             text = synth->getRuntime().masterCCtest(int(value));
6577             if (text != "")
6578                 getData->data.miscmsg = textMsgBuffer.push(text);
6579             return;
6580         }
6581         text = synth->getRuntime().masterCCtest(int(value));
6582         if (text != "")
6583             getData->data.miscmsg = textMsgBuffer.push(text);
6584         return;
6585     }
6586 }
6587 
6588 
6589 // more work needed here :(
returnLimits(CommandBlock * getData)6590 float InterChange::returnLimits(CommandBlock *getData)
6591 {
6592     // bit 5 set is used to denote midi learnable
6593     // bit 7 set denotes the value is used as an integer
6594 
6595     int control = (int) getData->data.control;
6596     int npart = (int) getData->data.part;
6597     int kititem = (int) getData->data.kit;
6598     int engine = (int) getData->data.engine;
6599     int insert = (int) getData->data.insert;
6600     int parameter = (int) getData->data.parameter;
6601     int miscmsg = (int) getData->data.miscmsg;
6602 
6603     float value = getData->data.value;
6604 
6605     getData->data.type &= TOPLEVEL::type::Default; // clear all flags
6606     int request = getData->data.type; // catches Adj, Min, Max, Def
6607     getData->data.type |= TOPLEVEL::type::Integer; // default is integer & not learnable
6608 
6609     if (npart == TOPLEVEL::section::config)
6610         return synth->getConfigLimits(getData);
6611 
6612     if (npart == TOPLEVEL::section::bank)
6613         return value;
6614 
6615     if (npart == TOPLEVEL::section::main)
6616         return synth->getLimits(getData);
6617 
6618     if (npart == TOPLEVEL::section::scales)
6619         return synth->microtonal.getLimits(getData);
6620 
6621     if (npart == TOPLEVEL::section::vector)
6622         return synth->getVectorLimits(getData);
6623 
6624     float min;
6625     float max;
6626     float def;
6627 
6628     if (insert == TOPLEVEL::insert::filterGroup)
6629     {
6630         filterLimit filterLimits;
6631         return filterLimits.getFilterLimits(getData);
6632     }
6633     // should prolly move other inserts up here
6634 
6635     if (kititem >= EFFECT::type::none && kititem <= EFFECT::type::dynFilter)
6636     {
6637         LimitMgr limits;
6638         return limits.geteffectlimits(getData);
6639     }
6640 
6641     if (npart < NUM_MIDI_PARTS)
6642     {
6643         Part *part;
6644         part = synth->part[npart];
6645 
6646         if (engine == PART::engine::subSynth && (insert == UNUSED || (insert >= TOPLEVEL::oscillatorGroup && insert <= TOPLEVEL::harmonicPhaseBandwidth)) && parameter == UNUSED)
6647         {
6648             SUBnoteParameters *subpars;
6649             subpars = part->kit[kititem].subpars;
6650             return subpars->getLimits(getData);
6651         }
6652 
6653         if (insert == TOPLEVEL::insert::partEffectSelect || (engine == UNUSED && (kititem == UNUSED || insert == TOPLEVEL::insert::kitGroup)))
6654             return part->getLimits(getData);
6655 
6656         if ((insert == TOPLEVEL::insert::kitGroup || insert == UNUSED) && parameter == UNUSED && miscmsg == UNUSED)
6657         {
6658             if (engine == PART::engine::addSynth || (engine >= PART::engine::addVoice1 && engine <= PART::engine::addMod8))
6659             {
6660                 ADnoteParameters *adpars;
6661                 adpars = part->kit[kititem].adpars;
6662                 return adpars->getLimits(getData);
6663             }
6664             if (engine == PART::engine::subSynth)
6665             {
6666                 SUBnoteParameters *subpars;
6667                 subpars = part->kit[kititem].subpars;
6668                 return subpars->getLimits(getData);
6669             }
6670             if (engine == PART::engine::padSynth)
6671             {
6672                 PADnoteParameters *padpars;
6673                 padpars = part->kit[kititem].padpars;
6674                 return padpars->getLimits(getData);
6675             }
6676             // there may be other stuff
6677 
6678             min = 0;
6679             max = 127;
6680             def = 0;
6681 
6682             std::cout << "Using engine defaults" << std::endl;
6683             switch (request)
6684             {
6685                 case TOPLEVEL::type::Adjust:
6686                     if (value < min)
6687                         value = min;
6688                     else if (value > max)
6689                         value = max;
6690                     break;
6691                 case TOPLEVEL::type::Minimum:
6692                     value = min;
6693                     break;
6694                 case TOPLEVEL::type::Maximum:
6695                     value = max;
6696                     break;
6697                 case TOPLEVEL::type::Default:
6698                     value = def;
6699                     break;
6700             }
6701             return value;
6702         }
6703         if (insert >= TOPLEVEL::insert::oscillatorGroup && insert <= TOPLEVEL::insert::harmonicPhaseBandwidth)
6704         {
6705             return part->kit[0].adpars->VoicePar[0].POscil->getLimits(getData);
6706             // we also use this for pad limits
6707             // as oscillator values identical
6708         }
6709         if (insert == TOPLEVEL::insert::resonanceGroup || insert == TOPLEVEL::insert::resonanceGraphInsert)
6710         {
6711             ResonanceLimits resonancelimits;
6712             return resonancelimits.getLimits(getData);
6713         }
6714         if (insert == TOPLEVEL::insert::LFOgroup && engine != PART::engine::subSynth && parameter <= TOPLEVEL::insertType::filter)
6715         {
6716             LFOlimit lfolimits;
6717             return lfolimits.getLFOlimits(getData);
6718         }
6719         if (insert == TOPLEVEL::insert::envelopeGroup)
6720         {
6721             envelopeLimit envelopeLimits;
6722             return envelopeLimits.getEnvelopeLimits(getData);
6723         }
6724         if (insert == TOPLEVEL::insert::envelopePoints || insert == TOPLEVEL::insert::envelopePointChange)
6725             return 1; // temporary solution :(
6726         min = 0;
6727         max = 127;
6728         def = 0;
6729         std::cout << "Using insert defaults" << std::endl;
6730 
6731             switch (request)
6732             {
6733                 case TOPLEVEL::type::Adjust:
6734                     if (value < min)
6735                         value = min;
6736                     else if (value > max)
6737                         value = max;
6738                 break;
6739                 case TOPLEVEL::type::Minimum:
6740                     value = min;
6741                     break;
6742                 case TOPLEVEL::type::Maximum:
6743                     value = max;
6744                     break;
6745                 case TOPLEVEL::type::Default:
6746                     value = def;
6747                     break;
6748             }
6749             return value;
6750     }
6751 
6752     // not sure where the following should realy be
6753     if (npart == TOPLEVEL::section::systemEffects)
6754     {
6755         min = 0;
6756         def = 0;
6757         max = 8;
6758         switch (control)
6759         {
6760             case EFFECT::sysIns::toEffect1:
6761             case EFFECT::sysIns::toEffect2:
6762             case EFFECT::sysIns::toEffect3:
6763                 max = 127;
6764                 getData->data.type |= TOPLEVEL::type::Learnable;
6765                 break;
6766             case EFFECT::sysIns::effectNumber:
6767                 max = 3;
6768                 break;
6769             case EFFECT::sysIns::effectType:
6770                 break;
6771             case EFFECT::sysIns::effectEnable:
6772                 def = 1;
6773                 max = 1;
6774                 getData->data.type |= TOPLEVEL::type::Learnable;
6775                 break;
6776         }
6777 
6778         switch (request)
6779         {
6780             case TOPLEVEL::type::Adjust:
6781                 if (value < min)
6782                     value = min;
6783                 else if (value > max)
6784                     value = max;
6785             break;
6786             case TOPLEVEL::type::Minimum:
6787                 value = min;
6788                 break;
6789             case TOPLEVEL::type::Maximum:
6790                 value = max;
6791                 break;
6792             case TOPLEVEL::type::Default:
6793                 value = def;
6794                 break;
6795         }
6796         return value;
6797     }
6798 
6799     if (npart == TOPLEVEL::section::insertEffects)
6800     {
6801         min = 0;
6802         def = 0;
6803         max = 8;
6804         switch (control)
6805         {
6806             case EFFECT::sysIns::effectNumber:
6807                 max = 7;
6808                 break;
6809             case EFFECT::sysIns::effectType:
6810                 break;
6811             case EFFECT::sysIns::effectDestination:
6812                 min = -2;
6813                 def = -1;
6814                 max = 63;
6815                 break;
6816         }
6817 
6818         switch (request)
6819         {
6820             case TOPLEVEL::type::Adjust:
6821                 if (value < min)
6822                     value = min;
6823                 else if (value > max)
6824                     value = max;
6825             break;
6826             case TOPLEVEL::type::Minimum:
6827                 value = min;
6828                 break;
6829             case TOPLEVEL::type::Maximum:
6830                 value = max;
6831                 break;
6832             case TOPLEVEL::type::Default:
6833                 value = def;
6834                 break;
6835         }
6836         return value;
6837     }
6838 
6839     if (npart == TOPLEVEL::section::midiIn)
6840     {
6841         min = 0;
6842         max = 127;
6843         switch (control)
6844         {
6845             case PART::control::volume:
6846                 def = 96;
6847                 break;
6848             case PART::control::midiExpression:
6849                 def = 127;
6850                 break;
6851             case PART::control::midiSustain:
6852                 def = 0;
6853                 break;
6854             case PART::control::midiPortamento:
6855                 def = 0;
6856                 break;
6857             case PART::control::midiFMamp:
6858                 def = 127;
6859                 break;
6860             default:
6861                 def = 64;
6862         }
6863         //std::cout << "here " << int(def) << std::endl;
6864 
6865 
6866         switch (request)
6867         {
6868             case TOPLEVEL::type::Adjust:
6869                 if (value < min)
6870                     value = min;
6871                 else if (value > max)
6872                     value = max;
6873             break;
6874             case TOPLEVEL::type::Minimum:
6875                 value = min;
6876                 break;
6877             case TOPLEVEL::type::Maximum:
6878                 value = max;
6879                 break;
6880             case TOPLEVEL::type::Default:
6881                 value = def;
6882                 break;
6883         }
6884         return value;
6885     }
6886 
6887     min = 0;
6888     max = 127;
6889     def = 0;
6890     std::cout << "Using unknown defaults" << std::endl;
6891 
6892     switch (request)
6893     {
6894         case TOPLEVEL::type::Adjust:
6895             if (value < min)
6896                 value = min;
6897             else if (value > max)
6898                 value = max;
6899         break;
6900         case TOPLEVEL::type::Minimum:
6901             value = min;
6902             break;
6903         case TOPLEVEL::type::Maximum:
6904             value = max;
6905             break;
6906         case TOPLEVEL::type::Default:
6907             value = def;
6908             break;
6909     }
6910     return value;
6911 }
6912