28 |
namespace LinuxSampler { namespace gig { |
namespace LinuxSampler { namespace gig { |
29 |
|
|
30 |
EngineChannel::EngineChannel() : |
EngineChannel::EngineChannel() : |
31 |
InstrumentChangeCommandReader(InstrumentChangeCommand) { |
InstrumentChangeCommandReader(InstrumentChangeCommand), |
32 |
|
virtualMidiDevicesReader_AudioThread(virtualMidiDevices), |
33 |
|
virtualMidiDevicesReader_MidiThread(virtualMidiDevices) |
34 |
|
{ |
35 |
pMIDIKeyInfo = new midi_key_info_t[128]; |
pMIDIKeyInfo = new midi_key_info_t[128]; |
36 |
pEngine = NULL; |
pEngine = NULL; |
37 |
pInstrument = NULL; |
pInstrument = NULL; |
511 |
event.pEngineChannel = this; |
event.pEngineChannel = this; |
512 |
if (this->pEventQueue->write_space() > 0) this->pEventQueue->push(&event); |
if (this->pEventQueue->write_space() > 0) this->pEventQueue->push(&event); |
513 |
else dmsg(1,("EngineChannel: Input event queue full!")); |
else dmsg(1,("EngineChannel: Input event queue full!")); |
514 |
// inform instrument editor(s), if any ... |
// inform connected virtual MIDI devices if any ... |
515 |
pEngine->instruments.TrySendNoteOnToEditors(Key, Velocity, pInstrument); |
// (e.g. virtual MIDI keyboard in instrument editor(s)) |
516 |
|
ArrayList<VirtualMidiDevice*>& devices = |
517 |
|
const_cast<ArrayList<VirtualMidiDevice*>&>( |
518 |
|
virtualMidiDevicesReader_MidiThread.Lock() |
519 |
|
); |
520 |
|
for (int i = 0; i < devices.size(); i++) { |
521 |
|
devices[i]->SendNoteOnToDevice(Key, Velocity); |
522 |
|
} |
523 |
|
virtualMidiDevicesReader_MidiThread.Unlock(); |
524 |
} |
} |
525 |
} |
} |
526 |
|
|
547 |
event.pEngineChannel = this; |
event.pEngineChannel = this; |
548 |
if (this->pEventQueue->write_space() > 0) this->pEventQueue->push(&event); |
if (this->pEventQueue->write_space() > 0) this->pEventQueue->push(&event); |
549 |
else dmsg(1,("EngineChannel: Input event queue full!")); |
else dmsg(1,("EngineChannel: Input event queue full!")); |
550 |
// inform instrument editor(s), if any ... |
// inform connected virtual MIDI devices if any ... |
551 |
pEngine->instruments.TrySendNoteOnToEditors(Key, Velocity, pInstrument); |
// (e.g. virtual MIDI keyboard in instrument editor(s)) |
552 |
|
ArrayList<VirtualMidiDevice*>& devices = |
553 |
|
const_cast<ArrayList<VirtualMidiDevice*>&>( |
554 |
|
virtualMidiDevicesReader_MidiThread.Lock() |
555 |
|
); |
556 |
|
for (int i = 0; i < devices.size(); i++) { |
557 |
|
devices[i]->SendNoteOnToDevice(Key, Velocity); |
558 |
|
} |
559 |
|
virtualMidiDevicesReader_MidiThread.Unlock(); |
560 |
} |
} |
561 |
} |
} |
562 |
|
|
578 |
event.pEngineChannel = this; |
event.pEngineChannel = this; |
579 |
if (this->pEventQueue->write_space() > 0) this->pEventQueue->push(&event); |
if (this->pEventQueue->write_space() > 0) this->pEventQueue->push(&event); |
580 |
else dmsg(1,("EngineChannel: Input event queue full!")); |
else dmsg(1,("EngineChannel: Input event queue full!")); |
581 |
// inform instrument editor(s), if any ... |
// inform connected virtual MIDI devices if any ... |
582 |
pEngine->instruments.TrySendNoteOffToEditors(Key, Velocity, pInstrument); |
// (e.g. virtual MIDI keyboard in instrument editor(s)) |
583 |
|
ArrayList<VirtualMidiDevice*>& devices = |
584 |
|
const_cast<ArrayList<VirtualMidiDevice*>&>( |
585 |
|
virtualMidiDevicesReader_MidiThread.Lock() |
586 |
|
); |
587 |
|
for (int i = 0; i < devices.size(); i++) { |
588 |
|
devices[i]->SendNoteOffToDevice(Key, Velocity); |
589 |
|
} |
590 |
|
virtualMidiDevicesReader_MidiThread.Unlock(); |
591 |
} |
} |
592 |
} |
} |
593 |
|
|
614 |
event.pEngineChannel = this; |
event.pEngineChannel = this; |
615 |
if (this->pEventQueue->write_space() > 0) this->pEventQueue->push(&event); |
if (this->pEventQueue->write_space() > 0) this->pEventQueue->push(&event); |
616 |
else dmsg(1,("EngineChannel: Input event queue full!")); |
else dmsg(1,("EngineChannel: Input event queue full!")); |
617 |
// inform instrument editor(s), if any ... |
// inform connected virtual MIDI devices if any ... |
618 |
pEngine->instruments.TrySendNoteOffToEditors(Key, Velocity, pInstrument); |
// (e.g. virtual MIDI keyboard in instrument editor(s)) |
619 |
|
ArrayList<VirtualMidiDevice*>& devices = |
620 |
|
const_cast<ArrayList<VirtualMidiDevice*>&>( |
621 |
|
virtualMidiDevicesReader_MidiThread.Lock() |
622 |
|
); |
623 |
|
for (int i = 0; i < devices.size(); i++) { |
624 |
|
devices[i]->SendNoteOffToDevice(Key, Velocity); |
625 |
|
} |
626 |
|
virtualMidiDevicesReader_MidiThread.Unlock(); |
627 |
} |
} |
628 |
} |
} |
629 |
|
|
763 |
* current audio cycle |
* current audio cycle |
764 |
*/ |
*/ |
765 |
void EngineChannel::ImportEvents(uint Samples) { |
void EngineChannel::ImportEvents(uint Samples) { |
766 |
|
// import events from pure software MIDI "devices" |
767 |
|
// (e.g. virtual keyboard in instrument editor) |
768 |
|
{ |
769 |
|
const int FragmentPos = 0; // randomly chosen, we don't care about jitter for virtual MIDI devices |
770 |
|
Event event = pEngine->pEventGenerator->CreateEvent(FragmentPos); |
771 |
|
VirtualMidiDevice::event_t devEvent; // the event format we get from the virtual MIDI device |
772 |
|
// as we're going to (carefully) write some status to the |
773 |
|
// synchronized struct, we cast away the const |
774 |
|
ArrayList<VirtualMidiDevice*>& devices = |
775 |
|
const_cast<ArrayList<VirtualMidiDevice*>&>(virtualMidiDevicesReader_AudioThread.Lock()); |
776 |
|
// iterate through all virtual MIDI devices |
777 |
|
for (int i = 0; i < devices.size(); i++) { |
778 |
|
VirtualMidiDevice* pDev = devices[i]; |
779 |
|
// I think we can simply flush the whole FIFO(s), the user shouldn't be so fast ;-) |
780 |
|
while (pDev->GetMidiEventFromDevice(devEvent)) { |
781 |
|
event.Type = |
782 |
|
(devEvent.Type == VirtualMidiDevice::EVENT_TYPE_NOTEON) ? |
783 |
|
Event::type_note_on : Event::type_note_off; |
784 |
|
event.Param.Note.Key = devEvent.Key; |
785 |
|
event.Param.Note.Velocity = devEvent.Velocity; |
786 |
|
event.pEngineChannel = this; |
787 |
|
// copy event to internal event list |
788 |
|
if (pEvents->poolIsEmpty()) { |
789 |
|
dmsg(1,("Event pool emtpy!\n")); |
790 |
|
goto exitVirtualDevicesLoop; |
791 |
|
} |
792 |
|
*pEvents->allocAppend() = event; |
793 |
|
} |
794 |
|
} |
795 |
|
} |
796 |
|
exitVirtualDevicesLoop: |
797 |
|
virtualMidiDevicesReader_AudioThread.Unlock(); |
798 |
|
|
799 |
|
// import events from the regular MIDI devices |
800 |
RingBuffer<Event,false>::NonVolatileReader eventQueueReader = pEventQueue->get_non_volatile_reader(); |
RingBuffer<Event,false>::NonVolatileReader eventQueueReader = pEventQueue->get_non_volatile_reader(); |
801 |
Event* pEvent; |
Event* pEvent; |
802 |
while (true) { |
while (true) { |
842 |
if (pEngine) pEngine->Enable(); |
if (pEngine) pEngine->Enable(); |
843 |
} |
} |
844 |
|
|
845 |
|
void EngineChannel::Connect(VirtualMidiDevice* pDevice) { |
846 |
|
// double buffer ... double work ... |
847 |
|
{ |
848 |
|
ArrayList<VirtualMidiDevice*>& devices = virtualMidiDevices.GetConfigForUpdate(); |
849 |
|
devices.add(pDevice); |
850 |
|
} |
851 |
|
{ |
852 |
|
ArrayList<VirtualMidiDevice*>& devices = virtualMidiDevices.SwitchConfig(); |
853 |
|
devices.add(pDevice); |
854 |
|
} |
855 |
|
} |
856 |
|
|
857 |
|
void EngineChannel::Disconnect(VirtualMidiDevice* pDevice) { |
858 |
|
// double buffer ... double work ... |
859 |
|
{ |
860 |
|
ArrayList<VirtualMidiDevice*>& devices = virtualMidiDevices.GetConfigForUpdate(); |
861 |
|
devices.remove(pDevice); |
862 |
|
} |
863 |
|
{ |
864 |
|
ArrayList<VirtualMidiDevice*>& devices = virtualMidiDevices.SwitchConfig(); |
865 |
|
devices.remove(pDevice); |
866 |
|
} |
867 |
|
} |
868 |
|
|
869 |
float EngineChannel::Volume() { |
float EngineChannel::Volume() { |
870 |
return GlobalVolume; |
return GlobalVolume; |
871 |
} |
} |