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

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

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

revision 1644 by persson, Sat Jan 19 16:55:03 2008 UTC revision 1646 by persson, Sun Jan 20 15:04:51 2008 UTC
# Line 74  namespace LinuxSampler { namespace gig { Line 74  namespace LinuxSampler { namespace gig {
74    
75      /**      /**
76       * Once an engine channel is disconnected from an audio output device,       * Once an engine channel is disconnected from an audio output device,
77       * it wil immediately call this method to unregister itself from the       * it will immediately call this method to unregister itself from the
78       * engine instance and if that engine instance is not used by any other       * engine instance and if that engine instance is not used by any other
79       * engine channel anymore, then that engine instance will be destroyed.       * engine channel anymore, then that engine instance will be destroyed.
80       *       *
# Line 108  namespace LinuxSampler { namespace gig { Line 108  namespace LinuxSampler { namespace gig {
108          pEventQueue        = new RingBuffer<Event,false>(CONFIG_MAX_EVENTS_PER_FRAGMENT, 0);          pEventQueue        = new RingBuffer<Event,false>(CONFIG_MAX_EVENTS_PER_FRAGMENT, 0);
109          pEventPool         = new Pool<Event>(CONFIG_MAX_EVENTS_PER_FRAGMENT);          pEventPool         = new Pool<Event>(CONFIG_MAX_EVENTS_PER_FRAGMENT);
110          pVoicePool         = new Pool<Voice>(CONFIG_MAX_VOICES);          pVoicePool         = new Pool<Voice>(CONFIG_MAX_VOICES);
111          pDimRegionsInUse   = new ::gig::DimensionRegion*[CONFIG_MAX_VOICES + 1];          pDimRegionPool[0]  = new Pool< ::gig::DimensionRegion*>(CONFIG_MAX_VOICES);
112            pDimRegionPool[1]  = new Pool< ::gig::DimensionRegion*>(CONFIG_MAX_VOICES);
113          pVoiceStealingQueue = new RTList<Event>(pEventPool);          pVoiceStealingQueue = new RTList<Event>(pEventPool);
114          pGlobalEvents      = new RTList<Event>(pEventPool);          pGlobalEvents      = new RTList<Event>(pEventPool);
         InstrumentChangeQueue      = new RingBuffer<instrument_change_command_t,false>(1, 0);  
         InstrumentChangeReplyQueue = new RingBuffer<instrument_change_reply_t,false>(1, 0);  
115    
116          for (RTList<Voice>::Iterator iterVoice = pVoicePool->allocAppend(); iterVoice == pVoicePool->last(); iterVoice = pVoicePool->allocAppend()) {          for (RTList<Voice>::Iterator iterVoice = pVoicePool->allocAppend(); iterVoice == pVoicePool->last(); iterVoice = pVoicePool->allocAppend()) {
117              iterVoice->SetEngine(this);              iterVoice->SetEngine(this);
# Line 145  namespace LinuxSampler { namespace gig { Line 144  namespace LinuxSampler { namespace gig {
144          if (pVoiceStealingQueue) delete pVoiceStealingQueue;          if (pVoiceStealingQueue) delete pVoiceStealingQueue;
145          if (pSysexBuffer) delete pSysexBuffer;          if (pSysexBuffer) delete pSysexBuffer;
146          if (pGlobalEvents) delete pGlobalEvents;          if (pGlobalEvents) delete pGlobalEvents;
147          if (InstrumentChangeQueue) delete InstrumentChangeQueue;          if (pDimRegionPool[0]) delete pDimRegionPool[0];
148          if (InstrumentChangeReplyQueue) delete InstrumentChangeReplyQueue;          if (pDimRegionPool[1]) delete pDimRegionPool[1];
         if (pDimRegionsInUse) delete[] pDimRegionsInUse;  
149          ResetSuspendedRegions();          ResetSuspendedRegions();
150          Unregister();          Unregister();
151      }      }
# Line 460  namespace LinuxSampler { namespace gig { Line 458  namespace LinuxSampler { namespace gig {
458              // free request slot for next caller (and to make sure that              // free request slot for next caller (and to make sure that
459              // we're not going to process the same request in the next cycle)              // we're not going to process the same request in the next cycle)
460              pPendingRegionSuspension = NULL;              pPendingRegionSuspension = NULL;
461              // if no disk stream deletions are pending, awaker other side, as              // if no disk stream deletions are pending, awaken other side, as
462              // we're done in this case              // we're done in this case
463              if (!iPendingStreamDeletions) SuspensionChangeOngoing.Set(false);              if (!iPendingStreamDeletions) SuspensionChangeOngoing.Set(false);
464          }          }
# Line 613  namespace LinuxSampler { namespace gig { Line 611  namespace LinuxSampler { namespace gig {
611          ActiveVoiceCountTemp = 0;          ActiveVoiceCountTemp = 0;
612    
613          // handle instrument change commands          // handle instrument change commands
614          instrument_change_command_t command;          bool instrumentChanged = false;
615          if (InstrumentChangeQueue->pop(&command) > 0) {          for (int i = 0; i < engineChannels.size(); i++) {
616              EngineChannel* pEngineChannel = command.pEngineChannel;              EngineChannel* pEngineChannel = engineChannels[i];
             pEngineChannel->pInstrument = command.pInstrument;  
   
             //TODO: this is a lazy solution ATM and not safe in case somebody is currently editing the instrument we're currently switching to (we should store all suspended regions on instrument manager side and when switching to another instrument copy that list to the engine's local list of suspensions  
             ResetSuspendedRegions();  
617    
618              // iterate through all active voices and mark their              // as we're going to (carefully) write some status to the
619              // dimension regions as "in use". The instrument resource              // synchronized struct, we cast away the const
620              // manager may delete all of the instrument except the              EngineChannel::instrument_change_command_t& cmd =
621              // dimension regions and samples that are in use.                  const_cast<EngineChannel::instrument_change_command_t&>(pEngineChannel->InstrumentChangeCommandReader.Lock());
622              int i = 0;  
623              RTList<uint>::Iterator iuiKey = pEngineChannel->pActiveKeys->first();              pEngineChannel->pDimRegionsInUse = cmd.pDimRegionsInUse;
624              RTList<uint>::Iterator end    = pEngineChannel->pActiveKeys->end();              pEngineChannel->pDimRegionsInUse->clear();
625              while (iuiKey != end) { // iterate through all active keys  
626                  midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[*iuiKey];              if (cmd.bChangeInstrument) {
627                  ++iuiKey;                  // change instrument
628                    dmsg(5,("Engine: instrument change command received\n"));
629                    cmd.bChangeInstrument = false;
630                    pEngineChannel->pInstrument = cmd.pInstrument;
631                    instrumentChanged = true;
632    
633                    // Iterate through all active voices and mark them as
634                    // "orphans", which means that the dimension regions
635                    // and samples they use should be released to the
636                    // instrument resource manager when the voices die.
637                    int i = 0;
638                    RTList<uint>::Iterator iuiKey = pEngineChannel->pActiveKeys->first();
639                    RTList<uint>::Iterator end    = pEngineChannel->pActiveKeys->end();
640                    while (iuiKey != end) { // iterate through all active keys
641                        midi_key_info_t* pKey = &pEngineChannel->pMIDIKeyInfo[*iuiKey];
642                        ++iuiKey;
643    
644                  RTList<Voice>::Iterator itVoice     = pKey->pActiveVoices->first();                      RTList<Voice>::Iterator itVoice     = pKey->pActiveVoices->first();
645                  RTList<Voice>::Iterator itVoicesEnd = pKey->pActiveVoices->end();                      RTList<Voice>::Iterator itVoicesEnd = pKey->pActiveVoices->end();
646                  for (; itVoice != itVoicesEnd; ++itVoice) { // iterate through all voices on this key                      for (; itVoice != itVoicesEnd; ++itVoice) { // iterate through all voices on this key
                     if (!itVoice->Orphan) {  
647                          itVoice->Orphan = true;                          itVoice->Orphan = true;
                         pDimRegionsInUse[i++] = itVoice->pDimRgn;  
648                      }                      }
649                  }                  }
650              }              }
651              pDimRegionsInUse[i] = 0; // end of list          }
652            if (instrumentChanged) {
653              // send a reply to the calling thread, which is waiting              //TODO: this is a lazy solution ATM and not safe in case somebody is currently editing the instrument we're currently switching to (we should store all suspended regions on instrument manager side and when switching to another instrument copy that list to the engine's local list of suspensions
654              instrument_change_reply_t reply;              ResetSuspendedRegions();
             InstrumentChangeReplyQueue->push(&reply);  
655          }          }
656    
657          // handle events on all engine channels          // handle events on all engine channels
# Line 688  namespace LinuxSampler { namespace gig { Line 694  namespace LinuxSampler { namespace gig {
694          // been deleted by the disk thread          // been deleted by the disk thread
695          if (iPendingStreamDeletions) ProcessPendingStreamDeletions();          if (iPendingStreamDeletions) ProcessPendingStreamDeletions();
696    
697            for (int i = 0; i < engineChannels.size(); i++) {
698                engineChannels[i]->InstrumentChangeCommandReader.Unlock();
699            }
700          FrameTime += Samples;          FrameTime += Samples;
701    
702          return 0;          return 0;
# Line 769  namespace LinuxSampler { namespace gig { Line 778  namespace LinuxSampler { namespace gig {
778                  // now render current voice                  // now render current voice
779                  itVoice->Render(Samples);                  itVoice->Render(Samples);
780                  if (itVoice->IsActive()) { // still active                  if (itVoice->IsActive()) { // still active
781                        if (!itVoice->Orphan) {
782                            *(pEngineChannel->pDimRegionsInUse->allocAppend()) = itVoice->pDimRgn;
783                        }
784                      ActiveVoiceCountTemp++;                      ActiveVoiceCountTemp++;
785                      voiceCount++;                      voiceCount++;
786    
# Line 809  namespace LinuxSampler { namespace gig { Line 821  namespace LinuxSampler { namespace gig {
821              if (itNewVoice) {              if (itNewVoice) {
822                  itNewVoice->Render(Samples);                  itNewVoice->Render(Samples);
823                  if (itNewVoice->IsActive()) { // still active                  if (itNewVoice->IsActive()) { // still active
824                        *(pEngineChannel->pDimRegionsInUse->allocAppend()) = itNewVoice->pDimRgn;
825                      ActiveVoiceCountTemp++;                      ActiveVoiceCountTemp++;
826                      pEngineChannel->SetVoiceCount(pEngineChannel->GetVoiceCount() + 1);                      pEngineChannel->SetVoiceCount(pEngineChannel->GetVoiceCount() + 1);
827    
# Line 1977  namespace LinuxSampler { namespace gig { Line 1990  namespace LinuxSampler { namespace gig {
1990      }      }
1991    
1992      String Engine::Version() {      String Engine::Version() {
1993          String s = "$Revision: 1.86 $";          String s = "$Revision: 1.87 $";
1994          return s.substr(11, s.size() - 13); // cut dollar signs, spaces and CVS macro keyword          return s.substr(11, s.size() - 13); // cut dollar signs, spaces and CVS macro keyword
1995      }      }
1996    
# Line 2027  namespace LinuxSampler { namespace gig { Line 2040  namespace LinuxSampler { namespace gig {
2040          return y;          return y;
2041      }      }
2042    
     /**  
      * Changes the instrument for an engine channel.  
      *  
      * @param pEngineChannel - engine channel on which the instrument  
      *                         should be changed  
      * @param pInstrument - new instrument  
      * @returns a list of dimension regions from the old instrument  
      *          that are still in use  
      */  
     ::gig::DimensionRegion** Engine::ChangeInstrument(EngineChannel* pEngineChannel, ::gig::Instrument* pInstrument) {  
         instrument_change_command_t command;  
         command.pEngineChannel = pEngineChannel;  
         command.pInstrument = pInstrument;  
         InstrumentChangeQueue->push(&command);  
   
         // wait for the audio thread to confirm that the instrument  
         // change has been done  
         instrument_change_reply_t reply;  
         while (InstrumentChangeReplyQueue->pop(&reply) == 0) {  
             usleep(10000);  
         }  
         return pDimRegionsInUse;  
     }  
   
2043  }} // namespace LinuxSampler::gig  }} // namespace LinuxSampler::gig

Legend:
Removed from v.1644  
changed lines
  Added in v.1646

  ViewVC Help
Powered by ViewVC