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

Diff of /linuxsampler/trunk/src/engines/AbstractEngineChannel.cpp

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

revision 2594 by schoenebeck, Thu Jun 5 00:16:25 2014 UTC revision 2665 by schoenebeck, Sun Jul 6 00:49:36 2014 UTC
# Line 46  namespace LinuxSampler { Line 46  namespace LinuxSampler {
46          ResetControllers();          ResetControllers();
47          PortamentoMode = false;          PortamentoMode = false;
48          PortamentoTime = CONFIG_PORTAMENTO_TIME_DEFAULT;          PortamentoTime = CONFIG_PORTAMENTO_TIME_DEFAULT;
49          pScriptEvents = NULL;          pScript = NULL;
50      }      }
51    
52      AbstractEngineChannel::~AbstractEngineChannel() {      AbstractEngineChannel::~AbstractEngineChannel() {
         unloadCurrentInstrumentScript();  
         if (pScriptEvents) delete pScriptEvents;  
53          delete pEventQueue;          delete pEventQueue;
54          DeleteGroupEventLists();          DeleteGroupEventLists();
55          RemoveAllFxSends();          RemoveAllFxSends();
# Line 145  namespace LinuxSampler { Line 143  namespace LinuxSampler {
143      }      }
144    
145      /**      /**
      * Loads the real-time instrument script given by @a text on this engine  
      * channel. A resource manager is used to allocate and share equivalent  
      * scripts on multiple engine channels.  
      *  
      * @param text - source code of script  
      */  
     void AbstractEngineChannel::loadInstrumentScript(const String& text) {  
         dmsg(1,("Loading real-time instrument script ... "));  
   
         // hand back old script reference and VM execution contexts  
         // (if not done already)  
         unloadCurrentInstrumentScript();  
   
         // get new script reference  
         script.parserContext = pEngine->scripts.Borrow(text, this);  
         if (!script.parserContext->errors().empty()) {  
             std::vector<ParserIssue> errors = script.parserContext->errors();  
             std::cerr << "[ScriptVM] Could not load instrument script, there were "  
                       << errors.size() << " parser errors:\n";  
             for (int i = 0; i < errors.size(); ++i)  
                 errors[i].dump();  
             return; // stop here if there were any parser errors  
         }  
   
         script.handlerInit = script.parserContext->eventHandlerByName("init");  
         script.handlerNote = script.parserContext->eventHandlerByName("note");  
         script.handlerController = script.parserContext->eventHandlerByName("controller");  
         script.bHasValidScript =  
             script.handlerInit || script.handlerNote || script.handlerController;  
   
         // amount of script handlers each script event has to execute  
         int handlerExecCount = 0;  
         if (script.handlerInit) handlerExecCount++;  
         if (script.handlerNote || script.handlerController) handlerExecCount++;  
   
         // create script event pool (if it doesn't exist already)  
         if (!pScriptEvents)  
             pScriptEvents = new Pool<ScriptEvent>(CONFIG_MAX_EVENTS_PER_FRAGMENT);  
   
         // create new VM execution contexts for new script  
         while (!pScriptEvents->poolIsEmpty()) {  
             RTList<ScriptEvent>::Iterator it = pScriptEvents->allocAppend();  
             it->execCtx = pEngine->pScriptVM->createExecContext(  
                 script.parserContext  
             );  
             it->handlers = new VMEventHandler*[handlerExecCount+1];  
         }  
         pScriptEvents->clear();  
   
         dmsg(1,("Done\n"));  
     }  
   
     /**  
      * Unloads the currently used real-time instrument script on this sampler  
      * channel. A resource manager is used to share equivalent scripts among  
      * multiple sampler channels, and to deallocate the parsed script once not  
      * used on any engine channel anymore.  
      */  
     void AbstractEngineChannel::unloadCurrentInstrumentScript() {  
         if (script.parserContext)  
             dmsg(1,("Unloading current instrument script."));  
   
         // free allocated VM execution contexts  
         if (pScriptEvents) {  
             pScriptEvents->clear();  
             while (!pScriptEvents->poolIsEmpty()) {  
                 RTList<ScriptEvent>::Iterator it = pScriptEvents->allocAppend();  
                 if (it->execCtx) {  
                     // free VM execution context object  
                     delete it->execCtx;  
                     it->execCtx = NULL;  
                     // free C array of handler pointers  
                     delete [] it->handlers;  
                 }  
             }  
             pScriptEvents->clear();  
         }  
         // hand back VM representation of script  
         if (script.parserContext) {  
             pEngine->scripts.HandBack(script.parserContext, this);  
             script.parserContext = NULL;  
             script.handlerInit = NULL;  
             script.handlerNote = NULL;  
             script.handlerController = NULL;  
         }  
         script.bHasValidScript = false;  
     }  
   
     /**  
146       * Implementation of virtual method from abstract EngineChannel interface.       * Implementation of virtual method from abstract EngineChannel interface.
147       * This method will periodically be polled (e.g. by the LSCP server) to       * This method will periodically be polled (e.g. by the LSCP server) to
148       * check if some engine channel parameter has changed since the last       * check if some engine channel parameter has changed since the last
# Line 467  namespace LinuxSampler { Line 376  namespace LinuxSampler {
376              event.Param.Note.Key      = Key;              event.Param.Note.Key      = Key;
377              event.Param.Note.Velocity = Velocity;              event.Param.Note.Velocity = Velocity;
378              event.Param.Note.Channel  = MidiChannel;              event.Param.Note.Channel  = MidiChannel;
379                memset(&event.Format, 0, sizeof(event.Format)); // init format speific stuff with zeroes
380              event.pEngineChannel      = this;              event.pEngineChannel      = this;
381              if (this->pEventQueue->write_space() > 0) this->pEventQueue->push(&event);              if (this->pEventQueue->write_space() > 0) this->pEventQueue->push(&event);
382              else dmsg(1,("EngineChannel: Input event queue full!"));              else dmsg(1,("EngineChannel: Input event queue full!"));
# Line 508  namespace LinuxSampler { Line 418  namespace LinuxSampler {
418              event.Param.Note.Key      = Key;              event.Param.Note.Key      = Key;
419              event.Param.Note.Velocity = Velocity;              event.Param.Note.Velocity = Velocity;
420              event.Param.Note.Channel  = MidiChannel;              event.Param.Note.Channel  = MidiChannel;
421                memset(&event.Format, 0, sizeof(event.Format)); // init format speific stuff with zeroes
422              event.pEngineChannel      = this;              event.pEngineChannel      = this;
423              if (this->pEventQueue->write_space() > 0) this->pEventQueue->push(&event);              if (this->pEventQueue->write_space() > 0) this->pEventQueue->push(&event);
424              else dmsg(1,("EngineChannel: Input event queue full!"));              else dmsg(1,("EngineChannel: Input event queue full!"));
# Line 544  namespace LinuxSampler { Line 455  namespace LinuxSampler {
455              event.Param.Note.Key      = Key;              event.Param.Note.Key      = Key;
456              event.Param.Note.Velocity = Velocity;              event.Param.Note.Velocity = Velocity;
457              event.Param.Note.Channel  = MidiChannel;              event.Param.Note.Channel  = MidiChannel;
458                memset(&event.Format, 0, sizeof(event.Format)); // init format speific stuff with zeroes
459              event.pEngineChannel      = this;              event.pEngineChannel      = this;
460              if (this->pEventQueue->write_space() > 0) this->pEventQueue->push(&event);              if (this->pEventQueue->write_space() > 0) this->pEventQueue->push(&event);
461              else dmsg(1,("EngineChannel: Input event queue full!"));              else dmsg(1,("EngineChannel: Input event queue full!"));
# Line 585  namespace LinuxSampler { Line 497  namespace LinuxSampler {
497              event.Param.Note.Key      = Key;              event.Param.Note.Key      = Key;
498              event.Param.Note.Velocity = Velocity;              event.Param.Note.Velocity = Velocity;
499              event.Param.Note.Channel  = MidiChannel;              event.Param.Note.Channel  = MidiChannel;
500                memset(&event.Format, 0, sizeof(event.Format)); // init format speific stuff with zeroes
501              event.pEngineChannel      = this;              event.pEngineChannel      = this;
502              if (this->pEventQueue->write_space() > 0) this->pEventQueue->push(&event);              if (this->pEventQueue->write_space() > 0) this->pEventQueue->push(&event);
503              else dmsg(1,("EngineChannel: Input event queue full!"));              else dmsg(1,("EngineChannel: Input event queue full!"));
# Line 619  namespace LinuxSampler { Line 532  namespace LinuxSampler {
532              event.Type              = Event::type_pitchbend;              event.Type              = Event::type_pitchbend;
533              event.Param.Pitch.Pitch = Pitch;              event.Param.Pitch.Pitch = Pitch;
534              event.Param.Pitch.Channel = MidiChannel;              event.Param.Pitch.Channel = MidiChannel;
535                memset(&event.Format, 0, sizeof(event.Format)); // init format speific stuff with zeroes
536              event.pEngineChannel    = this;              event.pEngineChannel    = this;
537              if (this->pEventQueue->write_space() > 0) this->pEventQueue->push(&event);              if (this->pEventQueue->write_space() > 0) this->pEventQueue->push(&event);
538              else dmsg(1,("EngineChannel: Input event queue full!"));              else dmsg(1,("EngineChannel: Input event queue full!"));
# Line 648  namespace LinuxSampler { Line 562  namespace LinuxSampler {
562              event.Type              = Event::type_pitchbend;              event.Type              = Event::type_pitchbend;
563              event.Param.Pitch.Pitch = Pitch;              event.Param.Pitch.Pitch = Pitch;
564              event.Param.Pitch.Channel = MidiChannel;              event.Param.Pitch.Channel = MidiChannel;
565                memset(&event.Format, 0, sizeof(event.Format)); // init format speific stuff with zeroes
566              event.pEngineChannel    = this;              event.pEngineChannel    = this;
567              if (this->pEventQueue->write_space() > 0) this->pEventQueue->push(&event);              if (this->pEventQueue->write_space() > 0) this->pEventQueue->push(&event);
568              else dmsg(1,("AbstractEngineChannel: Input event queue full!"));              else dmsg(1,("AbstractEngineChannel: Input event queue full!"));
# Line 674  namespace LinuxSampler { Line 589  namespace LinuxSampler {
589              event.Param.CC.Controller = Controller;              event.Param.CC.Controller = Controller;
590              event.Param.CC.Value      = Value;              event.Param.CC.Value      = Value;
591              event.Param.CC.Channel    = MidiChannel;              event.Param.CC.Channel    = MidiChannel;
592                memset(&event.Format, 0, sizeof(event.Format)); // init format speific stuff with zeroes
593              event.pEngineChannel      = this;              event.pEngineChannel      = this;
594              if (this->pEventQueue->write_space() > 0) this->pEventQueue->push(&event);              if (this->pEventQueue->write_space() > 0) this->pEventQueue->push(&event);
595              else dmsg(1,("AbstractEngineChannel: Input event queue full!"));              else dmsg(1,("AbstractEngineChannel: Input event queue full!"));
# Line 705  namespace LinuxSampler { Line 621  namespace LinuxSampler {
621              event.Param.CC.Controller = Controller;              event.Param.CC.Controller = Controller;
622              event.Param.CC.Value      = Value;              event.Param.CC.Value      = Value;
623              event.Param.CC.Channel    = MidiChannel;              event.Param.CC.Channel    = MidiChannel;
624                memset(&event.Format, 0, sizeof(event.Format)); // init format speific stuff with zeroes
625              event.pEngineChannel      = this;              event.pEngineChannel      = this;
626              if (this->pEventQueue->write_space() > 0) this->pEventQueue->push(&event);              if (this->pEventQueue->write_space() > 0) this->pEventQueue->push(&event);
627              else dmsg(1,("AbstractEngineChannel: Input event queue full!"));              else dmsg(1,("AbstractEngineChannel: Input event queue full!"));
# Line 719  namespace LinuxSampler { Line 636  namespace LinuxSampler {
636    
637              Event event = pEngine->pEventGenerator->CreateEvent();              Event event = pEngine->pEventGenerator->CreateEvent();
638              event.Type                          = Event::type_channel_pressure;              event.Type                          = Event::type_channel_pressure;
639                event.Param.ChannelPressure.Controller = CTRL_TABLE_IDX_AFTERTOUCH; // required for instrument scripts
640              event.Param.ChannelPressure.Value   = Value;              event.Param.ChannelPressure.Value   = Value;
641              event.Param.ChannelPressure.Channel = MidiChannel;              event.Param.ChannelPressure.Channel = MidiChannel;
642                memset(&event.Format, 0, sizeof(event.Format)); // init format speific stuff with zeroes
643              event.pEngineChannel                = this;              event.pEngineChannel                = this;
644              if (this->pEventQueue->write_space() > 0) this->pEventQueue->push(&event);              if (this->pEventQueue->write_space() > 0) this->pEventQueue->push(&event);
645              else dmsg(1,("AbstractEngineChannel: Input event queue full!"));              else dmsg(1,("AbstractEngineChannel: Input event queue full!"));
# Line 735  namespace LinuxSampler { Line 654  namespace LinuxSampler {
654    
655              Event event = pEngine->pEventGenerator->CreateEvent(FragmentPos);              Event event = pEngine->pEventGenerator->CreateEvent(FragmentPos);
656              event.Type                          = Event::type_channel_pressure;              event.Type                          = Event::type_channel_pressure;
657                event.Param.ChannelPressure.Controller = CTRL_TABLE_IDX_AFTERTOUCH; // required for instrument scripts
658              event.Param.ChannelPressure.Value   = Value;              event.Param.ChannelPressure.Value   = Value;
659              event.Param.ChannelPressure.Channel = MidiChannel;              event.Param.ChannelPressure.Channel = MidiChannel;
660                memset(&event.Format, 0, sizeof(event.Format)); // init format speific stuff with zeroes
661              event.pEngineChannel                = this;              event.pEngineChannel                = this;
662              if (this->pEventQueue->write_space() > 0) this->pEventQueue->push(&event);              if (this->pEventQueue->write_space() > 0) this->pEventQueue->push(&event);
663              else dmsg(1,("AbstractEngineChannel: Input event queue full!"));              else dmsg(1,("AbstractEngineChannel: Input event queue full!"));
# Line 754  namespace LinuxSampler { Line 675  namespace LinuxSampler {
675              event.Param.NotePressure.Key     = Key;              event.Param.NotePressure.Key     = Key;
676              event.Param.NotePressure.Value   = Value;              event.Param.NotePressure.Value   = Value;
677              event.Param.NotePressure.Channel = MidiChannel;              event.Param.NotePressure.Channel = MidiChannel;
678                memset(&event.Format, 0, sizeof(event.Format)); // init format speific stuff with zeroes
679              event.pEngineChannel             = this;              event.pEngineChannel             = this;
680              if (this->pEventQueue->write_space() > 0) this->pEventQueue->push(&event);              if (this->pEventQueue->write_space() > 0) this->pEventQueue->push(&event);
681              else dmsg(1,("AbstractEngineChannel: Input event queue full!"));              else dmsg(1,("AbstractEngineChannel: Input event queue full!"));
# Line 771  namespace LinuxSampler { Line 693  namespace LinuxSampler {
693              event.Param.NotePressure.Key     = Key;              event.Param.NotePressure.Key     = Key;
694              event.Param.NotePressure.Value   = Value;              event.Param.NotePressure.Value   = Value;
695              event.Param.NotePressure.Channel = MidiChannel;              event.Param.NotePressure.Channel = MidiChannel;
696                memset(&event.Format, 0, sizeof(event.Format)); // init format speific stuff with zeroes
697              event.pEngineChannel             = this;              event.pEngineChannel             = this;
698              if (this->pEventQueue->write_space() > 0) this->pEventQueue->push(&event);              if (this->pEventQueue->write_space() > 0) this->pEventQueue->push(&event);
699              else dmsg(1,("AbstractEngineChannel: Input event queue full!"));              else dmsg(1,("AbstractEngineChannel: Input event queue full!"));
# Line 848  namespace LinuxSampler { Line 771  namespace LinuxSampler {
771                                        << devEvent.Type << "). This is a bug!";                                        << devEvent.Type << "). This is a bug!";
772                              continue;                              continue;
773                      }                      }
774                        memset(&event.Format, 0, sizeof(event.Format)); // init format specific stuff with zeroes
775                      event.pEngineChannel = this;                      event.pEngineChannel = this;
776                      // copy event to internal event list                      // copy event to internal event list
777                      if (pEvents->poolIsEmpty()) {                      if (pEvents->poolIsEmpty()) {
# Line 884  namespace LinuxSampler { Line 808  namespace LinuxSampler {
808          eventQueueReader.free(); // free all copied events from input queue          eventQueueReader.free(); // free all copied events from input queue
809      }      }
810    
811        /**
812         * Called by real-time instrument script functions to schedule a new event
813         * somewhere in future.
814         *
815         * @returns unique event ID of scheduled new event
816         */
817        int AbstractEngineChannel::ScheduleEvent(const Event* pEvent, int delay) { //TODO: delay not implemented yet
818            // since delay is not implemented yet, we simply add the new event
819            // to the event list of the current audio fragmet cycle for now
820            RTList<Event>::Iterator itEvent = pEvents->allocAppend();
821            if (itEvent) *itEvent = *pEvent; // copy event
822            return pEvents->getID(itEvent);
823        }
824    
825        /**
826         * Called by real-time instrument script functions to ignore the event
827         * reflected by given event ID. The event will be freed immediately to its
828         * pool and cannot be dereferenced by its old ID anymore. Even if its
829         * allocated back from the Pool later on, it will have a different ID.
830         */
831        void AbstractEngineChannel::IgnoreEvent(int id) {
832            RTList<Event>::Iterator it = pEvents->fromID(id);
833            if (it) pEvents->free(it);
834        }
835    
836      FxSend* AbstractEngineChannel::AddFxSend(uint8_t MidiCtrl, String Name) throw (Exception) {      FxSend* AbstractEngineChannel::AddFxSend(uint8_t MidiCtrl, String Name) throw (Exception) {
837          if (pEngine) pEngine->DisableAndLock();          if (pEngine) pEngine->DisableAndLock();
838          FxSend* pFxSend = new FxSend(this, MidiCtrl, Name);          FxSend* pFxSend = new FxSend(this, MidiCtrl, Name);

Legend:
Removed from v.2594  
changed lines
  Added in v.2665

  ViewVC Help
Powered by ViewVC