package com.frinika.sequencer.patchname;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Serializable;
import java.lang.reflect.Method;
import java.util.List;
import java.util.Vector;
import javax.sound.midi.Instrument;
import javax.sound.midi.Patch;
import javax.sound.midi.Synthesizer;
public class PatchNameMap implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
private Vector<Node> topList = new Vector<Node>();
// these are used to build keynames whilst parsing a text file.
transient private Node currentPatchNode;
transient private String[] keyNames;
// String mapName;
public PatchNameMap(InputStream str) throws Exception {
// mapName=file.getName();
BufferedReader reader = new BufferedReader(new InputStreamReader(str));
boolean readPatches = false;
String line;
while ((line = reader.readLine()) != null) {
int opB = line.indexOf('[');
if (opB == -1) {
continue;
}
int clB = line.indexOf(']');
if (clB == -1) {
throw new Exception(" Parse error " + line + "<");
}
String cmd = line.substring(opB + 1, clB);
String rest = line.substring(clB + 1);
String name = rest.trim();
// System.out.println(cmd);
if (!readPatches) {
if (cmd.equals("define patchnames")) {
readPatches = true;
}
} else {
if (cmd.charAt(0) == 'p') {
if (keyNames != null) {
currentPatchNode.keynames = keyNames;
keyNames = null;
}
patchName(cmd, name);
} else if (cmd.charAt(0) == 'g') {
groupName(cmd, name);
} else if (cmd.charAt(0) == 'k') {
if (keyNames == null) {
keyNames = new String[128];
}
int key = Integer.parseInt(cmd.substring(2));
// System.out.println(" keyname["+key+"]="+name);
keyNames[key] = name;
}
}
}
if (keyNames != null) {
currentPatchNode.keynames = keyNames;
keyNames = null;
}
}
public PatchNameMap(Synthesizer synthesizer, int channel) {
// System.out.println(" Creating patch map for " + synthesizer.toString() + " channel =" + channel);
Instrument[] loadedins = synthesizer.getLoadedInstruments();
Instrument[] availins = synthesizer.getAvailableInstruments();
Instrument[] availableInstruments;
if (loadedins == availins) {
availableInstruments = loadedins;
} else {
availableInstruments = new Instrument[loadedins.length + availins.length];
int ix = 0;
for (int i = 0; i < loadedins.length; i++) {
availableInstruments[ix++] = loadedins[i];
}
for (int i = 0; i < availins.length; i++) {
availableInstruments[ix++] = availins[i];
}
}
Method getChannels = null;
Method getKeys = null;
if (availableInstruments.length > 0) {
try {
getChannels = availableInstruments[0].getClass().getMethod(
"getChannels");
} catch (Exception e) {
}
try {
getKeys = availableInstruments[0].getClass().getMethod(
"getKeys");
} catch (Exception e) {
}
}
for (Instrument instr : availableInstruments) {
// System.out.println(" Loading patch for " +instr.getName());
Patch p = instr.getPatch();
boolean[] channels = null;
if (getChannels != null) {
try {
channels = (boolean[]) getChannels.invoke(instr);
} catch (Exception e) {
}
}
String[] keynames = null;
if (getKeys != null) {
try {
keynames = (String[]) getKeys.invoke(instr);
} catch (Exception e) {
}
}
if (channels == null || channels[channel]) {
// System.out.println("OK for the channel ");
MyPatch patch = new MyPatch(p.getProgram(), p.getBank() >> 7, p.getBank() & 0x7f);
Node node = new Node(instr.getName(), patch);
node.keynames = keynames;
listAtLevel(0).add(node);
} else {
// System.out.println("channel does not support it");
}
}
}
private void groupName(String cmd, String name) throws IOException {
int level = Integer.parseInt(cmd.substring(1));
listAtLevel(level).add(new Node(name, new Vector<Node>()));
// System.out.println(" g"+level+ " > "+name);
}
private Vector<Node> listAtLevel(int level) {
if (level == 1) {
return topList;
}
Vector<Node> p = topList;
while (level > 1) {
p = (Vector<Node>) (p.lastElement().getData());
level--;
}
return (Vector<Node>) p;
}
private void patchName(String cmd, String name) throws IOException {
String toks[] = cmd.split(",");
int level = Integer.parseInt(toks[0].substring(1));
int prog = Integer.parseInt(toks[1].trim());
int msb = Integer.parseInt(toks[2].trim());
int lsb;
if (toks.length < 4) {
// int msb_orig = msb;
lsb = msb % 128;
msb = msb / 128;
// System.out.println(msb_orig + " --- > " + msb + ":" + lsb);
} else {
lsb = Integer.parseInt(toks[3].trim());
}
MyPatch patch = new MyPatch(prog, msb, lsb);
currentPatchNode = new Node(name, patch);
listAtLevel(level).add(currentPatchNode);
// System.out.println(" p"+level+ " > "+name + " " +
// prog+"|"+msb+"|"+lsb);
// TODO Auto-generated method stub
}
/**
*
* Find patches which contain the substring name
*
* @param name
* @return
*/
public List<MyPatch> getPatchesWithNamesLike(String name) {
Vector<MyPatch> list = new Vector<MyPatch>();
getPatchesWithNameLike(name, topList, list);
return list;
}
private void getPatchesWithNameLike(String name, Vector<Node> root,
List<MyPatch> list) {
for (Node o : root) {
if (o.getData() instanceof Vector) {
getPatchesWithNameLike(name, (Vector<Node>) (o.getData()), list);
} else if (o.toString().toLowerCase().contains(name)) {
list.add((MyPatch) o.getData());
}
}
}
boolean contians(String name, Vector<Node> searchMe,
Vector<Vector<Node>> ret) {
for (Node o : searchMe) {
if (o.getData() instanceof Vector) {
if (contians(name, (Vector<Node>) (o.getData()), ret)) {
ret.insertElementAt((Vector<Node>) (o.getData()), 0);
System.out.println(" in list " + o.getData());
return true;
}
} else if (name.equals(o.toString())) {
System.out.println(" FOUND NAME " + name);
return true;
} else {
System.out.println(" It's not " + o.toString());
}
}
return false;
}
public Vector<Node> getList() {
// TODO Auto-generated method stub
return topList;
}
public static void main(String args) throws FileNotFoundException, Exception {
File file = new File("/home/pjl/frinika/patchnames/xgnames.txt");
FileInputStream io = new FileInputStream(file);
new PatchNameMap(io);
}
}