package net.sf.nmedit.jnmprotocol; import java.util.Iterator; import javax.sound.midi.MidiDevice; import javax.sound.midi.MidiSystem; import junit.framework.Assert; import junit.framework.TestCase; import net.sf.nmedit.jnmprotocol.helper.GetPatchMessageReplyAcceptor; import net.sf.nmedit.jnmprotocol.utils.NmLookup; import net.sf.nmedit.jpdl.BitStream; public class ProtocolTester extends TestCase { static private int pid0; MidiDevice.Info[] nmDevice = new MidiDevice.Info[0]; static MidiDriver nmDriver = null; protected void setUp() { if (nmDriver != null) return; nmDevice = NmLookup.lookup(NmLookup.getHardwareDevices(), 1, 1000 /* 1 second timeout for each midi device pair*/ ); if (nmDevice.length != 2) throw new RuntimeException("Nord Modular device not available"); nmDriver = new MidiDriver(nmDevice[0], nmDevice[1]); } private NmProtocol createProtocol(MidiDriver driver, MessageHandler messageHandler) { return configureProtocol(new NmProtocol(), driver, messageHandler); } private NmProtocol configureProtocol(NmProtocol protocol, MidiDriver driver, MessageHandler messageHandler) { protocol.getTransmitter().setReceiver(driver.getReceiver()); driver.getTransmitter().setReceiver(protocol.getReceiver()); protocol.setMessageHandler(messageHandler); return protocol; } public void testMidiDriver() throws Exception { MidiDevice.Info[] info = MidiSystem.getMidiDeviceInfo(); System.out.println(""); System.out.println("MIDI devices:"); for (int i = 0; i < info.length; i++) { System.out.println(info[i].getName() + " " + info[i].getDescription() + " " + info[i].getVendor()); System.out.println("Receivers: " + MidiSystem.getMidiDevice(info[i]).getMaxReceivers()); System.out.println("Transmitters: " + MidiSystem.getMidiDevice(info[i]).getMaxTransmitters()); } nmDriver.connect(); try { /* for (int i = 0; i < 10; i++) { System.out.print("" + i + ":"); byte[] data = md.receive(); for (int j = 0; j < data.length; j++) { System.out.print(" " + data[j]); } System.out.println(""); Thread.sleep(100); } */ } finally { nmDriver.disconnect(); } } public void testNewModuleMessage() throws Exception { int[] correctEncoding = { 0xf0, 0x33, 0x7c, 0x06, 0x05, 0x18, 0x01, 0x60, 0x10, 0x50, 0x08, 0x12, 0x4f, 0x39, 0x58, 0x68, 0x13, 0x10, 0x01, 0x25, 0x00, 0x00, 0x13, 0x30, 0x11, 0x20, 0x78, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x5b, 0x40, 0x45, 0x00, 0x20, 0x02, 0x6a, 0x02, 0x0a, 0x27, 0x5c, 0x6c, 0x34, 0x09, 0x48, 0x00, 0x1e, 0xf7 }; //NewModuleMessage.usePdlFile("/patch.pdl", new TestTracer()); //MidiMessage.usePdlFile("/midi.pdl", new TestTracer()); NewModuleMessage nm = new NewModuleMessage(); nm.set("pid", 5); BitStream bitStream = null; try { int[] parameterValues = {64, 64, 64, 64, 0, 0, 0, 0, 0, 0}; int[] customValues = {0}; nm.newModule(7, 1, 10, 2, 9, "OscA2", parameterValues, customValues); bitStream = (BitStream)nm.getBitStream().get(0); } catch(Exception e) { e.printStackTrace(); } int n = 0; System.out.println("Size: " + bitStream.getSize()); while (bitStream.isAvailable(8)) { int data = bitStream.getInt(8); //System.out.println(" " + data + " " + correctEncoding[n]); Assert.assertEquals(data, correctEncoding[n]); n++; } } public void testNoParameterNewModuleMessage() throws Exception { //NewModuleMessage.usePdlFile("/patch.pdl", new TestTracer()); //MidiMessage.usePdlFile("/midi.pdl", new TestTracer()); NewModuleMessage nm = new NewModuleMessage(); nm.set("pid", 5); BitStream bitStream = null; try { int[] parameterValues = {}; int[] customValues = {}; nm.newModule(1, 1, 9, 0, 28, "Some1", parameterValues, customValues); bitStream = (BitStream)nm.getBitStream().get(0); } catch(Exception e) { e.printStackTrace(); } int n = 0; System.out.println("Size: " + bitStream.getSize()); while (bitStream.isAvailable(8)) { int data = bitStream.getInt(8); //System.out.println(" " + data + " " + correctEncoding[n]); n++; } } public void testProtocol() throws Exception { try { nmDriver.connect(); MessageMulticaster multicaster = new MessageMulticaster(); NmProtocol p = createProtocol(nmDriver, multicaster); multicaster.addProtocolListener(new Listener(p, multicaster)); p.send(new IAmMessage()); p.send(new RequestPatchMessage()); int n = 0; while(n < 100) { n++; p.heartbeat(); Thread.sleep(10); } pid0 = multicaster.getActivePid(0); } catch (MidiException me) { me.printStackTrace(); System.out.println("" + me.getError()); } catch (Throwable e) { e.printStackTrace(); } finally { nmDriver.disconnect(); } } public void testModuleMessages() throws Exception { System.out.println("testModuleMessages: " + pid0); try { nmDriver.connect(); MessageMulticaster multicaster = new MessageMulticaster(); NmProtocol p = createProtocol(nmDriver, multicaster); //MidiMessage.usePdlFile("/midi.pdl", new TestTracer()); multicaster.addProtocolListener(new Listener(p, multicaster)); MoveModuleMessage mm = new MoveModuleMessage(); mm.set("pid", pid0); mm.moveModule(1, 10, 40, 40); p.send(mm); DeleteModuleMessage dm = new DeleteModuleMessage(); dm.set("pid", pid0); dm.deleteModule(1, 10); p.send(dm); int n = 0; NewModuleMessage nm = new NewModuleMessage(); nm.set("pid", pid0); int[] parameterValues = {64, 64, 64, 64, 0, 0, 0, 0, 0, 0}; int[] customValues = {0}; nm.newModule(7, 1, 10, 2, 90, "OscA2", parameterValues, customValues); p.send(nm); NewModuleMessage nm2 = new NewModuleMessage(); nm2.set("pid", pid0); int[] parameterValues2 = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,15,0,0}; int[] customValues2 = {}; nm2.newModule(91, 1, 11, 1, 30, "CtrlSeqN", parameterValues2, customValues2); p.send(nm2); while(n < 100) { n++; p.heartbeat(); Thread.sleep(10); } } catch (MidiException me) { me.printStackTrace(); System.out.println("" + me.getError()); } catch (Throwable e) { e.printStackTrace(); } finally { nmDriver.disconnect(); } } /** * Tests if each of the 13 PatchMessages is received */ public void testGetPatchMessage() throws Exception { System.out.println("test GetPatchMessage"); try { nmDriver.connect(); MessageMulticaster multicaster = new MessageMulticaster(); NmProtocol protocol = new NmProtocol(); GetPatchMessageReplyAcceptor acceptor = new GetPatchMessageReplyAcceptor(protocol); configureProtocol(protocol, nmDriver, multicaster); multicaster.addProtocolListener(acceptor); acceptor.sendInitialMessage(); long timeout = System.currentTimeMillis()+20*1000; while (System.currentTimeMillis()<timeout && !acceptor.accepted()) { protocol.heartbeat(); protocol.waitForActivity(1000); } assertFalse("replies expected (PatchMessages:"+acceptor.getPatchMessageReplyCount()+", expected 13)", !acceptor.accepted()); } finally { nmDriver.disconnect(); } } /** * Tests if the PatchListMessage is received */ public void testGetPatchListMessage() throws Exception { System.out.println("test GetPatchListMessage"); nmDriver.connect(); try { NmProtocol protocol = configureProtocol(new NmProtocol(), nmDriver, null); MessageAcceptor acceptor = new MessageAcceptor(protocol, PatchListMessage.class); protocol.setMessageHandler(acceptor); protocol.send(new IAmMessage()); int section = 0; int position = 0; do { GetPatchListMessage gpl = new GetPatchListMessage(); gpl.set("section", section); gpl.set("position", position); protocol.send(gpl); // returns if the message is received or otherwise throws an exception acceptor.waitUntilAccepted(3000); // everything is ok System.out.print("section("+section+"),position("+position+")="); PatchListMessage patchListMessage = (PatchListMessage)acceptor.getMessage(); for (Iterator<PatchListEntry> i = patchListMessage.getEntries().iterator(); i.hasNext(); ) { System.out.print("" + i.next() + ", "); } System.out.println(); section = patchListMessage.getNextSection(); position = patchListMessage.getNextPosition(); acceptor.reset(); } while (section>=0 && position>=0); System.out.println("success"); } catch (Exception e) { e.printStackTrace(); System.out.println("failed"); throw e; } finally { nmDriver.disconnect(); } } public void testLoadPatchMessage() throws Exception { System.out.println("test LoadPatchMessage"); try { nmDriver.connect(); MessageMulticaster multicaster = new MessageMulticaster(); NmProtocol p = createProtocol(nmDriver, multicaster); multicaster.addProtocolListener(new Listener(p, multicaster)); LoadPatchMessage lpm = new LoadPatchMessage(); lpm.set("loadslot", 0); lpm.set("section", 0); lpm.set("position", 0); p.send(lpm); lpm.set("loadslot", 1); lpm.set("section", 1); lpm.set("position", 1); p.send(lpm); lpm.set("loadslot", 2); lpm.set("section", 2); lpm.set("position", 2); p.send(lpm); lpm.set("loadslot", 3); lpm.set("section", 3); lpm.set("position", 3); p.send(lpm); int n = 0; while(n < 400) { n++; p.heartbeat(); Thread.sleep(10); } } catch (Exception e) { e.printStackTrace(); System.out.println("failed"); throw e; } finally { nmDriver.disconnect(); } } public void testStorePatchMessage() throws Exception { System.out.println("test StorePatchMessage"); try { nmDriver.connect(); MessageMulticaster multicaster = new MessageMulticaster(); NmProtocol p = createProtocol(nmDriver, multicaster); multicaster.addProtocolListener(new Listener(p, multicaster)); StorePatchMessage lpm = new StorePatchMessage(); lpm.set("storeslot", 0); lpm.set("section", 8); lpm.set("position", 95); p.send(lpm); lpm.set("storeslot", 1); lpm.set("section", 8); lpm.set("position", 96); p.send(lpm); lpm.set("storeslot", 2); lpm.set("section", 8); lpm.set("position", 97); p.send(lpm); lpm.set("storeslot", 3); lpm.set("section", 8); lpm.set("position", 98); p.send(lpm); int n = 0; while(n < 400) { n++; p.heartbeat(); Thread.sleep(10); } } catch (Exception e) { e.printStackTrace(); System.out.println("failed"); throw e; } finally { nmDriver.disconnect(); } } public void testDeletePatchMessage() throws Exception { System.out.println("test DeletePatchMessage"); try { nmDriver.connect(); MessageMulticaster multicaster = new MessageMulticaster(); NmProtocol p = createProtocol(nmDriver, multicaster); multicaster.addProtocolListener(new Listener(p, multicaster)); DeletePatchMessage lpm = new DeletePatchMessage(); lpm.set("section", 8); lpm.set("position", 95); p.send(lpm); lpm.set("section", 8); lpm.set("position", 96); p.send(lpm); lpm.set("section", 8); lpm.set("position", 97); p.send(lpm); lpm.set("section", 8); lpm.set("position", 98); p.send(lpm); int n = 0; while(n < 400) { n++; p.heartbeat(); Thread.sleep(10); } } catch (Exception e) { e.printStackTrace(); System.out.println("failed"); throw e; } finally { nmDriver.disconnect(); } } public void testSlotsSelectedMessage() throws Exception { System.out.println("test SlotsSelectedMessage"); try { nmDriver.connect(); MessageMulticaster multicaster = new MessageMulticaster(); NmProtocol p = createProtocol(nmDriver, multicaster); multicaster.addProtocolListener(new Listener(p, multicaster)); SlotsSelectedMessage lpm = new SlotsSelectedMessage(); lpm.set("slot0Selected", 0); lpm.set("slot1Selected", 1); lpm.set("slot2Selected", 0); lpm.set("slot3Selected", 1); p.send(lpm); int n = 0; while(n < 100) { n++; p.heartbeat(); Thread.sleep(10); } } catch (Exception e) { e.printStackTrace(); System.out.println("failed"); throw e; } finally { nmDriver.disconnect(); } } private static class MessageAcceptor implements MessageHandler { // TODO use NmMessageAcceptor instead of this class private final Class<? extends MidiMessage> messageClass; private final NmProtocol protocol; private MidiMessage acceptedMessage = null; public MessageAcceptor(NmProtocol protocol, Class<? extends MidiMessage> messageClass) { this.protocol = protocol; this.messageClass = messageClass; } public void reset() { acceptedMessage = null; } public MidiMessage getMessage() { return acceptedMessage; } public void processMessage( MidiMessage message ) { if (message.getClass().equals(messageClass) && !accepted()) { this.acceptedMessage = message; } } public boolean accepted() { return acceptedMessage != null; } public void waitUntilAccepted(final long timeout) throws Exception { final long threshold = System.currentTimeMillis()+timeout; while(!accepted()) { if (System.currentTimeMillis()>threshold) throw new InterruptedException("timeout: "+timeout); try { protocol.heartbeat(); } catch (Exception e1) { throw e1; } protocol.waitForActivity(10); } } } class TestTracer implements net.sf.nmedit.jpdl.Tracer { public void trace(String message) { System.out.println("T: " + message); } } class Listener extends NmProtocolListener { private NmProtocol p; private MessageMulticaster multicaster; public Listener(NmProtocol p, MessageMulticaster multicaster) { this.p = p; this.multicaster = multicaster; } public void messageReceived(IAmMessage message) { System.out.println(message); } public void messageReceived(LightMessage message) { System.out.println(message); } public void messageReceived(MeterMessage message) { System.out.println(message); } public void messageReceived(PatchMessage message) { System.out.println(message); } public void messageReceived(AckMessage message) { System.out.println(message); try { GetPatchMessage gpm = new GetPatchMessage(); gpm.set("pid", multicaster.getActivePid(0)); p.send(gpm); } catch (MidiException me) { me.printStackTrace(); System.out.println("" + me.getError()); } catch (Throwable e) { e.printStackTrace(); } } public void messageReceived(PatchListMessage message) { System.out.println(message); for (Iterator<PatchListEntry> i = message.getEntries().iterator(); i.hasNext(); ) { System.out.print("" + i.next() + ", "); } System.out.println(); } public void messageReceived(NewPatchInSlotMessage message) { System.out.println(message); } public void messageReceived(VoiceCountMessage message) { System.out.println(message); } public void messageReceived(SlotsSelectedMessage message) { System.out.println(message); } public void messageReceived(SlotActivatedMessage message) { System.out.println(message); } public void messageReceived(ParameterMessage message) { System.out.println(message); } public void messageReceived(ErrorMessage message) { System.out.println(message); } } }