/[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 2382 by persson, Sun Dec 2 16:30:42 2012 UTC revision 2598 by schoenebeck, Fri Jun 6 12:38:54 2014 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) 2013-2014 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 41  namespace LinuxSampler { Line 42  namespace LinuxSampler {
42          pChannelRight = NULL;          pChannelRight = NULL;
43          AudioDeviceChannelLeft  = -1;          AudioDeviceChannelLeft  = -1;
44          AudioDeviceChannelRight = -1;          AudioDeviceChannelRight = -1;
         pMidiInputPort = NULL;  
45          midiChannel = midi_chan_all;          midiChannel = midi_chan_all;
46          ResetControllers();          ResetControllers();
47          PortamentoMode = false;          PortamentoMode = false;
48          PortamentoTime = CONFIG_PORTAMENTO_TIME_DEFAULT;          PortamentoTime = CONFIG_PORTAMENTO_TIME_DEFAULT;
49            pScriptEvents = NULL;
50      }      }
51    
52      AbstractEngineChannel::~AbstractEngineChannel() {      AbstractEngineChannel::~AbstractEngineChannel() {
53            unloadCurrentInstrumentScript();
54            if (pScriptEvents) delete pScriptEvents;
55          delete pEventQueue;          delete pEventQueue;
56          DeleteGroupEventLists();          DeleteGroupEventLists();
57          RemoveAllFxSends();          RemoveAllFxSends();
# Line 142  namespace LinuxSampler { Line 145  namespace LinuxSampler {
145      }      }
146    
147      /**      /**
148         * Loads the real-time instrument script given by @a text on this engine
149         * channel. A resource manager is used to allocate and share equivalent
150         * scripts on multiple engine channels.
151         *
152         * @param text - source code of script
153         */
154        void AbstractEngineChannel::loadInstrumentScript(const String& text) {
155            dmsg(1,("Loading real-time instrument script ... "));
156    
157            // hand back old script reference and VM execution contexts
158            // (if not done already)
159            unloadCurrentInstrumentScript();
160    
161            // get new script reference
162            script.parserContext = pEngine->scripts.Borrow(text, this);
163            if (!script.parserContext->errors().empty()) {
164                std::vector<ParserIssue> errors = script.parserContext->errors();
165                std::cerr << "[ScriptVM] Could not load instrument script, there were "
166                          << errors.size() << " parser errors:\n";
167                for (int i = 0; i < errors.size(); ++i)
168                    errors[i].dump();
169                return; // stop here if there were any parser errors
170            }
171    
172            script.handlerInit = script.parserContext->eventHandlerByName("init");
173            script.handlerNote = script.parserContext->eventHandlerByName("note");
174            script.handlerRelease = script.parserContext->eventHandlerByName("release");
175            script.handlerController = script.parserContext->eventHandlerByName("controller");
176            script.bHasValidScript =
177                script.handlerInit || script.handlerNote || script.handlerRelease ||
178                script.handlerController;
179    
180            // amount of script handlers each script event has to execute
181            int handlerExecCount = 0;
182            if (script.handlerInit) handlerExecCount++; // "init" handler is always executed before the actual event handler
183            if (script.handlerNote || script.handlerRelease || script.handlerController) // only one of these are executed after "init" handler
184                handlerExecCount++;
185    
186            // create script event pool (if it doesn't exist already)
187            if (!pScriptEvents)
188                pScriptEvents = new Pool<ScriptEvent>(CONFIG_MAX_EVENTS_PER_FRAGMENT);
189    
190            // create new VM execution contexts for new script
191            while (!pScriptEvents->poolIsEmpty()) {
192                RTList<ScriptEvent>::Iterator it = pScriptEvents->allocAppend();
193                it->execCtx = pEngine->pScriptVM->createExecContext(
194                    script.parserContext
195                );
196                it->handlers = new VMEventHandler*[handlerExecCount+1];
197            }
198            pScriptEvents->clear();
199    
200            dmsg(1,("Done\n"));
201        }
202    
203        /**
204         * Unloads the currently used real-time instrument script on this sampler
205         * channel. A resource manager is used to share equivalent scripts among
206         * multiple sampler channels, and to deallocate the parsed script once not
207         * used on any engine channel anymore.
208         */
209        void AbstractEngineChannel::unloadCurrentInstrumentScript() {
210            if (script.parserContext)
211                dmsg(1,("Unloading current instrument script."));
212    
213            // free allocated VM execution contexts
214            if (pScriptEvents) {
215                pScriptEvents->clear();
216                while (!pScriptEvents->poolIsEmpty()) {
217                    RTList<ScriptEvent>::Iterator it = pScriptEvents->allocAppend();
218                    if (it->execCtx) {
219                        // free VM execution context object
220                        delete it->execCtx;
221                        it->execCtx = NULL;
222                        // free C array of handler pointers
223                        delete [] it->handlers;
224                    }
225                }
226                pScriptEvents->clear();
227            }
228            // hand back VM representation of script
229            if (script.parserContext) {
230                pEngine->scripts.HandBack(script.parserContext, this);
231                script.parserContext = NULL;
232                script.handlerInit = NULL;
233                script.handlerNote = NULL;
234                script.handlerRelease = NULL;
235                script.handlerController = NULL;
236            }
237            script.bHasValidScript = false;
238        }
239    
240        /**
241       * Implementation of virtual method from abstract EngineChannel interface.       * Implementation of virtual method from abstract EngineChannel interface.
242       * 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
243       * check if some engine channel parameter has changed since the last       * check if some engine channel parameter has changed since the last
# Line 192  namespace LinuxSampler { Line 288  namespace LinuxSampler {
288       * device from other threads than the lscp thread.       * device from other threads than the lscp thread.
289       */       */
290      AudioOutputDevice* AbstractEngineChannel::GetAudioOutputDeviceSafe() {      AudioOutputDevice* AbstractEngineChannel::GetAudioOutputDeviceSafe() {
291          EngineMutex.Lock();          LockGuard lock(EngineMutex);
292          AudioOutputDevice* res = GetAudioOutputDevice();          return GetAudioOutputDevice();
         EngineMutex.Unlock();  
         return res;  
293      }      }
294    
295      void AbstractEngineChannel::SetOutputChannel(uint EngineAudioChannel, uint AudioDeviceChannel) {      void AbstractEngineChannel::SetOutputChannel(uint EngineAudioChannel, uint AudioDeviceChannel) {
# Line 230  namespace LinuxSampler { Line 324  namespace LinuxSampler {
324          }          }
325      }      }
326    
327        void AbstractEngineChannel::Connect(MidiInputPort* pMidiPort) {
328            if (!pMidiPort) return;
329    
330            Sync< ArrayList<MidiInputPort*> > connections = midiInputs.back();
331    
332            // check if connection already exists
333            for (int i = 0; i < connections->size(); ++i)
334                if ((*connections)[i] == pMidiPort)
335                    return; // to avoid endless recursion
336    
337            connections->add(pMidiPort);
338    
339            // inform MIDI port about this new connection
340            pMidiPort->Connect(this, MidiChannel());
341        }
342    
343        void AbstractEngineChannel::Disconnect(MidiInputPort* pMidiPort) {
344            if (!pMidiPort) return;
345    
346            Sync< ArrayList<MidiInputPort*> > connections = midiInputs.back();
347    
348            for (int i = 0; i < connections->size(); ++i) {
349                if ((*connections)[i] == pMidiPort) {
350                    connections->remove(i);
351                    // inform MIDI port about this disconnection
352                    pMidiPort->Disconnect(this);
353                    return;
354                }
355            }
356        }
357    
358        void AbstractEngineChannel::DisconnectAllMidiInputPorts() {
359            Sync< ArrayList<MidiInputPort*> > connections = midiInputs.back();
360            ArrayList<MidiInputPort*> clonedList = *connections;
361            connections->clear();
362            for (int i = 0; i < clonedList.size(); ++i) clonedList[i]->Disconnect(this);
363        }
364    
365        uint AbstractEngineChannel::GetMidiInputPortCount() {
366            Sync< ArrayList<MidiInputPort*> > connections = midiInputs.back();
367            return connections->size();
368        }
369    
370        MidiInputPort* AbstractEngineChannel::GetMidiInputPort(uint index) {
371            Sync< ArrayList<MidiInputPort*> > connections = midiInputs.back();
372            return (index < connections->size()) ? (*connections)[index] : NULL;
373        }
374    
375        // deprecated (just for API backward compatibility) - may be removed in future
376      void AbstractEngineChannel::Connect(MidiInputPort* pMidiPort, midi_chan_t MidiChannel) {      void AbstractEngineChannel::Connect(MidiInputPort* pMidiPort, midi_chan_t MidiChannel) {
377          if (!pMidiPort || pMidiPort == this->pMidiInputPort) return;          if (!pMidiPort) return;
378          DisconnectMidiInputPort();  
379          this->pMidiInputPort = pMidiPort;          Sync< ArrayList<MidiInputPort*> > connections = midiInputs.back();
380          this->midiChannel    = MidiChannel;  
381            // check against endless recursion
382            if (connections->size() == 1 && (*connections)[0] == pMidiPort && this->midiChannel == MidiChannel)
383                return;
384            
385            if (!isValidMidiChan(MidiChannel))
386                throw MidiInputException("Invalid MIDI channel (" + ToString(int(MidiChannel)) + ")");
387    
388            this->midiChannel = MidiChannel;
389    
390            // disconnect all currently connected MIDI ports
391            ArrayList<MidiInputPort*> clonedList = *connections;
392            connections->clear();
393            for (int i = 0; i < clonedList.size(); ++i)
394                clonedList[i]->Disconnect(this);
395    
396            // connect the new port
397            connections->add(pMidiPort);
398          pMidiPort->Connect(this, MidiChannel);          pMidiPort->Connect(this, MidiChannel);
399      }      }
400    
401        // deprecated (just for API backward compatibility) - may be removed in future
402      void AbstractEngineChannel::DisconnectMidiInputPort() {      void AbstractEngineChannel::DisconnectMidiInputPort() {
403          MidiInputPort* pOldPort = this->pMidiInputPort;          DisconnectAllMidiInputPorts();
         this->pMidiInputPort = NULL;  
         if (pOldPort) pOldPort->Disconnect(this);  
404      }      }
405    
406        // deprecated (just for API backward compatibility) - may be removed in future
407      MidiInputPort* AbstractEngineChannel::GetMidiInputPort() {      MidiInputPort* AbstractEngineChannel::GetMidiInputPort() {
408          return pMidiInputPort;          return GetMidiInputPort(0);
409      }      }
410    
411      midi_chan_t AbstractEngineChannel::MidiChannel() {      midi_chan_t AbstractEngineChannel::MidiChannel() {
412          return midiChannel;          return midiChannel;
413      }      }
414    
415        void AbstractEngineChannel::SetMidiChannel(midi_chan_t MidiChannel) {
416            if (this->midiChannel == MidiChannel) return;
417            if (!isValidMidiChan(MidiChannel))
418                throw MidiInputException("Invalid MIDI channel (" + ToString(int(MidiChannel)) + ")");
419    
420            this->midiChannel = MidiChannel;
421            
422            Sync< ArrayList<MidiInputPort*> > connections = midiInputs.back();
423            ArrayList<MidiInputPort*> clonedList = *connections;
424    
425            DisconnectAllMidiInputPorts();
426    
427            for (int i = 0; i < clonedList.size(); ++i) Connect(clonedList[i]);
428        }
429    
430      void AbstractEngineChannel::Connect(VirtualMidiDevice* pDevice) {      void AbstractEngineChannel::Connect(VirtualMidiDevice* pDevice) {
431          // double buffer ... double work ...          // double buffer ... double work ...
432          {          {
# Line 287  namespace LinuxSampler { Line 462  namespace LinuxSampler {
462       */       */
463      void AbstractEngineChannel::SendNoteOn(uint8_t Key, uint8_t Velocity, uint8_t MidiChannel) {      void AbstractEngineChannel::SendNoteOn(uint8_t Key, uint8_t Velocity, uint8_t MidiChannel) {
464          if (pEngine) {          if (pEngine) {
465                // protection in case there are more than 1 MIDI input threads sending MIDI events to this EngineChannel
466                LockGuard g;
467                if (hasMultipleMIDIInputs()) g = LockGuard(MidiInputMutex);
468    
469              Event event               = pEngine->pEventGenerator->CreateEvent();              Event event               = pEngine->pEventGenerator->CreateEvent();
470              event.Type                = Event::type_note_on;              event.Type                = Event::type_note_on;
471              event.Param.Note.Key      = Key;              event.Param.Note.Key      = Key;
# Line 324  namespace LinuxSampler { Line 503  namespace LinuxSampler {
503              dmsg(1,("EngineChannel::SendNoteOn(): negative FragmentPos! Seems MIDI driver is buggy!"));              dmsg(1,("EngineChannel::SendNoteOn(): negative FragmentPos! Seems MIDI driver is buggy!"));
504          }          }
505          else if (pEngine) {          else if (pEngine) {
506                // protection in case there are more than 1 MIDI input threads sending MIDI events to this EngineChannel
507                LockGuard g;
508                if (hasMultipleMIDIInputs()) g = LockGuard(MidiInputMutex);
509    
510              Event event               = pEngine->pEventGenerator->CreateEvent(FragmentPos);              Event event               = pEngine->pEventGenerator->CreateEvent(FragmentPos);
511              event.Type                = Event::type_note_on;              event.Type                = Event::type_note_on;
512              event.Param.Note.Key      = Key;              event.Param.Note.Key      = Key;
# Line 356  namespace LinuxSampler { Line 539  namespace LinuxSampler {
539       */       */
540      void AbstractEngineChannel::SendNoteOff(uint8_t Key, uint8_t Velocity, uint8_t MidiChannel) {      void AbstractEngineChannel::SendNoteOff(uint8_t Key, uint8_t Velocity, uint8_t MidiChannel) {
541          if (pEngine) {          if (pEngine) {
542                // protection in case there are more than 1 MIDI input threads sending MIDI events to this EngineChannel
543                LockGuard g;
544                if (hasMultipleMIDIInputs()) g = LockGuard(MidiInputMutex);
545    
546              Event event               = pEngine->pEventGenerator->CreateEvent();              Event event               = pEngine->pEventGenerator->CreateEvent();
547              event.Type                = Event::type_note_off;              event.Type                = Event::type_note_off;
548              event.Param.Note.Key      = Key;              event.Param.Note.Key      = Key;
# Line 393  namespace LinuxSampler { Line 580  namespace LinuxSampler {
580              dmsg(1,("EngineChannel::SendNoteOff(): negative FragmentPos! Seems MIDI driver is buggy!"));              dmsg(1,("EngineChannel::SendNoteOff(): negative FragmentPos! Seems MIDI driver is buggy!"));
581          }          }
582          else if (pEngine) {          else if (pEngine) {
583                // protection in case there are more than 1 MIDI input threads sending MIDI events to this EngineChannel
584                LockGuard g;
585                if (hasMultipleMIDIInputs()) g = LockGuard(MidiInputMutex);
586    
587              Event event               = pEngine->pEventGenerator->CreateEvent(FragmentPos);              Event event               = pEngine->pEventGenerator->CreateEvent(FragmentPos);
588              event.Type                = Event::type_note_off;              event.Type                = Event::type_note_off;
589              event.Param.Note.Key      = Key;              event.Param.Note.Key      = Key;
# Line 424  namespace LinuxSampler { Line 615  namespace LinuxSampler {
615       */       */
616      void AbstractEngineChannel::SendPitchbend(int Pitch, uint8_t MidiChannel) {      void AbstractEngineChannel::SendPitchbend(int Pitch, uint8_t MidiChannel) {
617          if (pEngine) {          if (pEngine) {
618                // protection in case there are more than 1 MIDI input threads sending MIDI events to this EngineChannel
619                LockGuard g;
620                if (hasMultipleMIDIInputs()) g = LockGuard(MidiInputMutex);
621    
622              Event event             = pEngine->pEventGenerator->CreateEvent();              Event event             = pEngine->pEventGenerator->CreateEvent();
623              event.Type              = Event::type_pitchbend;              event.Type              = Event::type_pitchbend;
624              event.Param.Pitch.Pitch = Pitch;              event.Param.Pitch.Pitch = Pitch;
# Line 449  namespace LinuxSampler { Line 644  namespace LinuxSampler {
644              dmsg(1,("AbstractEngineChannel::SendPitchBend(): negative FragmentPos! Seems MIDI driver is buggy!"));              dmsg(1,("AbstractEngineChannel::SendPitchBend(): negative FragmentPos! Seems MIDI driver is buggy!"));
645          }          }
646          else if (pEngine) {          else if (pEngine) {
647                // protection in case there are more than 1 MIDI input threads sending MIDI events to this EngineChannel
648                LockGuard g;
649                if (hasMultipleMIDIInputs()) g = LockGuard(MidiInputMutex);
650    
651              Event event             = pEngine->pEventGenerator->CreateEvent(FragmentPos);              Event event             = pEngine->pEventGenerator->CreateEvent(FragmentPos);
652              event.Type              = Event::type_pitchbend;              event.Type              = Event::type_pitchbend;
653              event.Param.Pitch.Pitch = Pitch;              event.Param.Pitch.Pitch = Pitch;
# Line 470  namespace LinuxSampler { Line 669  namespace LinuxSampler {
669       */       */
670      void AbstractEngineChannel::SendControlChange(uint8_t Controller, uint8_t Value, uint8_t MidiChannel) {      void AbstractEngineChannel::SendControlChange(uint8_t Controller, uint8_t Value, uint8_t MidiChannel) {
671          if (pEngine) {          if (pEngine) {
672                // protection in case there are more than 1 MIDI input threads sending MIDI events to this EngineChannel
673                LockGuard g;
674                if (hasMultipleMIDIInputs()) g = LockGuard(MidiInputMutex);
675    
676              Event event               = pEngine->pEventGenerator->CreateEvent();              Event event               = pEngine->pEventGenerator->CreateEvent();
677              event.Type                = Event::type_control_change;              event.Type                = Event::type_control_change;
678              event.Param.CC.Controller = Controller;              event.Param.CC.Controller = Controller;
# Line 497  namespace LinuxSampler { Line 700  namespace LinuxSampler {
700              dmsg(1,("AbstractEngineChannel::SendControlChange(): negative FragmentPos! Seems MIDI driver is buggy!"));              dmsg(1,("AbstractEngineChannel::SendControlChange(): negative FragmentPos! Seems MIDI driver is buggy!"));
701          }          }
702          else if (pEngine) {          else if (pEngine) {
703                // protection in case there are more than 1 MIDI input threads sending MIDI events to this EngineChannel
704                LockGuard g;
705                if (hasMultipleMIDIInputs()) g = LockGuard(MidiInputMutex);
706    
707              Event event               = pEngine->pEventGenerator->CreateEvent(FragmentPos);              Event event               = pEngine->pEventGenerator->CreateEvent(FragmentPos);
708              event.Type                = Event::type_control_change;              event.Type                = Event::type_control_change;
709              event.Param.CC.Controller = Controller;              event.Param.CC.Controller = Controller;
# Line 508  namespace LinuxSampler { Line 715  namespace LinuxSampler {
715          }          }
716      }      }
717    
718        void AbstractEngineChannel::SendChannelPressure(uint8_t Value, uint8_t MidiChannel) {
719            if (pEngine) {
720                // protection in case there are more than 1 MIDI input threads sending MIDI events to this EngineChannel
721                LockGuard g;
722                if (hasMultipleMIDIInputs()) g = LockGuard(MidiInputMutex);
723    
724                Event event = pEngine->pEventGenerator->CreateEvent();
725                event.Type                          = Event::type_channel_pressure;
726                event.Param.ChannelPressure.Value   = Value;
727                event.Param.ChannelPressure.Channel = MidiChannel;
728                event.pEngineChannel                = this;
729                if (this->pEventQueue->write_space() > 0) this->pEventQueue->push(&event);
730                else dmsg(1,("AbstractEngineChannel: Input event queue full!"));
731            }
732        }
733    
734        void AbstractEngineChannel::SendChannelPressure(uint8_t Value, uint8_t MidiChannel, int32_t FragmentPos) {
735            if (pEngine) {
736                // protection in case there are more than 1 MIDI input threads sending MIDI events to this EngineChannel
737                LockGuard g;
738                if (hasMultipleMIDIInputs()) g = LockGuard(MidiInputMutex);
739    
740                Event event = pEngine->pEventGenerator->CreateEvent(FragmentPos);
741                event.Type                          = Event::type_channel_pressure;
742                event.Param.ChannelPressure.Value   = Value;
743                event.Param.ChannelPressure.Channel = MidiChannel;
744                event.pEngineChannel                = this;
745                if (this->pEventQueue->write_space() > 0) this->pEventQueue->push(&event);
746                else dmsg(1,("AbstractEngineChannel: Input event queue full!"));
747            }
748        }
749    
750        void AbstractEngineChannel::SendPolyphonicKeyPressure(uint8_t Key, uint8_t Value, uint8_t MidiChannel) {
751            if (pEngine) {
752                // protection in case there are more than 1 MIDI input threads sending MIDI events to this EngineChannel
753                LockGuard g;
754                if (hasMultipleMIDIInputs()) g = LockGuard(MidiInputMutex);
755    
756                Event event = pEngine->pEventGenerator->CreateEvent();
757                event.Type                       = Event::type_note_pressure;
758                event.Param.NotePressure.Key     = Key;
759                event.Param.NotePressure.Value   = Value;
760                event.Param.NotePressure.Channel = MidiChannel;
761                event.pEngineChannel             = this;
762                if (this->pEventQueue->write_space() > 0) this->pEventQueue->push(&event);
763                else dmsg(1,("AbstractEngineChannel: Input event queue full!"));
764            }
765        }
766    
767        void AbstractEngineChannel::SendPolyphonicKeyPressure(uint8_t Key, uint8_t Value, uint8_t MidiChannel, int32_t FragmentPos) {
768            if (pEngine) {
769                // protection in case there are more than 1 MIDI input threads sending MIDI events to this EngineChannel
770                LockGuard g;
771                if (hasMultipleMIDIInputs()) g = LockGuard(MidiInputMutex);
772    
773                Event event = pEngine->pEventGenerator->CreateEvent(FragmentPos);
774                event.Type                       = Event::type_note_pressure;
775                event.Param.NotePressure.Key     = Key;
776                event.Param.NotePressure.Value   = Value;
777                event.Param.NotePressure.Channel = MidiChannel;
778                event.pEngineChannel             = this;
779                if (this->pEventQueue->write_space() > 0) this->pEventQueue->push(&event);
780                else dmsg(1,("AbstractEngineChannel: Input event queue full!"));
781            }
782        }
783    
784      /**      /**
785       * Copy all events from the engine channel's input event queue buffer to       * Copy all events from the engine channel's input event queue buffer to
786       * the internal event list. This will be done at the beginning of each       * the internal event list. This will be done at the beginning of each
# Line 552  namespace LinuxSampler { Line 825  namespace LinuxSampler {
825                              event.Param.Note.Channel  = channel;                              event.Param.Note.Channel  = channel;
826                              break;                              break;
827                          case VirtualMidiDevice::EVENT_TYPE_CC:                          case VirtualMidiDevice::EVENT_TYPE_CC:
828                              event.Type = Event::type_control_change;                              switch (devEvent.Arg1) {
829                              event.Param.CC.Controller = devEvent.Arg1;                                  case 0: // bank select MSB ...
830                              event.Param.CC.Value      = devEvent.Arg2;                                      SetMidiBankMsb(devEvent.Arg2);
831                              event.Param.CC.Channel    = channel;                                      continue; // don't push this event into FIFO
832                                    case 32: // bank select LSB ...
833                                        SetMidiBankLsb(devEvent.Arg2);
834                                        continue; // don't push this event into FIFO
835                                    default: // regular MIDI CC ...
836                                        event.Type = Event::type_control_change;
837                                        event.Param.CC.Controller = devEvent.Arg1;
838                                        event.Param.CC.Value      = devEvent.Arg2;
839                                        event.Param.CC.Channel    = channel;
840                                }
841                                break;
842                            case VirtualMidiDevice::EVENT_TYPE_PITCHBEND:
843                                event.Type = Event::type_pitchbend;
844                                event.Param.Pitch.Pitch = int(devEvent.Arg2 << 7 | devEvent.Arg1) - 8192;
845                                event.Param.Pitch.Channel = channel;
846                              break;                              break;
847                            case VirtualMidiDevice::EVENT_TYPE_PROGRAM:
848                                SendProgramChange(devEvent.Arg1);
849                                continue; // don't push this event into FIFO
850                          default:                          default:
851                              std::cerr << "AbstractEngineChannel::ImportEvents() ERROR: unknown event type ("                              std::cerr << "AbstractEngineChannel::ImportEvents() ERROR: unknown event type ("
852                                        << devEvent.Type << "). This is a bug!";                                        << devEvent.Type << "). This is a bug!";
# Line 598  namespace LinuxSampler { Line 888  namespace LinuxSampler {
888          eventQueueReader.free(); // free all copied events from input queue          eventQueueReader.free(); // free all copied events from input queue
889      }      }
890    
891        /**
892         * Called by real-time instrument script functions to schedule a new event
893         * somewhere in future.
894         *
895         * @returns unique event ID of scheduled new event
896         */
897        int AbstractEngineChannel::ScheduleEvent(const Event* pEvent, int delay) { //TODO: delay not implemented yet
898            // since delay is not implemented yet, we simply add the new event
899            // to the event list of the current audio fragmet cycle for now
900            RTList<Event>::Iterator itEvent = pEvents->allocAppend();
901            if (itEvent) *itEvent = *pEvent; // copy event
902            return pEvents->getID(itEvent);
903        }
904    
905        /**
906         * Called by real-time instrument script functions to ignore the event
907         * reflected by given event ID. The event will be freed immediately to its
908         * pool and cannot be dereferenced by its old ID anymore. Even if its
909         * allocated back from the Pool later on, it will have a different ID.
910         */
911        void AbstractEngineChannel::IgnoreEvent(int id) {
912            RTList<Event>::Iterator it = pEvents->fromID(id);
913            if (it) pEvents->free(it);
914        }
915    
916      FxSend* AbstractEngineChannel::AddFxSend(uint8_t MidiCtrl, String Name) throw (Exception) {      FxSend* AbstractEngineChannel::AddFxSend(uint8_t MidiCtrl, String Name) throw (Exception) {
917          if (pEngine) pEngine->DisableAndLock();          if (pEngine) pEngine->DisableAndLock();
918          FxSend* pFxSend = new FxSend(this, MidiCtrl, Name);          FxSend* pFxSend = new FxSend(this, MidiCtrl, Name);

Legend:
Removed from v.2382  
changed lines
  Added in v.2598

  ViewVC Help
Powered by ViewVC