/* Nord Modular Midi Protocol 3.03 Library Copyright (C) 2003-2006 Marcus Andersson This program 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 2 of the License, or (at your option) any later version. This program 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 this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package net.sf.nmedit.jnmprotocol; import net.sf.nmedit.jnmprotocol.AbstractNmProtocol; import net.sf.nmedit.jnmprotocol.EnqueuedPacket; import net.sf.nmedit.jnmprotocol.MidiException; import net.sf.nmedit.jnmprotocol.MidiMessage; import net.sf.nmedit.jpdl.BitStream; public class NmProtocol extends AbstractNmProtocol { // timeout interval in milliseconds private static final long TIMEOUT_INTERVAL = 3000; /* ms */ // timeout of the most current midi message // note: do not remove 'volatile', the variable has to be thread safe (see #getTimeout()) private volatile long timeout; public NmProtocol() { timeout = 0; } private static long time() { return System.currentTimeMillis(); } protected void heartbeatImpl() throws MidiException { // check for timeout if (timeout != 0 && time() > timeout) { clearSendQueue(); long rememberTimeout = timeout; timeout = 0; throw new MidiException("Communication timed out.", (int) rememberTimeout); } if (timeout == 0) { EnqueuedPacket packet = peekSendQueue(); if (packet != null) { send(packet); // Set up timer for expected reply message if (packet.expectsReply()) { timeout = time() + TIMEOUT_INTERVAL; } else { timeout = 0; removeFromSendQueue(); } } } byte[] receiveBytes = getReceivedBytes(); while (receiveBytes.length > 0) { MidiMessage midiMessage = MidiMessage.create(BitStream.wrap(receiveBytes)); if (midiMessage != null) { // Check if message is a reply if (midiMessage.isReply()) { if (!isSendQueueEmpty() && timeout != 0) { removeFromSendQueue(); timeout = 0; } } // enqeues the midi message in the event queue eventQueue_offer(midiMessage); } else if (timeout > 0) { // Resend last message, // as we always expect an answer we can parse send(peekSendQueue()); timeout = time() + TIMEOUT_INTERVAL; } receiveBytes = getReceivedBytes(); } // dispatches all events in the event queue dispatchEvents(); } protected long getTimeout() { long t = timeout; if (t>TIMEOUT_INTERVAL) t = TIMEOUT_INTERVAL; return t; } }