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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3971 - (hide annotations) (download)
Fri Jun 25 09:26:00 2021 UTC (2 years, 9 months ago) by schoenebeck
File size: 22139 byte(s)
* Fix: Do not share compiled instrument scripts among multiple engine
  channels (sampler parts) as this can lead to crashes and would allow the
  same global script variables to be accessible from multiple engine
  channels which would not be the expected behaviour by instrument script
  authors.

* Bumped version (2.2.0.svn5).

1 schoenebeck 2594 /*
2 schoenebeck 3848 * Copyright (c) 2014 - 2021 Christian Schoenebeck
3 schoenebeck 2594 *
4     * http://www.linuxsampler.org
5     *
6     * This file is part of LinuxSampler and released under the same terms.
7     * See README file for details.
8     */
9    
10 schoenebeck 3035 #include "../../common/global_private.h"
11 schoenebeck 2594 #include "InstrumentScriptVM.h"
12     #include "../AbstractEngineChannel.h"
13 schoenebeck 2600 #include "../../common/global_private.h"
14 schoenebeck 2611 #include "AbstractInstrumentManager.h"
15 schoenebeck 2613 #include "MidiKeyboardManager.h"
16 schoenebeck 3246 #include "Fade.h"
17 schoenebeck 2594
18     namespace LinuxSampler {
19    
20 schoenebeck 2611 ///////////////////////////////////////////////////////////////////////
21 schoenebeck 2630 // class 'EventGroup'
22    
23 schoenebeck 3557 void EventGroup::insert(vmint eventID) {
24 schoenebeck 2630 if (contains(eventID)) return;
25    
26     AbstractEngine* pEngine = m_script->pEngineChannel->pEngine;
27    
28     // before adding the new event ID, check if there are any dead events
29     // 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 schoenebeck 3557 ssize_t firstDead = -1;
35     for (size_t i = 0; i < size(); ++i) {
36 schoenebeck 2630 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 schoenebeck 3848 if (firstDead >= 0)
46     remove(firstDead, size() - firstDead);
47 schoenebeck 2630
48     append(eventID);
49     }
50    
51 schoenebeck 3557 void EventGroup::erase(vmint eventID) {
52     size_t index = find(eventID);
53 schoenebeck 2630 remove(index);
54     }
55    
56     ///////////////////////////////////////////////////////////////////////
57 schoenebeck 2611 // class 'InstrumentScript'
58    
59 schoenebeck 2630 InstrumentScript::InstrumentScript(AbstractEngineChannel* pEngineChannel) {
60     parserContext = NULL;
61     bHasValidScript = false;
62     handlerInit = NULL;
63     handlerNote = NULL;
64     handlerRelease = NULL;
65     handlerController = NULL;
66 schoenebeck 3690 handlerRpn = NULL;
67     handlerNrpn = NULL;
68 schoenebeck 2630 pEvents = NULL;
69 schoenebeck 2645 for (int i = 0; i < 128; ++i)
70     pKeyEvents[i] = NULL;
71 schoenebeck 2630 this->pEngineChannel = pEngineChannel;
72     for (int i = 0; i < INSTR_SCRIPT_EVENT_GROUPS; ++i)
73     eventGroups[i].setScript(this);
74     }
75    
76 schoenebeck 2645 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 schoenebeck 2611 /** @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 schoenebeck 3733 * @param patchVars - 'patch' variables being overridden by instrument
94 schoenebeck 2611 */
95 schoenebeck 3733 void InstrumentScript::load(const String& text,
96     const std::map<String,String>& patchVars)
97     {
98 schoenebeck 2611 dmsg(1,("Loading real-time instrument script ... "));
99    
100     // hand back old script reference and VM execution contexts
101     // (if not done already)
102 schoenebeck 2612 unload();
103 schoenebeck 2611
104 schoenebeck 2612 code = text;
105    
106 schoenebeck 2611 AbstractInstrumentManager* pManager =
107     dynamic_cast<AbstractInstrumentManager*>(pEngineChannel->pEngine->GetInstrumentManager());
108    
109 schoenebeck 3971 /*
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 schoenebeck 3733 );
141 schoenebeck 2611 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 schoenebeck 3690 handlerRpn = parserContext->eventHandlerByName("rpn");
155     handlerNrpn = parserContext->eventHandlerByName("nrpn");
156 schoenebeck 2611 bHasValidScript =
157 schoenebeck 3690 handlerInit || handlerNote || handlerRelease || handlerController ||
158     handlerRpn || handlerNrpn;
159 schoenebeck 2611
160     // amount of script handlers each script event has to execute
161     int handlerExecCount = 0;
162 schoenebeck 3690 if (handlerNote || handlerRelease || handlerController || handlerRpn ||
163     handlerNrpn) // only one of these are executed after "init" handler
164 schoenebeck 2611 handlerExecCount++;
165    
166     // create script event pool (if it doesn't exist already)
167 schoenebeck 2645 if (!pEvents) {
168 schoenebeck 2611 pEvents = new Pool<ScriptEvent>(CONFIG_MAX_EVENTS_PER_FRAGMENT);
169 schoenebeck 2645 for (int i = 0; i < 128; ++i)
170     pKeyEvents[i] = new RTList<ScriptEvent>(pEvents);
171 schoenebeck 2948 // 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 schoenebeck 2645 }
178 schoenebeck 3802 pEvents->clear(); // outside of upper block, as loop below must always start from cleared list
179 schoenebeck 2611
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 schoenebeck 2612 *
201 schoenebeck 2614 * Calling this method will however not clear the @c code member variable.
202 schoenebeck 2612 * Thus, the script can be parsed again afterwards.
203 schoenebeck 2611 */
204 schoenebeck 2612 void InstrumentScript::unload() {
205 schoenebeck 2618 //dmsg(1,("InstrumentScript::unload(this=0x%llx)\n", this));
206    
207 schoenebeck 2611 if (parserContext)
208 schoenebeck 2612 dmsg(1,("Unloading current instrument script.\n"));
209 schoenebeck 2611
210 schoenebeck 2871 resetEvents();
211    
212 schoenebeck 2611 // free allocated VM execution contexts
213     if (pEvents) {
214     pEvents->clear();
215     while (!pEvents->poolIsEmpty()) {
216     RTList<ScriptEvent>::Iterator it = pEvents->allocAppend();
217 schoenebeck 3802 if (!it) break;
218 schoenebeck 2611 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 schoenebeck 3802 it->handlers = NULL;
225 schoenebeck 2611 }
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 schoenebeck 3690 handlerRpn = NULL;
241     handlerNrpn = NULL;
242 schoenebeck 2611 }
243     bHasValidScript = false;
244     }
245    
246 schoenebeck 2612 /**
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 schoenebeck 2871
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 schoenebeck 2612
263 schoenebeck 2871 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 schoenebeck 2611 ///////////////////////////////////////////////////////////////////////
273     // class 'InstrumentScriptVM'
274    
275 schoenebeck 2596 InstrumentScriptVM::InstrumentScriptVM() :
276 schoenebeck 2600 m_event(NULL), m_fnPlayNote(this), m_fnSetController(this),
277 schoenebeck 3691 m_fnSetRpn(this), m_fnSetNrpn(this),
278 schoenebeck 2630 m_fnIgnoreEvent(this), m_fnIgnoreController(this), m_fnNoteOff(this),
279 schoenebeck 2931 m_fnSetEventMark(this), m_fnDeleteEventMark(this), m_fnByMarks(this),
280 schoenebeck 3188 m_fnChangeVol(this), m_fnChangeVolTime(this),
281     m_fnChangeTune(this), m_fnChangeTuneTime(this), m_fnChangePan(this),
282 schoenebeck 3335 m_fnChangePanTime(this), m_fnChangePanCurve(this),
283 schoenebeck 2953 m_fnChangeCutoff(this), m_fnChangeReso(this), m_fnChangeAttack(this),
284 schoenebeck 3316 m_fnChangeDecay(this), m_fnChangeSustain(this), m_fnChangeRelease(this),
285 schoenebeck 3360 m_fnChangeCutoffAttack(this), m_fnChangeCutoffDecay(this),
286     m_fnChangeCutoffSustain(this), m_fnChangeCutoffRelease(this),
287 schoenebeck 3118 m_fnChangeAmpLFODepth(this), m_fnChangeAmpLFOFreq(this),
288 schoenebeck 3360 m_fnChangeCutoffLFODepth(this), m_fnChangeCutoffLFOFreq(this),
289 schoenebeck 3118 m_fnChangePitchLFODepth(this), m_fnChangePitchLFOFreq(this),
290 schoenebeck 3293 m_fnChangeNote(this), m_fnChangeVelo(this), m_fnFork(this),
291 schoenebeck 3118 m_fnEventStatus(this), m_fnWait2(this), m_fnStopWait(this),
292 schoenebeck 3277 m_fnAbort(this), m_fnFadeIn(this), m_fnFadeOut(this),
293 schoenebeck 3246 m_fnChangeVolCurve(this), m_fnChangeTuneCurve(this),
294 schoenebeck 3255 m_fnGetEventPar(this), m_fnSetEventPar(this), m_fnChangePlayPos(this),
295 schoenebeck 3296 m_fnCallbackStatus(this),
296 schoenebeck 3293 m_varEngineUptime(this), m_varCallbackID(this), m_varAllEvents(this),
297     m_varCallbackChildID(this)
298 schoenebeck 2596 {
299 schoenebeck 2595 m_CC.size = _MEMBER_SIZEOF(AbstractEngineChannel, ControllerTable);
300 schoenebeck 2598 m_CC_NUM = DECLARE_VMINT(m_event, class ScriptEvent, cause.Param.CC.Controller);
301 schoenebeck 2948 m_EVENT_ID = DECLARE_VMINT_READONLY(m_event, class ScriptEvent, id);
302 schoenebeck 3253 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 schoenebeck 3690 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 schoenebeck 2613 m_KEY_DOWN.size = 128;
307 schoenebeck 3253 m_KEY_DOWN.readonly = true;
308 schoenebeck 2948 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 schoenebeck 3293 m_NKSP_CALLBACK_PARENT_ID = DECLARE_VMINT_READONLY(m_event, class ScriptEvent, parentHandlerID);
311 schoenebeck 2594 }
312    
313     VMExecStatus_t InstrumentScriptVM::exec(VMParserContext* parserCtx, ScriptEvent* event) {
314     AbstractEngineChannel* pEngineChannel =
315     static_cast<AbstractEngineChannel*>(event->cause.pEngineChannel);
316    
317     // prepare built-in script variables for script execution
318 schoenebeck 2598 m_event = event;
319 schoenebeck 2594 m_CC.data = (int8_t*) &pEngineChannel->ControllerTable[0];
320 schoenebeck 2613 m_KEY_DOWN.data = &pEngineChannel->GetMidiKeyboardManager()->KeyDown[0];
321 schoenebeck 2594
322     // if script is in start condition, then do mandatory MIDI event
323     // preprocessing tasks, which essentially means updating i.e. controller
324     // table with new CC value in case of a controller event, because the
325     // script might access the new CC value
326     if (!event->executionSlices) {
327 schoenebeck 2598 switch (event->cause.Type) {
328 schoenebeck 2594 case Event::type_control_change:
329 schoenebeck 2598 pEngineChannel->ControllerTable[event->cause.Param.CC.Controller] =
330     event->cause.Param.CC.Value;
331 schoenebeck 2594 break;
332     case Event::type_channel_pressure:
333     pEngineChannel->ControllerTable[CTRL_TABLE_IDX_AFTERTOUCH] =
334 schoenebeck 2598 event->cause.Param.ChannelPressure.Value;
335 schoenebeck 2594 break;
336     case Event::type_pitchbend:
337     pEngineChannel->ControllerTable[CTRL_TABLE_IDX_PITCHBEND] =
338 schoenebeck 2598 event->cause.Param.Pitch.Pitch;
339 schoenebeck 2594 break;
340 schoenebeck 3054 default:
341     ; // noop
342 schoenebeck 2594 }
343     }
344    
345     // run the script handler(s)
346     VMExecStatus_t res = VM_EXEC_NOT_RUNNING;
347 schoenebeck 2596 for ( ; event->handlers[event->currentHandler]; event->currentHandler++) {
348 schoenebeck 2594 res = ScriptVM::exec(
349 schoenebeck 2596 parserCtx, event->execCtx, event->handlers[event->currentHandler]
350 schoenebeck 2594 );
351     event->executionSlices++;
352 schoenebeck 3293 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 schoenebeck 2594 if (res & VM_EXEC_SUSPENDED || res & VM_EXEC_ERROR) return res;
365     }
366    
367     return res;
368     }
369    
370 schoenebeck 3557 std::map<String,VMIntPtr*> InstrumentScriptVM::builtInIntVariables() {
371 schoenebeck 2942 // first get built-in integer variables of derived VM class
372 schoenebeck 3557 std::map<String,VMIntPtr*> m = ScriptVM::builtInIntVariables();
373 schoenebeck 2594
374     // now add own built-in variables
375     m["$CC_NUM"] = &m_CC_NUM;
376 schoenebeck 2598 m["$EVENT_ID"] = &m_EVENT_ID;
377 schoenebeck 2594 m["$EVENT_NOTE"] = &m_EVENT_NOTE;
378     m["$EVENT_VELOCITY"] = &m_EVENT_VELOCITY;
379     // m["$POLY_AT_NUM"] = &m_POLY_AT_NUM;
380 schoenebeck 3690 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 schoenebeck 2948 m["$NI_CALLBACK_TYPE"] = &m_NI_CALLBACK_TYPE;
383     m["$NKSP_IGNORE_WAIT"] = &m_NKSP_IGNORE_WAIT;
384 schoenebeck 3293 m["$NKSP_CALLBACK_PARENT_ID"] = &m_NKSP_CALLBACK_PARENT_ID;
385 schoenebeck 2594
386     return m;
387     }
388    
389     std::map<String,VMInt8Array*> InstrumentScriptVM::builtInIntArrayVariables() {
390 schoenebeck 2942 // first get built-in integer array variables of derived VM class
391 schoenebeck 2594 std::map<String,VMInt8Array*> m = ScriptVM::builtInIntArrayVariables();
392    
393     // now add own built-in variables
394     m["%CC"] = &m_CC;
395 schoenebeck 2613 m["%KEY_DOWN"] = &m_KEY_DOWN;
396 schoenebeck 2594 //m["%POLY_AT"] = &m_POLY_AT;
397    
398     return m;
399     }
400    
401 schoenebeck 3557 std::map<String,vmint> InstrumentScriptVM::builtInConstIntVariables() {
402 schoenebeck 2942 // first get built-in integer variables of derived VM class
403 schoenebeck 3557 std::map<String,vmint> m = ScriptVM::builtInConstIntVariables();
404 schoenebeck 2594
405 schoenebeck 2935 m["$EVENT_STATUS_INACTIVE"] = EVENT_STATUS_INACTIVE;
406     m["$EVENT_STATUS_NOTE_QUEUE"] = EVENT_STATUS_NOTE_QUEUE;
407 schoenebeck 2594 m["$VCC_MONO_AT"] = CTRL_TABLE_IDX_AFTERTOUCH;
408     m["$VCC_PITCH_BEND"] = CTRL_TABLE_IDX_PITCHBEND;
409 schoenebeck 2630 for (int i = 0; i < INSTR_SCRIPT_EVENT_GROUPS; ++i) {
410     m["$MARK_" + ToString(i+1)] = i;
411     }
412 schoenebeck 3193 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 schoenebeck 3246 m["$NKSP_LINEAR"] = FADE_CURVE_LINEAR;
421     m["$NKSP_EASE_IN_EASE_OUT"] = FADE_CURVE_EASE_IN_EASE_OUT;
422 schoenebeck 3296 m["$CALLBACK_STATUS_TERMINATED"] = CALLBACK_STATUS_TERMINATED;
423     m["$CALLBACK_STATUS_QUEUE"] = CALLBACK_STATUS_QUEUE;
424     m["$CALLBACK_STATUS_RUNNING"] = CALLBACK_STATUS_RUNNING;
425 schoenebeck 2594
426     return m;
427     }
428    
429 schoenebeck 2942 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 schoenebeck 3073 m["%ALL_EVENTS"] = &m_varAllEvents;
434 schoenebeck 2942 m["$ENGINE_UPTIME"] = &m_varEngineUptime;
435 schoenebeck 2948 m["$NI_CALLBACK_ID"] = &m_varCallbackID;
436 schoenebeck 3293 m["%NKSP_CALLBACK_CHILD_ID"] = &m_varCallbackChildID;
437 schoenebeck 2942
438     return m;
439     }
440    
441 schoenebeck 2596 VMFunction* InstrumentScriptVM::functionByName(const String& name) {
442     // built-in script functions of this class
443 schoenebeck 2598 if (name == "play_note") return &m_fnPlayNote;
444 schoenebeck 2600 else if (name == "set_controller") return &m_fnSetController;
445 schoenebeck 3691 else if (name == "set_rpn") return &m_fnSetRpn;
446     else if (name == "set_nrpn") return &m_fnSetNrpn;
447 schoenebeck 2598 else if (name == "ignore_event") return &m_fnIgnoreEvent;
448     else if (name == "ignore_controller") return &m_fnIgnoreController;
449 schoenebeck 2629 else if (name == "note_off") return &m_fnNoteOff;
450 schoenebeck 2630 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 schoenebeck 2931 else if (name == "change_vol") return &m_fnChangeVol;
454 schoenebeck 3188 else if (name == "change_vol_time") return &m_fnChangeVolTime;
455 schoenebeck 2931 else if (name == "change_tune") return &m_fnChangeTune;
456 schoenebeck 3188 else if (name == "change_tune_time") return &m_fnChangeTuneTime;
457 schoenebeck 3214 else if (name == "change_note") return &m_fnChangeNote;
458     else if (name == "change_velo") return &m_fnChangeVelo;
459 schoenebeck 2931 else if (name == "change_pan") return &m_fnChangePan;
460 schoenebeck 3335 else if (name == "change_pan_time") return &m_fnChangePanTime;
461     else if (name == "change_pan_curve") return &m_fnChangePanCurve;
462 schoenebeck 2935 else if (name == "change_cutoff") return &m_fnChangeCutoff;
463     else if (name == "change_reso") return &m_fnChangeReso;
464 schoenebeck 2953 else if (name == "change_attack") return &m_fnChangeAttack;
465     else if (name == "change_decay") return &m_fnChangeDecay;
466 schoenebeck 3316 else if (name == "change_sustain") return &m_fnChangeSustain;
467 schoenebeck 2953 else if (name == "change_release") return &m_fnChangeRelease;
468 schoenebeck 3360 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 schoenebeck 3118 else if (name == "change_amp_lfo_depth") return &m_fnChangeAmpLFODepth;
473     else if (name == "change_amp_lfo_freq") return &m_fnChangeAmpLFOFreq;
474 schoenebeck 3360 else if (name == "change_cutoff_lfo_depth") return &m_fnChangeCutoffLFODepth;
475     else if (name == "change_cutoff_lfo_freq") return &m_fnChangeCutoffLFOFreq;
476 schoenebeck 3118 else if (name == "change_pitch_lfo_depth") return &m_fnChangePitchLFODepth;
477     else if (name == "change_pitch_lfo_freq") return &m_fnChangePitchLFOFreq;
478 schoenebeck 3188 else if (name == "fade_in") return &m_fnFadeIn;
479     else if (name == "fade_out") return &m_fnFadeOut;
480 schoenebeck 3246 else if (name == "change_vol_curve") return &m_fnChangeVolCurve;
481     else if (name == "change_tune_curve") return &m_fnChangeTuneCurve;
482 schoenebeck 3255 else if (name == "change_play_pos") return &m_fnChangePlayPos;
483 schoenebeck 3193 else if (name == "get_event_par") return &m_fnGetEventPar;
484     else if (name == "set_event_par") return &m_fnSetEventPar;
485 schoenebeck 2935 else if (name == "event_status") return &m_fnEventStatus;
486 schoenebeck 2948 else if (name == "wait") return &m_fnWait2; // override wait() core implementation
487     else if (name == "stop_wait") return &m_fnStopWait;
488 schoenebeck 3277 else if (name == "abort") return &m_fnAbort;
489 schoenebeck 3293 else if (name == "fork") return &m_fnFork;
490 schoenebeck 3296 else if (name == "callback_status") return &m_fnCallbackStatus;
491 schoenebeck 2596
492     // built-in script functions of derived VM class
493     return ScriptVM::functionByName(name);
494     }
495    
496 schoenebeck 2594 } // namespace LinuxSampler

  ViewVC Help
Powered by ViewVC