/[svn]/linuxsampler/trunk/src/engines/EngineChannelBase.h
ViewVC logotype

Diff of /linuxsampler/trunk/src/engines/EngineChannelBase.h

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

revision 2114 by persson, Tue Aug 10 12:05:19 2010 UTC revision 2884 by schoenebeck, Wed Apr 20 15:22:58 2016 UTC
# Line 4  Line 4 
4   *                                                                         *   *                                                                         *
5   *   Copyright (C) 2003,2004 by Benno Senoner and Christian Schoenebeck    *   *   Copyright (C) 2003,2004 by Benno Senoner and Christian Schoenebeck    *
6   *   Copyright (C) 2005-2008 Christian Schoenebeck                         *   *   Copyright (C) 2005-2008 Christian Schoenebeck                         *
7   *   Copyright (C) 2009-2010 Christian Schoenebeck and Grigor Iliev        *   *   Copyright (C) 2009-2012 Christian Schoenebeck and Grigor Iliev        *
8     *   Copyright (C) 2012-2016 Christian Schoenebeck and Andreas Persson     *
9   *                                                                         *   *                                                                         *
10   *   This program is free software; you can redistribute it and/or modify  *   *   This program is free software; you can redistribute it and/or modify  *
11   *   it under the terms of the GNU General Public License as published by  *   *   it under the terms of the GNU General Public License as published by  *
# Line 39  namespace LinuxSampler { Line 40  namespace LinuxSampler {
40              bool bChangeInstrument;       ///< Set to true by the loader when the channel should change instrument.              bool bChangeInstrument;       ///< Set to true by the loader when the channel should change instrument.
41              I* pInstrument;               ///< The new instrument. Also used by the loader to read the previously loaded instrument.              I* pInstrument;               ///< The new instrument. Also used by the loader to read the previously loaded instrument.
42              RTList<R*>* pRegionsInUse; ///< List of dimension regions in use by the currently loaded instrument. Continuously updated by the audio thread.              RTList<R*>* pRegionsInUse; ///< List of dimension regions in use by the currently loaded instrument. Continuously updated by the audio thread.
43                InstrumentScript* pScript; ///< Instrument script to be executed for this instrument. This is never NULL, it is always a valid InstrumentScript pointer. Use InstrumentScript::bHasValidScript whether it reflects a valid instrument script to be executed.
44      };      };
45    
46      template<class R>      template<class R>
# Line 48  namespace LinuxSampler { Line 50  namespace LinuxSampler {
50      };      };
51    
52      template<class V>      template<class V>
53      class VoicePool {      class NotePool {
54          public:          public:
55              virtual Pool<V>* GetVoicePool() = 0;              virtual Pool<V>* GetVoicePool() = 0;
56                virtual Pool< Note<V> >* GetNotePool() = 0;
57                virtual Pool<note_id_t>* GetNodeIDPool() = 0;
58      };      };
59    
60      template <class V /* Voice */, class R /* Region */, class I /* Instrument */>      template <class V /* Voice */, class R /* Region */, class I /* Instrument */>
61      class EngineChannelBase: public AbstractEngineChannel, public MidiKeyboardManager<V>, public ResourceConsumer<I> {      class EngineChannelBase: public AbstractEngineChannel, public MidiKeyboardManager<V>, public ResourceConsumer<I> {
62          public:          public:
63                typedef typename RTList< Note<V> >::Iterator NoteIterator;
64              typedef typename RTList<R*>::Iterator RTListRegionIterator;              typedef typename RTList<R*>::Iterator RTListRegionIterator;
65              typedef typename MidiKeyboardManager<V>::MidiKey MidiKey;              typedef typename MidiKeyboardManager<V>::MidiKey MidiKey;
66    
67                virtual MidiKeyboardManagerBase* GetMidiKeyboardManager() OVERRIDE {
68                    return this;
69                }
70    
71              virtual void HandBack(I* Instrument) {              virtual void HandBack(I* Instrument) {
72                  ResourceManager<InstrumentManager::instrument_id_t, I>* mgr =                  ResourceManager<InstrumentManager::instrument_id_t, I>* mgr =
73                      dynamic_cast<ResourceManager<InstrumentManager::instrument_id_t, I>*>(pEngine->GetInstrumentManager());                      dynamic_cast<ResourceManager<InstrumentManager::instrument_id_t, I>*>(pEngine->GetInstrumentManager());
# Line 68  namespace LinuxSampler { Line 77  namespace LinuxSampler {
77              virtual void ClearRegionsInUse() {              virtual void ClearRegionsInUse() {
78                  {                  {
79                      InstrumentChangeCmd<R, I>& cmd = InstrumentChangeCommand.GetConfigForUpdate();                      InstrumentChangeCmd<R, I>& cmd = InstrumentChangeCommand.GetConfigForUpdate();
80                      if(cmd.pRegionsInUse != NULL) cmd.pRegionsInUse->clear();                      if (cmd.pRegionsInUse) cmd.pRegionsInUse->clear();
81                        cmd.bChangeInstrument = false;
82                  }                  }
83                  {                  {
84                      InstrumentChangeCmd<R, I>& cmd = InstrumentChangeCommand.SwitchConfig();                      InstrumentChangeCmd<R, I>& cmd = InstrumentChangeCommand.SwitchConfig();
85                      if(cmd.pRegionsInUse != NULL) cmd.pRegionsInUse->clear();                      if (cmd.pRegionsInUse) cmd.pRegionsInUse->clear();
86                        cmd.bChangeInstrument = false;
87                  }                  }
88              }              }
89    
# Line 82  namespace LinuxSampler { Line 93  namespace LinuxSampler {
93              }              }
94    
95              virtual void DeleteRegionsInUse() {              virtual void DeleteRegionsInUse() {
96                    RTList<R*>* previous = NULL; // prevent double free
97                  {                  {
98                      InstrumentChangeCmd<R, I>& cmd = InstrumentChangeCommand.GetConfigForUpdate();                      InstrumentChangeCmd<R, I>& cmd = InstrumentChangeCommand.GetConfigForUpdate();
99                      if(cmd.pRegionsInUse != NULL) {                      if (cmd.pRegionsInUse) {
100                            previous = cmd.pRegionsInUse;
101                          delete cmd.pRegionsInUse;                          delete cmd.pRegionsInUse;
102                          cmd.pRegionsInUse = NULL;                          cmd.pRegionsInUse = NULL;
103                      }                      }
104                        cmd.bChangeInstrument = false;
105                  }                  }
106                  {                  {
107                      InstrumentChangeCmd<R, I>& cmd = InstrumentChangeCommand.SwitchConfig();                      InstrumentChangeCmd<R, I>& cmd = InstrumentChangeCommand.SwitchConfig();
108                      if(cmd.pRegionsInUse != NULL) {                      if (cmd.pRegionsInUse) {
109                          delete cmd.pRegionsInUse;                          if (cmd.pRegionsInUse != previous)
110                                delete cmd.pRegionsInUse;
111                          cmd.pRegionsInUse = NULL;                          cmd.pRegionsInUse = NULL;
112                      }                      }
113                        cmd.bChangeInstrument = false;
114                  }                  }
115              }              }
116    
# Line 102  namespace LinuxSampler { Line 118  namespace LinuxSampler {
118                  {                  {
119                      InstrumentChangeCmd<R, I>& cmd = InstrumentChangeCommand.GetConfigForUpdate();                      InstrumentChangeCmd<R, I>& cmd = InstrumentChangeCommand.GetConfigForUpdate();
120                      cmd.pRegionsInUse = new RTList<R*>(pRegionPool[0]);                      cmd.pRegionsInUse = new RTList<R*>(pRegionPool[0]);
121                        cmd.bChangeInstrument = false;
122                  }                  }
123                  {                  {
124                      InstrumentChangeCmd<R, I>& cmd = InstrumentChangeCommand.SwitchConfig();                      InstrumentChangeCmd<R, I>& cmd = InstrumentChangeCommand.SwitchConfig();
125                      cmd.pRegionsInUse = new RTList<R*>(pRegionPool[1]);                      cmd.pRegionsInUse = new RTList<R*>(pRegionPool[1]);
126                        cmd.bChangeInstrument = false;
127                  }                  }
128              }              }
129    
# Line 114  namespace LinuxSampler { Line 132  namespace LinuxSampler {
132                      if (pEngine->pAudioOutputDevice == pAudioOut) return;                      if (pEngine->pAudioOutputDevice == pAudioOut) return;
133                      DisconnectAudioOutputDevice();                      DisconnectAudioOutputDevice();
134                  }                  }
135                  pEngine = AbstractEngine::AcquireEngine(this, pAudioOut);                  AbstractEngine* newEngine = AbstractEngine::AcquireEngine(this, pAudioOut);
136                  ResetInternal();                  {
137                        LockGuard lock(EngineMutex);
138                        pEngine = newEngine;
139                    }
140                    ResetInternal(false/*don't reset engine*/); // 'false' is error prone here, but the danger of recursion with 'true' would be worse, there could be a better solution though
141                  pEvents = new RTList<Event>(pEngine->pEventPool);                  pEvents = new RTList<Event>(pEngine->pEventPool);
142                    delayedEvents.pList = new RTList<Event>(pEngine->pEventPool);
143    
144                  RegionPools<R>* pRegionPool = dynamic_cast<RegionPools<R>*>(pEngine);                  RegionPools<R>* pRegionPool = dynamic_cast<RegionPools<R>*>(pEngine);
145                  // reset the instrument change command struct (need to be done                  // reset the instrument change command struct (need to be done
# Line 143  namespace LinuxSampler { Line 166  namespace LinuxSampler {
166                      bStatusChanged = true;                      bStatusChanged = true;
167                  }                  }
168    
169                  VoicePool<V>* pVoicePool = dynamic_cast<VoicePool<V>*>(pEngine);                  NotePool<V>* pNotePool = dynamic_cast<NotePool<V>*>(pEngine);
170                  MidiKeyboardManager<V>::AllocateActiveVoices(pVoicePool->GetVoicePool());                  MidiKeyboardManager<V>::AllocateActiveNotesLists(
171                  MidiKeyboardManager<V>::AllocateEvents(pEngine->pEventPool);                      pNotePool->GetNotePool(),
172                        pNotePool->GetVoicePool()
173                    );
174                    MidiKeyboardManager<V>::AllocateEventsLists(pEngine->pEventPool);
175    
176                  AudioDeviceChannelLeft  = 0;                  AudioDeviceChannelLeft  = 0;
177                  AudioDeviceChannelRight = 1;                  AudioDeviceChannelRight = 1;
# Line 166  namespace LinuxSampler { Line 192  namespace LinuxSampler {
192              virtual void DisconnectAudioOutputDevice() {              virtual void DisconnectAudioOutputDevice() {
193                  if (pEngine) { // if clause to prevent disconnect loops                  if (pEngine) { // if clause to prevent disconnect loops
194    
195                      ResetInternal();                      ResetInternal(false/*don't reset engine*/); // 'false' is error prone here, but the danger of recursion with 'true' would be worse, there could be a better solution though
196    
197                      DeleteRegionsInUse();                      DeleteRegionsInUse();
198                        UnloadScriptInUse();
199    
200                      InstrumentChangeCmd<R, I>& cmd = InstrumentChangeCommand.GetConfigForUpdate();                      InstrumentChangeCmd<R, I>& cmd = InstrumentChangeCommand.GetConfigForUpdate();
201                      if (cmd.pInstrument) {                      if (cmd.pInstrument) {
# Line 180  namespace LinuxSampler { Line 207  namespace LinuxSampler {
207                          delete pEvents;                          delete pEvents;
208                          pEvents = NULL;                          pEvents = NULL;
209                      }                      }
210                        if (delayedEvents.pList) {
211                            delete delayedEvents.pList;
212                            delayedEvents.pList = NULL;
213                        }
214    
215                      MidiKeyboardManager<V>::DeleteActiveVoices();                      MidiKeyboardManager<V>::DeleteActiveNotesLists();
216                      MidiKeyboardManager<V>::DeleteEvents();                      MidiKeyboardManager<V>::DeleteEventsLists();
217                      DeleteGroupEventLists();                      DeleteGroupEventLists();
218    
219                      AudioOutputDevice* oldAudioDevice = pEngine->pAudioOutputDevice;                      AudioOutputDevice* oldAudioDevice = pEngine->pAudioOutputDevice;
220                      pEngine = NULL;                      {
221                            LockGuard lock(EngineMutex);
222                            pEngine = NULL;
223                        }
224                      AbstractEngine::FreeEngine(this, oldAudioDevice);                      AbstractEngine::FreeEngine(this, oldAudioDevice);
225                      AudioDeviceChannelLeft  = -1;                      AudioDeviceChannelLeft  = -1;
226                      AudioDeviceChannelRight = -1;                      AudioDeviceChannelRight = -1;
# Line 204  namespace LinuxSampler { Line 238  namespace LinuxSampler {
238                      virtual bool Process(MidiKey* pMidiKey) { pMidiKey->pEvents->clear(); return false; }                      virtual bool Process(MidiKey* pMidiKey) { pMidiKey->pEvents->clear(); return false; }
239              };              };
240    
241              void ClearEventLists() {              /**
242                 * Free all events of the current audio fragment cycle. Calling
243                 * this method will @b NOT free events scheduled past the current
244                 * fragment's boundary! (@see AbstractEngineChannel::delayedEvents).
245                 */
246                void ClearEventListsOfCurrentFragment() {
247                  pEvents->clear();                  pEvents->clear();
248                  // empty MIDI key specific event lists                  // empty MIDI key specific event lists
249                  ClearEventListsHandler handler;                  ClearEventListsHandler handler;
250                  ProcessActiveVoices(&handler);                  this->ProcessActiveVoices(&handler);
251    
252                  // empty exclusive group specific event lists                  // empty exclusive group specific event lists
253                  ClearGroupEventLists();                  // (pInstrument == 0 could mean that LoadInstrument is
254                    // building new group event lists, so we must check
255                    // for that)
256                    if (pInstrument) ClearGroupEventLists();
257              }              }
258    
259              // implementation of abstract methods derived from interface class 'InstrumentConsumer'              // implementation of abstract methods derived from interface class 'InstrumentConsumer'
# Line 221  namespace LinuxSampler { Line 263  namespace LinuxSampler {
263               * we are currently using on this EngineChannel is going to be updated,               * we are currently using on this EngineChannel is going to be updated,
264               * so we can stop playback before that happens.               * so we can stop playback before that happens.
265               */               */
266              virtual void ResourceToBeUpdated(I* pResource, void*& pUpdateArg) {              virtual void ResourceToBeUpdated(I* pResource, void*& pUpdateArg) OVERRIDE {
267                  dmsg(3,("EngineChannelBase: Received instrument update message.\n"));                  dmsg(3,("EngineChannelBase: Received instrument update message.\n"));
268                  if (pEngine) pEngine->DisableAndLock();                  if (pEngine) pEngine->DisableAndLock();
269                  ResetInternal();                  ResetInternal(false/*don't reset engine*/);
270                  this->pInstrument = NULL;                  this->pInstrument = NULL;
271              }              }
272    
# Line 232  namespace LinuxSampler { Line 274  namespace LinuxSampler {
274               * Will be called by the InstrumentResourceManager when the instrument               * Will be called by the InstrumentResourceManager when the instrument
275               * update process was completed, so we can continue with playback.               * update process was completed, so we can continue with playback.
276               */               */
277              virtual void ResourceUpdated(I* pOldResource, I* pNewResource, void* pUpdateArg) {              virtual void ResourceUpdated(I* pOldResource, I* pNewResource, void* pUpdateArg) OVERRIDE {
278                  this->pInstrument = pNewResource; //TODO: there are couple of engine parameters we should update here as well if the instrument was updated (see LoadInstrument())                  this->pInstrument = pNewResource; //TODO: there are couple of engine parameters we should update here as well if the instrument was updated (see LoadInstrument())
279                  if (pEngine) pEngine->Enable();                  if (pEngine) pEngine->Enable();
280                  bStatusChanged = true; // status of engine has changed, so set notify flag                  bStatusChanged = true; // status of engine has changed, so set notify flag
# Line 244  namespace LinuxSampler { Line 286  namespace LinuxSampler {
286               *               *
287               * @param fProgress - current progress as value between 0.0 and 1.0               * @param fProgress - current progress as value between 0.0 and 1.0
288               */               */
289              virtual void OnResourceProgress(float fProgress) {              virtual void OnResourceProgress(float fProgress) OVERRIDE {
290                  this->InstrumentStat = int(fProgress * 100.0f);                  this->InstrumentStat = int(fProgress * 100.0f);
291                  dmsg(7,("EngineChannelBase: progress %d%", InstrumentStat));                  dmsg(7,("EngineChannelBase: progress %d%%", InstrumentStat));
292                  bStatusChanged = true; // status of engine has changed, so set notify flag                  bStatusChanged = true; // status of engine has changed, so set notify flag
293              }              }
294    
295              void RenderActiveVoices(uint Samples) {              void RenderActiveVoices(uint Samples) {
296                  RenderVoicesHandler handler(this, Samples);                  RenderVoicesHandler handler(this, Samples);
297                  ProcessActiveVoices(&handler);                  this->ProcessActiveVoices(&handler);
298    
299                  SetVoiceCount(handler.VoiceCount);                  SetVoiceCount(handler.VoiceCount);
300                  SetDiskStreamCount(handler.StreamCount);                  SetDiskStreamCount(handler.StreamCount);
301              }              }
302    
303                /**
304                 * Called by real-time instrument script functions to schedule a
305                 * new note (new note-on event and a new @c Note object linked to it)
306                 * @a delay microseconds in future.
307                 *
308                 * @b IMPORTANT: for the supplied @a delay to be scheduled
309                 * correctly, the passed @a pEvent must be assigned a valid
310                 * fragment time within the current audio fragment boundaries. That
311                 * fragment time will be used by this method as basis for
312                 * interpreting what "now" acutally is, and thus it will be used as
313                 * basis for calculating the precise scheduling time for @a delay.
314                 * The easiest way to achieve this is by copying a recent event
315                 * which happened within the current audio fragment cycle: i.e. the
316                 * original event which caused calling this method here, or by using
317                 * Event::copyTimefrom() method to only copy the time, without any
318                 * other event data.
319                 *
320                 * @param pEvent - note-on event to be scheduled in future (event
321                 *                 data will be copied)
322                 * @param delay - amount of microseconds in future (from now) when
323                 *                event shall be processed
324                 * @returns unique note ID of scheduled new note, or NULL on error
325                 */
326                note_id_t ScheduleNoteMicroSec(const Event* pEvent, int delay) OVERRIDE {
327                    // add (copied) note-on event into scheduler queue
328                    const event_id_t noteOnEventID = ScheduleEventMicroSec(pEvent, delay);
329                    if (!noteOnEventID) return 0; // error
330                    // get access to (copied) event on the scheduler queue
331                    RTList<Event>::Iterator itEvent = pEvents->fromID(noteOnEventID);
332                    // stick a new note to the (copied) event on the queue
333                    const note_id_t noteID = pEngine->LaunchNewNote(this, &*itEvent);
334                    return noteID;
335                }
336    
337                /**
338                 * Called by real-time instrument script functions to ignore the note
339                 * reflected by given note ID. The note's event will be freed immediately
340                 * to its event pool and this will prevent voices to be launched for the
341                 * note.
342                 *
343                 * NOTE: preventing a note by calling this method works only if the note
344                 * was launched within the current audio fragment cycle.
345                 *
346                 * @param id - unique ID of note to be dropped
347                 */
348                void IgnoreNote(note_id_t id) OVERRIDE {
349                    Pool< Note<V> >* pNotePool =
350                        dynamic_cast<NotePool<V>*>(pEngine)->GetNotePool();
351    
352                    NoteIterator itNote = pNotePool->fromID(id);
353                    if (!itNote) return; // note probably already released
354    
355                    // if the note already got active voices, then it is too late to drop it
356                    if (!itNote->pActiveVoices->isEmpty()) return;
357    
358                    // if the original (note-on) event is not available anymore, then it is too late to drop it
359                    RTList<Event>::Iterator itEvent = pEvents->fromID(itNote->eventID);
360                    if (!itEvent) return;
361    
362                    // drop the note
363                    pNotePool->free(itNote);
364    
365                    // drop the original event
366                    pEvents->free(itEvent);
367                }
368    
369              RTList<R*>* pRegionsInUse;     ///< temporary pointer into the instrument change command, used by the audio thread              RTList<R*>* pRegionsInUse;     ///< temporary pointer into the instrument change command, used by the audio thread
370              I* pInstrument;              I* pInstrument;
371    
372              template<class TV, class TRR, class TR, class TD, class TIM, class TI> friend class EngineBase;              template<class TV, class TRR, class TR, class TD, class TIM, class TI> friend class EngineBase;
373    
374          protected:          protected:
375              EngineChannelBase() : InstrumentChangeCommandReader(InstrumentChangeCommand) {              EngineChannelBase() :
376                    MidiKeyboardManager<V>(this),
377                    InstrumentChangeCommandReader(InstrumentChangeCommand)
378                {
379                  pInstrument = NULL;                  pInstrument = NULL;
380    
381                  // reset the instrument change command struct (need to be done                  // reset the instrument change command struct (need to be done
# Line 273  namespace LinuxSampler { Line 384  namespace LinuxSampler {
384                      InstrumentChangeCmd<R, I>& cmd = InstrumentChangeCommand.GetConfigForUpdate();                      InstrumentChangeCmd<R, I>& cmd = InstrumentChangeCommand.GetConfigForUpdate();
385                      cmd.pRegionsInUse = NULL;                      cmd.pRegionsInUse = NULL;
386                      cmd.pInstrument = NULL;                      cmd.pInstrument = NULL;
387                        cmd.pScript = new InstrumentScript(this);
388                      cmd.bChangeInstrument = false;                      cmd.bChangeInstrument = false;
389                  }                  }
390                  {                  {
391                      InstrumentChangeCmd<R, I>& cmd = InstrumentChangeCommand.SwitchConfig();                      InstrumentChangeCmd<R, I>& cmd = InstrumentChangeCommand.SwitchConfig();
392                      cmd.pRegionsInUse = NULL;                      cmd.pRegionsInUse = NULL;
393                      cmd.pInstrument = NULL;                      cmd.pInstrument = NULL;
394                        cmd.pScript = new InstrumentScript(this);
395                      cmd.bChangeInstrument = false;                      cmd.bChangeInstrument = false;
396                  }                  }
397              }              }
398    
399              virtual ~EngineChannelBase() { }              virtual ~EngineChannelBase() {
400                    InstrumentScript* previous = NULL; // prevent double free
401                    {
402                        InstrumentChangeCmd<R, I>& cmd = InstrumentChangeCommand.GetConfigForUpdate();
403                        if (cmd.pScript) {
404                            previous = cmd.pScript;
405                            delete cmd.pScript;
406                            cmd.pScript = NULL;
407                        }
408                    }
409                    {
410                        InstrumentChangeCmd<R, I>& cmd = InstrumentChangeCommand.SwitchConfig();
411                        if (cmd.pScript) {
412                            if (previous != cmd.pScript)
413                                delete cmd.pScript;
414                            cmd.pScript = NULL;
415                        }
416                    }
417                }
418    
419              typedef typename RTList<V>::Iterator RTListVoiceIterator;              typedef typename RTList<V>::Iterator RTListVoiceIterator;
420    
# Line 310  namespace LinuxSampler { Line 441  namespace LinuxSampler {
441                                  if ((itVoice->DiskStreamRef).State != Stream::state_unused) StreamCount++;                                  if ((itVoice->DiskStreamRef).State != Stream::state_unused) StreamCount++;
442                              }                              }
443                          }  else { // voice reached end, is now inactive                          }  else { // voice reached end, is now inactive
444                                itVoice->VoiceFreed();
445                              pChannel->FreeVoice(itVoice); // remove voice from the list of active voices                              pChannel->FreeVoice(itVoice); // remove voice from the list of active voices
446                          }                          }
447                      }                      }
# Line 321  namespace LinuxSampler { Line 453  namespace LinuxSampler {
453              SyncConfInstrChangeCmdReader InstrumentChangeCommandReader;              SyncConfInstrChangeCmdReader InstrumentChangeCommandReader;
454    
455              /** This method is not thread safe! */              /** This method is not thread safe! */
456              virtual void ResetInternal() {              virtual void ResetInternal(bool bResetEngine) OVERRIDE {
457                  AbstractEngineChannel::ResetInternal();                  AbstractEngineChannel::ResetInternal(bResetEngine);
458    
459                  MidiKeyboardManager<V>::Reset();                  MidiKeyboardManager<V>::Reset();
460              }              }
# Line 335  namespace LinuxSampler { Line 467  namespace LinuxSampler {
467              }              }
468    
469              /**              /**
470                 * Unload the currently used and loaded real-time instrument script.
471                 * The source code of the script is retained, so that it can still
472                 * be reloaded.
473                 */
474                void UnloadScriptInUse() {
475                    {
476                        InstrumentChangeCmd<R, I>& cmd = InstrumentChangeCommand.GetConfigForUpdate();
477                        if (cmd.pScript) cmd.pScript->unload();
478                    }
479                    {
480                        InstrumentChangeCmd<R, I>& cmd = InstrumentChangeCommand.SwitchConfig();
481                        if (cmd.pScript) cmd.pScript->unload();
482                    }
483                    InstrumentChangeCommand.SwitchConfig(); // switch back to original one
484                }
485    
486                /**
487                 * Load real-time instrument script and all its resources required
488                 * for the upcoming instrument change.
489                 *
490                 * @param text - source code of script
491                 */
492                void LoadInstrumentScript(const String& text) {
493                    InstrumentChangeCmd<R, I>& cmd = InstrumentChangeCommand.GetConfigForUpdate();
494                    // load the new script
495                    cmd.pScript->load(text);
496                }
497    
498                /**
499               * Changes the instrument for an engine channel.               * Changes the instrument for an engine channel.
500               *               *
501               * @param pInstrument - new instrument               * @param pInstrument - new instrument

Legend:
Removed from v.2114  
changed lines
  Added in v.2884

  ViewVC Help
Powered by ViewVC