/[svn]/linuxsampler/trunk/src/engines/gig/InstrumentResourceManager.cpp
ViewVC logotype

Diff of /linuxsampler/trunk/src/engines/gig/InstrumentResourceManager.cpp

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

revision 1868 by schoenebeck, Wed Mar 18 22:16:14 2009 UTC revision 2687 by schoenebeck, Sun Jan 4 17:16:05 2015 UTC
# Line 3  Line 3 
3   *   LinuxSampler - modular, streaming capable sampler                     *   *   LinuxSampler - modular, streaming capable sampler                     *
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 - 2009 Christian Schoenebeck                       *   *   Copyright (C) 2005 - 2013 Christian Schoenebeck                       *
7   *                                                                         *   *                                                                         *
8   *   This program is free software; you can redistribute it and/or modify  *   *   This program is free software; you can redistribute it and/or modify  *
9   *   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 24  Line 24 
24  #include <sstream>  #include <sstream>
25    
26  #include "InstrumentResourceManager.h"  #include "InstrumentResourceManager.h"
27    #include "EngineChannel.h"
28    #include "Engine.h"
29    
30  #include "../../common/global_private.h"  #include "../../common/global_private.h"
31  #include "../../plugins/InstrumentEditorFactory.h"  #include "../../plugins/InstrumentEditorFactory.h"
32    
 // We need to know the maximum number of sample points which are going to  
 // be processed for each render cycle of the audio output driver, to know  
 // how much initial sample points we need to cache into RAM. If the given  
 // sampler channel does not have an audio output device assigned yet  
 // though, we simply use this default value.  
 #define GIG_RESOURCE_MANAGER_DEFAULT_MAX_SAMPLES_PER_CYCLE     128  
   
