634 |
// if a valid real-time instrument script is loaded, pre-process |
// if a valid real-time instrument script is loaded, pre-process |
635 |
// the event list by running the script now, since the script |
// the event list by running the script now, since the script |
636 |
// might filter events or add new ones for this cycle |
// might filter events or add new ones for this cycle |
637 |
if (pChannel->script.bHasValidScript) { |
if (pChannel->pScript && pChannel->pScript->bHasValidScript) { |
638 |
// resume any suspended script executions still hanging |
// resume any suspended script executions still hanging |
639 |
// around of previous audio fragment cycles |
// around of previous audio fragment cycles |
640 |
for (RTList<ScriptEvent>::Iterator itEvent = pChannel->pScriptEvents->first(), |
for (RTList<ScriptEvent>::Iterator itEvent = pChannel->pScript->pEvents->first(), |
641 |
end = pChannel->pScriptEvents->end(); itEvent != end; ++itEvent) |
end = pChannel->pScript->pEvents->end(); itEvent != end; ++itEvent) |
642 |
{ |
{ |
643 |
ResumeScriptEvent(pChannel, itEvent); //TODO: implement support for actual suspension time (i.e. passed to a script's wait() function call) |
ResumeScriptEvent(pChannel, itEvent); //TODO: implement support for actual suspension time (i.e. passed to a script's wait() function call) |
644 |
} |
} |
650 |
{ |
{ |
651 |
switch (itEvent->Type) { |
switch (itEvent->Type) { |
652 |
case Event::type_note_on: |
case Event::type_note_on: |
653 |
if (pChannel->script.handlerNote) |
if (pChannel->pScript->handlerNote) |
654 |
ProcessEventByScript(pChannel, itEvent, pChannel->script.handlerNote); |
ProcessEventByScript(pChannel, itEvent, pChannel->pScript->handlerNote); |
655 |
break; |
break; |
656 |
case Event::type_note_off: |
case Event::type_note_off: |
657 |
if (pChannel->script.handlerRelease) |
if (pChannel->pScript->handlerRelease) |
658 |
ProcessEventByScript(pChannel, itEvent, pChannel->script.handlerRelease); |
ProcessEventByScript(pChannel, itEvent, pChannel->pScript->handlerRelease); |
659 |
break; |
break; |
660 |
case Event::type_control_change: |
case Event::type_control_change: |
661 |
case Event::type_channel_pressure: |
case Event::type_channel_pressure: |
662 |
case Event::type_pitchbend: |
case Event::type_pitchbend: |
663 |
if (pChannel->script.handlerController) |
if (pChannel->pScript->handlerController) |
664 |
ProcessEventByScript(pChannel, itEvent, pChannel->script.handlerController); |
ProcessEventByScript(pChannel, itEvent, pChannel->pScript->handlerController); |
665 |
break; |
break; |
666 |
case Event::type_note_pressure: |
case Event::type_note_pressure: |
667 |
//TODO: ... |
//TODO: ... |
724 |
*/ |
*/ |
725 |
void ProcessEventByScript(AbstractEngineChannel* pChannel, RTList<Event>::Iterator& itEvent, VMEventHandler* pEventHandler) { |
void ProcessEventByScript(AbstractEngineChannel* pChannel, RTList<Event>::Iterator& itEvent, VMEventHandler* pEventHandler) { |
726 |
RTList<ScriptEvent>::Iterator itScriptEvent = |
RTList<ScriptEvent>::Iterator itScriptEvent = |
727 |
pChannel->pScriptEvents->allocAppend(); |
pChannel->pScript->pEvents->allocAppend(); |
728 |
|
|
729 |
if (!itScriptEvent) return; // no free script event left for execution |
if (!itScriptEvent) return; // no free script event left for execution |
730 |
|
|
731 |
// fill the list of script handlers to be executed by this event |
// fill the list of script handlers to be executed by this event |
732 |
int i = 0; |
int i = 0; |
|
if (pChannel->script.handlerInit) |
|
|
itScriptEvent->handlers[i++] = pChannel->script.handlerInit; |
|
733 |
itScriptEvent->handlers[i++] = pEventHandler; // actual event handler (i.e. note, controller) |
itScriptEvent->handlers[i++] = pEventHandler; // actual event handler (i.e. note, controller) |
734 |
itScriptEvent->handlers[i] = NULL; // NULL termination of list |
itScriptEvent->handlers[i] = NULL; // NULL termination of list |
735 |
|
|
741 |
|
|
742 |
// run script handler(s) |
// run script handler(s) |
743 |
VMExecStatus_t res = pScriptVM->exec( |
VMExecStatus_t res = pScriptVM->exec( |
744 |
pChannel->script.parserContext, &*itScriptEvent |
pChannel->pScript->parserContext, &*itScriptEvent |
745 |
); |
); |
746 |
|
|
747 |
// in case the script was suspended, keep it on the allocated |
// in case the script was suspended, keep it on the allocated |
749 |
// otherwise if execution has been finished, free it for a new |
// otherwise if execution has been finished, free it for a new |
750 |
// future script event to be triggered from start |
// future script event to be triggered from start |
751 |
if (!(res & VM_EXEC_SUSPENDED)) |
if (!(res & VM_EXEC_SUSPENDED)) |
752 |
pChannel->pScriptEvents->free(itScriptEvent); |
pChannel->pScript->pEvents->free(itScriptEvent); |
753 |
} |
} |
754 |
|
|
755 |
/** @brief Resume execution of instrument script. |
/** @brief Resume execution of instrument script. |
772 |
void ResumeScriptEvent(AbstractEngineChannel* pChannel, RTList<ScriptEvent>::Iterator& itScriptEvent) { |
void ResumeScriptEvent(AbstractEngineChannel* pChannel, RTList<ScriptEvent>::Iterator& itScriptEvent) { |
773 |
// run script |
// run script |
774 |
VMExecStatus_t res = pScriptVM->exec( |
VMExecStatus_t res = pScriptVM->exec( |
775 |
pChannel->script.parserContext, &*itScriptEvent |
pChannel->pScript->parserContext, &*itScriptEvent |
776 |
); |
); |
777 |
// in case the script was again suspended, keep it on the allocated |
// in case the script was again suspended, keep it on the allocated |
778 |
// ScriptEvent list to be continued on the next audio cycle, |
// ScriptEvent list to be continued on the next audio cycle, |
779 |
// otherwise if execution has been finished, free it for a new |
// otherwise if execution has been finished, free it for a new |
780 |
// future script event to be triggered from start |
// future script event to be triggered from start |
781 |
if (!(res & VM_EXEC_SUSPENDED)) |
if (!(res & VM_EXEC_SUSPENDED)) |
782 |
pChannel->pScriptEvents->free(itScriptEvent); |
pChannel->pScript->pEvents->free(itScriptEvent); |
783 |
} |
} |
784 |
|
|
785 |
/** |
/** |
914 |
dmsg(5,("Engine: instrument change command received\n")); |
dmsg(5,("Engine: instrument change command received\n")); |
915 |
cmd.bChangeInstrument = false; |
cmd.bChangeInstrument = false; |
916 |
pEngineChannel->pInstrument = cmd.pInstrument; |
pEngineChannel->pInstrument = cmd.pInstrument; |
917 |
|
pEngineChannel->pScript = cmd.pScript; //TODO: previous script should be freed as soon as EngineBase switched the instrument, right now 2 scripts are kept in memory all the time, even though the old one is not used anymore |
918 |
instrumentChanged = true; |
instrumentChanged = true; |
919 |
|
|
920 |
pEngineChannel->MarkAllActiveVoicesAsOrphans(); |
pEngineChannel->MarkAllActiveVoicesAsOrphans(); |
921 |
|
|
922 |
|
// the script's "init" event handler is only executed |
923 |
|
// once (when the script is loaded or reloaded) |
924 |
|
if (pEngineChannel->pScript && pEngineChannel->pScript->handlerInit) { |
925 |
|
RTList<ScriptEvent>::Iterator itScriptEvent = |
926 |
|
pEngineChannel->pScript->pEvents->allocAppend(); |
927 |
|
|
928 |
|
VMExecStatus_t res = pScriptVM->exec( |
929 |
|
pEngineChannel->pScript->parserContext, &*itScriptEvent |
930 |
|
); |
931 |
|
|
932 |
|
pEngineChannel->pScript->pEvents->free(itScriptEvent); |
933 |
|
} |
934 |
} |
} |
935 |
} |
} |
936 |
|
|