28 |
namespace LinuxSampler { namespace gig { |
namespace LinuxSampler { namespace gig { |
29 |
|
|
30 |
EngineChannel::EngineChannel() : |
EngineChannel::EngineChannel() : |
31 |
InstrumentChangeCommandReader(InstrumentChangeCommand) { |
InstrumentChangeCommandReader(InstrumentChangeCommand), |
32 |
|
virtualMidiDevicesReader(virtualMidiDevices) |
33 |
|
{ |
34 |
pMIDIKeyInfo = new midi_key_info_t[128]; |
pMIDIKeyInfo = new midi_key_info_t[128]; |
35 |
pEngine = NULL; |
pEngine = NULL; |
36 |
pInstrument = NULL; |
pInstrument = NULL; |
730 |
* current audio cycle |
* current audio cycle |
731 |
*/ |
*/ |
732 |
void EngineChannel::ImportEvents(uint Samples) { |
void EngineChannel::ImportEvents(uint Samples) { |
733 |
|
// import events from pure software MIDI "devices" |
734 |
|
// (e.g. virtual keyboard in instrument editor) |
735 |
|
{ |
736 |
|
const int FragmentPos = 0; // randomly chosen, we don't care about jitter for virtual MIDI devices |
737 |
|
Event event = pEngine->pEventGenerator->CreateEvent(FragmentPos); |
738 |
|
VirtualMidiDevice::event_t devEvent; // the event format we get from the virtual MIDI device |
739 |
|
// as we're going to (carefully) write some status to the |
740 |
|
// synchronized struct, we cast away the const |
741 |
|
ArrayList<VirtualMidiDevice*>& devices = |
742 |
|
const_cast<ArrayList<VirtualMidiDevice*>&>(virtualMidiDevicesReader.Lock()); |
743 |
|
// iterate through all virtual MIDI devices |
744 |
|
for (int i = 0; i < devices.size(); i++) { |
745 |
|
VirtualMidiDevice* pDev = devices[i]; |
746 |
|
// I think we can simply flush the whole FIFO(s), the user shouldn't be so fast ;-) |
747 |
|
while (pDev->GetMidiEventFromDevice(devEvent)) { |
748 |
|
event.Type = |
749 |
|
(devEvent.Type == VirtualMidiDevice::EVENT_TYPE_NOTEON) ? |
750 |
|
Event::type_note_on : Event::type_note_off; |
751 |
|
event.Param.Note.Key = devEvent.Key; |
752 |
|
event.Param.Note.Velocity = devEvent.Velocity; |
753 |
|
event.pEngineChannel = this; |
754 |
|
// copy event to internal event list |
755 |
|
if (pEvents->poolIsEmpty()) { |
756 |
|
dmsg(1,("Event pool emtpy!\n")); |
757 |
|
goto exitVirtualDevicesLoop; |
758 |
|
} |
759 |
|
*pEvents->allocAppend() = event; |
760 |
|
} |
761 |
|
} |
762 |
|
} |
763 |
|
exitVirtualDevicesLoop: |
764 |
|
virtualMidiDevicesReader.Unlock(); |
765 |
|
|
766 |
|
// import events from the regular MIDI devices |
767 |
RingBuffer<Event,false>::NonVolatileReader eventQueueReader = pEventQueue->get_non_volatile_reader(); |
RingBuffer<Event,false>::NonVolatileReader eventQueueReader = pEventQueue->get_non_volatile_reader(); |
768 |
Event* pEvent; |
Event* pEvent; |
769 |
while (true) { |
while (true) { |
809 |
if (pEngine) pEngine->Enable(); |
if (pEngine) pEngine->Enable(); |
810 |
} |
} |
811 |
|
|
812 |
|
void EngineChannel::Connect(VirtualMidiDevice* pDevice) { |
813 |
|
// double buffer ... double work ... |
814 |
|
{ |
815 |
|
ArrayList<VirtualMidiDevice*>& devices = virtualMidiDevices.GetConfigForUpdate(); |
816 |
|
devices.add(pDevice); |
817 |
|
} |
818 |
|
{ |
819 |
|
ArrayList<VirtualMidiDevice*>& devices = virtualMidiDevices.SwitchConfig(); |
820 |
|
devices.add(pDevice); |
821 |
|
} |
822 |
|
} |
823 |
|
|
824 |
|
void EngineChannel::Disconnect(VirtualMidiDevice* pDevice) { |
825 |
|
// double buffer ... double work ... |
826 |
|
{ |
827 |
|
ArrayList<VirtualMidiDevice*>& devices = virtualMidiDevices.GetConfigForUpdate(); |
828 |
|
devices.remove(pDevice); |
829 |
|
} |
830 |
|
{ |
831 |
|
ArrayList<VirtualMidiDevice*>& devices = virtualMidiDevices.SwitchConfig(); |
832 |
|
devices.remove(pDevice); |
833 |
|
} |
834 |
|
} |
835 |
|
|
836 |
float EngineChannel::Volume() { |
float EngineChannel::Volume() { |
837 |
return GlobalVolume; |
return GlobalVolume; |
838 |
} |
} |