46 |
ResetControllers(); |
ResetControllers(); |
47 |
PortamentoMode = false; |
PortamentoMode = false; |
48 |
PortamentoTime = CONFIG_PORTAMENTO_TIME_DEFAULT; |
PortamentoTime = CONFIG_PORTAMENTO_TIME_DEFAULT; |
49 |
pScriptEvents = NULL; |
pScript = NULL; |
50 |
} |
} |
51 |
|
|
52 |
AbstractEngineChannel::~AbstractEngineChannel() { |
AbstractEngineChannel::~AbstractEngineChannel() { |
53 |
unloadCurrentInstrumentScript(); |
if (pScript) pScript->reset(); // unloads script (in case one is loaded) |
|
if (pScriptEvents) delete pScriptEvents; |
|
54 |
delete pEventQueue; |
delete pEventQueue; |
55 |
DeleteGroupEventLists(); |
DeleteGroupEventLists(); |
56 |
RemoveAllFxSends(); |
RemoveAllFxSends(); |
144 |
} |
} |
145 |
|
|
146 |
/** |
/** |
|
* Loads the real-time instrument script given by @a text on this engine |
|
|
* channel. A resource manager is used to allocate and share equivalent |
|
|
* scripts on multiple engine channels. |
|
|
* |
|
|
* @param text - source code of script |
|
|
*/ |
|
|
void AbstractEngineChannel::loadInstrumentScript(const String& text) { |
|
|
dmsg(1,("Loading real-time instrument script ... ")); |
|
|
|
|
|
// hand back old script reference and VM execution contexts |
|
|
// (if not done already) |
|
|
unloadCurrentInstrumentScript(); |
|
|
|
|
|
// get new script reference |
|
|
script.parserContext = pEngine->scripts.Borrow(text, this); |
|
|
if (!script.parserContext->errors().empty()) { |
|
|
std::vector<ParserIssue> errors = script.parserContext->errors(); |
|
|
std::cerr << "[ScriptVM] Could not load instrument script, there were " |
|
|
<< errors.size() << " parser errors:\n"; |
|
|
for (int i = 0; i < errors.size(); ++i) |
|
|
errors[i].dump(); |
|
|
return; // stop here if there were any parser errors |
|
|
} |
|
|
|
|
|
script.handlerInit = script.parserContext->eventHandlerByName("init"); |
|
|
script.handlerNote = script.parserContext->eventHandlerByName("note"); |
|
|
script.handlerRelease = script.parserContext->eventHandlerByName("release"); |
|
|
script.handlerController = script.parserContext->eventHandlerByName("controller"); |
|
|
script.bHasValidScript = |
|
|
script.handlerInit || script.handlerNote || script.handlerRelease || |
|
|
script.handlerController; |
|
|
|
|
|
// amount of script handlers each script event has to execute |
|
|
int handlerExecCount = 0; |
|
|
if (script.handlerInit) handlerExecCount++; // "init" handler is always executed before the actual event handler |
|
|
if (script.handlerNote || script.handlerRelease || script.handlerController) // only one of these are executed after "init" handler |
|
|
handlerExecCount++; |
|
|
|
|
|
// create script event pool (if it doesn't exist already) |
|
|
if (!pScriptEvents) |
|
|
pScriptEvents = new Pool<ScriptEvent>(CONFIG_MAX_EVENTS_PER_FRAGMENT); |
|
|
|
|
|
// create new VM execution contexts for new script |
|
|
while (!pScriptEvents->poolIsEmpty()) { |
|
|
RTList<ScriptEvent>::Iterator it = pScriptEvents->allocAppend(); |
|
|
it->execCtx = pEngine->pScriptVM->createExecContext( |
|
|
script.parserContext |
|
|
); |
|
|
it->handlers = new VMEventHandler*[handlerExecCount+1]; |
|
|
} |
|
|
pScriptEvents->clear(); |
|
|
|
|
|
dmsg(1,("Done\n")); |
|
|
} |
|
|
|
|
|
/** |
|
|
* Unloads the currently used real-time instrument script on this sampler |
|
|
* channel. A resource manager is used to share equivalent scripts among |
|
|
* multiple sampler channels, and to deallocate the parsed script once not |
|
|
* used on any engine channel anymore. |
|
|
*/ |
|
|
void AbstractEngineChannel::unloadCurrentInstrumentScript() { |
|
|
if (script.parserContext) |
|
|
dmsg(1,("Unloading current instrument script.")); |
|
|
|
|
|
// free allocated VM execution contexts |
|
|
if (pScriptEvents) { |
|
|
pScriptEvents->clear(); |
|
|
while (!pScriptEvents->poolIsEmpty()) { |
|
|
RTList<ScriptEvent>::Iterator it = pScriptEvents->allocAppend(); |
|
|
if (it->execCtx) { |
|
|
// free VM execution context object |
|
|
delete it->execCtx; |
|
|
it->execCtx = NULL; |
|
|
// free C array of handler pointers |
|
|
delete [] it->handlers; |
|
|
} |
|
|
} |
|
|
pScriptEvents->clear(); |
|
|
} |
|
|
// hand back VM representation of script |
|
|
if (script.parserContext) { |
|
|
pEngine->scripts.HandBack(script.parserContext, this); |
|
|
script.parserContext = NULL; |
|
|
script.handlerInit = NULL; |
|
|
script.handlerNote = NULL; |
|
|
script.handlerRelease = NULL; |
|
|
script.handlerController = NULL; |
|
|
} |
|
|
script.bHasValidScript = false; |
|
|
} |
|
|
|
|
|
/** |
|
147 |
* Implementation of virtual method from abstract EngineChannel interface. |
* Implementation of virtual method from abstract EngineChannel interface. |
148 |
* This method will periodically be polled (e.g. by the LSCP server) to |
* This method will periodically be polled (e.g. by the LSCP server) to |
149 |
* check if some engine channel parameter has changed since the last |
* check if some engine channel parameter has changed since the last |
637 |
|
|
638 |
Event event = pEngine->pEventGenerator->CreateEvent(); |
Event event = pEngine->pEventGenerator->CreateEvent(); |
639 |
event.Type = Event::type_channel_pressure; |
event.Type = Event::type_channel_pressure; |
640 |
|
event.Param.ChannelPressure.Controller = CTRL_TABLE_IDX_AFTERTOUCH; // required for instrument scripts |
641 |
event.Param.ChannelPressure.Value = Value; |
event.Param.ChannelPressure.Value = Value; |
642 |
event.Param.ChannelPressure.Channel = MidiChannel; |
event.Param.ChannelPressure.Channel = MidiChannel; |
643 |
memset(&event.Format, 0, sizeof(event.Format)); // init format speific stuff with zeroes |
memset(&event.Format, 0, sizeof(event.Format)); // init format speific stuff with zeroes |
655 |
|
|
656 |
Event event = pEngine->pEventGenerator->CreateEvent(FragmentPos); |
Event event = pEngine->pEventGenerator->CreateEvent(FragmentPos); |
657 |
event.Type = Event::type_channel_pressure; |
event.Type = Event::type_channel_pressure; |
658 |
|
event.Param.ChannelPressure.Controller = CTRL_TABLE_IDX_AFTERTOUCH; // required for instrument scripts |
659 |
event.Param.ChannelPressure.Value = Value; |
event.Param.ChannelPressure.Value = Value; |
660 |
event.Param.ChannelPressure.Channel = MidiChannel; |
event.Param.ChannelPressure.Channel = MidiChannel; |
661 |
memset(&event.Format, 0, sizeof(event.Format)); // init format speific stuff with zeroes |
memset(&event.Format, 0, sizeof(event.Format)); // init format speific stuff with zeroes |