| 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 */  | 
 | 
 | 
 | 
package com.sun.media.sound;  | 
 | 
 | 
 | 
import java.util.ArrayList;  | 
 | 
import java.util.List;  | 
 | 
import java.util.Collections;  | 
 | 
 | 
 | 
import javax.sound.midi.*;  | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 */  | 
 | 
abstract class AbstractMidiDevice implements MidiDevice, ReferenceCountingDevice { | 
 | 
 | 
 | 
      | 
 | 
    private static final boolean TRACE_TRANSMITTER = false;  | 
 | 
 | 
 | 
    // INSTANCE VARIABLES  | 
 | 
 | 
 | 
    private ArrayList<Receiver> receiverList;  | 
 | 
 | 
 | 
    private TransmitterList transmitterList;  | 
 | 
 | 
 | 
    // lock to protect receiverList and transmitterList  | 
 | 
    // from simultaneous creation and destruction  | 
 | 
    // reduces possibility of deadlock, compared to  | 
 | 
      | 
 | 
    private final Object traRecLock = new Object();  | 
 | 
 | 
 | 
    // DEVICE ATTRIBUTES  | 
 | 
 | 
 | 
    private final MidiDevice.Info info;  | 
 | 
 | 
 | 
 | 
 | 
    // DEVICE STATE  | 
 | 
 | 
 | 
    private volatile boolean open;  | 
 | 
    private int openRefCount;  | 
 | 
 | 
 | 
      | 
 | 
     */  | 
 | 
    private List openKeepingObjects;  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
     */  | 
 | 
    protected volatile long id;  | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
    // CONSTRUCTOR  | 
 | 
 | 
 | 
 | 
 | 
    /**  | 
 | 
     * Constructs an AbstractMidiDevice with the specified info object.  | 
 | 
     * @param info the description of the device  | 
 | 
     */  | 
 | 
      | 
 | 
 | 
 | 
     */  | 
 | 
    protected AbstractMidiDevice(MidiDevice.Info info) { | 
 | 
 | 
 | 
        if(Printer.trace) Printer.trace(">> AbstractMidiDevice CONSTRUCTOR"); | 
 | 
 | 
 | 
        this.info = info;  | 
 | 
        openRefCount = 0;  | 
 | 
 | 
 | 
        if(Printer.trace) Printer.trace("<< AbstractMidiDevice CONSTRUCTOR completed"); | 
 | 
    }  | 
 | 
 | 
 | 
 | 
 | 
    // MIDI DEVICE METHODS  | 
 | 
 | 
 | 
    public final MidiDevice.Info getDeviceInfo() { | 
 | 
        return info;  | 
 | 
    }  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    public final void open() throws MidiUnavailableException { | 
 | 
        if (Printer.trace) Printer.trace("> AbstractMidiDevice: open()"); | 
 | 
        synchronized(this) { | 
 | 
            openRefCount = -1;  | 
 | 
            doOpen();  | 
 | 
        }  | 
 | 
        if (Printer.trace) Printer.trace("< AbstractMidiDevice: open() completed"); | 
 | 
    }  | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    private void openInternal(Object object) throws MidiUnavailableException { | 
 | 
        if (Printer.trace) Printer.trace("> AbstractMidiDevice: openInternal()"); | 
 | 
        synchronized(this) { | 
 | 
            if (openRefCount != -1) { | 
 | 
                openRefCount++;  | 
 | 
                getOpenKeepingObjects().add(object);  | 
 | 
            }  | 
 | 
              | 
 | 
            doOpen();  | 
 | 
        }  | 
 | 
        if (Printer.trace) Printer.trace("< AbstractMidiDevice: openInternal() completed"); | 
 | 
    }  | 
 | 
 | 
 | 
 | 
 | 
    private void doOpen() throws MidiUnavailableException { | 
 | 
        if (Printer.trace) Printer.trace("> AbstractMidiDevice: doOpen()"); | 
 | 
        synchronized(this) { | 
 | 
            if (! isOpen()) { | 
 | 
                implOpen();  | 
 | 
                open = true;  | 
 | 
            }  | 
 | 
        }  | 
 | 
        if (Printer.trace) Printer.trace("< AbstractMidiDevice: doOpen() completed"); | 
 | 
    }  | 
 | 
 | 
 | 
 | 
 | 
    public final void close() { | 
 | 
        if (Printer.trace) Printer.trace("> AbstractMidiDevice: close()"); | 
 | 
        synchronized (this) { | 
 | 
            doClose();  | 
 | 
            openRefCount = 0;  | 
 | 
        }  | 
 | 
        if (Printer.trace) Printer.trace("< AbstractMidiDevice: close() completed"); | 
 | 
    }  | 
 | 
 | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    public final void closeInternal(Object object) { | 
 | 
        if (Printer.trace) Printer.trace("> AbstractMidiDevice: closeInternal()"); | 
 | 
        synchronized(this) { | 
 | 
            if (getOpenKeepingObjects().remove(object)) { | 
 | 
                if (openRefCount > 0) { | 
 | 
                    openRefCount--;  | 
 | 
                    if (openRefCount == 0) { | 
 | 
                        doClose();  | 
 | 
                    }  | 
 | 
                }  | 
 | 
            }  | 
 | 
        }  | 
 | 
        if (Printer.trace) Printer.trace("< AbstractMidiDevice: closeInternal() completed"); | 
 | 
    }  | 
 | 
 | 
 | 
 | 
 | 
    public final void doClose() { | 
 | 
        if (Printer.trace) Printer.trace("> AbstractMidiDevice: doClose()"); | 
 | 
        synchronized(this) { | 
 | 
            if (isOpen()) { | 
 | 
                implClose();  | 
 | 
                open = false;  | 
 | 
            }  | 
 | 
        }  | 
 | 
        if (Printer.trace) Printer.trace("< AbstractMidiDevice: doClose() completed"); | 
 | 
    }  | 
 | 
 | 
 | 
 | 
 | 
    public final boolean isOpen() { | 
 | 
        return open;  | 
 | 
    }  | 
 | 
 | 
 | 
 | 
 | 
    protected void implClose() { | 
 | 
        synchronized (traRecLock) { | 
 | 
            if (receiverList != null) { | 
 | 
                  | 
 | 
                for(int i = 0; i < receiverList.size(); i++) { | 
 | 
                    receiverList.get(i).close();  | 
 | 
                }  | 
 | 
                receiverList.clear();  | 
 | 
            }  | 
 | 
            if (transmitterList != null) { | 
 | 
                  | 
 | 
                transmitterList.close();  | 
 | 
            }  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    public long getMicrosecondPosition() { | 
 | 
        return -1;  | 
 | 
    }  | 
 | 
 | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    public final int getMaxReceivers() { | 
 | 
        if (hasReceivers()) { | 
 | 
            return -1;  | 
 | 
        } else { | 
 | 
            return 0;  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    public final int getMaxTransmitters() { | 
 | 
        if (hasTransmitters()) { | 
 | 
            return -1;  | 
 | 
        } else { | 
 | 
            return 0;  | 
 | 
        }  | 
 | 
    }  | 
 | 
 | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    public final Receiver getReceiver() throws MidiUnavailableException { | 
 | 
        Receiver receiver;  | 
 | 
        synchronized (traRecLock) { | 
 | 
            receiver = createReceiver();   | 
 | 
            getReceiverList().add(receiver);  | 
 | 
        }  | 
 | 
        return receiver;  | 
 | 
    }  | 
 | 
 | 
 | 
 | 
 | 
    public final List<Receiver> getReceivers() { | 
 | 
        List<Receiver> recs;  | 
 | 
        synchronized (traRecLock) { | 
 | 
            if (receiverList == null) { | 
 | 
                recs = Collections.unmodifiableList(new ArrayList<Receiver>(0));  | 
 | 
            } else { | 
 | 
                recs = Collections.unmodifiableList  | 
 | 
                    ((List<Receiver>) (receiverList.clone()));  | 
 | 
            }  | 
 | 
        }  | 
 | 
        return recs;  | 
 | 
    }  | 
 | 
 | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    public final Transmitter getTransmitter() throws MidiUnavailableException { | 
 | 
        Transmitter transmitter;  | 
 | 
        synchronized (traRecLock) { | 
 | 
            transmitter = createTransmitter();   | 
 | 
            getTransmitterList().add(transmitter);  | 
 | 
        }  | 
 | 
        return transmitter;  | 
 | 
    }  | 
 | 
 | 
 | 
 | 
 | 
    public final List<Transmitter> getTransmitters() { | 
 | 
        List<Transmitter> tras;  | 
 | 
        synchronized (traRecLock) { | 
 | 
            if (transmitterList == null  | 
 | 
                || transmitterList.transmitters.size() == 0) { | 
 | 
                tras = Collections.unmodifiableList(new ArrayList<Transmitter>(0));  | 
 | 
            } else { | 
 | 
                tras = Collections.unmodifiableList((List<Transmitter>) (transmitterList.transmitters.clone()));  | 
 | 
            }  | 
 | 
        }  | 
 | 
        return tras;  | 
 | 
    }  | 
 | 
 | 
 | 
 | 
 | 
    // HELPER METHODS  | 
 | 
 | 
 | 
    final long getId() { | 
 | 
        return id;  | 
 | 
    }  | 
 | 
 | 
 | 
 | 
 | 
    // REFERENCE COUNTING  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
     */  | 
 | 
    public final Receiver getReceiverReferenceCounting()  | 
 | 
            throws MidiUnavailableException { | 
 | 
          | 
 | 
 | 
 | 
        */  | 
 | 
        Receiver receiver;  | 
 | 
        synchronized (traRecLock) { | 
 | 
            receiver = getReceiver();  | 
 | 
            AbstractMidiDevice.this.openInternal(receiver);  | 
 | 
        }  | 
 | 
        return receiver;  | 
 | 
    }  | 
 | 
 | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
     */  | 
 | 
    public final Transmitter getTransmitterReferenceCounting()  | 
 | 
            throws MidiUnavailableException { | 
 | 
          | 
 | 
 | 
 | 
        */  | 
 | 
        Transmitter transmitter;  | 
 | 
        synchronized (traRecLock) { | 
 | 
            transmitter = getTransmitter();  | 
 | 
            AbstractMidiDevice.this.openInternal(transmitter);  | 
 | 
        }  | 
 | 
        return transmitter;  | 
 | 
    }  | 
 | 
 | 
 | 
 | 
 | 
      | 
 | 
     */  | 
 | 
    private synchronized List getOpenKeepingObjects() { | 
 | 
        if (openKeepingObjects == null) { | 
 | 
            openKeepingObjects = new ArrayList();  | 
 | 
        }  | 
 | 
        return openKeepingObjects;  | 
 | 
    }  | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
    // RECEIVER HANDLING METHODS  | 
 | 
 | 
 | 
 | 
 | 
      | 
 | 
     */  | 
 | 
    private List<Receiver> getReceiverList() { | 
 | 
        synchronized (traRecLock) { | 
 | 
            if (receiverList == null) { | 
 | 
                receiverList = new ArrayList<Receiver>();  | 
 | 
            }  | 
 | 
        }  | 
 | 
        return receiverList;  | 
 | 
    }  | 
 | 
 | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
    */  | 
 | 
    protected boolean hasReceivers() { | 
 | 
        return false;  | 
 | 
    }  | 
 | 
 | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
    */  | 
 | 
    protected Receiver createReceiver() throws MidiUnavailableException { | 
 | 
        throw new MidiUnavailableException("MIDI IN receiver not available"); | 
 | 
    }  | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
    // TRANSMITTER HANDLING  | 
 | 
 | 
 | 
      | 
 | 
     */  | 
 | 
    final TransmitterList getTransmitterList() { | 
 | 
        synchronized (traRecLock) { | 
 | 
            if (transmitterList == null) { | 
 | 
                transmitterList = new TransmitterList();  | 
 | 
            }  | 
 | 
        }  | 
 | 
        return transmitterList;  | 
 | 
    }  | 
 | 
 | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
    */  | 
 | 
    protected boolean hasTransmitters() { | 
 | 
        return false;  | 
 | 
    }  | 
 | 
 | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
    */  | 
 | 
    protected Transmitter createTransmitter() throws MidiUnavailableException { | 
 | 
        throw new MidiUnavailableException("MIDI OUT transmitter not available"); | 
 | 
    }  | 
 | 
 | 
 | 
    // ABSTRACT METHODS  | 
 | 
 | 
 | 
    protected abstract void implOpen() throws MidiUnavailableException;  | 
 | 
 | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
     */  | 
 | 
    protected final void finalize() { | 
 | 
        close();  | 
 | 
    }  | 
 | 
 | 
 | 
    // INNER CLASSES  | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    abstract class AbstractReceiver implements MidiDeviceReceiver { | 
 | 
        private volatile boolean open = true;  | 
 | 
 | 
 | 
 | 
 | 
          | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
        */  | 
 | 
        @Override  | 
 | 
        public final synchronized void send(final MidiMessage message,  | 
 | 
                                            final long timeStamp) { | 
 | 
            if (!open) { | 
 | 
                throw new IllegalStateException("Receiver is not open"); | 
 | 
            }  | 
 | 
            implSend(message, timeStamp);  | 
 | 
        }  | 
 | 
 | 
 | 
        abstract void implSend(MidiMessage message, long timeStamp);  | 
 | 
 | 
 | 
          | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
         */  | 
 | 
        @Override  | 
 | 
        public final void close() { | 
 | 
            open = false;  | 
 | 
            synchronized (AbstractMidiDevice.this.traRecLock) { | 
 | 
                AbstractMidiDevice.this.getReceiverList().remove(this);  | 
 | 
            }  | 
 | 
            AbstractMidiDevice.this.closeInternal(this);  | 
 | 
        }  | 
 | 
 | 
 | 
        @Override  | 
 | 
        public final MidiDevice getMidiDevice() { | 
 | 
            return AbstractMidiDevice.this;  | 
 | 
        }  | 
 | 
 | 
 | 
        final boolean isOpen() { | 
 | 
            return open;  | 
 | 
        }  | 
 | 
 | 
 | 
        //$$fb is that a good idea?  | 
 | 
        //protected void finalize() { | 
 | 
        //    close();  | 
 | 
        //}  | 
 | 
 | 
 | 
    } // class AbstractReceiver  | 
 | 
 | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
     */  | 
 | 
    class BasicTransmitter implements MidiDeviceTransmitter { | 
 | 
 | 
 | 
        private Receiver receiver = null;  | 
 | 
        TransmitterList tlist = null;  | 
 | 
 | 
 | 
        protected BasicTransmitter() { | 
 | 
        }  | 
 | 
 | 
 | 
        private void setTransmitterList(TransmitterList tlist) { | 
 | 
            this.tlist = tlist;  | 
 | 
        }  | 
 | 
 | 
 | 
        public final void setReceiver(Receiver receiver) { | 
 | 
            if (tlist != null && this.receiver != receiver) { | 
 | 
                if (Printer.debug) Printer.debug("Transmitter "+toString()+": set receiver "+receiver); | 
 | 
                tlist.receiverChanged(this, this.receiver, receiver);  | 
 | 
                this.receiver = receiver;  | 
 | 
            }  | 
 | 
        }  | 
 | 
 | 
 | 
        public final Receiver getReceiver() { | 
 | 
            return receiver;  | 
 | 
        }  | 
 | 
 | 
 | 
 | 
 | 
          | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
         */  | 
 | 
        public final void close() { | 
 | 
            AbstractMidiDevice.this.closeInternal(this);  | 
 | 
            if (tlist != null) { | 
 | 
                tlist.receiverChanged(this, this.receiver, null);  | 
 | 
                tlist.remove(this);  | 
 | 
                tlist = null;  | 
 | 
            }  | 
 | 
        }  | 
 | 
 | 
 | 
        public final MidiDevice getMidiDevice() { | 
 | 
            return AbstractMidiDevice.this;  | 
 | 
        }  | 
 | 
 | 
 | 
    } // class BasicTransmitter  | 
 | 
 | 
 | 
 | 
 | 
      | 
 | 
 | 
 | 
     */  | 
 | 
    final class TransmitterList { | 
 | 
 | 
 | 
        private final ArrayList<Transmitter> transmitters = new ArrayList<Transmitter>();  | 
 | 
        private MidiOutDevice.MidiOutReceiver midiOutReceiver;  | 
 | 
 | 
 | 
        // how many transmitters must be present for optimized  | 
 | 
          | 
 | 
        private int optimizedReceiverCount = 0;  | 
 | 
 | 
 | 
 | 
 | 
        private void add(Transmitter t) { | 
 | 
            synchronized(transmitters) { | 
 | 
                transmitters.add(t);  | 
 | 
            }  | 
 | 
            if (t instanceof BasicTransmitter) { | 
 | 
                ((BasicTransmitter) t).setTransmitterList(this);  | 
 | 
            }  | 
 | 
            if (Printer.debug) Printer.debug("--added transmitter "+t); | 
 | 
        }  | 
 | 
 | 
 | 
        private void remove(Transmitter t) { | 
 | 
            synchronized(transmitters) { | 
 | 
                int index = transmitters.indexOf(t);  | 
 | 
                if (index >= 0) { | 
 | 
                    transmitters.remove(index);  | 
 | 
                    if (Printer.debug) Printer.debug("--removed transmitter "+t); | 
 | 
                }  | 
 | 
            }  | 
 | 
        }  | 
 | 
 | 
 | 
        private void receiverChanged(BasicTransmitter t,  | 
 | 
                                     Receiver oldR,  | 
 | 
                                     Receiver newR) { | 
 | 
            synchronized(transmitters) { | 
 | 
                  | 
 | 
                if (midiOutReceiver == oldR) { | 
 | 
                    midiOutReceiver = null;  | 
 | 
                }  | 
 | 
                if (newR != null) { | 
 | 
                    if ((newR instanceof MidiOutDevice.MidiOutReceiver)  | 
 | 
                        && (midiOutReceiver == null)) { | 
 | 
                        midiOutReceiver = ((MidiOutDevice.MidiOutReceiver) newR);  | 
 | 
                    }  | 
 | 
                }  | 
 | 
                optimizedReceiverCount =  | 
 | 
                      ((midiOutReceiver!=null)?1:0);  | 
 | 
            }  | 
 | 
            // more potential for optimization here  | 
 | 
        }  | 
 | 
 | 
 | 
 | 
 | 
          | 
 | 
        void close() { | 
 | 
            synchronized (transmitters) { | 
 | 
                for(int i = 0; i < transmitters.size(); i++) { | 
 | 
                    transmitters.get(i).close();  | 
 | 
                }  | 
 | 
                transmitters.clear();  | 
 | 
            }  | 
 | 
            if (Printer.trace) Printer.trace("TransmitterList.close() succeeded"); | 
 | 
        }  | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
          | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
 | 
        */  | 
 | 
        void sendMessage(int packedMessage, long timeStamp) { | 
 | 
            try { | 
 | 
                synchronized(transmitters) { | 
 | 
                    int size = transmitters.size();  | 
 | 
                    if (optimizedReceiverCount == size) { | 
 | 
                        if (midiOutReceiver != null) { | 
 | 
                            if (TRACE_TRANSMITTER) Printer.println("Sending packed message to MidiOutReceiver"); | 
 | 
                            midiOutReceiver.sendPackedMidiMessage(packedMessage, timeStamp);  | 
 | 
                        }  | 
 | 
                    } else { | 
 | 
                        if (TRACE_TRANSMITTER) Printer.println("Sending packed message to "+size+" transmitter's receivers"); | 
 | 
                        for (int i = 0; i < size; i++) { | 
 | 
                            Receiver receiver = ((Transmitter)transmitters.get(i)).getReceiver();  | 
 | 
                            if (receiver != null) { | 
 | 
                                if (optimizedReceiverCount > 0) { | 
 | 
                                    if (receiver instanceof MidiOutDevice.MidiOutReceiver) { | 
 | 
                                        ((MidiOutDevice.MidiOutReceiver) receiver).sendPackedMidiMessage(packedMessage, timeStamp);  | 
 | 
                                    } else { | 
 | 
                                        receiver.send(new FastShortMessage(packedMessage), timeStamp);  | 
 | 
                                    }  | 
 | 
                                } else { | 
 | 
                                    receiver.send(new FastShortMessage(packedMessage), timeStamp);  | 
 | 
                                }  | 
 | 
                            }  | 
 | 
                        }  | 
 | 
                    }  | 
 | 
                }  | 
 | 
            } catch (InvalidMidiDataException e) { | 
 | 
                // this happens when invalid data comes over the wire. Ignore it.  | 
 | 
            }  | 
 | 
        }  | 
 | 
 | 
 | 
        void sendMessage(byte[] data, long timeStamp) { | 
 | 
            try { | 
 | 
                synchronized(transmitters) { | 
 | 
                    int size = transmitters.size();  | 
 | 
                    if (TRACE_TRANSMITTER) Printer.println("Sending long message to "+size+" transmitter's receivers"); | 
 | 
                    for (int i = 0; i < size; i++) { | 
 | 
                        Receiver receiver = ((Transmitter)transmitters.get(i)).getReceiver();  | 
 | 
                        if (receiver != null) { | 
 | 
                            //$$fb 2002-04-02: SysexMessages are mutable, so  | 
 | 
                            // an application could change the contents of this object,  | 
 | 
                            // or try to use the object later. So we can't get around object creation  | 
 | 
                            // But the array need not be unique for each FastSysexMessage object,  | 
 | 
                              | 
 | 
                            receiver.send(new FastSysexMessage(data), timeStamp);  | 
 | 
                        }  | 
 | 
                    }  | 
 | 
                }  | 
 | 
            } catch (InvalidMidiDataException e) { | 
 | 
                  | 
 | 
                return;  | 
 | 
            }  | 
 | 
        }  | 
 | 
 | 
 | 
 | 
 | 
          | 
 | 
 | 
 | 
        */  | 
 | 
        void sendMessage(MidiMessage message, long timeStamp) { | 
 | 
            if (message instanceof FastShortMessage) { | 
 | 
                sendMessage(((FastShortMessage) message).getPackedMsg(), timeStamp);  | 
 | 
                return;  | 
 | 
            }  | 
 | 
            synchronized(transmitters) { | 
 | 
                int size = transmitters.size();  | 
 | 
                if (optimizedReceiverCount == size) { | 
 | 
                    if (midiOutReceiver != null) { | 
 | 
                        if (TRACE_TRANSMITTER) Printer.println("Sending MIDI message to MidiOutReceiver"); | 
 | 
                        midiOutReceiver.send(message, timeStamp);  | 
 | 
                    }  | 
 | 
                } else { | 
 | 
                    if (TRACE_TRANSMITTER) Printer.println("Sending MIDI message to "+size+" transmitter's receivers"); | 
 | 
                    for (int i = 0; i < size; i++) { | 
 | 
                        Receiver receiver = ((Transmitter)transmitters.get(i)).getReceiver();  | 
 | 
                        if (receiver != null) { | 
 | 
                            //$$fb 2002-04-02: ShortMessages are mutable, so  | 
 | 
                            // an application could change the contents of this object,  | 
 | 
                            // or try to use the object later.  | 
 | 
                            // We violate this spec here, to avoid costly (and gc-intensive)  | 
 | 
                            // object creation for potentially hundred of messages per second.  | 
 | 
                            // The spec should be changed to allow Immutable MidiMessages  | 
 | 
                              | 
 | 
                            receiver.send(message, timeStamp);  | 
 | 
                        }  | 
 | 
                    }  | 
 | 
                }  | 
 | 
            }  | 
 | 
        }  | 
 | 
 | 
 | 
 | 
 | 
    } // TransmitterList  | 
 | 
 | 
 | 
}  |