/[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 3246 by schoenebeck, Sun May 28 22:22:56 2017 UTC revision 3303 by schoenebeck, Mon Jul 10 17:45:30 2017 UTC
# Line 23  namespace LinuxSampler { Line 23  namespace LinuxSampler {
23      VMFnResult* InstrumentScriptVMFunction_play_note::exec(VMFnArgs* args) {      VMFnResult* InstrumentScriptVMFunction_play_note::exec(VMFnArgs* args) {
24          int note = args->arg(0)->asInt()->evalInt();          int note = args->arg(0)->asInt()->evalInt();
25          int velocity = (args->argsCount() >= 2) ? args->arg(1)->asInt()->evalInt() : 127;          int velocity = (args->argsCount() >= 2) ? args->arg(1)->asInt()->evalInt() : 127;
         int sampleoffset = (args->argsCount() >= 3) ? args->arg(2)->asInt()->evalInt() : 0;  
26          int duration = (args->argsCount() >= 4) ? args->arg(3)->asInt()->evalInt() : 0; //TODO: -1 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
27    
28          if (note < 0 || note > 127) {          if (note < 0 || note > 127) {
# Line 36  namespace LinuxSampler { Line 35  namespace LinuxSampler {
35              return errorResult(0);              return errorResult(0);
36          }          }
37    
38          if (sampleoffset < 0) {          if (duration < -2) {
39              errMsg("play_note(): argument 3 may not be a negative sample offset");              errMsg("play_note(): argument 4 must be a duration value of at least -2 or higher");
             return errorResult(0);  
         } else if (sampleoffset != 0) {  
             wrnMsg("play_note(): argument 3 does not support a sample offset other than 0 yet");  
         }  
   
         if (duration < -1) {  
             errMsg("play_note(): argument 4 must be a duration value of at least -1 or higher");  
40              return errorResult(0);              return errorResult(0);
41          }          }
42    
# Line 63  namespace LinuxSampler { Line 55  namespace LinuxSampler {
55                  return errorResult(0);                  return errorResult(0);
56              }              }
57              e.Param.Note.ParentNoteID = m_vm->m_event->cause.Param.Note.ID;              e.Param.Note.ParentNoteID = m_vm->m_event->cause.Param.Note.ID;
58                // check if that requested parent note is actually still alive
59                NoteBase* pParentNote =
60                    pEngineChannel->pEngine->NoteByID( e.Param.Note.ParentNoteID );
61                // if parent note is already gone then this new note is not required anymore
62                if (!pParentNote)
63                    return successResult(0);
64          }          }
65    
66          const note_id_t id = pEngineChannel->ScheduleNoteMicroSec(&e, 0);          const note_id_t id = pEngineChannel->ScheduleNoteMicroSec(&e, 0);
67    
68            // if a sample offset is supplied, assign the offset as override
69            // to the previously created Note object
70            if (args->argsCount() >= 3) {
71                int sampleoffset = args->arg(2)->asInt()->evalInt();
72                if (sampleoffset >= 0) {
73                    NoteBase* pNote = pEngineChannel->pEngine->NoteByID(id);
74                    if (pNote) {
75                        pNote->Override.SampleOffset = sampleoffset;
76                    }
77                } else if (sampleoffset < -1) {
78                    errMsg("play_note(): sample offset of argument 3 may not be less than -1");
79                }
80            }
81    
82          // if a duration is supplied (and play-note event was scheduled          // if a duration is supplied (and play-note event was scheduled
83          // successfully above), then schedule a subsequent stop-note event          // successfully above), then schedule a subsequent stop-note event
84          if (id && duration > 0) {          if (id && duration > 0) {
# Line 826  namespace LinuxSampler { Line 838  namespace LinuxSampler {
838    
839      VMFnResult* InstrumentScriptVMFunction_change_attack::exec(VMFnArgs* args) {      VMFnResult* InstrumentScriptVMFunction_change_attack::exec(VMFnArgs* args) {
840          int attack = args->arg(1)->asInt()->evalInt();          int attack = args->arg(1)->asInt()->evalInt();
841          if (attack > VM_EG_PAR_MAX_VALUE) {          // note: intentionally not checking against a max. value here!
842              wrnMsg("change_attack(): argument 2 may not be larger than 1000000");          // (to allow i.e. passing 2000000 for doubling the attack time)
843              attack = VM_EG_PAR_MAX_VALUE;          if (attack < 0) {
         } else if (attack < 0) {  
844              wrnMsg("change_attack(): argument 2 may not be negative");              wrnMsg("change_attack(): argument 2 may not be negative");
845              attack = 0;              attack = 0;
846          }          }
# Line 913  namespace LinuxSampler { Line 924  namespace LinuxSampler {
924    
925      VMFnResult* InstrumentScriptVMFunction_change_decay::exec(VMFnArgs* args) {      VMFnResult* InstrumentScriptVMFunction_change_decay::exec(VMFnArgs* args) {
926          int decay = args->arg(1)->asInt()->evalInt();          int decay = args->arg(1)->asInt()->evalInt();
927          if (decay > VM_EG_PAR_MAX_VALUE) {          // note: intentionally not checking against a max. value here!
928              wrnMsg("change_decay(): argument 2 may not be larger than 1000000");          // (to allow i.e. passing 2000000 for doubling the decay time)
929              decay = VM_EG_PAR_MAX_VALUE;          if (decay < 0) {
         } else if (decay < 0) {  
930              wrnMsg("change_decay(): argument 2 may not be negative");              wrnMsg("change_decay(): argument 2 may not be negative");
931              decay = 0;              decay = 0;
932          }          }
# Line 1000  namespace LinuxSampler { Line 1010  namespace LinuxSampler {
1010    
1011      VMFnResult* InstrumentScriptVMFunction_change_release::exec(VMFnArgs* args) {      VMFnResult* InstrumentScriptVMFunction_change_release::exec(VMFnArgs* args) {
1012          int release = args->arg(1)->asInt()->evalInt();          int release = args->arg(1)->asInt()->evalInt();
1013          if (release > VM_EG_PAR_MAX_VALUE) {          // note: intentionally not checking against a max. value here!
1014              wrnMsg("change_release(): argument 2 may not be larger than 1000000");          // (to allow i.e. passing 2000000 for doubling the release time)
1015              release = VM_EG_PAR_MAX_VALUE;          if (release < 0) {
         } else if (release < 0) {  
1016              wrnMsg("change_release(): argument 2 may not be negative");              wrnMsg("change_release(): argument 2 may not be negative");
1017              release = 0;              release = 0;
1018          }          }
# Line 1793  namespace LinuxSampler { Line 1802  namespace LinuxSampler {
1802          return successResult();          return successResult();
1803      }      }
1804    
1805        // change_play_pos() function
1806    
1807        InstrumentScriptVMFunction_change_play_pos::InstrumentScriptVMFunction_change_play_pos(InstrumentScriptVM* parent)
1808        : m_vm(parent)
1809        {
1810        }
1811    
1812        VMFnResult* InstrumentScriptVMFunction_change_play_pos::exec(VMFnArgs* args) {
1813            const ScriptID id = args->arg(0)->asInt()->evalInt();
1814            if (!id) {
1815                wrnMsg("change_play_pos(): note ID for argument 1 may not be zero");
1816                return successResult();
1817            }
1818            if (!id.isNoteID()) {
1819                wrnMsg("change_play_pos(): argument 1 is not a note ID");
1820                return successResult();
1821            }
1822    
1823            const int pos = args->arg(1)->asInt()->evalInt();
1824            if (pos < 0) {
1825                wrnMsg("change_play_pos(): playback position of argument 2 may not be negative");
1826                return successResult();
1827            }
1828    
1829            AbstractEngineChannel* pEngineChannel =
1830                static_cast<AbstractEngineChannel*>(m_vm->m_event->cause.pEngineChannel);
1831    
1832            NoteBase* pNote = pEngineChannel->pEngine->NoteByID( id.noteID() );
1833            if (!pNote) return successResult();
1834    
1835            pNote->Override.SampleOffset = pos;
1836    
1837            return successResult();
1838        }
1839    
1840      // event_status() function      // event_status() function
1841    
1842      InstrumentScriptVMFunction_event_status::InstrumentScriptVMFunction_event_status(InstrumentScriptVM* parent)      InstrumentScriptVMFunction_event_status::InstrumentScriptVMFunction_event_status(InstrumentScriptVM* parent)
# Line 1818  namespace LinuxSampler { Line 1862  namespace LinuxSampler {
1862          return successResult(pNote ? EVENT_STATUS_NOTE_QUEUE : EVENT_STATUS_INACTIVE);          return successResult(pNote ? EVENT_STATUS_NOTE_QUEUE : EVENT_STATUS_INACTIVE);
1863      }      }
1864    
1865        // callback_status() function
1866    
1867        InstrumentScriptVMFunction_callback_status::InstrumentScriptVMFunction_callback_status(InstrumentScriptVM* parent)
1868            : m_vm(parent)
1869        {
1870        }
1871    
1872        VMFnResult* InstrumentScriptVMFunction_callback_status::exec(VMFnArgs* args) {
1873            const script_callback_id_t id = args->arg(0)->asInt()->evalInt();
1874            if (!id) {
1875                wrnMsg("callback_status(): callback ID for argument 1 may not be zero");
1876                return successResult();
1877            }
1878    
1879            AbstractEngineChannel* pEngineChannel =
1880                static_cast<AbstractEngineChannel*>(m_vm->m_event->cause.pEngineChannel);
1881    
1882            RTList<ScriptEvent>::Iterator itCallback = pEngineChannel->ScriptCallbackByID(id);
1883            if (!itCallback)
1884                return successResult(CALLBACK_STATUS_TERMINATED);
1885    
1886            return successResult(
1887                (m_vm->m_event->execCtx == itCallback->execCtx) ?
1888                    CALLBACK_STATUS_RUNNING : CALLBACK_STATUS_QUEUE
1889            );
1890        }
1891    
1892      // wait() function (overrides core wait() implementation)      // wait() function (overrides core wait() implementation)
1893    
1894      InstrumentScriptVMFunction_wait::InstrumentScriptVMFunction_wait(InstrumentScriptVM* parent)      InstrumentScriptVMFunction_wait::InstrumentScriptVMFunction_wait(InstrumentScriptVM* parent)
# Line 1864  namespace LinuxSampler { Line 1935  namespace LinuxSampler {
1935          return successResult();          return successResult();
1936      }      }
1937    
1938        // abort() function
1939    
1940        InstrumentScriptVMFunction_abort::InstrumentScriptVMFunction_abort(InstrumentScriptVM* parent)
1941            : m_vm(parent)
1942        {
1943        }
1944    
1945        VMFnResult* InstrumentScriptVMFunction_abort::exec(VMFnArgs* args) {
1946            const script_callback_id_t id = args->arg(0)->asInt()->evalInt();
1947            if (!id) {
1948                wrnMsg("abort(): callback ID for argument 1 may not be zero");
1949                return successResult();
1950            }
1951    
1952            AbstractEngineChannel* pEngineChannel =
1953                static_cast<AbstractEngineChannel*>(m_vm->m_event->cause.pEngineChannel);
1954    
1955            RTList<ScriptEvent>::Iterator itCallback = pEngineChannel->ScriptCallbackByID(id);
1956            if (!itCallback) return successResult(); // ignore if callback is i.e. not alive anymore
1957    
1958            itCallback->execCtx->signalAbort();
1959    
1960            return successResult();
1961        }
1962    
1963        // fork() function
1964    
1965        InstrumentScriptVMFunction_fork::InstrumentScriptVMFunction_fork(InstrumentScriptVM* parent)
1966            : m_vm(parent)
1967        {
1968        }
1969    
1970        VMFnResult* InstrumentScriptVMFunction_fork::exec(VMFnArgs* args) {
1971            // check if this is actually the parent going to fork, or rather one of
1972            // the children which is already forked
1973            if (m_vm->m_event->forkIndex != 0) { // this is the entry point for a child ...
1974                int forkResult = m_vm->m_event->forkIndex;
1975                // reset so that this child may i.e. also call fork() later on
1976                m_vm->m_event->forkIndex = 0;
1977                return successResult(forkResult);
1978            }
1979    
1980            // if we are here, then this is the parent, so we must fork this parent
1981    
1982            const int n =
1983                (args->argsCount() >= 1) ? args->arg(0)->asInt()->evalInt() : 1;
1984            const bool bAutoAbort =
1985                (args->argsCount() >= 2) ? args->arg(1)->asInt()->evalInt() : true;
1986    
1987            if (m_vm->m_event->countChildHandlers() + n > MAX_FORK_PER_SCRIPT_HANDLER) {
1988                wrnMsg("fork(): requested amount would exceed allowed limit per event handler");
1989                return successResult(-1);
1990            }
1991    
1992            AbstractEngineChannel* pEngineChannel =
1993                static_cast<AbstractEngineChannel*>(m_vm->m_event->cause.pEngineChannel);
1994    
1995            if (!pEngineChannel->hasFreeScriptCallbacks(n)) {
1996                wrnMsg("fork(): global limit of event handlers exceeded");
1997                return successResult(-1);
1998            }
1999    
2000            for (int iChild = 0; iChild < n; ++iChild) {
2001                RTList<ScriptEvent>::Iterator itChild =
2002                    pEngineChannel->forkScriptCallback(m_vm->m_event, bAutoAbort);
2003                if (!itChild) { // should never happen, otherwise its a bug ...
2004                    errMsg("fork(): internal error while allocating child");
2005                    return errorResult(-1); // terminate script
2006                }
2007                // since both parent, as well all child script execution instances
2008                // all land in this exect() method, the following is (more or less)
2009                // the only feature that lets us distinguish the parent and
2010                // respective children from each other in this exect() method
2011                itChild->forkIndex = iChild + 1;
2012            }
2013    
2014            return successResult(0);
2015        }
2016    
2017  } // namespace LinuxSampler  } // namespace LinuxSampler

Legend:
Removed from v.3246  
changed lines
  Added in v.3303

  ViewVC Help
Powered by ViewVC