/[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 3296 by schoenebeck, Wed Jun 28 09:45:56 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_fnFork(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),
# Line 251  namespace LinuxSampler { Line 301  namespace LinuxSampler {
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);
# Line 315  namespace LinuxSampler { Line 367  namespace LinuxSampler {
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 325  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;          m["$NKSP_CALLBACK_PARENT_ID"] = &m_NKSP_CALLBACK_PARENT_ID;
# Line 344  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 388  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 401  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;

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

  ViewVC Help
Powered by ViewVC