/[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 2114 by persson, Tue Aug 10 12:05:19 2010 UTC revision 2326 by persson, Thu Mar 8 19:40:14 2012 UTC
# Line 4  Line 4 
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-2008 Christian Schoenebeck                         *   *   Copyright (C) 2005-2008 Christian Schoenebeck                         *
7   *   Copyright (C) 2009-2010 Christian Schoenebeck and Grigor Iliev        *   *   Copyright (C) 2009-2012 Christian Schoenebeck and Grigor Iliev        *
8   *                                                                         *   *                                                                         *
9   *   This program is free software; you can redistribute it and/or modify  *   *   This program is free software; you can redistribute it and/or modify  *
10   *   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 191  namespace LinuxSampler { Line 191  namespace LinuxSampler {
191          return (pEngine) ? pEngine->pAudioOutputDevice : NULL;          return (pEngine) ? pEngine->pAudioOutputDevice : NULL;
192      }      }
193    
194        /**
195         * Gets thread safe access to the currently connected audio output
196         * device from other threads than the lscp thread.
197         */
198        AudioOutputDevice* AbstractEngineChannel::GetAudioOutputDeviceSafe() {
199            EngineMutex.Lock();
200            AudioOutputDevice* res = GetAudioOutputDevice();
201            EngineMutex.Unlock();
202            return res;
203        }
204    
205      void AbstractEngineChannel::SetOutputChannel(uint EngineAudioChannel, uint AudioDeviceChannel) {      void AbstractEngineChannel::SetOutputChannel(uint EngineAudioChannel, uint AudioDeviceChannel) {
206          if (!pEngine || !pEngine->pAudioOutputDevice) throw AudioOutputException("No audio output device connected yet.");          if (!pEngine || !pEngine->pAudioOutputDevice) throw AudioOutputException("No audio output device connected yet.");
207    
# Line 278  namespace LinuxSampler { Line 289  namespace LinuxSampler {
289       *  @param Key      - MIDI key number of the triggered key       *  @param Key      - MIDI key number of the triggered key
290       *  @param Velocity - MIDI velocity value of the triggered key       *  @param Velocity - MIDI velocity value of the triggered key
291       */       */
292      void AbstractEngineChannel::SendNoteOn(uint8_t Key, uint8_t Velocity) {      void AbstractEngineChannel::SendNoteOn(uint8_t Key, uint8_t Velocity, uint8_t MidiChannel) {
293          if (pEngine) {          if (pEngine) {
294              Event event               = pEngine->pEventGenerator->CreateEvent();              Event event               = pEngine->pEventGenerator->CreateEvent();
295              event.Type                = Event::type_note_on;              event.Type                = Event::type_note_on;
296              event.Param.Note.Key      = Key;              event.Param.Note.Key      = Key;
297              event.Param.Note.Velocity = Velocity;              event.Param.Note.Velocity = Velocity;
298                event.Param.Note.Channel  = MidiChannel;
299              event.pEngineChannel      = this;              event.pEngineChannel      = this;
300              if (this->pEventQueue->write_space() > 0) this->pEventQueue->push(&event);              if (this->pEventQueue->write_space() > 0) this->pEventQueue->push(&event);
301              else dmsg(1,("EngineChannel: Input event queue full!"));              else dmsg(1,("EngineChannel: Input event queue full!"));
# Line 311  namespace LinuxSampler { Line 323  namespace LinuxSampler {
323       *  @param FragmentPos - sample point position in the current audio       *  @param FragmentPos - sample point position in the current audio
324       *                       fragment to which this event belongs to       *                       fragment to which this event belongs to
325       */       */
326      void AbstractEngineChannel::SendNoteOn(uint8_t Key, uint8_t Velocity, int32_t FragmentPos) {      void AbstractEngineChannel::SendNoteOn(uint8_t Key, uint8_t Velocity, uint8_t MidiChannel, int32_t FragmentPos) {
327          if (FragmentPos < 0) {          if (FragmentPos < 0) {
328              dmsg(1,("EngineChannel::SendNoteOn(): negative FragmentPos! Seems MIDI driver is buggy!"));              dmsg(1,("EngineChannel::SendNoteOn(): negative FragmentPos! Seems MIDI driver is buggy!"));
329          }          }
# Line 320  namespace LinuxSampler { Line 332  namespace LinuxSampler {
332              event.Type                = Event::type_note_on;              event.Type                = Event::type_note_on;
333              event.Param.Note.Key      = Key;              event.Param.Note.Key      = Key;
334              event.Param.Note.Velocity = Velocity;              event.Param.Note.Velocity = Velocity;
335                event.Param.Note.Channel  = MidiChannel;
336              event.pEngineChannel      = this;              event.pEngineChannel      = this;
337              if (this->pEventQueue->write_space() > 0) this->pEventQueue->push(&event);              if (this->pEventQueue->write_space() > 0) this->pEventQueue->push(&event);
338              else dmsg(1,("EngineChannel: Input event queue full!"));              else dmsg(1,("EngineChannel: Input event queue full!"));
# Line 345  namespace LinuxSampler { Line 358  namespace LinuxSampler {
358       *  @param Key      - MIDI key number of the released key       *  @param Key      - MIDI key number of the released key
359       *  @param Velocity - MIDI release velocity value of the released key       *  @param Velocity - MIDI release velocity value of the released key
360       */       */
361      void AbstractEngineChannel::SendNoteOff(uint8_t Key, uint8_t Velocity) {      void AbstractEngineChannel::SendNoteOff(uint8_t Key, uint8_t Velocity, uint8_t MidiChannel) {
362          if (pEngine) {          if (pEngine) {
363              Event event               = pEngine->pEventGenerator->CreateEvent();              Event event               = pEngine->pEventGenerator->CreateEvent();
364              event.Type                = Event::type_note_off;              event.Type                = Event::type_note_off;
365              event.Param.Note.Key      = Key;              event.Param.Note.Key      = Key;
366              event.Param.Note.Velocity = Velocity;              event.Param.Note.Velocity = Velocity;
367                event.Param.Note.Channel  = MidiChannel;
368              event.pEngineChannel      = this;              event.pEngineChannel      = this;
369              if (this->pEventQueue->write_space() > 0) this->pEventQueue->push(&event);              if (this->pEventQueue->write_space() > 0) this->pEventQueue->push(&event);
370              else dmsg(1,("EngineChannel: Input event queue full!"));              else dmsg(1,("EngineChannel: Input event queue full!"));
# Line 378  namespace LinuxSampler { Line 392  namespace LinuxSampler {
392       *  @param FragmentPos - sample point position in the current audio       *  @param FragmentPos - sample point position in the current audio
393       *                       fragment to which this event belongs to       *                       fragment to which this event belongs to
394       */       */
395      void AbstractEngineChannel::SendNoteOff(uint8_t Key, uint8_t Velocity, int32_t FragmentPos) {      void AbstractEngineChannel::SendNoteOff(uint8_t Key, uint8_t Velocity, uint8_t MidiChannel, int32_t FragmentPos) {
396          if (FragmentPos < 0) {          if (FragmentPos < 0) {
397              dmsg(1,("EngineChannel::SendNoteOff(): negative FragmentPos! Seems MIDI driver is buggy!"));              dmsg(1,("EngineChannel::SendNoteOff(): negative FragmentPos! Seems MIDI driver is buggy!"));
398          }          }
# Line 387  namespace LinuxSampler { Line 401  namespace LinuxSampler {
401              event.Type                = Event::type_note_off;              event.Type                = Event::type_note_off;
402              event.Param.Note.Key      = Key;              event.Param.Note.Key      = Key;
403              event.Param.Note.Velocity = Velocity;              event.Param.Note.Velocity = Velocity;
404                event.Param.Note.Channel  = MidiChannel;
405              event.pEngineChannel      = this;              event.pEngineChannel      = this;
406              if (this->pEventQueue->write_space() > 0) this->pEventQueue->push(&event);              if (this->pEventQueue->write_space() > 0) this->pEventQueue->push(&event);
407              else dmsg(1,("EngineChannel: Input event queue full!"));              else dmsg(1,("EngineChannel: Input event queue full!"));
# Line 411  namespace LinuxSampler { Line 426  namespace LinuxSampler {
426       *       *
427       *  @param Pitch - MIDI pitch value (-8192 ... +8191)       *  @param Pitch - MIDI pitch value (-8192 ... +8191)
428       */       */
429      void AbstractEngineChannel::SendPitchbend(int Pitch) {      void AbstractEngineChannel::SendPitchbend(int Pitch, uint8_t MidiChannel) {
430          if (pEngine) {          if (pEngine) {
431              Event event             = pEngine->pEventGenerator->CreateEvent();              Event event             = pEngine->pEventGenerator->CreateEvent();
432              event.Type              = Event::type_pitchbend;              event.Type              = Event::type_pitchbend;
433              event.Param.Pitch.Pitch = Pitch;              event.Param.Pitch.Pitch = Pitch;
434                event.Param.Pitch.Channel = MidiChannel;
435              event.pEngineChannel    = this;              event.pEngineChannel    = this;
436              if (this->pEventQueue->write_space() > 0) this->pEventQueue->push(&event);              if (this->pEventQueue->write_space() > 0) this->pEventQueue->push(&event);
437              else dmsg(1,("EngineChannel: Input event queue full!"));              else dmsg(1,("EngineChannel: Input event queue full!"));
# Line 432  namespace LinuxSampler { Line 448  namespace LinuxSampler {
448       *  @param FragmentPos - sample point position in the current audio       *  @param FragmentPos - sample point position in the current audio
449       *                       fragment to which this event belongs to       *                       fragment to which this event belongs to
450       */       */
451      void AbstractEngineChannel::SendPitchbend(int Pitch, int32_t FragmentPos) {      void AbstractEngineChannel::SendPitchbend(int Pitch, uint8_t MidiChannel, int32_t FragmentPos) {
452          if (FragmentPos < 0) {          if (FragmentPos < 0) {
453              dmsg(1,("AbstractEngineChannel::SendPitchBend(): negative FragmentPos! Seems MIDI driver is buggy!"));              dmsg(1,("AbstractEngineChannel::SendPitchBend(): negative FragmentPos! Seems MIDI driver is buggy!"));
454          }          }
# Line 440  namespace LinuxSampler { Line 456  namespace LinuxSampler {
456              Event event             = pEngine->pEventGenerator->CreateEvent(FragmentPos);              Event event             = pEngine->pEventGenerator->CreateEvent(FragmentPos);
457              event.Type              = Event::type_pitchbend;              event.Type              = Event::type_pitchbend;
458              event.Param.Pitch.Pitch = Pitch;              event.Param.Pitch.Pitch = Pitch;
459                event.Param.Pitch.Channel = MidiChannel;
460              event.pEngineChannel    = this;              event.pEngineChannel    = this;
461              if (this->pEventQueue->write_space() > 0) this->pEventQueue->push(&event);              if (this->pEventQueue->write_space() > 0) this->pEventQueue->push(&event);
462              else dmsg(1,("AbstractEngineChannel: Input event queue full!"));              else dmsg(1,("AbstractEngineChannel: Input event queue full!"));
# Line 455  namespace LinuxSampler { Line 472  namespace LinuxSampler {
472       *  @param Controller - MIDI controller number of the occured control change       *  @param Controller - MIDI controller number of the occured control change
473       *  @param Value      - value of the control change       *  @param Value      - value of the control change
474       */       */
475      void AbstractEngineChannel::SendControlChange(uint8_t Controller, uint8_t Value) {      void AbstractEngineChannel::SendControlChange(uint8_t Controller, uint8_t Value, uint8_t MidiChannel) {
476          if (pEngine) {          if (pEngine) {
477              Event event               = pEngine->pEventGenerator->CreateEvent();              Event event               = pEngine->pEventGenerator->CreateEvent();
478              event.Type                = Event::type_control_change;              event.Type                = Event::type_control_change;
479              event.Param.CC.Controller = Controller;              event.Param.CC.Controller = Controller;
480              event.Param.CC.Value      = Value;              event.Param.CC.Value      = Value;
481                event.Param.CC.Channel    = MidiChannel;
482              event.pEngineChannel      = this;              event.pEngineChannel      = this;
483              if (this->pEventQueue->write_space() > 0) this->pEventQueue->push(&event);              if (this->pEventQueue->write_space() > 0) this->pEventQueue->push(&event);
484              else dmsg(1,("AbstractEngineChannel: Input event queue full!"));              else dmsg(1,("AbstractEngineChannel: Input event queue full!"));
# Line 478  namespace LinuxSampler { Line 496  namespace LinuxSampler {
496       *  @param FragmentPos - sample point position in the current audio       *  @param FragmentPos - sample point position in the current audio
497       *                       fragment to which this event belongs to       *                       fragment to which this event belongs to
498       */       */
499      void AbstractEngineChannel::SendControlChange(uint8_t Controller, uint8_t Value, int32_t FragmentPos) {      void AbstractEngineChannel::SendControlChange(uint8_t Controller, uint8_t Value, uint8_t MidiChannel, int32_t FragmentPos) {
500          if (FragmentPos < 0) {          if (FragmentPos < 0) {
501              dmsg(1,("AbstractEngineChannel::SendControlChange(): negative FragmentPos! Seems MIDI driver is buggy!"));              dmsg(1,("AbstractEngineChannel::SendControlChange(): negative FragmentPos! Seems MIDI driver is buggy!"));
502          }          }
# Line 487  namespace LinuxSampler { Line 505  namespace LinuxSampler {
505              event.Type                = Event::type_control_change;              event.Type                = Event::type_control_change;
506              event.Param.CC.Controller = Controller;              event.Param.CC.Controller = Controller;
507              event.Param.CC.Value      = Value;              event.Param.CC.Value      = Value;
508                event.Param.CC.Channel    = MidiChannel;
509              event.pEngineChannel      = this;              event.pEngineChannel      = this;
510              if (this->pEventQueue->write_space() > 0) this->pEventQueue->push(&event);              if (this->pEventQueue->write_space() > 0) this->pEventQueue->push(&event);
511              else dmsg(1,("AbstractEngineChannel: Input event queue full!"));              else dmsg(1,("AbstractEngineChannel: Input event queue full!"));
# Line 510  namespace LinuxSampler { Line 529  namespace LinuxSampler {
529          // import events from pure software MIDI "devices"          // import events from pure software MIDI "devices"
530          // (e.g. virtual keyboard in instrument editor)          // (e.g. virtual keyboard in instrument editor)
531          {          {
532                const uint8_t channel = MidiChannel() == midi_chan_all ? 0 : MidiChannel();
533              const int FragmentPos = 0; // randomly chosen, we don't care about jitter for virtual MIDI devices              const int FragmentPos = 0; // randomly chosen, we don't care about jitter for virtual MIDI devices
534              Event event = pEngine->pEventGenerator->CreateEvent(FragmentPos);              Event event = pEngine->pEventGenerator->CreateEvent(FragmentPos);
535              VirtualMidiDevice::event_t devEvent; // the event format we get from the virtual MIDI device              VirtualMidiDevice::event_t devEvent; // the event format we get from the virtual MIDI device
# Line 527  namespace LinuxSampler { Line 547  namespace LinuxSampler {
547                              event.Type = Event::type_note_on;                              event.Type = Event::type_note_on;
548                              event.Param.Note.Key      = devEvent.Arg1;                              event.Param.Note.Key      = devEvent.Arg1;
549                              event.Param.Note.Velocity = devEvent.Arg2;                              event.Param.Note.Velocity = devEvent.Arg2;
550                                event.Param.Note.Channel  = channel;
551                              break;                              break;
552                          case VirtualMidiDevice::EVENT_TYPE_NOTEOFF:                          case VirtualMidiDevice::EVENT_TYPE_NOTEOFF:
553                              event.Type = Event::type_note_off;                              event.Type = Event::type_note_off;
554                              event.Param.Note.Key      = devEvent.Arg1;                              event.Param.Note.Key      = devEvent.Arg1;
555                              event.Param.Note.Velocity = devEvent.Arg2;                              event.Param.Note.Velocity = devEvent.Arg2;
556                                event.Param.Note.Channel  = channel;
557                              break;                              break;
558                          case VirtualMidiDevice::EVENT_TYPE_CC:                          case VirtualMidiDevice::EVENT_TYPE_CC:
559                              event.Type = Event::type_control_change;                              event.Type = Event::type_control_change;
560                              event.Param.CC.Controller = devEvent.Arg1;                              event.Param.CC.Controller = devEvent.Arg1;
561                              event.Param.CC.Value      = devEvent.Arg2;                              event.Param.CC.Value      = devEvent.Arg2;
562                                event.Param.CC.Channel    = channel;
563                              break;                              break;
564                          default:                          default:
565                              std::cerr << "AbstractEngineChannel::ImportEvents() ERROR: unknown event type ("                              std::cerr << "AbstractEngineChannel::ImportEvents() ERROR: unknown event type ("
# Line 668  namespace LinuxSampler { Line 691  namespace LinuxSampler {
691       */       */
692      void AbstractEngineChannel::AddGroup(uint group) {      void AbstractEngineChannel::AddGroup(uint group) {
693          if (group) {          if (group) {
694              typedef std::map<uint, RTList<Event>*> map_t;              std::pair<ActiveKeyGroupMap::iterator, bool> p =
695                    ActiveKeyGroups.insert(ActiveKeyGroupMap::value_type(group, 0));
             std::pair<map_t::iterator, bool> p =  
                 ActiveKeyGroups.insert(map_t::value_type(group, 0));  
696              if (p.second) {              if (p.second) {
697                  (*p.first).second = new RTList<Event>(pEngine->pEventPool);                  // If the engine channel is pending deletion (see bug
698                    // #113), pEngine will be null, so we can't use
699                    // pEngine->pEventPool here. Instead we're using a
700                    // specialized RTList that allows specifying the pool
701                    // later.
702                    (*p.first).second = new LazyList<Event>;
703              }              }
704          }          }
705      }      }
# Line 685  namespace LinuxSampler { Line 711  namespace LinuxSampler {
711          dmsg(4,("HandelKeyGroupConflicts KeyGroup=%d\n", KeyGroup));          dmsg(4,("HandelKeyGroupConflicts KeyGroup=%d\n", KeyGroup));
712          if (KeyGroup) {          if (KeyGroup) {
713              // send a release event to all active voices in the group              // send a release event to all active voices in the group
714              RTList<Event>::Iterator itEvent = ActiveKeyGroups[KeyGroup]->allocAppend();              RTList<Event>::Iterator itEvent = ActiveKeyGroups[KeyGroup]->allocAppend(pEngine->pEventPool);
715              *itEvent = *itNoteOnEvent;              *itEvent = *itNoteOnEvent;
716          }          }
717      }      }
# Line 695  namespace LinuxSampler { Line 721  namespace LinuxSampler {
721       * audio thread, after all voices have been rendered.       * audio thread, after all voices have been rendered.
722       */       */
723      void AbstractEngineChannel::ClearGroupEventLists() {      void AbstractEngineChannel::ClearGroupEventLists() {
724          for (std::map<uint,RTList<Event>*>::iterator iter = ActiveKeyGroups.begin();          for (ActiveKeyGroupMap::iterator iter = ActiveKeyGroups.begin();
725               iter != ActiveKeyGroups.end(); iter++) {               iter != ActiveKeyGroups.end(); iter++) {
726              if (iter->second) {              if (iter->second) {
727                  iter->second->clear();                  iter->second->clear();
# Line 709  namespace LinuxSampler { Line 735  namespace LinuxSampler {
735       * Remove all lists with group events.       * Remove all lists with group events.
736       */       */
737      void AbstractEngineChannel::DeleteGroupEventLists() {      void AbstractEngineChannel::DeleteGroupEventLists() {
738          for (std::map<uint,RTList<Event>*>::iterator iter = ActiveKeyGroups.begin();          for (ActiveKeyGroupMap::iterator iter = ActiveKeyGroups.begin();
739               iter != ActiveKeyGroups.end(); iter++) {               iter != ActiveKeyGroups.end(); iter++) {
740              delete iter->second;              delete iter->second;
741          }          }

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

  ViewVC Help
Powered by ViewVC