33  namespace LinuxSampler { namespace gig {  namespace LinuxSampler { namespace gig {
34    
     // data stored as long as an instrument resource exists  
     struct instr_entry_t {  
         InstrumentManager::instrument_id_t ID;  
         ::gig::File*                       pGig;  
         uint                               MaxSamplesPerCycle; ///< if some engine requests an already allocated instrument with a higher value, we have to reallocate the instrument  
     };  
   
35      // some data needed for the libgig callback function      // some data needed for the libgig callback function
36      struct progress_callback_arg_t {      struct progress_callback_arg_t {
37          InstrumentResourceManager*          pManager;          InstrumentResourceManager*          pManager;
# Line 88  namespace LinuxSampler { namespace gig { Line 76  namespace LinuxSampler { namespace gig {
76          pArg->pManager->DispatchResourceProgressEvent(*pArg->pInstrumentKey, localProgress);          pArg->pManager->DispatchResourceProgressEvent(*pArg->pInstrumentKey, localProgress);
77      }      }
78    
     std::vector<InstrumentResourceManager::instrument_id_t> InstrumentResourceManager::Instruments() {  
         return Entries();  
     }  
   
     InstrumentManager::mode_t InstrumentResourceManager::GetMode(const instrument_id_t& ID) {  
         return static_cast<InstrumentManager::mode_t>(AvailabilityMode(ID));  
     }  
   
     void InstrumentResourceManager::SetMode(const instrument_id_t& ID, InstrumentManager::mode_t Mode) {  
         dmsg(2,("gig::InstrumentResourceManager: setting mode for %s (Index=%d) to %d\n",ID.FileName.c_str(),ID.Index,Mode));  
         SetAvailabilityMode(ID, static_cast<ResourceManager<InstrumentManager::instrument_id_t, ::gig::Instrument>::mode_t>(Mode));  
     }  
   
79      String InstrumentResourceManager::GetInstrumentName(instrument_id_t ID) {      String InstrumentResourceManager::GetInstrumentName(instrument_id_t ID) {
80          Lock();          Lock();
81          ::gig::Instrument* pInstrument = Resource(ID, false);          ::gig::Instrument* pInstrument = Resource(ID, false);
# Line 154  namespace LinuxSampler { namespace gig { Line 129  namespace LinuxSampler { namespace gig {
129          ::RIFF::File* riff = NULL;          ::RIFF::File* riff = NULL;
130          ::gig::File*  gig  = NULL;          ::gig::File*  gig  = NULL;
131          try {          try {
132              if(!loaded) {              if (!loaded) {
133                  riff = new ::RIFF::File(ID.FileName);                  riff = new ::RIFF::File(ID.FileName);
134                  gig  = new ::gig::File(riff);                  gig  = new ::gig::File(riff);
135                  gig->SetAutoLoad(false); // avoid time consuming samples scanning                  gig->SetAutoLoad(false); // avoid time consuming samples scanning
# Line 233  namespace LinuxSampler { namespace gig { Line 208  namespace LinuxSampler { namespace gig {
208          }          }
209      }      }
210    
211      InstrumentEditor* InstrumentResourceManager::LaunchInstrumentEditor(instrument_id_t ID) throw (InstrumentManagerException) {      InstrumentEditor* InstrumentResourceManager::LaunchInstrumentEditor(LinuxSampler::EngineChannel* pEngineChannel, instrument_id_t ID, void* pUserData) throw (InstrumentManagerException) {
212          const String sDataType    = GetInstrumentDataStructureName(ID);          const String sDataType    = GetInstrumentDataStructureName(ID);
213          const String sDataVersion = GetInstrumentDataStructureVersion(ID);          const String sDataVersion = GetInstrumentDataStructureVersion(ID);
214          // find instrument editors capable to handle given instrument          // find instrument editors capable to handle given instrument
# Line 260  namespace LinuxSampler { namespace gig { Line 235  namespace LinuxSampler { namespace gig {
235          InstrumentEditorProxies.add(pProxy);          InstrumentEditorProxies.add(pProxy);
236          InstrumentEditorProxiesMutex.Unlock();          InstrumentEditorProxiesMutex.Unlock();
237          // launch the instrument editor for the given instrument          // launch the instrument editor for the given instrument
238          pEditor->Launch(pInstrument, sDataType, sDataVersion);          pEditor->Launch(pEngineChannel, pInstrument, sDataType, sDataVersion, pUserData);
239    
240          // register the instrument editor as virtual MIDI device as well ...          // register the instrument editor as virtual MIDI device as well ...
241          VirtualMidiDevice* pVirtualMidiDevice =          VirtualMidiDevice* pVirtualMidiDevice =
# Line 271  namespace LinuxSampler { namespace gig { Line 246  namespace LinuxSampler { namespace gig {
246          }          }
247          // NOTE: for now connect the virtual MIDI keyboard of the instrument editor (if any) with all engine channels that have the same instrument as the editor was opened for ( other ideas ? )          // NOTE: for now connect the virtual MIDI keyboard of the instrument editor (if any) with all engine channels that have the same instrument as the editor was opened for ( other ideas ? )
248          Lock();          Lock();
249          std::set<gig::EngineChannel*> engineChannels =          std::set<EngineChannel*> engineChannels =
250              GetEngineChannelsUsing(pInstrument, false/*don't lock again*/);              GetEngineChannelsUsing(pInstrument, false/*don't lock again*/);
251          std::set<gig::EngineChannel*>::iterator iter = engineChannels.begin();          std::set<EngineChannel*>::iterator iter = engineChannels.begin();
252          std::set<gig::EngineChannel*>::iterator end  = engineChannels.end();          std::set<EngineChannel*>::iterator end  = engineChannels.end();
253          for (; iter != end; ++iter) (*iter)->Connect(pVirtualMidiDevice);          for (; iter != end; ++iter) (static_cast<AbstractEngineChannel*>(*iter))->Connect(pVirtualMidiDevice);
254          Unlock();          Unlock();
255    
256          return pEditor;          return pEditor;
# Line 296  namespace LinuxSampler { namespace gig { Line 271  namespace LinuxSampler { namespace gig {
271          int iProxyIndex                = -1;          int iProxyIndex                = -1;
272    
273          // first find the editor proxy entry for this editor          // first find the editor proxy entry for this editor
274          InstrumentEditorProxiesMutex.Lock();          {
275          for (int i = 0; i < InstrumentEditorProxies.size(); i++) {              LockGuard lock(InstrumentEditorProxiesMutex);
276              InstrumentEditorProxy* pCurProxy =              for (int i = 0; i < InstrumentEditorProxies.size(); i++) {
277                  dynamic_cast<InstrumentEditorProxy*>(                  InstrumentEditorProxy* pCurProxy =
278                      InstrumentEditorProxies[i]                      dynamic_cast<InstrumentEditorProxy*>(
279                  );                          InstrumentEditorProxies[i]
280              if (pCurProxy->pEditor == pSender) {                          );
281                  pProxy      = pCurProxy;                  if (pCurProxy->pEditor == pSender) {
282                  iProxyIndex = i;                      pProxy      = pCurProxy;
283                  pInstrument = pCurProxy->pInstrument;                      iProxyIndex = i;
284                        pInstrument = pCurProxy->pInstrument;
285                    }
286              }              }
287          }          }
         InstrumentEditorProxiesMutex.Unlock();  
288    
289          if (!pProxy) {          if (!pProxy) {
290              std::cerr << "Eeeek, could not find instrument editor proxy, "              std::cerr << "Eeeek, could not find instrument editor proxy, "
# Line 322  namespace LinuxSampler { namespace gig { Line 298  namespace LinuxSampler { namespace gig {
298          if (pVirtualMidiDevice) {          if (pVirtualMidiDevice) {
299              Lock();              Lock();
300              // NOTE: see note in LaunchInstrumentEditor()              // NOTE: see note in LaunchInstrumentEditor()
301              std::set<gig::EngineChannel*> engineChannels =              std::set<EngineChannel*> engineChannels =
302                  GetEngineChannelsUsing(pInstrument, false/*don't lock again*/);                  GetEngineChannelsUsing(pInstrument, false/*don't lock again*/);
303              std::set<gig::EngineChannel*>::iterator iter = engineChannels.begin();              std::set<EngineChannel*>::iterator iter = engineChannels.begin();
304              std::set<gig::EngineChannel*>::iterator end  = engineChannels.end();              std::set<EngineChannel*>::iterator end  = engineChannels.end();
305              for (; iter != end; ++iter) (*iter)->Disconnect(pVirtualMidiDevice);              for (; iter != end; ++iter) (*iter)->Disconnect(pVirtualMidiDevice);
306              Unlock();              Unlock();
307          } else {          } else {
# Line 336  namespace LinuxSampler { namespace gig { Line 312  namespace LinuxSampler { namespace gig {
312    
313          // finally delete proxy entry and hand back instrument          // finally delete proxy entry and hand back instrument
314          if (pInstrument) {          if (pInstrument) {
315              InstrumentEditorProxiesMutex.Lock();              {
316              InstrumentEditorProxies.remove(iProxyIndex);                  LockGuard lock(InstrumentEditorProxiesMutex);
317              InstrumentEditorProxiesMutex.Unlock();                  InstrumentEditorProxies.remove(iProxyIndex);
318                }
319    
320              HandBack(pInstrument, pProxy);              HandBack(pInstrument, pProxy);
321              delete pProxy;              delete pProxy;
# Line 432  namespace LinuxSampler { namespace gig { Line 409  namespace LinuxSampler { namespace gig {
409              ::gig::Instrument* pInstrument =              ::gig::Instrument* pInstrument =
410                  (::gig::Instrument*) pRegion->GetParent();                  (::gig::Instrument*) pRegion->GetParent();
411              Lock();              Lock();
412              std::set<gig::Engine*> engines =              std::set<Engine*> engines =
413                  GetEnginesUsing(pInstrument, false/*don't lock again*/);                  GetEnginesUsing(pInstrument, false/*don't lock again*/);
414              std::set<gig::Engine*>::iterator iter = engines.begin();              std::set<Engine*>::iterator iter = engines.begin();
415              std::set<gig::Engine*>::iterator end  = engines.end();              std::set<Engine*>::iterator end  = engines.end();
416              for (; iter != end; ++iter) (*iter)->Suspend(pRegion);              for (; iter != end; ++iter) (*iter)->Suspend(pRegion);
417              Unlock();              Unlock();
418          } else if (sStructType == "gig::DimensionRegion") {          } else if (sStructType == "gig::DimensionRegion") {
# Line 449  namespace LinuxSampler { namespace gig { Line 426  namespace LinuxSampler { namespace gig {
426              ::gig::Instrument* pInstrument =              ::gig::Instrument* pInstrument =
427                  (::gig::Instrument*) pRegion->GetParent();                  (::gig::Instrument*) pRegion->GetParent();
428              Lock();              Lock();
429              std::set<gig::Engine*> engines =              std::set<Engine*> engines =
430                  GetEnginesUsing(pInstrument, false/*don't lock again*/);                  GetEnginesUsing(pInstrument, false/*don't lock again*/);
431              std::set<gig::Engine*>::iterator iter = engines.begin();              std::set<Engine*>::iterator iter = engines.begin();
432              std::set<gig::Engine*>::iterator end  = engines.end();              std::set<Engine*>::iterator end  = engines.end();
433              for (; iter != end; ++iter) (*iter)->Suspend(pRegion);              for (; iter != end; ++iter) (*iter)->Suspend(pRegion);
434              Unlock();              Unlock();
435          } else {          } else {
# Line 485  namespace LinuxSampler { namespace gig { Line 462  namespace LinuxSampler { namespace gig {
462                  GetInstrumentsCurrentlyUsedOf(pFile, false/*don't lock again*/);                  GetInstrumentsCurrentlyUsedOf(pFile, false/*don't lock again*/);
463              for (int i = 0; i < instruments.size(); i++) {              for (int i = 0; i < instruments.size(); i++) {
464                  if (SampleReferencedByInstrument(pSample, instruments[i])) {                  if (SampleReferencedByInstrument(pSample, instruments[i])) {
465                      std::set<gig::EngineChannel*> engineChannels =                      std::set<EngineChannel*> engineChannels =
466                          GetEngineChannelsUsing(instruments[i], false/*don't lock again*/);                          GetEngineChannelsUsing(instruments[i], false/*don't lock again*/);
467                      std::set<gig::EngineChannel*>::iterator iter = engineChannels.begin();                      std::set<EngineChannel*>::iterator iter = engineChannels.begin();
468                      std::set<gig::EngineChannel*>::iterator end  = engineChannels.end();                      std::set<EngineChannel*>::iterator end  = engineChannels.end();
469                      for (; iter != end; ++iter)                      for (; iter != end; ++iter)
470                          CacheInitialSamples(pSample, *iter);                          CacheInitialSamples(pSample, *iter);
471                  }                  }
# Line 501  namespace LinuxSampler { namespace gig { Line 478  namespace LinuxSampler { namespace gig {
478              ::gig::Instrument* pInstrument =              ::gig::Instrument* pInstrument =
479                  (::gig::Instrument*) pRegion->GetParent();                  (::gig::Instrument*) pRegion->GetParent();
480              Lock();              Lock();
481              std::set<gig::Engine*> engines =              std::set<Engine*> engines =
482                  GetEnginesUsing(pInstrument, false/*don't lock again*/);                  GetEnginesUsing(pInstrument, false/*don't lock again*/);
483              std::set<gig::Engine*>::iterator iter = engines.begin();              std::set<Engine*>::iterator iter = engines.begin();
484              std::set<gig::Engine*>::iterator end  = engines.end();              std::set<Engine*>::iterator end  = engines.end();
485              for (; iter != end; ++iter) (*iter)->Resume(pRegion);              for (; iter != end; ++iter) (*iter)->Resume(pRegion);
486              Unlock();              Unlock();
487          } else if (sStructType == "gig::DimensionRegion") {          } else if (sStructType == "gig::DimensionRegion") {
# Line 516  namespace LinuxSampler { namespace gig { Line 493  namespace LinuxSampler { namespace gig {
493              ::gig::Instrument* pInstrument =              ::gig::Instrument* pInstrument =
494                  (::gig::Instrument*) pRegion->GetParent();                  (::gig::Instrument*) pRegion->GetParent();
495              Lock();              Lock();
496              std::set<gig::Engine*> engines =              std::set<Engine*> engines =
497                  GetEnginesUsing(pInstrument, false/*don't lock again*/);                  GetEnginesUsing(pInstrument, false/*don't lock again*/);
498              std::set<gig::Engine*>::iterator iter = engines.begin();              std::set<Engine*>::iterator iter = engines.begin();
499              std::set<gig::Engine*>::iterator end  = engines.end();              std::set<Engine*>::iterator end  = engines.end();
500              for (; iter != end; ++iter) (*iter)->Resume(pRegion);              for (; iter != end; ++iter) (*iter)->Resume(pRegion);
501              Unlock();              Unlock();
502          } else {          } else {
# Line 555  namespace LinuxSampler { namespace gig { Line 532  namespace LinuxSampler { namespace gig {
532              ::gig::Sample* pSample = (::gig::Sample*) pNewSample;              ::gig::Sample* pSample = (::gig::Sample*) pNewSample;
533              ::gig::File* pFile = (::gig::File*) pSample->GetParent();              ::gig::File* pFile = (::gig::File*) pSample->GetParent();
534              // get all engines that use that same gig::File              // get all engines that use that same gig::File
535              std::set<gig::Engine*> engines = GetEnginesUsing(pFile, false/*don't lock again*/);              std::set<Engine*> engines = GetEnginesUsing(pFile, false/*don't lock again*/);
536              std::set<gig::Engine*>::iterator iter = engines.begin();              std::set<Engine*>::iterator iter = engines.begin();
537              std::set<gig::Engine*>::iterator end  = engines.end();              std::set<Engine*>::iterator end  = engines.end();
538              for (; iter != end; ++iter)              for (; iter != end; ++iter)
539                  CacheInitialSamples(pSample, *iter);                  CacheInitialSamples(pSample, *iter);
540              Unlock();              Unlock();
# Line 566  namespace LinuxSampler { namespace gig { Line 543  namespace LinuxSampler { namespace gig {
543    
544      ::gig::Instrument* InstrumentResourceManager::Create(instrument_id_t Key, InstrumentConsumer* pConsumer, void*& pArg) {      ::gig::Instrument* InstrumentResourceManager::Create(instrument_id_t Key, InstrumentConsumer* pConsumer, void*& pArg) {
545          // get gig file from internal gig file manager          // get gig file from internal gig file manager
546          ::gig::File* pGig = Gigs.Borrow(Key.FileName, (GigConsumer*) Key.Index); // conversion kinda hackish :/          ::gig::File* pGig = Gigs.Borrow(Key.FileName, reinterpret_cast<GigConsumer*>(Key.Index)); // conversion kinda hackish :/
547    
548          // we pass this to the progress callback mechanism of libgig          // we pass this to the progress callback mechanism of libgig
549          progress_callback_arg_t callbackArg;          progress_callback_arg_t callbackArg;
# Line 587  namespace LinuxSampler { namespace gig { Line 564  namespace LinuxSampler { namespace gig {
564          pGig->GetFirstSample(); // just to force complete instrument loading          pGig->GetFirstSample(); // just to force complete instrument loading
565          dmsg(1,("OK\n"));          dmsg(1,("OK\n"));
566    
567            uint maxSamplesPerCycle = GetMaxSamplesPerCycle(pConsumer);
568    
569          // cache initial samples points (for actually needed samples)          // cache initial samples points (for actually needed samples)
570          dmsg(1,("Caching initial samples..."));          dmsg(1,("Caching initial samples..."));
571          uint iRegion = 0; // just for progress calculation          uint iRegion = 0; // just for progress calculation
# Line 598  namespace LinuxSampler { namespace gig { Line 577  namespace LinuxSampler { namespace gig {
577    
578              if (pRgn->GetSample() && !pRgn->GetSample()->GetCache().Size) {              if (pRgn->GetSample() && !pRgn->GetSample()->GetCache().Size) {
579                  dmsg(2,("C"));                  dmsg(2,("C"));
580                  CacheInitialSamples(pRgn->GetSample(), (gig::EngineChannel*) pConsumer);                  CacheInitialSamples(pRgn->GetSample(), maxSamplesPerCycle);
581              }              }
582              for (uint i = 0; i < pRgn->DimensionRegions; i++) {              for (uint i = 0; i < pRgn->DimensionRegions; i++) {
583                  CacheInitialSamples(pRgn->pDimensionRegions[i]->pSample, (gig::EngineChannel*) pConsumer);                  CacheInitialSamples(pRgn->pDimensionRegions[i]->pSample, maxSamplesPerCycle);
584              }              }
585    
586              pRgn = pInstrument->GetNextRegion();              pRgn = pInstrument->GetNextRegion();
# Line 614  namespace LinuxSampler { namespace gig { Line 593  namespace LinuxSampler { namespace gig {
593          instr_entry_t* pEntry = new instr_entry_t;          instr_entry_t* pEntry = new instr_entry_t;
594          pEntry->ID.FileName   = Key.FileName;          pEntry->ID.FileName   = Key.FileName;
595          pEntry->ID.Index      = Key.Index;          pEntry->ID.Index      = Key.Index;
596          pEntry->pGig          = pGig;          pEntry->pFile         = pGig;
597    
598          gig::EngineChannel* pEngineChannel = dynamic_cast<gig::EngineChannel*>(pConsumer);          // and we save this to check if we need to reallocate for an engine with higher value of 'MaxSamplesPerSecond'
599          // and we save this to check if we need to reallocate for a engine with higher value of 'MaxSamplesPerSecond'          pEntry->MaxSamplesPerCycle = maxSamplesPerCycle;
600          pEntry->MaxSamplesPerCycle =          
             (!pEngineChannel) ? 0 /* don't care for instrument editors */ :  
                 (pEngineChannel->GetEngine()) ?  
                     dynamic_cast<gig::Engine*>(pEngineChannel->GetEngine())->pAudioOutputDevice->MaxSamplesPerCycle()  
                     : GIG_RESOURCE_MANAGER_DEFAULT_MAX_SAMPLES_PER_CYCLE;  
601          pArg = pEntry;          pArg = pEntry;
602    
603          return pInstrument;          return pInstrument;
604      }      }
605    
606      void InstrumentResourceManager::Destroy( ::gig::Instrument* pResource, void* pArg) {      void InstrumentResourceManager::Destroy(::gig::Instrument* pResource, void* pArg) {
607          instr_entry_t* pEntry = (instr_entry_t*) pArg;          instr_entry_t* pEntry = (instr_entry_t*) pArg;
608          // we don't need the .gig file here anymore          // we don't need the .gig file here anymore
609          Gigs.HandBack(pEntry->pGig, (GigConsumer*) pEntry->ID.Index); // conversion kinda hackish :/          Gigs.HandBack(pEntry->pFile, reinterpret_cast<GigConsumer*>(pEntry->ID.Index)); // conversion kinda hackish :/
610          delete pEntry;          delete pEntry;
611      }      }
612    
613      void InstrumentResourceManager::OnBorrow(::gig::Instrument* pResource, InstrumentConsumer* pConsumer, void*& pArg) {      void InstrumentResourceManager::DeleteRegionIfNotUsed(::gig::DimensionRegion* pRegion, region_info_t* pRegInfo) {
614          instr_entry_t* pEntry = (instr_entry_t*) pArg;          // TODO: we could delete Region and Instrument here if they have become unused
         gig::EngineChannel* pEngineChannel = dynamic_cast<gig::EngineChannel*>(pConsumer);  
         uint maxSamplesPerCycle =  
             (pEngineChannel && pEngineChannel->GetEngine()) ? dynamic_cast<gig::Engine*>(pEngineChannel->GetEngine())->pAudioOutputDevice->MaxSamplesPerCycle()  
                                           : GIG_RESOURCE_MANAGER_DEFAULT_MAX_SAMPLES_PER_CYCLE;  
         if (pEntry->MaxSamplesPerCycle < maxSamplesPerCycle) {  
             Update(pResource, pConsumer);  
         }  
615      }      }
616    
617      /**      void InstrumentResourceManager::DeleteSampleIfNotUsed(::gig::Sample* pSample, region_info_t* pRegInfo) {
618       * Give back an instrument. This should be used instead of          ::gig::File* gig = pRegInfo->file;
619       * HandBack if there are some dimension regions that are still in          ::RIFF::File* riff = static_cast< ::RIFF::File*>(pRegInfo->pArg);
620       * use. (When an instrument is changed, the voices currently          if (gig) {
621       * playing are allowed to keep playing with the old instrument              gig->DeleteSample(pSample);
622       * until note off arrives. New notes will use the new instrument.)              if (!gig->GetFirstSample()) {
623       */                  dmsg(2,("No more samples in use - freeing gig\n"));
624      void InstrumentResourceManager::HandBackInstrument(::gig::Instrument* pResource, InstrumentConsumer* pConsumer,                  delete gig;
625                                                         RTList< ::gig::DimensionRegion*>* pDimRegionsInUse) {                  delete riff;
         DimRegInfoMutex.Lock();  
         for (RTList< ::gig::DimensionRegion*>::Iterator i = pDimRegionsInUse->first() ; i != pDimRegionsInUse->end() ; i++) {  
             DimRegInfo[*i].refCount++;  
             SampleRefCount[(*i)->pSample]++;  
         }  
         HandBack(pResource, pConsumer, true);  
         DimRegInfoMutex.Unlock();  
     }  
   
     /**  
      * Give back a dimension region that belongs to an instrument that  
      * was previously handed back.  
      */  
     void InstrumentResourceManager::HandBackDimReg(::gig::DimensionRegion* pDimReg) {  
         DimRegInfoMutex.Lock();  
         dimreg_info_t& dimRegInfo = DimRegInfo[pDimReg];  
         int dimRegRefCount = --dimRegInfo.refCount;  
         int sampleRefCount = --SampleRefCount[pDimReg->pSample];  
         if (dimRegRefCount == 0) {  
             ::gig::File* gig = dimRegInfo.file;  
             ::RIFF::File* riff = dimRegInfo.riff;  
             DimRegInfo.erase(pDimReg);  
             // TODO: we could delete Region and Instrument here if  
             // they have become unused  
   
             if (sampleRefCount == 0) {  
                 SampleRefCount.erase(pDimReg->pSample);  
   
                 if (gig) {  
                     gig->DeleteSample(pDimReg->pSample);  
                     if (!gig->GetFirstSample()) {  
                         dmsg(2,("No more samples in use - freeing gig\n"));  
                         delete gig;  
                         delete riff;  
                     }  
                 }  
626              }              }
627          }          }
         DimRegInfoMutex.Unlock();  
628      }      }
629    
630      /**      /**
# Line 704  namespace LinuxSampler { namespace gig { Line 635  namespace LinuxSampler { namespace gig {
635       *                   (may be NULL, in this case default amount of samples       *                   (may be NULL, in this case default amount of samples
636       *                   will be cached)       *                   will be cached)
637       */       */
638      void InstrumentResourceManager::CacheInitialSamples(::gig::Sample* pSample, gig::EngineChannel* pEngineChannel) {      void InstrumentResourceManager::CacheInitialSamples(::gig::Sample* pSample, EngineChannel* pEngineChannel) {
639          gig::Engine* pEngine =          Engine* pEngine =
640              (pEngineChannel && pEngineChannel->GetEngine()) ?              (pEngineChannel && pEngineChannel->GetEngine()) ?
641                  dynamic_cast<gig::Engine*>(pEngineChannel->GetEngine()) : NULL;                  dynamic_cast<Engine*>(pEngineChannel->GetEngine()) : NULL;
642          CacheInitialSamples(pSample, pEngine);          CacheInitialSamples(pSample, pEngine);
643      }      }
644    
# Line 722  namespace LinuxSampler { namespace gig { Line 653  namespace LinuxSampler { namespace gig {
653       *                   (may be NULL, in this case default amount of samples       *                   (may be NULL, in this case default amount of samples
654       *                   will be cached)       *                   will be cached)
655       */       */
656      void InstrumentResourceManager::CacheInitialSamples(::gig::Sample* pSample, gig::Engine* pEngine) {      void InstrumentResourceManager::CacheInitialSamples(::gig::Sample* pSample, AbstractEngine* pEngine) {
657            uint maxSamplesPerCycle =
658                (pEngine) ? pEngine->pAudioOutputDevice->MaxSamplesPerCycle() :
659                DefaultMaxSamplesPerCycle();
660            CacheInitialSamples(pSample, maxSamplesPerCycle);
661        }
662    
663        void InstrumentResourceManager::CacheInitialSamples(::gig::Sample* pSample, uint maxSamplesPerCycle) {
664          if (!pSample) {          if (!pSample) {
665              dmsg(4,("gig::InstrumentResourceManager: Skipping sample (pSample == NULL)\n"));              dmsg(4,("gig::InstrumentResourceManager: Skipping sample (pSample == NULL)\n"));
666              return;              return;
# Line 735  namespace LinuxSampler { namespace gig { Line 673  namespace LinuxSampler { namespace gig {
673              // number of '0' samples (silence samples) behind the official buffer              // number of '0' samples (silence samples) behind the official buffer
674              // border, to allow the interpolator do it's work even at the end of              // border, to allow the interpolator do it's work even at the end of
675              // the sample.              // the sample.
             const uint maxSamplesPerCycle =  
                 (pEngine) ? pEngine->pAudioOutputDevice->MaxSamplesPerCycle()  
                           : GIG_RESOURCE_MANAGER_DEFAULT_MAX_SAMPLES_PER_CYCLE;  
676              const uint neededSilenceSamples = (maxSamplesPerCycle << CONFIG_MAX_PITCH) + 3;              const uint neededSilenceSamples = (maxSamplesPerCycle << CONFIG_MAX_PITCH) + 3;
677              const uint currentlyCachedSilenceSamples = pSample->GetCache().NullExtensionSize / pSample->FrameSize;              const uint currentlyCachedSilenceSamples = pSample->GetCache().NullExtensionSize / pSample->FrameSize;
678              if (currentlyCachedSilenceSamples < neededSilenceSamples) {              if (currentlyCachedSilenceSamples < neededSilenceSamples) {
# Line 787  namespace LinuxSampler { namespace gig { Line 722  namespace LinuxSampler { namespace gig {
722       * @param bLock - whether we should lock (mutex) the instrument manager       * @param bLock - whether we should lock (mutex) the instrument manager
723       *                during this call and unlock at the end of this call       *                during this call and unlock at the end of this call
724       */       */
725      std::set<gig::EngineChannel*> InstrumentResourceManager::GetEngineChannelsUsing(::gig::Instrument* pInstrument, bool bLock) {      std::set<EngineChannel*> InstrumentResourceManager::GetEngineChannelsUsing(::gig::Instrument* pInstrument, bool bLock) {
726          if (bLock) Lock();          if (bLock) Lock();
727          std::set<gig::EngineChannel*> result;          std::set<EngineChannel*> result;
728          std::set<ResourceConsumer< ::gig::Instrument>*> consumers = ConsumersOf(pInstrument);          std::set<ResourceConsumer< ::gig::Instrument>*> consumers = ConsumersOf(pInstrument);
729          std::set<ResourceConsumer< ::gig::Instrument>*>::iterator iter = consumers.begin();          std::set<ResourceConsumer< ::gig::Instrument>*>::iterator iter = consumers.begin();
730          std::set<ResourceConsumer< ::gig::Instrument>*>::iterator end  = consumers.end();          std::set<ResourceConsumer< ::gig::Instrument>*>::iterator end  = consumers.end();
731          for (; iter != end; ++iter) {          for (; iter != end; ++iter) {
732              gig::EngineChannel* pEngineChannel = dynamic_cast<gig::EngineChannel*>(*iter);              EngineChannel* pEngineChannel = dynamic_cast<EngineChannel*>(*iter);
733              if (!pEngineChannel) continue;              if (!pEngineChannel) continue;
734              result.insert(pEngineChannel);              result.insert(pEngineChannel);
735          }          }
# Line 810  namespace LinuxSampler { namespace gig { Line 745  namespace LinuxSampler { namespace gig {
745       * @param bLock - whether we should lock (mutex) the instrument manager       * @param bLock - whether we should lock (mutex) the instrument manager
746       *                during this call and unlock at the end of this call       *                during this call and unlock at the end of this call
747       */       */
748      std::set<gig::Engine*> InstrumentResourceManager::GetEnginesUsing(::gig::Instrument* pInstrument, bool bLock) {      std::set<Engine*> InstrumentResourceManager::GetEnginesUsing(::gig::Instrument* pInstrument, bool bLock) {
749          if (bLock) Lock();          if (bLock) Lock();
750          std::set<gig::Engine*> result;          std::set<Engine*> result;
751          std::set<ResourceConsumer< ::gig::Instrument>*> consumers = ConsumersOf(pInstrument);          std::set<ResourceConsumer< ::gig::Instrument>*> consumers = ConsumersOf(pInstrument);
752          std::set<ResourceConsumer< ::gig::Instrument>*>::iterator iter = consumers.begin();          std::set<ResourceConsumer< ::gig::Instrument>*>::iterator iter = consumers.begin();
753          std::set<ResourceConsumer< ::gig::Instrument>*>::iterator end  = consumers.end();          std::set<ResourceConsumer< ::gig::Instrument>*>::iterator end  = consumers.end();
754          for (; iter != end; ++iter) {          for (; iter != end; ++iter) {
755              gig::EngineChannel* pEngineChannel = dynamic_cast<gig::EngineChannel*>(*iter);              EngineChannel* pEngineChannel = dynamic_cast<EngineChannel*>(*iter);
756              if (!pEngineChannel) continue;              if (!pEngineChannel) continue;
757              gig::Engine* pEngine = dynamic_cast<gig::Engine*>(pEngineChannel->GetEngine());              Engine* pEngine = dynamic_cast<Engine*>(pEngineChannel->GetEngine());
758              if (!pEngine) continue;              if (!pEngine) continue;
759              result.insert(pEngine);              result.insert(pEngine);
760          }          }
# Line 835  namespace LinuxSampler { namespace gig { Line 770  namespace LinuxSampler { namespace gig {
770       * @param bLock - whether we should lock (mutex) the instrument manager       * @param bLock - whether we should lock (mutex) the instrument manager
771       *                during this call and unlock at the end of this call       *                during this call and unlock at the end of this call
772       */       */
773      std::set<gig::Engine*> InstrumentResourceManager::GetEnginesUsing(::gig::File* pFile, bool bLock) {      std::set<Engine*> InstrumentResourceManager::GetEnginesUsing(::gig::File* pFile, bool bLock) {
774          if (bLock) Lock();          if (bLock) Lock();
775          // get all instruments (currently in usage) that use that same gig::File          // get all instruments (currently in usage) that use that same gig::File
776          std::vector< ::gig::Instrument*> instrumentsOfInterest =          std::vector< ::gig::Instrument*> instrumentsOfInterest =
777              GetInstrumentsCurrentlyUsedOf(pFile, false/*don't lock again*/);              GetInstrumentsCurrentlyUsedOf(pFile, false/*don't lock again*/);
778    
779          // get all engines that use that same gig::File          // get all engines that use that same gig::File
780          std::set<gig::Engine*> result;          std::set<Engine*> result;
781          {          {
782              for (int i = 0; i < instrumentsOfInterest.size(); i++) {              for (int i = 0; i < instrumentsOfInterest.size(); i++) {
783                  std::set<ResourceConsumer< ::gig::Instrument>*> consumers = ConsumersOf(instrumentsOfInterest[i]);                  std::set<ResourceConsumer< ::gig::Instrument>*> consumers = ConsumersOf(instrumentsOfInterest[i]);
784                  std::set<ResourceConsumer< ::gig::Instrument>*>::iterator iter = consumers.begin();                  std::set<ResourceConsumer< ::gig::Instrument>*>::iterator iter = consumers.begin();
785                  std::set<ResourceConsumer< ::gig::Instrument>*>::iterator end  = consumers.end();                  std::set<ResourceConsumer< ::gig::Instrument>*>::iterator end  = consumers.end();
786                  for (; iter != end; ++iter) {                  for (; iter != end; ++iter) {
787                      gig::EngineChannel* pEngineChannel = dynamic_cast<gig::EngineChannel*>(*iter);                      EngineChannel* pEngineChannel = dynamic_cast<EngineChannel*>(*iter);
788                      if (!pEngineChannel) continue;                      if (!pEngineChannel) continue;
789                      gig::Engine* pEngine = dynamic_cast<gig::Engine*>(pEngineChannel->GetEngine());                      Engine* pEngine = dynamic_cast<Engine*>(pEngineChannel->GetEngine());
790                      if (!pEngine) continue;                      if (!pEngine) continue;
791                      // the unique, sorted container std::set makes                      // the unique, sorted container std::set makes
792                      // sure we won't have duplicates                      // sure we won't have duplicates
# Line 905  namespace LinuxSampler { namespace gig { Line 840  namespace LinuxSampler { namespace gig {
840          // get all engines that use that same gig::Instrument          // get all engines that use that same gig::Instrument
841          suspendedEngines = GetEnginesUsing(pInstrument, true/*lock*/);          suspendedEngines = GetEnginesUsing(pInstrument, true/*lock*/);
842          // finally, completely suspend all engines that use that same gig::Instrument          // finally, completely suspend all engines that use that same gig::Instrument
843          std::set<gig::Engine*>::iterator iter = suspendedEngines.begin();          std::set<Engine*>::iterator iter = suspendedEngines.begin();
844          std::set<gig::Engine*>::iterator end  = suspendedEngines.end();          std::set<Engine*>::iterator end  = suspendedEngines.end();
845          for (; iter != end; ++iter) (*iter)->SuspendAll();          for (; iter != end; ++iter) (*iter)->SuspendAll();
846      }      }
847    
# Line 929  namespace LinuxSampler { namespace gig { Line 864  namespace LinuxSampler { namespace gig {
864          // get all engines that use that same gig::File          // get all engines that use that same gig::File
865          suspendedEngines = GetEnginesUsing(pFile, true/*lock*/);          suspendedEngines = GetEnginesUsing(pFile, true/*lock*/);
866          // finally, completely suspend all engines that use that same gig::File          // finally, completely suspend all engines that use that same gig::File
867          std::set<gig::Engine*>::iterator iter = suspendedEngines.begin();          std::set<Engine*>::iterator iter = suspendedEngines.begin();
868          std::set<gig::Engine*>::iterator end  = suspendedEngines.end();          std::set<Engine*>::iterator end  = suspendedEngines.end();
869          for (; iter != end; ++iter) (*iter)->SuspendAll();          for (; iter != end; ++iter) (*iter)->SuspendAll();
870      }      }
871    
# Line 965  namespace LinuxSampler { namespace gig { Line 900  namespace LinuxSampler { namespace gig {
900      }      }
901    
902      void InstrumentResourceManager::GigResourceManager::Destroy(::gig::File* pResource, void* pArg) {      void InstrumentResourceManager::GigResourceManager::Destroy(::gig::File* pResource, void* pArg) {
903          dmsg(1,("Freeing gig file from memory..."));          dmsg(1,("Freeing gig file '%s' from memory ...", pResource->GetFileName().c_str()));
904    
905          // Delete as much as possible of the gig file. Some of the          // Delete as much as possible of the gig file. Some of the
906          // dimension regions and samples may still be in use - these          // dimension regions and samples may still be in use - these
# Line 986  namespace LinuxSampler { namespace gig { Line 921  namespace LinuxSampler { namespace gig {
921                  for (int i = 0 ; i < region->DimensionRegions ; i++)                  for (int i = 0 ; i < region->DimensionRegions ; i++)
922                  {                  {
923                      ::gig::DimensionRegion *d = region->pDimensionRegions[i];                      ::gig::DimensionRegion *d = region->pDimensionRegions[i];
924                      std::map< ::gig::DimensionRegion*, dimreg_info_t>::iterator iter = parent->DimRegInfo.find(d);                      std::map< ::gig::DimensionRegion*, region_info_t>::iterator iter = parent->RegionInfo.find(d);
925                      if (iter != parent->DimRegInfo.end()) {                      if (iter != parent->RegionInfo.end()) {
926                          dimreg_info_t& dimRegInfo = (*iter).second;                          region_info_t& dimRegInfo = (*iter).second;
927                          dimRegInfo.file = pResource;                          dimRegInfo.file = pResource;
928                          dimRegInfo.riff = (::RIFF::File*)pArg;                          dimRegInfo.pArg = (::RIFF::File*)pArg;
929                          deleteFile = deleteInstrument = deleteRegion = false;                          deleteFile = deleteInstrument = deleteRegion = false;
930                      }                      }
931                  }                  }

Legend:
Removed from v.1868  
changed lines
  Added in v.2687

  ViewVC Help
Powered by ViewVC