/* 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.jnmprotocol2.utils; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import javax.sound.midi.MidiDevice; import javax.sound.midi.MidiSystem; import javax.sound.midi.MidiUnavailableException; import javax.sound.midi.Sequencer; import javax.sound.midi.Synthesizer; import net.sf.nmedit.jnmprotocol2.IAmMessage; import net.sf.nmedit.jnmprotocol2.MessageHandler; import net.sf.nmedit.jnmprotocol2.MidiDriver; import net.sf.nmedit.jnmprotocol2.MidiMessage; import net.sf.nmedit.jnmprotocol2.NmProtocol; public class NmLookup { public static void main(String[] args) { MidiDevice.Info[] devices = lookup(getHardwareDevices(), 0, 600); if (devices.length>0) { System.out.println("Nord Modular detected at "); int index = 1; for (int i=0;i<devices.length;i+=2) { System.out.println(index+":"+toString(devices[i])); System.out.println(index+":"+toString(devices[i+1])); index++; } } else { System.out.println("Nord Modular not detected."); } } private static String toString(MidiDevice.Info info) { return info.getName()+" "+info.getVendor()+" "+info.getDescription() +" "+info.getVersion(); } private static boolean isAvailable(int max) { return max == -1 || max > 0; } public static MidiDevice.Info[] lookup(MidiDevice.Info[] devices, int maxDevices, long timeout) { List<MidiDevice.Info> receiverList = new ArrayList<MidiDevice.Info>(devices.length); List<MidiDevice.Info> transmitterList = new ArrayList<MidiDevice.Info>(devices.length); for (int i=0;i<devices.length;i++) { try { MidiDevice dev = MidiSystem.getMidiDevice(devices[i]); if (isAvailable(dev.getMaxReceivers())) receiverList.add(devices[i]); if (isAvailable(dev.getMaxTransmitters())) transmitterList.add(devices[i]); } catch (MidiUnavailableException e) { // ignore device } } if (receiverList.isEmpty() || transmitterList.isEmpty()) return new MidiDevice.Info[0]; // no devices Iterator<MidiDevice.Info> iterR = receiverList.iterator(); Iterator<MidiDevice.Info> iterT = transmitterList.iterator(); MidiDevice.Info receiver = iterR.next(); MidiDevice.Info transmitter = iterT.next(); int index = 1; System.out.println("looking up nord modular:"); while (maxDevices > 0 || maxDevices <= 0) { MidiDriver driver = new MidiDriver(transmitter, receiver); try { System.out.println(index+":in :"+toString(transmitter)); System.out.println(index+":out:"+toString(receiver)); if (isNordModular(driver, timeout)) { System.out.println(index+":found"); maxDevices --; return new MidiDevice.Info[] {transmitter, receiver}; } else { System.out.println(index+":not found"); } index ++; } catch (Exception e) { e.printStackTrace(); } if (!iterT.hasNext()) { iterT = transmitterList.iterator(); if (iterR.hasNext()) receiver = iterR.next(); else break; } transmitter = iterT.next(); } return new MidiDevice.Info[0]; // no devices } public static boolean isNordModular(MidiDriver driver, long timeout) throws Exception { boolean doDisconnect = false; if (!driver.isConnected()) { driver.connect(); doDisconnect = true; } NmProtocol protocol = new NmProtocol(); IAmAcceptor acceptor = new IAmAcceptor(); protocol.setMessageHandler(acceptor); protocol.getTransmitter().setReceiver(driver.getReceiver()); driver.getTransmitter().setReceiver(protocol.getReceiver()); try { protocol.send(new IAmMessage()); long time = System.currentTimeMillis(); while (timeout>0) { protocol.heartbeat(); if (!acceptor.isAccepted()) { protocol.waitForActivity(timeout); long t = System.currentTimeMillis()-time; timeout-=t; time = System.currentTimeMillis(); } else { break; } } } finally { if (doDisconnect) driver.disconnect(); } return acceptor.isAccepted(); } private static boolean available(int count) { return count == -1 || count > 0; } public static MidiDevice.Info[] getMidiDevicePair() throws MidiUnavailableException { // return MidiSystem.getMidiDeviceInfo(); MidiDevice.Info[] pair = new MidiDevice.Info[] { getFirstInputDevice(), getFirstOutputDevice() }; return pair; } public static MidiDevice.Info getFirstInputDevice() throws MidiUnavailableException { MidiDevice.Info[] hwlist = getHardwareDevices(); for (int i=0;i<hwlist.length;i++) { MidiDevice.Info info = hwlist[i]; MidiDevice device = MidiSystem.getMidiDevice(info); if (available(device.getMaxTransmitters())) return info; } return null; } public static MidiDevice.Info getFirstOutputDevice() throws MidiUnavailableException { MidiDevice.Info[] hwlist = getHardwareDevices(); for (int i=0;i<hwlist.length;i++) { MidiDevice.Info info = hwlist[i]; MidiDevice device = MidiSystem.getMidiDevice(info); if (available(device.getMaxReceivers())) return info; } return null; } public static MidiDevice.Info[] getHardwareDevices() { MidiDevice.Info[] infoList = MidiSystem.getMidiDeviceInfo(); List<MidiDevice.Info> hwList = new ArrayList<MidiDevice.Info>(); for (int i=0;i<infoList.length;i++) { MidiDevice.Info candidateInfo = infoList[i]; try { MidiDevice candidate = MidiSystem.getMidiDevice(candidateInfo); if (isHardwareDevice(candidate)) hwList.add(candidateInfo); } catch (MidiUnavailableException e) { // ignore } } return hwList.toArray(new MidiDevice.Info[hwList.size()]); } public static boolean isHardwareDevice( MidiDevice dev ) { return !(dev instanceof Sequencer || dev instanceof Synthesizer); } private static class IAmAcceptor implements MessageHandler { private boolean accepted = false; public synchronized void processMessage( MidiMessage message ) { accepted |= (message instanceof IAmMessage); } public synchronized boolean isAccepted() { return accepted; } } }