/* Copyright (C) 2006 Christian Schneider
*
* This file is part of Nomad.
*
* Nomad 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.
*
* Nomad 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 Nomad; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/package net.sf.nmedit.test;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import javax.sound.midi.MidiDevice.Info;
import net.sf.nmedit.jnmprotocol2.AckMessage;
import net.sf.nmedit.jnmprotocol2.ErrorMessage;
import net.sf.nmedit.jnmprotocol2.GetPatchListMessage;
import net.sf.nmedit.jnmprotocol2.IAmMessage;
import net.sf.nmedit.jnmprotocol2.LightMessage;
import net.sf.nmedit.jnmprotocol2.MeterMessage;
import net.sf.nmedit.jnmprotocol2.MidiMessage;
import net.sf.nmedit.jnmprotocol2.NewPatchInSlotMessage;
import net.sf.nmedit.jnmprotocol2.NmProtocolListener;
import net.sf.nmedit.jnmprotocol2.ParameterMessage;
import net.sf.nmedit.jnmprotocol2.PatchListEntry;
import net.sf.nmedit.jnmprotocol2.PatchListMessage;
import net.sf.nmedit.jnmprotocol2.PatchMessage;
import net.sf.nmedit.jnmprotocol2.SlotActivatedMessage;
import net.sf.nmedit.jnmprotocol2.SlotsSelectedMessage;
import net.sf.nmedit.jnmprotocol2.VoiceCountMessage;
import net.sf.nmedit.jnmprotocol2.utils.NmLookup;
import net.sf.nmedit.jpatch.clavia.nordmodular.NM1ModuleDescriptions;
import net.sf.nmedit.jpatch.clavia.nordmodular.NMPatch;
import net.sf.nmedit.jsynth.Slot;
import net.sf.nmedit.jsynth.SynthException;
import net.sf.nmedit.jsynth.clavia.nordmodular.NmSlot;
import net.sf.nmedit.jsynth.clavia.nordmodular.NordModular;
import net.sf.nmedit.jsynth.clavia.nordmodular.utils.NmUtils;
import net.sf.nmedit.jsynth.event.SlotEvent;
import net.sf.nmedit.jsynth.event.SlotListener;
import net.sf.nmedit.jsynth.event.SlotManagerListener;
import net.sf.nmedit.jsynth.midi.MidiDescription;
import net.sf.nmedit.jsynth.midi.MidiPlug;
import net.sf.nmedit.jsynth.worker.PatchLocation;
import net.sf.nmedit.jsynth.worker.StorePatchWorker;
public class JSynthTest
{
public static void main(String[] args) throws Exception
{
(new JSynthTest()).run();
}
private App app;
private NordModular synth;
private void run() throws Exception
{
app = new App();
(new Thread(app)).start();
NM1ModuleDescriptions md = NmUtils.parseModuleDescriptions();
synth = new NordModular(md);
synth.getSlotManager().addSlotManagerListener(new SlotManagerInfo());
synth.addProtocolListener(new ProtocolInfo());
initPorts();
System.out.println("Using ports:");
System.out.println("\t-"+synth.getPCInPort());
System.out.println("\t-"+synth.getPCOutPort());
synth.setConnected(true);
if (!waitForSlots())
{
System.err.println("timeout: slots not available");
shutdown();
}
Slot slot = synth.getSlot(0);
NMPatch patch = new NMPatch(null);
patch.setName("Hallo123");
StorePatchWorker worker = synth.createStorePatchWorker();
worker.setSource(patch);
worker.setDestination(new PatchLocation(slot.getSlotIndex()));
worker.store();
//listBanks();
}
private boolean waitForSlots()
{
long timeout = System.currentTimeMillis() + 1000;
while(synth.isConnected() && synth.getSlotCount()<=0)
{
if (System.currentTimeMillis()>timeout)
break;
try
{
Thread.sleep(50);
}
catch (InterruptedException e)
{
// no op
}
}
return synth.isConnected() && synth.getSlotCount()>0;
}
void listBanks() throws Exception
{
BankListTest test = new BankListTest();
synth.addProtocolListener(test);
test.start();
}
private static class ProtocolInfo extends NmProtocolListener
{
public void messageReceived(IAmMessage m) { msg(m); }
public void messageReceived(LightMessage m) { /*msg(m);*/ }
public void messageReceived(MeterMessage m) { msg(m); }
public void messageReceived(PatchMessage m) { /*msg(m);*/ }
public void messageReceived(AckMessage m) { msg(m); }
public void messageReceived(PatchListMessage m) { msg(m); }
public void messageReceived(NewPatchInSlotMessage m) { msg(m); }
public void messageReceived(VoiceCountMessage m) { msg(m); }
public void messageReceived(SlotsSelectedMessage m) { msg(m); }
public void messageReceived(SlotActivatedMessage m) { msg(m); }
public void messageReceived(ParameterMessage m) { msg(m); }
public void messageReceived(ErrorMessage m) { msg(m); }
public void msg(MidiMessage m) { System.out.println(m); }
}
private class BankListTest extends NmProtocolListener
{
public void start() throws Exception
{
request(0,0);
}
protected void request(int section, int position) throws Exception
{
if (section<0 || position<0)
{
synth.removeProtocolListener(this);
return;
}
System.out.println("requesting patch list: section="+section+", position="+position);
synth.getProtocol().send( new GetPatchListMessage(section, position) );
}
public void messageReceived(PatchListMessage message)
{
for (PatchListEntry e: message.getEntries())
System.out.println(e);
System.out.println("next section="+message.getNextSection()+", position="+message.getNextPosition());
try
{
request(message.getNextSection(), message.getNextPosition());
}
catch (Exception e1)
{
e1.printStackTrace();
}
}
}
private void initPorts() throws SynthException
{
Info[] info = NmLookup.lookup(NmLookup.getHardwareDevices(), 1, 1000);
MidiDescription descIn = new MidiDescription(info[0], 1);
MidiDescription descOut = new MidiDescription(info[1], 0);
synth.getPCInPort().setPlug(new MidiPlug(descIn));
synth.getPCOutPort().setPlug(new MidiPlug(descOut));
}
private static class SlotManagerInfo implements SlotManagerListener,
SlotListener, PropertyChangeListener
{
public void slotAdded(SlotEvent e)
{
System.out.println("slot added: "+e.getSlot());
install((NmSlot) e.getSlot());
}
public void slotRemoved(SlotEvent e)
{
System.out.println("slot removed: "+e.getSlot());
uninstall((NmSlot) e.getSlot());
}
private void install(NmSlot slot)
{
slot.addSlotListener(this);
slot.addPropertyChangeListener(this);
}
private void uninstall(NmSlot slot)
{
slot.removeSlotListener(this);
slot.removePropertyChangeListener(this);
}
public void newPatchInSlot(SlotEvent e)
{
NmSlot slot = (NmSlot) e.getSlot();
System.out.println("new patch in slot "+slot.getName()+": "+slot.getPatch());
}
public void propertyChange(PropertyChangeEvent evt)
{
NmSlot slot = (NmSlot) evt.getSource();
System.out.println(slot.getName()+": "+evt.getPropertyName()+"="+evt.getNewValue()+" (old:"+evt.getOldValue()+")");
}
}
private void shutdown()
{
System.out.println("Shutting down...");
try
{
Thread.sleep(500);
}
catch (InterruptedException e1)
{
}
try
{
synth.setConnected(false);
}
catch (SynthException e)
{
e.printStackTrace();
}
System.exit(0);
}
private class App implements Runnable
{
private boolean stopped = false;
private long timeout = System.currentTimeMillis()+30000;
public void run()
{
try
{
loop:for (;;)
{
synchronized (this)
{
if (stopped)
break loop;
}
if (timeout<System.currentTimeMillis())
break loop;
delay();
}
}
finally
{
shutdown();
}
}
private void delay()
{
try
{
Thread.sleep(1000);
}
catch (InterruptedException e)
{
// ignore
}
}
public void stop()
{
synchronized (this)
{
stopped = true;
}
}
}
}