/** * This file is part of EWItool. * * EWItool is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * EWItool is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with EWItool. If not, see <http://www.gnu.org/licenses/>. */ /** * @author S.Merrony * * v.2.0 Add check for null MIDI message/type and empty SysEx */ package ewitool; import java.util.concurrent.BlockingQueue; import javax.sound.midi.InvalidMidiDataException; import javax.sound.midi.MidiDevice; import javax.sound.midi.MidiUnavailableException; import javax.sound.midi.Receiver; import javax.sound.midi.ShortMessage; import javax.sound.midi.SysexMessage; import ewitool.SendMsg.MidiMsgType; public class MidiSender implements Runnable { SharedData sharedData; BlockingQueue<SendMsg> msgQ; MidiDevice outDev; Receiver receiver; MidiMonitorMessage mmsg; private final static long NOW = -1; MidiSender( SharedData pSharedData, MidiDevice pOutDev ) { sharedData = pSharedData; msgQ = pSharedData.sendQ; outDev = pOutDev; if (!outDev.isOpen()) { System.err.println( "Error - MidiSender() called with non-open MIDI Device" ); System.exit( 1 ); } try { receiver = outDev.getReceiver(); } catch (MidiUnavailableException e) { e.printStackTrace(); System.err.println( "Error - MidiSender() could not obtain chosen MIDI OUT receiver" ); System.exit( 1 ); } mmsg = new MidiMonitorMessage(); mmsg.direction = MidiMonitorMessage.MidiDirection.SENT; } @Override public void run() { SendMsg msg; try { while (true) { msg = msgQ.take(); if (!outDev.isOpen()) { System.err.println( "Error - MidiSender: MIDI Out device is not open" ); System.exit( 1 ); } if (msg != null && msg.msgType != null) { switch ( msg.msgType ) { case CC: try { ShortMessage sm = new ShortMessage( ShortMessage.CONTROL_CHANGE, msg.cc, msg.value ); receiver.send( sm, NOW ); if (sharedData.getMidiMonitoring()) { mmsg.type = MidiMsgType.CC; mmsg.bytes = sm.getMessage(); sharedData.monitorQ.add( mmsg ); } } catch (InvalidMidiDataException e) { e.printStackTrace(); } break; case SYSEX: try { Debugger.log( "DBEUG - MidiSender thread got SysEx to send. Length: " + msg.bytes.length ); if (msg.bytes.length == 0 || msg.bytes[0] != MidiHandler.MIDI_SYSEX_HEADER) { System.err.println( "Error - MidiSender received invalid SysEx send request" ); System.exit( 1 ); } SysexMessage sysEx = new SysexMessage( msg.bytes, msg.bytes.length ); receiver.send( sysEx, NOW ); if (sharedData.getMidiMonitoring()) { mmsg.type = MidiMsgType.SYSEX; mmsg.bytes = sysEx.getMessage(); sharedData.monitorQ.add( mmsg ); } // N.B. The final Qt version had a SLEEP(250) here try { switch ( msg.delay ) { case LONG: Debugger.log( "DEBUG - MidiSender: Long pause after SysEx" ); Thread.sleep( MidiHandler.MIDI_MESSAGE_LONG_PAUSE_MS ); break; case NONE: Debugger.log( "DEBUG - MidiSender: No pause after SysEx" ); break; case SHORT: Debugger.log( "DEBUG - MidiSender: Short pause after SysEx" ); Thread.sleep( MidiHandler.MIDI_MESSAGE_SHORT_PAUSE_MS ); break; default: System.err.println( "ERROR - MidiSender: INVALID pause after SysEx" ); break; } } catch (InterruptedException e) { e.printStackTrace(); } } catch (InvalidMidiDataException e) { e.printStackTrace(); } break; case SYSTEM_RESET: try { Debugger.log( "DEBUG - MidiSender sending System Reset to EWI" ); ShortMessage sm = new ShortMessage( ShortMessage.SYSTEM_RESET ); receiver.send( sm, NOW ); } catch (InvalidMidiDataException e) { e.printStackTrace(); } try { Thread.sleep( MidiHandler.MIDI_MESSAGE_LONG_PAUSE_MS ); } catch (InterruptedException e) { e.printStackTrace(); } break; } } } } catch( InterruptedException e ) { Debugger.log( "DEBUG - MidiSender closing" ); receiver.close(); outDev.close(); } } }