/[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 2326 by persson, Thu Mar 8 19:40:14 2012 UTC revision 2871 by schoenebeck, Sun Apr 10 18:22:23 2016 UTC
# Line 5  Line 5 
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-2012 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 59  namespace LinuxSampler { Line 61  namespace LinuxSampler {
61              typedef typename RTList<R*>::Iterator RTListRegionIterator;              typedef typename RTList<R*>::Iterator RTListRegionIterator;
62              typedef typename MidiKeyboardManager<V>::MidiKey MidiKey;              typedef typename MidiKeyboardManager<V>::MidiKey MidiKey;
63    
64                virtual MidiKeyboardManagerBase* GetMidiKeyboardManager() OVERRIDE {
65                    return this;
66                }
67    
68              virtual void HandBack(I* Instrument) {              virtual void HandBack(I* Instrument) {
69                  ResourceManager<InstrumentManager::instrument_id_t, I>* mgr =                  ResourceManager<InstrumentManager::instrument_id_t, I>* mgr =
70                      dynamic_cast<ResourceManager<InstrumentManager::instrument_id_t, I>*>(pEngine->GetInstrumentManager());                      dynamic_cast<ResourceManager<InstrumentManager::instrument_id_t, I>*>(pEngine->GetInstrumentManager());
# Line 84  namespace LinuxSampler { Line 90  namespace LinuxSampler {
90              }              }
91    
92              virtual void DeleteRegionsInUse() {              virtual void DeleteRegionsInUse() {
93                    RTList<R*>* previous = NULL; // prevent double free
94                  {                  {
95                      InstrumentChangeCmd<R, I>& cmd = InstrumentChangeCommand.GetConfigForUpdate();                      InstrumentChangeCmd<R, I>& cmd = InstrumentChangeCommand.GetConfigForUpdate();
96                      if (cmd.pRegionsInUse) {                      if (cmd.pRegionsInUse) {
97                            previous = cmd.pRegionsInUse;
98                          delete cmd.pRegionsInUse;                          delete cmd.pRegionsInUse;
99                          cmd.pRegionsInUse = NULL;                          cmd.pRegionsInUse = NULL;
100                      }                      }
# Line 95  namespace LinuxSampler { Line 103  namespace LinuxSampler {
103                  {                  {
104                      InstrumentChangeCmd<R, I>& cmd = InstrumentChangeCommand.SwitchConfig();                      InstrumentChangeCmd<R, I>& cmd = InstrumentChangeCommand.SwitchConfig();
105                      if (cmd.pRegionsInUse) {                      if (cmd.pRegionsInUse) {
106                          delete cmd.pRegionsInUse;                          if (cmd.pRegionsInUse != previous)
107                                delete cmd.pRegionsInUse;
108                          cmd.pRegionsInUse = NULL;                          cmd.pRegionsInUse = NULL;
109                      }                      }
110                      cmd.bChangeInstrument = false;                      cmd.bChangeInstrument = false;
# Line 121  namespace LinuxSampler { Line 130  namespace LinuxSampler {
130                      DisconnectAudioOutputDevice();                      DisconnectAudioOutputDevice();
131                  }                  }
132                  AbstractEngine* newEngine = AbstractEngine::AcquireEngine(this, pAudioOut);                  AbstractEngine* newEngine = AbstractEngine::AcquireEngine(this, pAudioOut);
133                  EngineMutex.Lock();                  {
134                  pEngine = newEngine;                      LockGuard lock(EngineMutex);
135                  EngineMutex.Unlock();                      pEngine = newEngine;
136                  ResetInternal();                  }
137                    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
138                  pEvents = new RTList<Event>(pEngine->pEventPool);                  pEvents = new RTList<Event>(pEngine->pEventPool);
139                    delayedEvents.pList = new RTList<Event>(pEngine->pEventPool);
140    
141                  RegionPools<R>* pRegionPool = dynamic_cast<RegionPools<R>*>(pEngine);                  RegionPools<R>* pRegionPool = dynamic_cast<RegionPools<R>*>(pEngine);
142                  // reset the instrument change command struct (need to be done                  // reset the instrument change command struct (need to be done
# Line 175  namespace LinuxSampler { Line 186  namespace LinuxSampler {
186              virtual void DisconnectAudioOutputDevice() {              virtual void DisconnectAudioOutputDevice() {
187                  if (pEngine) { // if clause to prevent disconnect loops                  if (pEngine) { // if clause to prevent disconnect loops
188    
189                      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
190    
191                      DeleteRegionsInUse();                      DeleteRegionsInUse();
192                        UnloadScriptInUse();
193    
194                      InstrumentChangeCmd<R, I>& cmd = InstrumentChangeCommand.GetConfigForUpdate();                      InstrumentChangeCmd<R, I>& cmd = InstrumentChangeCommand.GetConfigForUpdate();
195                      if (cmd.pInstrument) {                      if (cmd.pInstrument) {
# Line 189  namespace LinuxSampler { Line 201  namespace LinuxSampler {
201                          delete pEvents;                          delete pEvents;
202                          pEvents = NULL;                          pEvents = NULL;
203                      }                      }
204                        if (delayedEvents.pList) {
205                            delete delayedEvents.pList;
206                            delayedEvents.pList = NULL;
207                        }
208    
209                      MidiKeyboardManager<V>::DeleteActiveVoices();                      MidiKeyboardManager<V>::DeleteActiveVoices();
210                      MidiKeyboardManager<V>::DeleteEvents();                      MidiKeyboardManager<V>::DeleteEvents();
211                      DeleteGroupEventLists();                      DeleteGroupEventLists();
212    
213                      AudioOutputDevice* oldAudioDevice = pEngine->pAudioOutputDevice;                      AudioOutputDevice* oldAudioDevice = pEngine->pAudioOutputDevice;
214                      EngineMutex.Lock();                      {
215                      pEngine = NULL;                          LockGuard lock(EngineMutex);
216                      EngineMutex.Unlock();                          pEngine = NULL;
217                        }
218                      AbstractEngine::FreeEngine(this, oldAudioDevice);                      AbstractEngine::FreeEngine(this, oldAudioDevice);
219                      AudioDeviceChannelLeft  = -1;                      AudioDeviceChannelLeft  = -1;
220                      AudioDeviceChannelRight = -1;                      AudioDeviceChannelRight = -1;
# Line 215  namespace LinuxSampler { Line 232  namespace LinuxSampler {
232                      virtual bool Process(MidiKey* pMidiKey) { pMidiKey->pEvents->clear(); return false; }                      virtual bool Process(MidiKey* pMidiKey) { pMidiKey->pEvents->clear(); return false; }
233              };              };
234    
235              void ClearEventLists() {              /**
236                 * Free all events of the current audio fragment cycle. Calling
237                 * this method will @b NOT free events scheduled past the current
238                 * fragment's boundary! (@see AbstractEngineChannel::delayedEvents).
239                 */
240                void ClearEventListsOfCurrentFragment() {
241                  pEvents->clear();                  pEvents->clear();
242                  // empty MIDI key specific event lists                  // empty MIDI key specific event lists
243                  ClearEventListsHandler handler;                  ClearEventListsHandler handler;
244                  ProcessActiveVoices(&handler);                  this->ProcessActiveVoices(&handler);
245    
246                  // empty exclusive group specific event lists                  // empty exclusive group specific event lists
247                  ClearGroupEventLists();                  // (pInstrument == 0 could mean that LoadInstrument is
248                    // building new group event lists, so we must check
249                    // for that)
250                    if (pInstrument) ClearGroupEventLists();
251              }              }
252    
253              // implementation of abstract methods derived from interface class 'InstrumentConsumer'              // implementation of abstract methods derived from interface class 'InstrumentConsumer'
# Line 232  namespace LinuxSampler { Line 257  namespace LinuxSampler {
257               * we are currently using on this EngineChannel is going to be updated,               * we are currently using on this EngineChannel is going to be updated,
258               * so we can stop playback before that happens.               * so we can stop playback before that happens.
259               */               */
260              virtual void ResourceToBeUpdated(I* pResource, void*& pUpdateArg) {              virtual void ResourceToBeUpdated(I* pResource, void*& pUpdateArg) OVERRIDE {
261                  dmsg(3,("EngineChannelBase: Received instrument update message.\n"));                  dmsg(3,("EngineChannelBase: Received instrument update message.\n"));
262                  if (pEngine) pEngine->DisableAndLock();                  if (pEngine) pEngine->DisableAndLock();
263                  ResetInternal();                  ResetInternal(false/*don't reset engine*/);
264                  this->pInstrument = NULL;                  this->pInstrument = NULL;
265              }              }
266    
# Line 243  namespace LinuxSampler { Line 268  namespace LinuxSampler {
268               * Will be called by the InstrumentResourceManager when the instrument               * Will be called by the InstrumentResourceManager when the instrument
269               * update process was completed, so we can continue with playback.               * update process was completed, so we can continue with playback.
270               */               */
271              virtual void ResourceUpdated(I* pOldResource, I* pNewResource, void* pUpdateArg) {              virtual void ResourceUpdated(I* pOldResource, I* pNewResource, void* pUpdateArg) OVERRIDE {
272                  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())
273                  if (pEngine) pEngine->Enable();                  if (pEngine) pEngine->Enable();
274                  bStatusChanged = true; // status of engine has changed, so set notify flag                  bStatusChanged = true; // status of engine has changed, so set notify flag
# Line 255  namespace LinuxSampler { Line 280  namespace LinuxSampler {
280               *               *
281               * @param fProgress - current progress as value between 0.0 and 1.0               * @param fProgress - current progress as value between 0.0 and 1.0
282               */               */
283              virtual void OnResourceProgress(float fProgress) {              virtual void OnResourceProgress(float fProgress) OVERRIDE {
284                  this->InstrumentStat = int(fProgress * 100.0f);                  this->InstrumentStat = int(fProgress * 100.0f);
285                  dmsg(7,("EngineChannelBase: progress %d%", InstrumentStat));                  dmsg(7,("EngineChannelBase: progress %d%%", InstrumentStat));
286                  bStatusChanged = true; // status of engine has changed, so set notify flag                  bStatusChanged = true; // status of engine has changed, so set notify flag
287              }              }
288    
289              void RenderActiveVoices(uint Samples) {              void RenderActiveVoices(uint Samples) {
290                  RenderVoicesHandler handler(this, Samples);                  RenderVoicesHandler handler(this, Samples);
291                  ProcessActiveVoices(&handler);                  this->ProcessActiveVoices(&handler);
292    
293                  SetVoiceCount(handler.VoiceCount);                  SetVoiceCount(handler.VoiceCount);
294                  SetDiskStreamCount(handler.StreamCount);                  SetDiskStreamCount(handler.StreamCount);
# Line 275  namespace LinuxSampler { Line 300  namespace LinuxSampler {
300              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;
301    
302          protected:          protected:
303              EngineChannelBase() : InstrumentChangeCommandReader(InstrumentChangeCommand) {              EngineChannelBase() :
304                    MidiKeyboardManager<V>(this),
305                    InstrumentChangeCommandReader(InstrumentChangeCommand)
306                {
307                  pInstrument = NULL;                  pInstrument = NULL;
308    
309                  // reset the instrument change command struct (need to be done                  // reset the instrument change command struct (need to be done
# Line 284  namespace LinuxSampler { Line 312  namespace LinuxSampler {
312                      InstrumentChangeCmd<R, I>& cmd = InstrumentChangeCommand.GetConfigForUpdate();                      InstrumentChangeCmd<R, I>& cmd = InstrumentChangeCommand.GetConfigForUpdate();
313                      cmd.pRegionsInUse = NULL;                      cmd.pRegionsInUse = NULL;
314                      cmd.pInstrument = NULL;                      cmd.pInstrument = NULL;
315                        cmd.pScript = new InstrumentScript(this);
316                      cmd.bChangeInstrument = false;                      cmd.bChangeInstrument = false;
317                  }                  }
318                  {                  {
319                      InstrumentChangeCmd<R, I>& cmd = InstrumentChangeCommand.SwitchConfig();                      InstrumentChangeCmd<R, I>& cmd = InstrumentChangeCommand.SwitchConfig();
320                      cmd.pRegionsInUse = NULL;                      cmd.pRegionsInUse = NULL;
321                      cmd.pInstrument = NULL;                      cmd.pInstrument = NULL;
322                        cmd.pScript = new InstrumentScript(this);
323                      cmd.bChangeInstrument = false;                      cmd.bChangeInstrument = false;
324                  }                  }
325              }              }
326    
327              virtual ~EngineChannelBase() { }              virtual ~EngineChannelBase() {
328                    InstrumentScript* previous = NULL; // prevent double free
329                    {
330                        InstrumentChangeCmd<R, I>& cmd = InstrumentChangeCommand.GetConfigForUpdate();
331                        if (cmd.pScript) {
332                            previous = cmd.pScript;
333                            delete cmd.pScript;
334                            cmd.pScript = NULL;
335                        }
336                    }
337                    {
338                        InstrumentChangeCmd<R, I>& cmd = InstrumentChangeCommand.SwitchConfig();
339                        if (cmd.pScript) {
340                            if (previous != cmd.pScript)
341                                delete cmd.pScript;
342                            cmd.pScript = NULL;
343                        }
344                    }
345                }
346    
347              typedef typename RTList<V>::Iterator RTListVoiceIterator;              typedef typename RTList<V>::Iterator RTListVoiceIterator;
348    
# Line 333  namespace LinuxSampler { Line 381  namespace LinuxSampler {
381              SyncConfInstrChangeCmdReader InstrumentChangeCommandReader;              SyncConfInstrChangeCmdReader InstrumentChangeCommandReader;
382    
383              /** This method is not thread safe! */              /** This method is not thread safe! */
384              virtual void ResetInternal() {              virtual void ResetInternal(bool bResetEngine) OVERRIDE {
385                  AbstractEngineChannel::ResetInternal();                  AbstractEngineChannel::ResetInternal(bResetEngine);
386    
387                  MidiKeyboardManager<V>::Reset();                  MidiKeyboardManager<V>::Reset();
388              }              }
# Line 347  namespace LinuxSampler { Line 395  namespace LinuxSampler {
395              }              }
396    
397              /**              /**
398                 * Unload the currently used and loaded real-time instrument script.
399                 * The source code of the script is retained, so that it can still
400                 * be reloaded.
401                 */
402                void UnloadScriptInUse() {
403                    {
404                        InstrumentChangeCmd<R, I>& cmd = InstrumentChangeCommand.GetConfigForUpdate();
405                        if (cmd.pScript) cmd.pScript->unload();
406                    }
407                    {
408                        InstrumentChangeCmd<R, I>& cmd = InstrumentChangeCommand.SwitchConfig();
409                        if (cmd.pScript) cmd.pScript->unload();
410                    }
411                    InstrumentChangeCommand.SwitchConfig(); // switch back to original one
412                }
413    
414                /**
415                 * Load real-time instrument script and all its resources required
416                 * for the upcoming instrument change.
417                 *
418                 * @param text - source code of script
419                 */
420                void LoadInstrumentScript(const String& text) {
421                    InstrumentChangeCmd<R, I>& cmd = InstrumentChangeCommand.GetConfigForUpdate();
422                    // load the new script
423                    cmd.pScript->load(text);
424                }
425    
426                /**
427               * Changes the instrument for an engine channel.               * Changes the instrument for an engine channel.
428               *               *
429               * @param pInstrument - new instrument               * @param pInstrument - new instrument

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

  ViewVC Help
Powered by ViewVC