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

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

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

revision 2871 by schoenebeck, Sun Apr 10 18:22:23 2016 UTC revision 2879 by schoenebeck, Tue Apr 19 14:07:53 2016 UTC
# Line 22  namespace LinuxSampler { Line 22  namespace LinuxSampler {
22          int note = args->arg(0)->asInt()->evalInt();          int note = args->arg(0)->asInt()->evalInt();
23          int velocity = (args->argsCount() >= 2) ? args->arg(1)->asInt()->evalInt() : 127;          int velocity = (args->argsCount() >= 2) ? args->arg(1)->asInt()->evalInt() : 127;
24          int sampleoffset = (args->argsCount() >= 3) ? args->arg(2)->asInt()->evalInt() : 0;          int sampleoffset = (args->argsCount() >= 3) ? args->arg(2)->asInt()->evalInt() : 0;
25          int duration = (args->argsCount() >= 4) ? args->arg(3)->asInt()->evalInt() : 0; //TODO: once -1 is implemented, it might be a better default value instead of 0          int duration = (args->argsCount() >= 4) ? args->arg(3)->asInt()->evalInt() : 0; //TODO: -1 might be a better default value instead of 0
26    
27          if (note < 0 || note > 127) {          if (note < 0 || note > 127) {
28              errMsg("play_note(): argument 1 is an invalid note number");              errMsg("play_note(): argument 1 is an invalid note number");
29              return errorResult(-1);              return errorResult(0);
30          }          }
31    
32          if (velocity < 0 || velocity > 127) {          if (velocity < 0 || velocity > 127) {
33              errMsg("play_note(): argument 2 is an invalid velocity value");              errMsg("play_note(): argument 2 is an invalid velocity value");
34              return errorResult(-1);              return errorResult(0);
35          }          }
36    
37          if (sampleoffset < 0) {          if (sampleoffset < 0) {
38              errMsg("play_note(): argument 3 may not be a negative sample offset");              errMsg("play_note(): argument 3 may not be a negative sample offset");
39              return errorResult(-1);              return errorResult(0);
40          } else if (sampleoffset != 0) {          } else if (sampleoffset != 0) {
41              wrnMsg("play_note(): argument 3 does not support a sample offset other than 0 yet");              wrnMsg("play_note(): argument 3 does not support a sample offset other than 0 yet");
42          }          }
43    
44          if (duration < -1) {          if (duration < -1) {
45              errMsg("play_note(): argument 4 must be a duration value of at least -1 or higher");              errMsg("play_note(): argument 4 must be a duration value of at least -1 or higher");
46              return errorResult(-1);              return errorResult(0);
         } else if (duration == -1) {  
             wrnMsg("play_note(): argument 4 does not support special value -1 as duration yet");  
47          }          }
48    
49          AbstractEngineChannel* pEngineChannel =          AbstractEngineChannel* pEngineChannel =
50              static_cast<AbstractEngineChannel*>(m_vm->m_event->cause.pEngineChannel);              static_cast<AbstractEngineChannel*>(m_vm->m_event->cause.pEngineChannel);
51    
52          Event e = m_vm->m_event->cause;          Event e = m_vm->m_event->cause; // copy to get fragment time for "now"
53            e.Init(); // clear IDs
54          e.Type = Event::type_note_on;          e.Type = Event::type_note_on;
55          e.Param.Note.Key = note;          e.Param.Note.Key = note;
56          e.Param.Note.Velocity = velocity;          e.Param.Note.Velocity = velocity;
57          memset(&e.Format, 0, sizeof(e.Format)); // init format specific stuff with zero          // make this new note dependent to the life time of the original note
58            if (duration == -1) {
59                if (m_vm->currentVMEventHandler()->eventHandlerType() != VM_EVENT_HANDLER_NOTE) {
60                    errMsg("play_note(): -1 for argument 4 may only be used for note event handlers");
61                    return errorResult(0);
62                }
63                e.Param.Note.ParentNoteID = m_vm->m_event->cause.Param.Note.ID;
64            }
65    
66          int id = pEngineChannel->ScheduleEventMicroSec(&e, 0);          const note_id_t id = pEngineChannel->ScheduleNoteMicroSec(&e, 0);
67    
68          // if a duration is supplied, then schedule a subsequent note-ff event          // if a duration is supplied (and note-on event was scheduled
69          if (duration > 0) {          // successfully above), then schedule a subsequent note-off event
70            if (id && duration > 0) {
71              e.Type = Event::type_note_off;              e.Type = Event::type_note_off;
72              e.Param.Note.Velocity = 127;              e.Param.Note.Velocity = 127;
73              pEngineChannel->ScheduleEventMicroSec(&e, duration);              pEngineChannel->ScheduleEventMicroSec(&e, duration);
74          }          }
75    
76          return successResult(id);          // even if id is null, don't return an errorResult() here, because that
77            // would abort the script, and under heavy load it may be considerable
78            // that ScheduleNoteMicroSec() fails above, so simply ignore that
79            return successResult( ScriptID::fromNoteID(id) );
80      }      }
81    
82      InstrumentScriptVMFunction_set_controller::InstrumentScriptVMFunction_set_controller(InstrumentScriptVM* parent)      InstrumentScriptVMFunction_set_controller::InstrumentScriptVMFunction_set_controller(InstrumentScriptVM* parent)
# Line 81  namespace LinuxSampler { Line 91  namespace LinuxSampler {
91          AbstractEngineChannel* pEngineChannel =          AbstractEngineChannel* pEngineChannel =
92              static_cast<AbstractEngineChannel*>(m_vm->m_event->cause.pEngineChannel);              static_cast<AbstractEngineChannel*>(m_vm->m_event->cause.pEngineChannel);
93    
94          Event e = m_vm->m_event->cause;          Event e = m_vm->m_event->cause; // copy to get fragment time for "now"
95          memset(&e.Format, 0, sizeof(e.Format)); // init format speific stuff with zero          e.Init(); // clear IDs
96          if (controller == CTRL_TABLE_IDX_AFTERTOUCH) {          if (controller == CTRL_TABLE_IDX_AFTERTOUCH) {
97              e.Type = Event::type_channel_pressure;              e.Type = Event::type_channel_pressure;
98              e.Param.ChannelPressure.Value = value & 127;              e.Param.ChannelPressure.Value = value & 127;
# Line 98  namespace LinuxSampler { Line 108  namespace LinuxSampler {
108              return errorResult();              return errorResult();
109          }          }
110    
111          int id = pEngineChannel->ScheduleEventMicroSec(&e, 0);          const event_id_t id = pEngineChannel->ScheduleEventMicroSec(&e, 0);
112    
113          return successResult(id);          // even if id is null, don't return an errorResult() here, because that
114            // would abort the script, and under heavy load it may be considerable
115            // that ScheduleEventMicroSec() fails above, so simply ignore that
116            return successResult( ScriptID::fromEventID(id) );
117      }          }    
118    
119      InstrumentScriptVMFunction_ignore_event::InstrumentScriptVMFunction_ignore_event(InstrumentScriptVM* parent)      InstrumentScriptVMFunction_ignore_event::InstrumentScriptVMFunction_ignore_event(InstrumentScriptVM* parent)
# Line 117  namespace LinuxSampler { Line 130  namespace LinuxSampler {
130                  static_cast<AbstractEngineChannel*>(m_vm->m_event->cause.pEngineChannel);                  static_cast<AbstractEngineChannel*>(m_vm->m_event->cause.pEngineChannel);
131    
132          if (args->arg(0)->exprType() == INT_EXPR) {          if (args->arg(0)->exprType() == INT_EXPR) {
133              int id = args->arg(0)->asInt()->evalInt();              const ScriptID id = args->arg(0)->asInt()->evalInt();
134              if (id < 0) {              if (!id) {
135                  wrnMsg("ignore_event(): argument may not be a negative event ID");                  wrnMsg("ignore_event(): event ID argument may not be zero");
136                    // not errorResult(), because that would abort the script, not intentional in this case
137                  return successResult();                  return successResult();
138              }              }
139              pEngineChannel->IgnoreEvent(id);              pEngineChannel->IgnoreEventByScriptID(id);
140          } else if (args->arg(0)->exprType() == INT_ARR_EXPR) {          } else if (args->arg(0)->exprType() == INT_ARR_EXPR) {
141              VMIntArrayExpr* ids = args->arg(0)->asIntArray();              VMIntArrayExpr* ids = args->arg(0)->asIntArray();
142              for (int i = 0; i < ids->arraySize(); ++i) {              for (int i = 0; i < ids->arraySize(); ++i) {
143                  int id = ids->evalIntElement(i);                  const ScriptID id = ids->evalIntElement(i);    
144                  pEngineChannel->IgnoreEvent(id);                  pEngineChannel->IgnoreEventByScriptID(id);
145              }              }
146          }          }
147    
# Line 140  namespace LinuxSampler { Line 154  namespace LinuxSampler {
154      }      }
155    
156      VMFnResult* InstrumentScriptVMFunction_ignore_controller::exec(VMFnArgs* args) {      VMFnResult* InstrumentScriptVMFunction_ignore_controller::exec(VMFnArgs* args) {
157          int id = (args->argsCount() >= 1) ? args->arg(0)->asInt()->evalInt() : m_vm->m_event->id;          const ScriptID id = (args->argsCount() >= 1) ? args->arg(0)->asInt()->evalInt() : m_vm->m_event->id;
158          if (id < 0) {          if (!id && args->argsCount() >= 1) {
159              wrnMsg("ignore_controller(): argument may not be a negative event ID");              wrnMsg("ignore_controller(): event ID argument may not be zero");
160              return successResult();              return successResult();
161          }          }
162    
163          AbstractEngineChannel* pEngineChannel =          AbstractEngineChannel* pEngineChannel =
164              static_cast<AbstractEngineChannel*>(m_vm->m_event->cause.pEngineChannel);              static_cast<AbstractEngineChannel*>(m_vm->m_event->cause.pEngineChannel);
165    
166          pEngineChannel->IgnoreEvent(id);          pEngineChannel->IgnoreEventByScriptID(id);
167    
168          return successResult();          return successResult();
169      }      }
# Line 174  namespace LinuxSampler { Line 188  namespace LinuxSampler {
188          }          }
189    
190          if (args->arg(0)->exprType() == INT_EXPR) {          if (args->arg(0)->exprType() == INT_EXPR) {
191              int id = args->arg(0)->asInt()->evalInt();                const ScriptID id = args->arg(0)->asInt()->evalInt();  
192              if (id < 0) {              if (!id) {
193                  wrnMsg("note_off(): argument 1 may not be a negative event ID");                  wrnMsg("note_off(): note ID for argument 1 may not be zero");
194                    return successResult();
195                }
196                if (!id.isNoteID()) {
197                    wrnMsg("note_off(): argument 1 is not a note ID");
198                  return successResult();                  return successResult();
199              }              }
200    
201              RTList<Event>::Iterator itEvent = pEngineChannel->pEngine->EventByID(id);              NoteBase* pNote = pEngineChannel->pEngine->NoteByID( id.noteID() );
202              if (!itEvent) return successResult();              if (!pNote) return successResult();
203    
204              Event e = *itEvent;              Event e = pNote->cause;
205                e.Init(); // clear IDs
206                e.CopyTimeFrom(m_vm->m_event->cause); // set fragment time for "now"
207              e.Type = Event::type_note_off;              e.Type = Event::type_note_off;
208              e.Param.Note.Velocity = velocity;              e.Param.Note.Velocity = velocity;
             memset(&e.Format, 0, sizeof(e.Format)); // init format speific stuff with zero  
209    
210              int releaseEventID = pEngineChannel->ScheduleEventMicroSec(&e, 0);              pEngineChannel->ScheduleEventMicroSec(&e, 0);
211          } else if (args->arg(0)->exprType() == INT_ARR_EXPR) {          } else if (args->arg(0)->exprType() == INT_ARR_EXPR) {
212              VMIntArrayExpr* ids = args->arg(0)->asIntArray();              VMIntArrayExpr* ids = args->arg(0)->asIntArray();
213              for (int i = 0; i < ids->arraySize(); ++i) {              for (int i = 0; i < ids->arraySize(); ++i) {
214                  int id = ids->evalIntElement(i);                  const ScriptID id = ids->evalIntElement(i);
215                    if (!id || !id.isNoteID()) continue;
216    
217                  RTList<Event>::Iterator itEvent = pEngineChannel->pEngine->EventByID(id);                  NoteBase* pNote = pEngineChannel->pEngine->NoteByID( id.noteID() );
218                  if (!itEvent) continue;                  if (!pNote) continue;
219    
220                  Event e = *itEvent;                  Event e = pNote->cause;
221                    e.Init(); // clear IDs
222                    e.CopyTimeFrom(m_vm->m_event->cause); // set fragment time for "now"
223                  e.Type = Event::type_note_off;                  e.Type = Event::type_note_off;
224                  e.Param.Note.Velocity = velocity;                  e.Param.Note.Velocity = velocity;
                 memset(&e.Format, 0, sizeof(e.Format)); // init format speific stuff with zero  
225    
226                  int releaseEventID = pEngineChannel->ScheduleEventMicroSec(&e, 0);                  pEngineChannel->ScheduleEventMicroSec(&e, 0);
227              }              }
228          }          }
229    
# Line 215  namespace LinuxSampler { Line 236  namespace LinuxSampler {
236      }      }
237    
238      VMFnResult* InstrumentScriptVMFunction_set_event_mark::exec(VMFnArgs* args) {      VMFnResult* InstrumentScriptVMFunction_set_event_mark::exec(VMFnArgs* args) {
239          int eventID = args->arg(0)->asInt()->evalInt();          const ScriptID id = args->arg(0)->asInt()->evalInt();
240          int groupID = args->arg(1)->asInt()->evalInt();          const int groupID = args->arg(1)->asInt()->evalInt();
241    
242          if (groupID < 0 || groupID >= INSTR_SCRIPT_EVENT_GROUPS) {          if (groupID < 0 || groupID >= INSTR_SCRIPT_EVENT_GROUPS) {
243              errMsg("set_event_mark(): argument 2 is an invalid group id");              errMsg("set_event_mark(): argument 2 is an invalid group id");
# Line 226  namespace LinuxSampler { Line 247  namespace LinuxSampler {
247          AbstractEngineChannel* pEngineChannel =          AbstractEngineChannel* pEngineChannel =
248              static_cast<AbstractEngineChannel*>(m_vm->m_event->cause.pEngineChannel);              static_cast<AbstractEngineChannel*>(m_vm->m_event->cause.pEngineChannel);
249    
250          RTList<Event>::Iterator itEvent = pEngineChannel->pEngine->EventByID(eventID);          // check if the event/note still exists
251          if (!itEvent) return successResult();          switch (id.type()) {
252                case ScriptID::EVENT: {
253                    RTList<Event>::Iterator itEvent = pEngineChannel->pEngine->EventByID( id.eventID() );
254                    if (!itEvent) return successResult();
255                    break;
256                }
257                case ScriptID::NOTE: {
258                    NoteBase* pNote = pEngineChannel->pEngine->NoteByID( id.noteID() );
259                    if (!pNote) return successResult();
260                    break;
261                }
262            }
263    
264          pEngineChannel->pScript->eventGroups[groupID].insert(eventID);          pEngineChannel->pScript->eventGroups[groupID].insert(id);
265    
266          return successResult();          return successResult();
267      }      }
# Line 240  namespace LinuxSampler { Line 272  namespace LinuxSampler {
272      }      }
273    
274      VMFnResult* InstrumentScriptVMFunction_delete_event_mark::exec(VMFnArgs* args) {      VMFnResult* InstrumentScriptVMFunction_delete_event_mark::exec(VMFnArgs* args) {
275          int eventID = args->arg(0)->asInt()->evalInt();          const ScriptID id = args->arg(0)->asInt()->evalInt();
276          int groupID = args->arg(1)->asInt()->evalInt();          const int groupID = args->arg(1)->asInt()->evalInt();
277    
278          if (groupID < 0 || groupID >= INSTR_SCRIPT_EVENT_GROUPS) {          if (groupID < 0 || groupID >= INSTR_SCRIPT_EVENT_GROUPS) {
279              errMsg("delete_event_mark(): argument 2 is an invalid group id");              errMsg("delete_event_mark(): argument 2 is an invalid group id");
# Line 251  namespace LinuxSampler { Line 283  namespace LinuxSampler {
283          AbstractEngineChannel* pEngineChannel =          AbstractEngineChannel* pEngineChannel =
284              static_cast<AbstractEngineChannel*>(m_vm->m_event->cause.pEngineChannel);              static_cast<AbstractEngineChannel*>(m_vm->m_event->cause.pEngineChannel);
285    
286          pEngineChannel->pScript->eventGroups[groupID].erase(eventID);          pEngineChannel->pScript->eventGroups[groupID].erase(id);
287    
288          return successResult();          return successResult();
289      }      }

Legend:
Removed from v.2871  
changed lines
  Added in v.2879

  ViewVC Help
Powered by ViewVC