/[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 3255 by schoenebeck, Tue May 30 15:43:39 2017 UTC revision 3971 by schoenebeck, Fri Jun 25 09:26:00 2021 UTC
# Line 1  Line 1 
1  /*  /*
2   * Copyright (c) 2014 - 2017 Christian Schoenebeck   * Copyright (c) 2014 - 2021 Christian Schoenebeck
3   *   *
4   * http://www.linuxsampler.org   * http://www.linuxsampler.org
5   *   *
# Line 20  namespace LinuxSampler { Line 20  namespace LinuxSampler {
20      ///////////////////////////////////////////////////////////////////////      ///////////////////////////////////////////////////////////////////////
21      // class 'EventGroup'      // class 'EventGroup'
22    
23      void EventGroup::insert(int eventID) {      void EventGroup::insert(vmint eventID) {
24          if (contains(eventID)) return;          if (contains(eventID)) return;
25    
26          AbstractEngine* pEngine = m_script->pEngineChannel->pEngine;          AbstractEngine* pEngine = m_script->pEngineChannel->pEngine;
# Line 31  namespace LinuxSampler { Line 31  namespace LinuxSampler {
31          // events die before being removed explicitly from the group by script          // 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?          // NOTE: or should we do this "dead ones" check only once in a while?
34          int firstDead = -1;          ssize_t firstDead = -1;
35          for (int i = 0; i < size(); ++i) {          for (size_t i = 0; i < size(); ++i) {
36              if (firstDead >= 0) {              if (firstDead >= 0) {
37                  if (pEngine->EventByID(eventID)) {                  if (pEngine->EventByID(eventID)) {
38                      remove(firstDead, i - firstDead);                      remove(firstDead, i - firstDead);
# Line 42  namespace LinuxSampler { Line 42  namespace LinuxSampler {
42                  if (!pEngine->EventByID(eventID)) firstDead = i;                  if (!pEngine->EventByID(eventID)) firstDead = i;
43              }              }
44          }          }
45            if (firstDead >= 0)
46                remove(firstDead, size() - firstDead);
47    
48          append(eventID);          append(eventID);
49      }      }
50    
51      void EventGroup::erase(int eventID) {      void EventGroup::erase(vmint eventID) {
52          int index = find(eventID);          size_t index = find(eventID);
53          remove(index);          remove(index);
54      }      }
55    
# Line 61  namespace LinuxSampler { Line 63  namespace LinuxSampler {
63          handlerNote = NULL;          handlerNote = NULL;
64          handlerRelease = NULL;          handlerRelease = NULL;
65          handlerController = NULL;          handlerController = NULL;
66            handlerRpn = NULL;
67            handlerNrpn = NULL;
68          pEvents = NULL;          pEvents = NULL;
69          for (int i = 0; i < 128; ++i)          for (int i = 0; i < 128; ++i)
70              pKeyEvents[i] = NULL;              pKeyEvents[i] = NULL;
# Line 86  namespace LinuxSampler { Line 90  namespace LinuxSampler {
90       * channels.       * channels.
91       *       *
92       * @param text - source code of script       * @param text - source code of script
93         * @param patchVars - 'patch' variables being overridden by instrument
94       */       */
95      void InstrumentScript::load(const String& text) {      void InstrumentScript::load(const String& text,
96                                    const std::map<String,String>& patchVars)
97        {
98          dmsg(1,("Loading real-time instrument script ... "));          dmsg(1,("Loading real-time instrument script ... "));
99    
100          // hand back old script reference and VM execution contexts          // hand back old script reference and VM execution contexts
# Line 99  namespace LinuxSampler { Line 106  namespace LinuxSampler {
106          AbstractInstrumentManager* pManager =          AbstractInstrumentManager* pManager =
107              dynamic_cast<AbstractInstrumentManager*>(pEngineChannel->pEngine->GetInstrumentManager());              dynamic_cast<AbstractInstrumentManager*>(pEngineChannel->pEngine->GetInstrumentManager());
108    
109          // get new script reference          /*
110          parserContext = pManager->scripts.Borrow(text, pEngineChannel);             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()) {          if (!parserContext->errors().empty()) {
142              std::vector<ParserIssue> errors = parserContext->errors();              std::vector<ParserIssue> errors = parserContext->errors();
143              std::cerr << "[ScriptVM] Could not load instrument script, there were "              std::cerr << "[ScriptVM] Could not load instrument script, there were "
# Line 114  namespace LinuxSampler { Line 151  namespace LinuxSampler {
151          handlerNote = parserContext->eventHandlerByName("note");          handlerNote = parserContext->eventHandlerByName("note");
152          handlerRelease = parserContext->eventHandlerByName("release");          handlerRelease = parserContext->eventHandlerByName("release");
153          handlerController = parserContext->eventHandlerByName("controller");          handlerController = parserContext->eventHandlerByName("controller");
154            handlerRpn = parserContext->eventHandlerByName("rpn");
155            handlerNrpn = parserContext->eventHandlerByName("nrpn");
156          bHasValidScript =          bHasValidScript =
157              handlerInit || handlerNote || handlerRelease || handlerController;              handlerInit || handlerNote || handlerRelease || handlerController ||
158                handlerRpn || handlerNrpn;
159    
160          // amount of script handlers each script event has to execute          // amount of script handlers each script event has to execute
161          int handlerExecCount = 0;          int handlerExecCount = 0;
162          if (handlerNote || handlerRelease || handlerController) // only one of these are executed after "init" handler          if (handlerNote || handlerRelease || handlerController || handlerRpn ||
163                handlerNrpn) // only one of these are executed after "init" handler
164              handlerExecCount++;              handlerExecCount++;
165    
166          // create script event pool (if it doesn't exist already)          // create script event pool (if it doesn't exist already)
# Line 133  namespace LinuxSampler { Line 174  namespace LinuxSampler {
174                  RTList<ScriptEvent>::Iterator it = pEvents->allocAppend();                  RTList<ScriptEvent>::Iterator it = pEvents->allocAppend();
175                  it->reset();                  it->reset();
176              }              }
             pEvents->clear();  
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          // create new VM execution contexts for new script
181          while (!pEvents->poolIsEmpty()) {          while (!pEvents->poolIsEmpty()) {
# Line 173  namespace LinuxSampler { Line 214  namespace LinuxSampler {
214              pEvents->clear();              pEvents->clear();
215              while (!pEvents->poolIsEmpty()) {              while (!pEvents->poolIsEmpty()) {
216                  RTList<ScriptEvent>::Iterator it = pEvents->allocAppend();                  RTList<ScriptEvent>::Iterator it = pEvents->allocAppend();
217                    if (!it) break;
218                  if (it->execCtx) {                  if (it->execCtx) {
219                      // free VM execution context object                      // free VM execution context object
220                      delete it->execCtx;                      delete it->execCtx;
221                      it->execCtx = NULL;                      it->execCtx = NULL;
222                      // free C array of handler pointers                      // free C array of handler pointers
223                      delete [] it->handlers;                      delete [] it->handlers;
224                        it->handlers = NULL;
225                  }                  }
226              }              }
227              pEvents->clear();              pEvents->clear();
# Line 194  namespace LinuxSampler { Line 237  namespace LinuxSampler {
237              handlerNote = NULL;              handlerNote = NULL;
238              handlerRelease = NULL;              handlerRelease = NULL;
239              handlerController = NULL;              handlerController = NULL;
240                handlerRpn = NULL;
241                handlerNrpn = NULL;
242          }          }
243          bHasValidScript = false;          bHasValidScript = false;
244      }      }
# Line 229  namespace LinuxSampler { Line 274  namespace LinuxSampler {
274    
275      InstrumentScriptVM::InstrumentScriptVM() :      InstrumentScriptVM::InstrumentScriptVM() :
276          m_event(NULL), m_fnPlayNote(this), m_fnSetController(this),          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),          m_fnIgnoreEvent(this), m_fnIgnoreController(this), m_fnNoteOff(this),
279          m_fnSetEventMark(this), m_fnDeleteEventMark(this), m_fnByMarks(this),          m_fnSetEventMark(this), m_fnDeleteEventMark(this), m_fnByMarks(this),
280          m_fnChangeVol(this), m_fnChangeVolTime(this),          m_fnChangeVol(this), m_fnChangeVolTime(this),
281          m_fnChangeTune(this), m_fnChangeTuneTime(this), m_fnChangePan(this),          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),          m_fnChangeCutoff(this), m_fnChangeReso(this),  m_fnChangeAttack(this),
284          m_fnChangeDecay(this), m_fnChangeRelease(this),          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),          m_fnChangeAmpLFODepth(this), m_fnChangeAmpLFOFreq(this),
288            m_fnChangeCutoffLFODepth(this), m_fnChangeCutoffLFOFreq(this),
289          m_fnChangePitchLFODepth(this), m_fnChangePitchLFOFreq(this),          m_fnChangePitchLFODepth(this), m_fnChangePitchLFOFreq(this),
290          m_fnChangeNote(this), m_fnChangeVelo(this),          m_fnChangeNote(this), m_fnChangeVelo(this), m_fnFork(this),
291          m_fnEventStatus(this), m_fnWait2(this), m_fnStopWait(this),          m_fnEventStatus(this), m_fnWait2(this), m_fnStopWait(this),
292          m_fnFadeIn(this), m_fnFadeOut(this),          m_fnAbort(this), m_fnFadeIn(this), m_fnFadeOut(this),
293          m_fnChangeVolCurve(this), m_fnChangeTuneCurve(this),          m_fnChangeVolCurve(this), m_fnChangeTuneCurve(this),
294          m_fnGetEventPar(this), m_fnSetEventPar(this), m_fnChangePlayPos(this),          m_fnGetEventPar(this), m_fnSetEventPar(this), m_fnChangePlayPos(this),
295          m_varEngineUptime(this), m_varCallbackID(this), m_varAllEvents(this)          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);          m_CC.size = _MEMBER_SIZEOF(AbstractEngineChannel, ControllerTable);
300          m_CC_NUM = DECLARE_VMINT(m_event, class ScriptEvent, cause.Param.CC.Controller);          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);          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);          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);          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;          m_KEY_DOWN.size = 128;
307          m_KEY_DOWN.readonly = true;          m_KEY_DOWN.readonly = true;
308          m_NI_CALLBACK_TYPE = DECLARE_VMINT_READONLY(m_event, class ScriptEvent, handlerType);          m_NI_CALLBACK_TYPE = DECLARE_VMINT_READONLY(m_event, class ScriptEvent, handlerType);
309          m_NKSP_IGNORE_WAIT = DECLARE_VMINT(m_event, class ScriptEvent, ignoreAllWaitCalls);          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 294  namespace LinuxSampler { Line 349  namespace LinuxSampler {
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 built-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;
# Line 310  namespace LinuxSampler { Line 377  namespace LinuxSampler {
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;          m["$NI_CALLBACK_TYPE"] = &m_NI_CALLBACK_TYPE;
383          m["$NKSP_IGNORE_WAIT"] = &m_NKSP_IGNORE_WAIT;          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      }      }
# Line 328  namespace LinuxSampler { Line 398  namespace LinuxSampler {
398          return m;          return m;
399      }      }
400    
401      std::map<String,int> InstrumentScriptVM::builtInConstIntVariables() {      std::map<String,vmint> InstrumentScriptVM::builtInConstIntVariables() {
402          // first get built-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;          m["$EVENT_STATUS_INACTIVE"] = EVENT_STATUS_INACTIVE;
406          m["$EVENT_STATUS_NOTE_QUEUE"] = EVENT_STATUS_NOTE_QUEUE;          m["$EVENT_STATUS_NOTE_QUEUE"] = EVENT_STATUS_NOTE_QUEUE;
# Line 349  namespace LinuxSampler { Line 419  namespace LinuxSampler {
419          m["$EVENT_PAR_3"] = EVENT_PAR_3;          m["$EVENT_PAR_3"] = EVENT_PAR_3;
420          m["$NKSP_LINEAR"] = FADE_CURVE_LINEAR;          m["$NKSP_LINEAR"] = FADE_CURVE_LINEAR;
421          m["$NKSP_EASE_IN_EASE_OUT"] = FADE_CURVE_EASE_IN_EASE_OUT;          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      }      }
# Line 360  namespace LinuxSampler { Line 433  namespace LinuxSampler {
433          m["%ALL_EVENTS"] = &m_varAllEvents;          m["%ALL_EVENTS"] = &m_varAllEvents;
434          m["$ENGINE_UPTIME"] = &m_varEngineUptime;          m["$ENGINE_UPTIME"] = &m_varEngineUptime;
435          m["$NI_CALLBACK_ID"] = &m_varCallbackID;          m["$NI_CALLBACK_ID"] = &m_varCallbackID;
436            m["%NKSP_CALLBACK_CHILD_ID"] = &m_varCallbackChildID;
437    
438          return m;          return m;
439      }      }
# Line 368  namespace LinuxSampler { Line 442  namespace LinuxSampler {
442          // built-in script functions of this class          // built-in script functions of this class
443          if      (name == "play_note") return &m_fnPlayNote;          if      (name == "play_note") return &m_fnPlayNote;
444          else if (name == "set_controller") return &m_fnSetController;          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;          else if (name == "ignore_event") return &m_fnIgnoreEvent;
448          else if (name == "ignore_controller") return &m_fnIgnoreController;          else if (name == "ignore_controller") return &m_fnIgnoreController;
449          else if (name == "note_off") return &m_fnNoteOff;          else if (name == "note_off") return &m_fnNoteOff;
# Line 381  namespace LinuxSampler { Line 457  namespace LinuxSampler {
457          else if (name == "change_note") return &m_fnChangeNote;          else if (name == "change_note") return &m_fnChangeNote;
458          else if (name == "change_velo") return &m_fnChangeVelo;          else if (name == "change_velo") return &m_fnChangeVelo;
459          else if (name == "change_pan") return &m_fnChangePan;          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;          else if (name == "change_cutoff") return &m_fnChangeCutoff;
463          else if (name == "change_reso") return &m_fnChangeReso;          else if (name == "change_reso") return &m_fnChangeReso;
464          else if (name == "change_attack") return &m_fnChangeAttack;          else if (name == "change_attack") return &m_fnChangeAttack;
465          else if (name == "change_decay") return &m_fnChangeDecay;          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;          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;          else if (name == "change_amp_lfo_depth") return &m_fnChangeAmpLFODepth;
473          else if (name == "change_amp_lfo_freq") return &m_fnChangeAmpLFOFreq;          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;          else if (name == "change_pitch_lfo_depth") return &m_fnChangePitchLFODepth;
477          else if (name == "change_pitch_lfo_freq") return &m_fnChangePitchLFOFreq;          else if (name == "change_pitch_lfo_freq") return &m_fnChangePitchLFOFreq;
478          else if (name == "fade_in") return &m_fnFadeIn;          else if (name == "fade_in") return &m_fnFadeIn;
# Line 400  namespace LinuxSampler { Line 485  namespace LinuxSampler {
485          else if (name == "event_status") return &m_fnEventStatus;          else if (name == "event_status") return &m_fnEventStatus;
486          else if (name == "wait") return &m_fnWait2; // override wait() core implementation          else if (name == "wait") return &m_fnWait2; // override wait() core implementation
487          else if (name == "stop_wait") return &m_fnStopWait;          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          // built-in script functions of derived VM class
493          return ScriptVM::functionByName(name);          return ScriptVM::functionByName(name);

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

  ViewVC Help
Powered by ViewVC