728 |
{ |
{ |
729 |
const uint8_t channel = MidiChannel() == midi_chan_all ? 0 : MidiChannel(); |
const uint8_t channel = MidiChannel() == midi_chan_all ? 0 : MidiChannel(); |
730 |
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 |
731 |
Event event = pEngine->pEventGenerator->CreateEvent(FragmentPos); |
const Event event = pEngine->pEventGenerator->CreateEvent(FragmentPos); |
732 |
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 |
733 |
// as we're going to (carefully) write some status to the |
// as we're going to (carefully) write some status to the |
734 |
// synchronized struct, we cast away the const |
// synchronized struct, we cast away the const |
739 |
VirtualMidiDevice* pDev = devices[i]; |
VirtualMidiDevice* pDev = devices[i]; |
740 |
// I think we can simply flush the whole FIFO(s), the user shouldn't be so fast ;-) |
// I think we can simply flush the whole FIFO(s), the user shouldn't be so fast ;-) |
741 |
while (pDev->GetMidiEventFromDevice(devEvent)) { |
while (pDev->GetMidiEventFromDevice(devEvent)) { |
742 |
|
if (pEvents->poolIsEmpty()) { |
743 |
|
dmsg(1,("Event pool emtpy!\n")); |
744 |
|
goto exitVirtualDevicesLoop; |
745 |
|
} |
746 |
|
|
747 |
|
// copy event to internal event list (this is already |
748 |
|
// required here, because the LaunchNewNote() call below |
749 |
|
// requires the event to be from the internal event pool for |
750 |
|
// being able to generate a valid event ID) |
751 |
|
RTList<Event>::Iterator itEvent = pEvents->allocAppend(); |
752 |
|
*itEvent = event; |
753 |
|
|
754 |
|
itEvent->pEngineChannel = this; |
755 |
|
|
756 |
switch (devEvent.Type) { |
switch (devEvent.Type) { |
757 |
case VirtualMidiDevice::EVENT_TYPE_NOTEON: |
case VirtualMidiDevice::EVENT_TYPE_NOTEON: |
758 |
event.Type = Event::type_note_on; |
itEvent->Type = Event::type_note_on; |
759 |
event.Param.Note.Key = devEvent.Arg1; |
itEvent->Param.Note.Key = devEvent.Arg1; |
760 |
event.Param.Note.Velocity = devEvent.Arg2; |
itEvent->Param.Note.Velocity = devEvent.Arg2; |
761 |
event.Param.Note.Channel = channel; |
itEvent->Param.Note.Channel = channel; |
762 |
// apply transpose setting to (note on/off) event |
// apply transpose setting to (note on/off) event |
763 |
if (!applyTranspose(&event)) |
if (!applyTranspose(&*itEvent)) { |
764 |
continue; // note value is out of range, so drop this event |
// note value is out of range, so drop this event |
765 |
|
pEvents->free(itEvent); |
766 |
|
continue; |
767 |
|
} |
768 |
// assign a new note to this note-on event |
// assign a new note to this note-on event |
769 |
if (!pEngine->LaunchNewNote(this, &event)) |
if (!pEngine->LaunchNewNote(this, itEvent)) { |
770 |
continue; // failed launching new note, so drop this event |
// failed launching new note, so drop this event |
771 |
|
pEvents->free(itEvent); |
772 |
|
continue; |
773 |
|
} |
774 |
break; |
break; |
775 |
case VirtualMidiDevice::EVENT_TYPE_NOTEOFF: |
case VirtualMidiDevice::EVENT_TYPE_NOTEOFF: |
776 |
event.Type = Event::type_note_off; |
itEvent->Type = Event::type_note_off; |
777 |
event.Param.Note.Key = devEvent.Arg1; |
itEvent->Param.Note.Key = devEvent.Arg1; |
778 |
event.Param.Note.Velocity = devEvent.Arg2; |
itEvent->Param.Note.Velocity = devEvent.Arg2; |
779 |
event.Param.Note.Channel = channel; |
itEvent->Param.Note.Channel = channel; |
780 |
if (!applyTranspose(&event)) |
if (!applyTranspose(&*itEvent)) { |
781 |
continue; // note value is out of range, so drop this event |
// note value is out of range, so drop this event |
782 |
|
pEvents->free(itEvent); |
783 |
|
continue; |
784 |
|
} |
785 |
break; |
break; |
786 |
case VirtualMidiDevice::EVENT_TYPE_CC: |
case VirtualMidiDevice::EVENT_TYPE_CC: |
787 |
switch (devEvent.Arg1) { |
switch (devEvent.Arg1) { |
788 |
case 0: // bank select MSB ... |
case 0: // bank select MSB ... |
789 |
SetMidiBankMsb(devEvent.Arg2); |
SetMidiBankMsb(devEvent.Arg2); |
790 |
continue; // don't push this event into FIFO |
// don't push this event into FIFO |
791 |
|
pEvents->free(itEvent); |
792 |
|
continue; |
793 |
case 32: // bank select LSB ... |
case 32: // bank select LSB ... |
794 |
SetMidiBankLsb(devEvent.Arg2); |
SetMidiBankLsb(devEvent.Arg2); |
795 |
continue; // don't push this event into FIFO |
// don't push this event into FIFO |
796 |
|
pEvents->free(itEvent); |
797 |
|
continue; |
798 |
default: // regular MIDI CC ... |
default: // regular MIDI CC ... |
799 |
event.Type = Event::type_control_change; |
itEvent->Type = Event::type_control_change; |
800 |
event.Param.CC.Controller = devEvent.Arg1; |
itEvent->Param.CC.Controller = devEvent.Arg1; |
801 |
event.Param.CC.Value = devEvent.Arg2; |
itEvent->Param.CC.Value = devEvent.Arg2; |
802 |
event.Param.CC.Channel = channel; |
itEvent->Param.CC.Channel = channel; |
803 |
} |
} |
804 |
break; |
break; |
805 |
case VirtualMidiDevice::EVENT_TYPE_PITCHBEND: |
case VirtualMidiDevice::EVENT_TYPE_PITCHBEND: |
806 |
event.Type = Event::type_pitchbend; |
itEvent->Type = Event::type_pitchbend; |
807 |
event.Param.Pitch.Pitch = int(devEvent.Arg2 << 7 | devEvent.Arg1) - 8192; |
itEvent->Param.Pitch.Pitch = int(devEvent.Arg2 << 7 | devEvent.Arg1) - 8192; |
808 |
event.Param.Pitch.Channel = channel; |
itEvent->Param.Pitch.Channel = channel; |
809 |
break; |
break; |
810 |
case VirtualMidiDevice::EVENT_TYPE_PROGRAM: |
case VirtualMidiDevice::EVENT_TYPE_PROGRAM: |
811 |
SendProgramChange(devEvent.Arg1); |
SendProgramChange(devEvent.Arg1); |
812 |
continue; // don't push this event into FIFO |
// don't push this event into FIFO |
813 |
|
pEvents->free(itEvent); |
814 |
|
continue; |
815 |
case VirtualMidiDevice::EVENT_TYPE_CHPRESSURE: |
case VirtualMidiDevice::EVENT_TYPE_CHPRESSURE: |
816 |
event.Type = Event::type_channel_pressure; |
itEvent->Type = Event::type_channel_pressure; |
817 |
event.Param.ChannelPressure.Controller = CTRL_TABLE_IDX_AFTERTOUCH; |
itEvent->Param.ChannelPressure.Controller = CTRL_TABLE_IDX_AFTERTOUCH; |
818 |
event.Param.ChannelPressure.Value = devEvent.Arg2; |
itEvent->Param.ChannelPressure.Value = devEvent.Arg2; |
819 |
event.Param.ChannelPressure.Channel = channel; |
itEvent->Param.ChannelPressure.Channel = channel; |
820 |
break; |
break; |
821 |
default: |
default: |
822 |
std::cerr << "AbstractEngineChannel::ImportEvents() ERROR: unknown event type (" |
std::cerr << "AbstractEngineChannel::ImportEvents() ERROR: unknown event type (" |
823 |
<< devEvent.Type << "). This is a bug!"; |
<< devEvent.Type << "). This is a bug!"; |
824 |
|
pEvents->free(itEvent); // drop event |
825 |
continue; |
continue; |
826 |
} |
} |
|
event.pEngineChannel = this; |
|
|
// copy event to internal event list |
|
|
if (pEvents->poolIsEmpty()) { |
|
|
dmsg(1,("Event pool emtpy!\n")); |
|
|
goto exitVirtualDevicesLoop; |
|
|
} |
|
|
*pEvents->allocAppend() = event; |
|
827 |
} |
} |
828 |
} |
} |
829 |
} |
} |
847 |
dmsg(1,("Event pool emtpy!\n")); |
dmsg(1,("Event pool emtpy!\n")); |
848 |
break; |
break; |
849 |
} |
} |
850 |
|
|
851 |
|
// copy event to internal event list |
852 |
|
// (required already because LaunchNewNote() relies on it, see |
853 |
|
// comment about it above) |
854 |
|
RTList<Event>::Iterator itEvent = pEvents->allocAppend(); |
855 |
|
*itEvent = *pEvent; |
856 |
|
|
857 |
// apply transpose setting to (note on/off) event |
// apply transpose setting to (note on/off) event |
858 |
if (!applyTranspose(pEvent)) |
if (!applyTranspose(&*itEvent)) { |
859 |
continue; // it's a note event which has a note value out of range, so drop this event |
// it's a note event which has a note value out of range, so drop this event |
860 |
|
pEvents->free(itEvent); |
861 |
|
continue; |
862 |
|
} |
863 |
// assign a new note to this event (if its a note-on event) |
// assign a new note to this event (if its a note-on event) |
864 |
if (pEvent->Type == Event::type_note_on) |
if (itEvent->Type == Event::type_note_on) { |
865 |
if (!pEngine->LaunchNewNote(this, pEvent)) |
if (!pEngine->LaunchNewNote(this, itEvent)) { |
866 |
continue; // failed launching new note, so drop this event |
// failed launching new note, so drop this event |
867 |
// copy event to internal event list |
pEvents->free(itEvent); |
868 |
*pEvents->allocAppend() = *pEvent; |
continue; |
869 |
|
} |
870 |
|
} |
871 |
|
|
872 |
} |
} |
873 |
eventQueueReader.free(); // free all copied events from input queue |
eventQueueReader.free(); // free all copied events from input queue |
874 |
} |
} |