/[svn]/linuxsampler/trunk/src/engines/common/InstrumentScriptVM.cpp
ViewVC logotype

Diff of /linuxsampler/trunk/src/engines/common/InstrumentScriptVM.cpp

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 2594 by schoenebeck, Thu Jun 5 00:16:25 2014 UTC revision 3971 by schoenebeck, Fri Jun 25 09:26:00 2021 UTC
# Line 1  Line 1 
1  /*  /*
2   * Copyright (c) 2014 Christian Schoenebeck   * Copyright (c) 2014 - 2021 Christian Schoenebeck
3   *   *
4   * http://www.linuxsampler.org   * http://www.linuxsampler.org
5   *   *
# Line 7  Line 7 
7   * See README file for details.   * See README file for details.
8   */   */
9    
10    #include "../../common/global_private.h"
11  #include "InstrumentScriptVM.h"  #include "InstrumentScriptVM.h"
12  #include "../AbstractEngineChannel.h"  #include "../AbstractEngineChannel.h"
13    #include "../../common/global_private.h"
14    #include "AbstractInstrumentManager.h"
15    #include "MidiKeyboardManager.h"
16    #include "Fade.h"
17    
18  namespace LinuxSampler {  namespace LinuxSampler {
19    
20      // circumvents a bug in GCC 4.4 which prevents the sizeof() expr to be used      ///////////////////////////////////////////////////////////////////////
21      // directly within the scrope of a class (would throw a compiler error with:      // class 'EventGroup'
22      // "object missing in reference to 'LinuxSampler::AbstractEngineChannel::ControllerTable'")  
23      static const int _AbstractEngineChannel_ControllerTable_size = sizeof(AbstractEngineChannel::ControllerTable);      void EventGroup::insert(vmint eventID) {
24            if (contains(eventID)) return;
25      InstrumentScriptVM::InstrumentScriptVM() : m_event(NULL) {  
26          m_CC.size = _AbstractEngineChannel_ControllerTable_size;          AbstractEngine* pEngine = m_script->pEngineChannel->pEngine;
27          m_CC_NUM = DECLARE_VMINT(m_cause, class Event, Param.CC.Controller);  
28          m_EVENT_NOTE = DECLARE_VMINT(m_cause, class Event, Param.Note.Key);          // before adding the new event ID, check if there are any dead events
29          m_EVENT_VELOCITY = DECLARE_VMINT(m_cause, class Event, Param.Note.Velocity);          // and remove them in that case, before otherwise we might run in danger
30            // to run out of free space on this group for event IDs if a lot of
31            // events die before being removed explicitly from the group by script
32            //
33            // NOTE: or should we do this "dead ones" check only once in a while?
34            ssize_t firstDead = -1;
35            for (size_t i = 0; i < size(); ++i) {
36                if (firstDead >= 0) {
37                    if (pEngine->EventByID(eventID)) {
38                        remove(firstDead, i - firstDead);
39                        firstDead = -1;
40                    }
41                } else {
42                    if (!pEngine->EventByID(eventID)) firstDead = i;
43                }
44            }
45            if (firstDead >= 0)
46                remove(firstDead, size() - firstDead);
47    
48            append(eventID);
49        }
50    
51        void EventGroup::erase(vmint eventID) {
52            size_t index = find(eventID);
53            remove(index);
54        }
55    
56        ///////////////////////////////////////////////////////////////////////
57        // class 'InstrumentScript'
58    
59        InstrumentScript::InstrumentScript(AbstractEngineChannel* pEngineChannel) {
60            parserContext = NULL;
61            bHasValidScript = false;
62            handlerInit = NULL;
63            handlerNote = NULL;
64            handlerRelease = NULL;
65            handlerController = NULL;
66            handlerRpn = NULL;
67            handlerNrpn = NULL;
68            pEvents = NULL;
69            for (int i = 0; i < 128; ++i)
70                pKeyEvents[i] = NULL;
71            this->pEngineChannel = pEngineChannel;
72            for (int i = 0; i < INSTR_SCRIPT_EVENT_GROUPS; ++i)
73                eventGroups[i].setScript(this);
74        }
75    
76        InstrumentScript::~InstrumentScript() {
77            resetAll();
78            if (pEvents) {
79                for (int i = 0; i < 128; ++i) delete pKeyEvents[i];
80                delete pEvents;
81            }
82        }
83    
84        /** @brief Load real-time instrument script.
85         *
86         * Loads the real-time instrument script given by @a text on the engine
87         * channel this InstrumentScript object belongs to (defined by
88         * pEngineChannel member variable). The sampler engine's resource manager is
89         * used to allocate and share equivalent scripts on multiple engine
90         * channels.
91         *
92         * @param text - source code of script
93         * @param patchVars - 'patch' variables being overridden by instrument
94         */
95        void InstrumentScript::load(const String& text,
96                                    const std::map<String,String>& patchVars)
97        {
98            dmsg(1,("Loading real-time instrument script ... "));
99    
100            // hand back old script reference and VM execution contexts
101            // (if not done already)
102            unload();
103    
104            code = text;
105    
106            AbstractInstrumentManager* pManager =
107                dynamic_cast<AbstractInstrumentManager*>(pEngineChannel->pEngine->GetInstrumentManager());
108    
109            /*
110               Get new script reference.
111    
112               Note: every engine channel now has its own compiled script object
113               (a.k.a. VMParserContext). Originally a compiled script was shared by
114               multiple engine channels. This was wrong: we cannot share compiled
115               script instances among multiple engine channels (parts), for two
116               reasons:
117    
118               1. VMParserContext not only encompasses the compiled tree
119                  presentation of the requested script, but also global variables
120                  and we don't want those global variables to be modified by
121                  different sampler parts, as this would not be expected behaviour
122                  by instrument script authors.
123    
124               2. If there is more than one sampler engine instance (e.g. if there
125                  are multiple audio output device instances) this would even crash,
126                  because each sampler engine instance has its own ScriptVM
127                  instance, and a (VM)ParserContext is always tied to exactly one
128                  ScriptVM instance.
129    
130               We would not be buying much by sharing compiled scripts anyway, as a
131               script usually compiles in couple microseconds and RAM usage is also
132               neglectable.
133            */
134            parserContext = pManager->scripts.Borrow({
135                    .code = text,
136                    .patchVars = patchVars,
137                    .engineChannel = pEngineChannel /* unique owner of script */
138                },
139                pEngineChannel /* who is asking to borrow */
140            );
141            if (!parserContext->errors().empty()) {
142                std::vector<ParserIssue> errors = parserContext->errors();
143                std::cerr << "[ScriptVM] Could not load instrument script, there were "
144                        << errors.size() << " parser errors:\n";
145                for (int i = 0; i < errors.size(); ++i)
146                    errors[i].dump();
147                return; // stop here if there were any parser errors
148            }
149    
150            handlerInit = parserContext->eventHandlerByName("init");
151            handlerNote = parserContext->eventHandlerByName("note");
152            handlerRelease = parserContext->eventHandlerByName("release");
153            handlerController = parserContext->eventHandlerByName("controller");
154            handlerRpn = parserContext->eventHandlerByName("rpn");
155            handlerNrpn = parserContext->eventHandlerByName("nrpn");
156            bHasValidScript =
157                handlerInit || handlerNote || handlerRelease || handlerController ||
158                handlerRpn || handlerNrpn;
159    
160            // amount of script handlers each script event has to execute
161            int handlerExecCount = 0;
162            if (handlerNote || handlerRelease || handlerController || handlerRpn ||
163                handlerNrpn) // only one of these are executed after "init" handler
164                handlerExecCount++;
165    
166            // create script event pool (if it doesn't exist already)
167            if (!pEvents) {
168                pEvents = new Pool<ScriptEvent>(CONFIG_MAX_EVENTS_PER_FRAGMENT);
169                for (int i = 0; i < 128; ++i)
170                    pKeyEvents[i] = new RTList<ScriptEvent>(pEvents);
171                // reset RTAVLNode's tree node member variables after nodes are allocated
172                // (since we can't use a constructor right now, we do that initialization here)
173                while (!pEvents->poolIsEmpty()) {
174                    RTList<ScriptEvent>::Iterator it = pEvents->allocAppend();
175                    it->reset();
176                }
177            }
178            pEvents->clear(); // outside of upper block, as loop below must always start from cleared list
179    
180            // create new VM execution contexts for new script
181            while (!pEvents->poolIsEmpty()) {
182                RTList<ScriptEvent>::Iterator it = pEvents->allocAppend();
183                it->execCtx = pEngineChannel->pEngine->pScriptVM->createExecContext(
184                    parserContext
185                );
186                it->handlers = new VMEventHandler*[handlerExecCount+1];
187            }
188            pEvents->clear();
189    
190            dmsg(1,("Done\n"));
191        }
192    
193        /** @brief Unload real-time instrument script.
194         *
195         * Unloads the currently used real-time instrument script and frees all
196         * resources allocated for that script. The sampler engine's resource manager
197         * is used to share equivalent scripts among multiple sampler channels, and
198         * to deallocate the parsed script once not used on any engine channel
199         * anymore.
200         *
201         * Calling this method will however not clear the @c code member variable.
202         * Thus, the script can be parsed again afterwards.
203         */
204        void InstrumentScript::unload() {
205            //dmsg(1,("InstrumentScript::unload(this=0x%llx)\n", this));
206    
207            if (parserContext)
208                dmsg(1,("Unloading current instrument script.\n"));
209    
210            resetEvents();
211    
212            // free allocated VM execution contexts
213            if (pEvents) {
214                pEvents->clear();
215                while (!pEvents->poolIsEmpty()) {
216                    RTList<ScriptEvent>::Iterator it = pEvents->allocAppend();
217                    if (!it) break;
218                    if (it->execCtx) {
219                        // free VM execution context object
220                        delete it->execCtx;
221                        it->execCtx = NULL;
222                        // free C array of handler pointers
223                        delete [] it->handlers;
224                        it->handlers = NULL;
225                    }
226                }
227                pEvents->clear();
228            }
229            // hand back VM representation of script
230            if (parserContext) {
231                AbstractInstrumentManager* pManager =
232                    dynamic_cast<AbstractInstrumentManager*>(pEngineChannel->pEngine->GetInstrumentManager());
233    
234                pManager->scripts.HandBack(parserContext, pEngineChannel);
235                parserContext = NULL;
236                handlerInit = NULL;
237                handlerNote = NULL;
238                handlerRelease = NULL;
239                handlerController = NULL;
240                handlerRpn = NULL;
241                handlerNrpn = NULL;
242            }
243            bHasValidScript = false;
244        }
245    
246        /**
247         * Same as unload(), but this one also empties the @c code member variable
248         * to an empty string.
249         */
250        void InstrumentScript::resetAll() {
251            unload();
252            code.clear();
253        }
254        
255        /**
256         * Clears all currently active script events. This should be called
257         * whenever the engine or engine channel was reset for some reason.
258         */
259        void InstrumentScript::resetEvents() {
260            for (int i = 0; i < INSTR_SCRIPT_EVENT_GROUPS; ++i)
261                eventGroups[i].clear();
262    
263            for (int i = 0; i < 128; ++i)
264                if (pKeyEvents[i])
265                    pKeyEvents[i]->clear();
266    
267            suspendedEvents.clear();
268    
269            if (pEvents) pEvents->clear();
270        }
271    
272        ///////////////////////////////////////////////////////////////////////
273        // class 'InstrumentScriptVM'
274    
275        InstrumentScriptVM::InstrumentScriptVM() :
276            m_event(NULL), m_fnPlayNote(this), m_fnSetController(this),
277            m_fnSetRpn(this), m_fnSetNrpn(this),
278            m_fnIgnoreEvent(this), m_fnIgnoreController(this), m_fnNoteOff(this),
279            m_fnSetEventMark(this), m_fnDeleteEventMark(this), m_fnByMarks(this),
280            m_fnChangeVol(this), m_fnChangeVolTime(this),
281            m_fnChangeTune(this), m_fnChangeTuneTime(this), m_fnChangePan(this),
282            m_fnChangePanTime(this), m_fnChangePanCurve(this),
283            m_fnChangeCutoff(this), m_fnChangeReso(this),  m_fnChangeAttack(this),
284            m_fnChangeDecay(this), m_fnChangeSustain(this), m_fnChangeRelease(this),
285            m_fnChangeCutoffAttack(this), m_fnChangeCutoffDecay(this),
286            m_fnChangeCutoffSustain(this), m_fnChangeCutoffRelease(this),
287            m_fnChangeAmpLFODepth(this), m_fnChangeAmpLFOFreq(this),
288            m_fnChangeCutoffLFODepth(this), m_fnChangeCutoffLFOFreq(this),
289            m_fnChangePitchLFODepth(this), m_fnChangePitchLFOFreq(this),
290            m_fnChangeNote(this), m_fnChangeVelo(this), m_fnFork(this),
291            m_fnEventStatus(this), m_fnWait2(this), m_fnStopWait(this),
292            m_fnAbort(this), m_fnFadeIn(this), m_fnFadeOut(this),
293            m_fnChangeVolCurve(this), m_fnChangeTuneCurve(this),
294            m_fnGetEventPar(this), m_fnSetEventPar(this), m_fnChangePlayPos(this),
295            m_fnCallbackStatus(this),
296            m_varEngineUptime(this), m_varCallbackID(this), m_varAllEvents(this),
297            m_varCallbackChildID(this)
298        {
299            m_CC.size = _MEMBER_SIZEOF(AbstractEngineChannel, ControllerTable);
300            m_CC_NUM = DECLARE_VMINT(m_event, class ScriptEvent, cause.Param.CC.Controller);
301            m_EVENT_ID = DECLARE_VMINT_READONLY(m_event, class ScriptEvent, id);
302            m_EVENT_NOTE = DECLARE_VMINT_READONLY(m_event, class ScriptEvent, cause.Param.Note.Key);
303            m_EVENT_VELOCITY = DECLARE_VMINT_READONLY(m_event, class ScriptEvent, cause.Param.Note.Velocity);
304            m_RPN_ADDRESS = DECLARE_VMINT_READONLY(m_event, class ScriptEvent, cause.Param.RPN.Parameter);
305            m_RPN_VALUE = DECLARE_VMINT_READONLY(m_event, class ScriptEvent, cause.Param.RPN.Value);
306            m_KEY_DOWN.size = 128;
307            m_KEY_DOWN.readonly = true;
308            m_NI_CALLBACK_TYPE = DECLARE_VMINT_READONLY(m_event, class ScriptEvent, handlerType);
309            m_NKSP_IGNORE_WAIT = DECLARE_VMINT(m_event, class ScriptEvent, ignoreAllWaitCalls);
310            m_NKSP_CALLBACK_PARENT_ID = DECLARE_VMINT_READONLY(m_event, class ScriptEvent, parentHandlerID);
311      }      }
312    
313      VMExecStatus_t InstrumentScriptVM::exec(VMParserContext* parserCtx, ScriptEvent* event) {      VMExecStatus_t InstrumentScriptVM::exec(VMParserContext* parserCtx, ScriptEvent* event) {
# Line 29  namespace LinuxSampler { Line 315  namespace LinuxSampler {
315              static_cast<AbstractEngineChannel*>(event->cause.pEngineChannel);              static_cast<AbstractEngineChannel*>(event->cause.pEngineChannel);
316    
317          // prepare built-in script variables for script execution          // prepare built-in script variables for script execution
318          m_cause = &event->cause;          m_event = event;
319          m_CC.data = (int8_t*) &pEngineChannel->ControllerTable[0];          m_CC.data = (int8_t*) &pEngineChannel->ControllerTable[0];
320            m_KEY_DOWN.data = &pEngineChannel->GetMidiKeyboardManager()->KeyDown[0];
321    
322          // if script is in start condition, then do mandatory MIDI event          // if script is in start condition, then do mandatory MIDI event
323          // preprocessing tasks, which essentially means updating i.e. controller          // preprocessing tasks, which essentially means updating i.e. controller
324          // table with new CC value in case of a controller event, because the          // table with new CC value in case of a controller event, because the
325          // script might access the new CC value          // script might access the new CC value
326          if (!event->executionSlices) {          if (!event->executionSlices) {
327              switch (m_cause->Type) {              switch (event->cause.Type) {
328                  case Event::type_control_change:                  case Event::type_control_change:
329                      pEngineChannel->ControllerTable[m_cause->Param.CC.Controller] =                      pEngineChannel->ControllerTable[event->cause.Param.CC.Controller] =
330                          m_cause->Param.CC.Value;                          event->cause.Param.CC.Value;
331                      break;                      break;
332                  case Event::type_channel_pressure:                  case Event::type_channel_pressure:
333                      pEngineChannel->ControllerTable[CTRL_TABLE_IDX_AFTERTOUCH] =                      pEngineChannel->ControllerTable[CTRL_TABLE_IDX_AFTERTOUCH] =
334                          m_cause->Param.ChannelPressure.Value;                          event->cause.Param.ChannelPressure.Value;
335                      break;                      break;
336                  case Event::type_pitchbend:                  case Event::type_pitchbend:
337                      pEngineChannel->ControllerTable[CTRL_TABLE_IDX_PITCHBEND] =                      pEngineChannel->ControllerTable[CTRL_TABLE_IDX_PITCHBEND] =
338                          m_cause->Param.Pitch.Pitch;                          event->cause.Param.Pitch.Pitch;
339                      break;                      break;
340                    default:
341                        ; // noop
342              }              }
343          }          }
344    
345          // run the script handler(s)          // run the script handler(s)
346          VMExecStatus_t res = VM_EXEC_NOT_RUNNING;          VMExecStatus_t res = VM_EXEC_NOT_RUNNING;
347          while (event->handlers[event->currentHandler]) {          for ( ; event->handlers[event->currentHandler]; event->currentHandler++) {
348              res = ScriptVM::exec(              res = ScriptVM::exec(
349                  parserCtx, event->execCtx, event->handlers[event->currentHandler++]                  parserCtx, event->execCtx, event->handlers[event->currentHandler]
350              );              );
351              event->executionSlices++;              event->executionSlices++;
352                if (!(res & VM_EXEC_SUSPENDED)) { // if script terminated ...
353                    // check if this script handler instance has any forked children
354                    // to be auto aborted
355                    for (int iChild = 0; iChild < MAX_FORK_PER_SCRIPT_HANDLER &&
356                         event->childHandlerID[iChild]; ++iChild)
357                    {
358                        RTList<ScriptEvent>::Iterator itChild =
359                            pEngineChannel->ScriptCallbackByID(event->childHandlerID[iChild]);
360                        if (itChild && itChild->autoAbortByParent)
361                            itChild->execCtx->signalAbort();
362                    }
363                }
364              if (res & VM_EXEC_SUSPENDED || res & VM_EXEC_ERROR) return res;              if (res & VM_EXEC_SUSPENDED || res & VM_EXEC_ERROR) return res;
365          }          }
366    
367          return res;          return res;
368      }      }
369    
370      std::map<String,VMIntRelPtr*> InstrumentScriptVM::builtInIntVariables() {      std::map<String,VMIntPtr*> InstrumentScriptVM::builtInIntVariables() {
371          // first get buil-in integer variables of derived VM class          // first get built-in integer variables of derived VM class
372          std::map<String,VMIntRelPtr*> m = ScriptVM::builtInIntVariables();          std::map<String,VMIntPtr*> m = ScriptVM::builtInIntVariables();
373    
374          // now add own built-in variables          // now add own built-in variables
375          m["$CC_NUM"] = &m_CC_NUM;          m["$CC_NUM"] = &m_CC_NUM;
376            m["$EVENT_ID"] = &m_EVENT_ID;
377          m["$EVENT_NOTE"] = &m_EVENT_NOTE;          m["$EVENT_NOTE"] = &m_EVENT_NOTE;
378          m["$EVENT_VELOCITY"] = &m_EVENT_VELOCITY;          m["$EVENT_VELOCITY"] = &m_EVENT_VELOCITY;
379  //         m["$POLY_AT_NUM"] = &m_POLY_AT_NUM;  //         m["$POLY_AT_NUM"] = &m_POLY_AT_NUM;
380            m["$RPN_ADDRESS"] = &m_RPN_ADDRESS; // used for both RPN and NRPN events
381            m["$RPN_VALUE"] = &m_RPN_VALUE;     // used for both RPN and NRPN events
382            m["$NI_CALLBACK_TYPE"] = &m_NI_CALLBACK_TYPE;
383            m["$NKSP_IGNORE_WAIT"] = &m_NKSP_IGNORE_WAIT;
384            m["$NKSP_CALLBACK_PARENT_ID"] = &m_NKSP_CALLBACK_PARENT_ID;
385    
386          return m;          return m;
387      }      }
388    
389      std::map<String,VMInt8Array*> InstrumentScriptVM::builtInIntArrayVariables() {      std::map<String,VMInt8Array*> InstrumentScriptVM::builtInIntArrayVariables() {
390          // first get buil-in integer array variables of derived VM class          // first get built-in integer array variables of derived VM class
391          std::map<String,VMInt8Array*> m = ScriptVM::builtInIntArrayVariables();          std::map<String,VMInt8Array*> m = ScriptVM::builtInIntArrayVariables();
392    
393          // now add own built-in variables          // now add own built-in variables
394          m["%CC"] = &m_CC;          m["%CC"] = &m_CC;
395          //m["%KEY_DOWN"] = &m_KEY_DOWN;          m["%KEY_DOWN"] = &m_KEY_DOWN;
396          //m["%POLY_AT"] = &m_POLY_AT;          //m["%POLY_AT"] = &m_POLY_AT;
397    
398          return m;          return m;
399      }      }
400    
401      std::map<String,int> InstrumentScriptVM::builtInConstIntVariables() {      std::map<String,vmint> InstrumentScriptVM::builtInConstIntVariables() {
402          // first get buil-in integer variables of derived VM class          // first get built-in integer variables of derived VM class
403          std::map<String,int> m = ScriptVM::builtInConstIntVariables();          std::map<String,vmint> m = ScriptVM::builtInConstIntVariables();
404    
405            m["$EVENT_STATUS_INACTIVE"] = EVENT_STATUS_INACTIVE;
406            m["$EVENT_STATUS_NOTE_QUEUE"] = EVENT_STATUS_NOTE_QUEUE;
407          m["$VCC_MONO_AT"] = CTRL_TABLE_IDX_AFTERTOUCH;          m["$VCC_MONO_AT"] = CTRL_TABLE_IDX_AFTERTOUCH;
408          m["$VCC_PITCH_BEND"] = CTRL_TABLE_IDX_PITCHBEND;          m["$VCC_PITCH_BEND"] = CTRL_TABLE_IDX_PITCHBEND;
409            for (int i = 0; i < INSTR_SCRIPT_EVENT_GROUPS; ++i) {
410                m["$MARK_" + ToString(i+1)] = i;
411            }
412            m["$EVENT_PAR_NOTE"] = EVENT_PAR_NOTE;
413            m["$EVENT_PAR_VELOCITY"] = EVENT_PAR_VELOCITY;
414            m["$EVENT_PAR_VOLUME"] = EVENT_PAR_VOLUME;
415            m["$EVENT_PAR_TUNE"] = EVENT_PAR_TUNE;
416            m["$EVENT_PAR_0"] = EVENT_PAR_0;
417            m["$EVENT_PAR_1"] = EVENT_PAR_1;
418            m["$EVENT_PAR_2"] = EVENT_PAR_2;
419            m["$EVENT_PAR_3"] = EVENT_PAR_3;
420            m["$NKSP_LINEAR"] = FADE_CURVE_LINEAR;
421            m["$NKSP_EASE_IN_EASE_OUT"] = FADE_CURVE_EASE_IN_EASE_OUT;
422            m["$CALLBACK_STATUS_TERMINATED"] = CALLBACK_STATUS_TERMINATED;
423            m["$CALLBACK_STATUS_QUEUE"]      = CALLBACK_STATUS_QUEUE;
424            m["$CALLBACK_STATUS_RUNNING"]    = CALLBACK_STATUS_RUNNING;
425    
426          return m;          return m;
427      }      }
428    
429        std::map<String,VMDynVar*> InstrumentScriptVM::builtInDynamicVariables() {
430            // first get built-in dynamic variables of derived VM class
431            std::map<String,VMDynVar*> m = ScriptVM::builtInDynamicVariables();
432    
433            m["%ALL_EVENTS"] = &m_varAllEvents;
434            m["$ENGINE_UPTIME"] = &m_varEngineUptime;
435            m["$NI_CALLBACK_ID"] = &m_varCallbackID;
436            m["%NKSP_CALLBACK_CHILD_ID"] = &m_varCallbackChildID;
437    
438            return m;
439        }
440    
441        VMFunction* InstrumentScriptVM::functionByName(const String& name) {
442            // built-in script functions of this class
443            if      (name == "play_note") return &m_fnPlayNote;
444            else if (name == "set_controller") return &m_fnSetController;
445            else if (name == "set_rpn") return &m_fnSetRpn;
446            else if (name == "set_nrpn") return &m_fnSetNrpn;
447            else if (name == "ignore_event") return &m_fnIgnoreEvent;
448            else if (name == "ignore_controller") return &m_fnIgnoreController;
449            else if (name == "note_off") return &m_fnNoteOff;
450            else if (name == "set_event_mark") return &m_fnSetEventMark;
451            else if (name == "delete_event_mark") return &m_fnDeleteEventMark;
452            else if (name == "by_marks") return &m_fnByMarks;
453            else if (name == "change_vol") return &m_fnChangeVol;
454            else if (name == "change_vol_time") return &m_fnChangeVolTime;
455            else if (name == "change_tune") return &m_fnChangeTune;
456            else if (name == "change_tune_time") return &m_fnChangeTuneTime;
457            else if (name == "change_note") return &m_fnChangeNote;
458            else if (name == "change_velo") return &m_fnChangeVelo;
459            else if (name == "change_pan") return &m_fnChangePan;
460            else if (name == "change_pan_time") return &m_fnChangePanTime;
461            else if (name == "change_pan_curve") return &m_fnChangePanCurve;
462            else if (name == "change_cutoff") return &m_fnChangeCutoff;
463            else if (name == "change_reso") return &m_fnChangeReso;
464            else if (name == "change_attack") return &m_fnChangeAttack;
465            else if (name == "change_decay") return &m_fnChangeDecay;
466            else if (name == "change_sustain") return &m_fnChangeSustain;
467            else if (name == "change_release") return &m_fnChangeRelease;
468            else if (name == "change_cutoff_attack") return &m_fnChangeCutoffAttack;
469            else if (name == "change_cutoff_decay") return &m_fnChangeCutoffDecay;
470            else if (name == "change_cutoff_sustain") return &m_fnChangeCutoffSustain;
471            else if (name == "change_cutoff_release") return &m_fnChangeCutoffRelease;
472            else if (name == "change_amp_lfo_depth") return &m_fnChangeAmpLFODepth;
473            else if (name == "change_amp_lfo_freq") return &m_fnChangeAmpLFOFreq;
474            else if (name == "change_cutoff_lfo_depth") return &m_fnChangeCutoffLFODepth;
475            else if (name == "change_cutoff_lfo_freq") return &m_fnChangeCutoffLFOFreq;
476            else if (name == "change_pitch_lfo_depth") return &m_fnChangePitchLFODepth;
477            else if (name == "change_pitch_lfo_freq") return &m_fnChangePitchLFOFreq;
478            else if (name == "fade_in") return &m_fnFadeIn;
479            else if (name == "fade_out") return &m_fnFadeOut;
480            else if (name == "change_vol_curve") return &m_fnChangeVolCurve;
481            else if (name == "change_tune_curve") return &m_fnChangeTuneCurve;
482            else if (name == "change_play_pos") return &m_fnChangePlayPos;
483            else if (name == "get_event_par") return &m_fnGetEventPar;
484            else if (name == "set_event_par") return &m_fnSetEventPar;
485            else if (name == "event_status") return &m_fnEventStatus;
486            else if (name == "wait") return &m_fnWait2; // override wait() core implementation
487            else if (name == "stop_wait") return &m_fnStopWait;
488            else if (name == "abort") return &m_fnAbort;
489            else if (name == "fork") return &m_fnFork;
490            else if (name == "callback_status") return &m_fnCallbackStatus;
491    
492            // built-in script functions of derived VM class
493            return ScriptVM::functionByName(name);
494        }
495    
496  } // namespace LinuxSampler  } // namespace LinuxSampler

Legend:
Removed from v.2594  
changed lines
  Added in v.3971

  ViewVC Help
Powered by ViewVC