/*
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;
import net.sf.nmedit.jnmprotocol2.utils.NmCharacter;
import net.sf.nmedit.jpdl2.PDLException;
import net.sf.nmedit.jpdl2.PDLMessage;
import net.sf.nmedit.jpdl2.PDLPacket;
import net.sf.nmedit.jpdl2.PDLPacketParser;
import net.sf.nmedit.jpdl2.dom.PDLDocument;
import net.sf.nmedit.jpdl2.stream.BitStream;
import net.sf.nmedit.jpdl2.stream.IntStream;
public class PatchMessage extends MidiMessage
{
private BitStream bitstream;
private BitStream patchStream;
private boolean isFirstInSequence;
private boolean isLastInSequence;
private PatchMessage()
{
super();
addParameter("pid", "data:pid");
set("cc", 0x1c);
set("pid", 0);
expectsreply = true;
isreply = true;
}
public static BitStream getEmbeddedStream(PDLPacket packet)
{
int[] embedded_stream = packet.getVariableList("data:embedded_stream");
BitStream bitStream = new BitStream(embedded_stream.length/4);
for (int value: embedded_stream)
bitStream.append(value&0x7F, 7);
// Remove padding
bitStream.setSize((bitStream.getSize()/8)*8);
return bitStream;
}
public PatchMessage(PDLPacket packet)
{
this();
bitstream = new BitStream(); // not really ok
patchStream = getEmbeddedStream(packet);
setAll(packet);
isFirstInSequence = packet.getVariable("first")>0;
isLastInSequence = packet.getVariable("last")>0;
/*
packet = packet.getPacket("data:next");
while (packet != null) {
patchStream.append(packet.getVariable("data"), 7);
packet = packet.getPacket("next");
}
// Remove padding
patchStream.setSize((patchStream.getSize()/8)*8);
*/
}
public PatchMessage(BitStream section, int slot, int sectionIndex, int sectionCount) throws MidiException
{
this();
set("slot", slot);
// Create sysex messages
int first = sectionIndex == 0 ? 1 : 0;
int last = sectionIndex == (sectionCount-1) ? 1 : 0;
isFirstInSequence = first>0;
isLastInSequence = last>0;
int sectionsEnded = sectionIndex+1;
this.patchStream = BitStream.copyOf(section);
BitStream partialPatchStream = patchStream;
partialPatchStream.setSize((partialPatchStream.getSize()/8)*8);
// Pad. Extra bits are ignored later.
partialPatchStream.append(0, 6);
// Generate sysex bistream
IntStream intStream = new IntStream();
intStream.append(get("cc") + first + 2*last);
first = 0;
intStream.append(get("slot"));
intStream.append(0x01);
intStream.append(sectionsEnded);
partialPatchStream.setPosition(0);
while (partialPatchStream.isAvailable(7)) {
intStream.append(partialPatchStream.getInt(7));
}
intStream.setPosition(0);
// Generate sysex bitstream
this.bitstream = getBitStream(intStream);
}
public boolean isFirstInSequence()
{
return this.isFirstInSequence;
}
public boolean isLastInSequence()
{
return this.isLastInSequence;
}
public boolean isSingleMessage()
{
return isFirstInSequence && isLastInSequence;
}
public BitStream getBitStream()
{
return bitstream;
}
public void notifyListener(NmProtocolListener listener)
{
listener.messageReceived(this);
}
private PDLMessage patchMessage = null;
public PDLMessage getPatchMessage() throws PDLException
{
if (patchMessage == null)
{
PDLDocument doc = PDLData.getPatchDoc();
PDLPacketParser parser = new PDLPacketParser(doc);
patchStream.setPosition(0);
try
{
patchMessage = parser.parseMessage(patchStream);
}
finally
{
patchStream.setPosition(0);
}
}
return patchMessage;
}
public BitStream getPatchStream()
{
return patchStream;
}
public boolean containsSection(int sectionId)
{
try
{
PDLMessage message = getPatchMessage();
PDLPacket packet = message.getPacket();
do
{
PDLPacket section = packet.getPacket("section");
// PDLPacket sectionData = section.getPacket("data");
int foundSectionId = section.getVariable("type");
if (sectionId == foundSectionId)
return true;
packet = packet.getPacket("next");
}
while (packet != null);
}
catch (PDLException e)
{
// ignore
}
return false;
}
public final static int S_NAME_1 = 55;
public final static int S_NAME_2 = 39;
private String patchName;
private static final String NO_PATCHNAME_PRESENT = "------------------";
public String getPatchNameIfPresent()
{
if (patchName == NO_PATCHNAME_PRESENT)
return null;
if (patchName != null)
return patchName;
try
{
PDLMessage message = getPatchMessage();
PDLPacket packet = message.getPacket();
do
{
PDLPacket section = packet.getPacket("section");
PDLPacket sectionData = section.getPacket("data");
switch (section.getVariable("type"))
{
// Name section
case S_NAME_1:
case S_NAME_2:
// patch name
patchName = NmCharacter.extractName(sectionData.getPacket("name"));
return patchName;
}
packet = packet.getPacket("next");
}
while (packet != null);
}
catch (PDLException e)
{
// ignore
}
patchName = NO_PATCHNAME_PRESENT;
return null;
}
}