--- jlscp/trunk/src/org/linuxsampler/lscp/Client.java 2007/09/10 21:26:10 1340 +++ jlscp/trunk/src/org/linuxsampler/lscp/Client.java 2008/03/19 10:05:33 1718 @@ -34,9 +34,10 @@ import java.util.logging.Level; import java.util.logging.Logger; -import static org.linuxsampler.lscp.Parser.*; import org.linuxsampler.lscp.event.*; +import static org.linuxsampler.lscp.Parser.*; + /** * This class is the abstraction representing a client endpoint for communication with LinuxSampler @@ -343,6 +344,7 @@ if(!llFSI.isEmpty()) subscribe("FX_SEND_INFO"); if(!llSC.isEmpty()) subscribe("STREAM_COUNT"); if(!llVC.isEmpty()) subscribe("VOICE_COUNT"); + if(!llTSC.isEmpty()) subscribe("TOTAL_STREAM_COUNT"); if(!llTVC.isEmpty()) subscribe("TOTAL_VOICE_COUNT"); if(!llMIMC.isEmpty()) subscribe("MIDI_INSTRUMENT_MAP_COUNT"); if(!llMIMI.isEmpty()) subscribe("MIDI_INSTRUMENT_MAP_INFO"); @@ -353,6 +355,7 @@ subscribe("DB_INSTRUMENT_DIRECTORY_INFO"); subscribe("DB_INSTRUMENT_COUNT"); subscribe("DB_INSTRUMENT_INFO"); + subscribe("DB_INSTRUMENTS_JOB_INFO"); } if(!llGI.isEmpty()) subscribe("GLOBAL_INFO"); } @@ -484,6 +487,7 @@ private final Vector llMIDI = new Vector(); private final Vector llSC = new Vector(); private final Vector llVC = new Vector(); + private final Vector llTSC = new Vector(); private final Vector llTVC = new Vector(); /** MIDI instrument map count listeners */ @@ -521,6 +525,7 @@ !llMIDI.isEmpty() || !llSC.isEmpty() || !llVC.isEmpty() || + !llTSC.isEmpty() || !llTVC.isEmpty() || !llMIMC.isEmpty() || !llMIMI.isEmpty() || @@ -542,8 +547,10 @@ if(s.startsWith("NAME ")) { String[] list; try { - list = parseQuotedStringList(s.substring("NAME ".length()), ' '); + s = s.substring("NAME ".length()); + list = parseEscapedStringList(s, ' '); if(list.length != 2) throw new LscpException(); + list[1] = toNonEscapedString(list[1]); e = new InstrumentsDbEvent(this, list[0], list[1]); for(InstrumentsDbListener l : llID) { l.directoryNameChanged(e); @@ -569,8 +576,10 @@ if(s.startsWith("NAME ")) { String[] list; try { - list = parseQuotedStringList(s.substring("NAME ".length()), ' '); + s = s.substring("NAME ".length()); + list = parseEscapedStringList(s, ' '); if(list.length != 2) throw new LscpException(); + list[1] = toNonEscapedString(list[1]); e = new InstrumentsDbEvent(this, list[0], list[1]); for(InstrumentsDbListener l : llID) { l.instrumentNameChanged(e); @@ -657,6 +666,17 @@ } catch(NumberFormatException x) { getLogger().log(Level.WARNING, "Unknown CHANNEL_INFO format", x); } + } else if(s.startsWith("TOTAL_STREAM_COUNT:")) { + try { + s = s.substring("TOTAL_STREAM_COUNT:".length()); + int i = Integer.parseInt(s); + TotalStreamCountEvent e = new TotalStreamCountEvent(this, i); + for(TotalStreamCountListener l : llTSC) l.totalStreamCountChanged(e); + } catch(NumberFormatException x) { + getLogger().log ( + Level.WARNING, "Unknown TOTAL_STREAM_COUNT format", x + ); + } } else if(s.startsWith("TOTAL_VOICE_COUNT:")) { try { s = s.substring("TOTAL_VOICE_COUNT:".length()); @@ -1129,6 +1149,28 @@ /** * Registers the specified listener for receiving event messages. * Listeners can be registered regardless of the connection state. + * @param l The TotalStreamCountListener to register. + */ + public synchronized void + addTotalStreamCountListener(TotalStreamCountListener l) { + if(llTSC.isEmpty()) subscribe("TOTAL_STREAM_COUNT"); + llTSC.add(l); + } + + /** + * Removes the specified listener. + * Listeners can be removed regardless of the connection state. + * @param l The TotalStreamCountListener to remove. + */ + public synchronized void + removeTotalStreamCountListener(TotalStreamCountListener l) { + boolean b = llTSC.remove(l); + if(b && llTSC.isEmpty()) unsubscribe("TOTAL_STREAM_COUNT"); + } + + /** + * Registers the specified listener for receiving event messages. + * Listeners can be registered regardless of the connection state. * @param l The TotalVoiceCountListener to register. */ public synchronized void @@ -1413,7 +1455,7 @@ args.append(' ').append(param); for(Parameter p : deplist) { - if(p.getValue() == null) continue; + if(p == null || p.getName() == null || p.getValue() == null) continue; args.append(' ').append(p.getName()).append('=').append(p.getStringValue()); } @@ -1477,7 +1519,7 @@ StringBuffer args = new StringBuffer(aoDriver); for(Parameter p : paramList) { - if(p.getValue() == null) continue; + if(p == null || p.getName() == null || p.getValue() == null) continue; args.append(' ').append(p.getName()).append('=').append(p.getStringValue()); } @@ -1999,7 +2041,7 @@ args.append(' ').append(param); for(Parameter p : deplist) { - if(p.getValue() == null) continue; + if(p == null || p.getName() == null || p.getValue() == null) continue; args.append(' ').append(p.getName()).append('=').append(p.getStringValue()); } @@ -2064,7 +2106,7 @@ StringBuffer args = new StringBuffer(miDriver); for(Parameter p : paramList) { - if(p.getValue() == null) continue; + if(p == null || p.getName() == null || p.getValue() == null) continue; args.append(' ').append(p.getName()).append('=').append(p.getStringValue()); } @@ -2211,8 +2253,15 @@ mid.setActive(Boolean.parseBoolean(s)); } else if(s.startsWith("PORTS: ")) { s = s.substring("PORTS: ".length()); - int ports = Parser.parseInt(s); - MidiPort[] midiPorts = new MidiPort[ports > 0 ? ports : 0]; + + Parameter ports = (Parameter) + getMidiInputDriverParameterInfo(drv, "PORTS"); + + ports.parseValue(s); + mid.setPortsParameter(ports); + + int j = ports.getValue(); + MidiPort[] midiPorts = new MidiPort[j > 0 ? j : 0]; for(int i = 0; i < midiPorts.length; i++) midiPorts[i] = getMidiInputPortInfo(deviceId, i); @@ -2455,7 +2504,7 @@ public synchronized int addMidiInstrumentMap(String name) throws IOException, LSException, LscpException { verifyConnection(); - out.writeLine("ADD MIDI_INSTRUMENT_MAP '" + name + "'"); + out.writeLine("ADD MIDI_INSTRUMENT_MAP '" + toEscapedString(name) + "'"); if(getPrintOnlyMode()) return -1; ResultSet rs = getEmptyResultSet(); @@ -2558,7 +2607,7 @@ for(String s : lnS) { if(s.startsWith("NAME: ")) { - name = s.substring("NAME: ".length()); + name = toNonEscapedString(s.substring("NAME: ".length())); } else if(s.startsWith("DEFAULT: ")) { b = Boolean.parseBoolean(s.substring("DEFAULT: ".length())); } else { @@ -2606,6 +2655,7 @@ throws IOException, LscpException, LSException { verifyConnection(); + name = toEscapedString(name); out.writeLine("SET MIDI_INSTRUMENT_MAP NAME " + + mapId + " '" + name + "'"); if(getPrintOnlyMode()) return; @@ -2661,7 +2711,11 @@ if(!info.getLoadMode().name().equals("DEFAULT")) { cmd.append(' ').append(info.getLoadMode().name()); } - if(info.getName() != null) cmd.append(" '").append(info.getName()).append("'"); + + if(info.getName() != null) { + String s = toEscapedString(info.getName()); + cmd.append(" '").append(s).append("'"); + } out.writeLine(cmd.toString()); if(getPrintOnlyMode()) return; @@ -2750,10 +2804,42 @@ } /** - * Gets all MIDI instrument contained int the specified MIDI instrument map. + * Gets all MIDI instrument entries contained int the specified MIDI instrument map. + * @param mapId The ID of the map, which instruments should be obtained. + * @return An int array providing all MIDI instrument entries + * in the specified MIDI instrument map. + * @throws IOException If some I/O error occurs. + * @throws LscpException If LSCP protocol corruption occurs. + * @throws LSException If some other error occurs. + */ + public synchronized int[][] + getMidiInstrumentEntries(int mapId) throws IOException, LscpException, LSException { + verifyConnection(); + out.writeLine("LIST MIDI_INSTRUMENTS " + String.valueOf(mapId)); + if(getPrintOnlyMode()) return null; + + String[] entries = parseArray(getSingleLineResultSet().getResult()); + int[][] e = new int[entries.length][3]; + + for(int i = 0; i < entries.length; i++) { + Integer[] vals = parseIntList(entries[i]); + if(vals.length != 3) { + throw new LscpException(LscpI18n.getLogMsg("CommandFailed!")); + } + + e[i][0] = vals[0]; + e[i][1] = vals[1]; + e[i][2] = vals[2]; + } + + return e; + } + + /** + * Gets all MIDI instruments contained int the specified MIDI instrument map. * @param mapId The ID of the map, which instruments should be obtained. * @return A MidiInstrumentInfo array providing - * all MIDI instruments from all MIDI instrument maps. + * all MIDI instruments in the specified MIDI instrument map. * @throws IOException If some I/O error occurs. * @throws LscpException If LSCP protocol corruption occurs. * @throws LSException If some other error occurs. @@ -2801,14 +2887,25 @@ throws IOException, LscpException, LSException { verifyConnection(); + requestMidiInstrumentInfo(mapId, bank, program); + return getMidiInstrumentInfoResponse(mapId, bank, program); + } + + private void + requestMidiInstrumentInfo(int mapId, int bank, int program) throws IOException { StringBuffer cmd = new StringBuffer("GET MIDI_INSTRUMENT INFO "); cmd.append(mapId).append(' '); cmd.append(bank).append(' '); cmd.append(program); out.writeLine(cmd.toString()); - if(getPrintOnlyMode()) return null; + } + + private MidiInstrumentInfo + getMidiInstrumentInfoResponse(int mapId, int bank, int program) + throws IOException, LscpException, LSException { + if(getPrintOnlyMode()) return null; ResultSet rs = getMultiLineResultSet(); MidiInstrumentEntry entry = new MidiInstrumentEntry(bank, program); return new MidiInstrumentInfo(mapId, entry, rs.getMultiLineResult()); @@ -2857,7 +2954,6 @@ loadInstrument(String filename, int instrIdx, int samplerChn, boolean nonModal) throws IOException, LscpException, LSException { - filename = getEscapedString(filename); String cmd = nonModal ? "LOAD INSTRUMENT NON_MODAL " : "LOAD INSTRUMENT "; String args = '\'' + filename + "' " + instrIdx + ' ' + samplerChn; @@ -3040,7 +3136,7 @@ out.writeLine("LIST AVAILABLE_ENGINES"); if(getPrintOnlyMode()) return null; - return parseQuotedStringList(getSingleLineResultSet().getResult()); + return parseStringList(getSingleLineResultSet().getResult()); } /** @@ -3511,7 +3607,7 @@ verifyConnection(); String s = String.valueOf(channel) + " " + String.valueOf(midiCtrl); - if(name != null) s += " '" + name + "'"; + if(name != null) s += " '" + toEscapedString(name) + "'"; out.writeLine("CREATE FX_SEND " + s); if(getPrintOnlyMode()) return -1; @@ -3642,7 +3738,7 @@ throws IOException, LscpException, LSException { verifyConnection(); - String args = " " + channel + " " + fxSend + " '" + name + "'"; + String args = " " + channel + " " + fxSend + " '" + toEscapedString(name) + "'"; out.writeLine("SET FX_SEND NAME" + args); if(getPrintOnlyMode()) return; @@ -3741,9 +3837,9 @@ * @see #getSamplerChannels */ public synchronized void - editInstrument(int samplerChn) throws IOException, LscpException, LSException { + editChannelInstrument(int samplerChn) throws IOException, LscpException, LSException { verifyConnection(); - out.writeLine("EDIT INSTRUMENT " + samplerChn); + out.writeLine("EDIT CHANNEL INSTRUMENT " + samplerChn); if(getPrintOnlyMode()) return; ResultSet rs = getEmptyResultSet(); @@ -3753,7 +3849,7 @@ /** * Adds the specified directory to the instruments database. - * @param dir The absolute path name of the directory to add. + * @param dir The absolute (escaped) path name of the directory to add. * @throws IOException If some I/O error occurs. * @throws LSException If the creation of the directory failed. * @throws LscpException If LSCP protocol corruption occurs. @@ -3769,7 +3865,7 @@ /** * Removes the specified directory from the instruments database. - * @param dir The absolute path name of the directory to remove. + * @param dir The absolute (escaped) path name of the directory to remove. * @throws IOException If some I/O error occurs. * @throws LscpException If LSCP protocol corruption occurs. * @throws LSException If the specified directory is not @@ -3804,7 +3900,7 @@ /** * Removes the specified directories from the instruments database. - * @param dirs The absolute path names of the directories to remove. + * @param dirs The absolute (escaped) path names of the directories to remove. * @param force If true forces the removal of non-empty * directories. * @throws IOException If some I/O error occurs. @@ -3879,7 +3975,11 @@ out.writeLine("LIST DB_INSTRUMENT_DIRECTORIES '" + dir + "'"); if(getPrintOnlyMode()) return null; - return parseQuotedStringList(getSingleLineResultSet().getResult()); + String[] names = parseEscapedStringList(getSingleLineResultSet().getResult()); + for(int i = 0; i < names.length; i++) { + names[i] = toNonEscapedString(names[i]); + } + return names; } /** @@ -3901,15 +4001,13 @@ DbDirectoryInfo info = new DbDirectoryInfo(rs.getMultiLineResult()); if(dir.equals("/")) { info.setName("/"); - } else if(dir.length() > 1 && dir.charAt(dir.length() - 1) == '/') { - dir = dir.substring(0, dir.length() - 1); - } - int i = dir.lastIndexOf('/'); - if(i != -1 && i < dir.length() - 1) { - info.setName(dir.substring(i + 1)); - if(i == 0) info.setParentDirectoryPath("/"); - else info.setParentDirectoryPath(dir.substring(0, i)); + } else { + dir = removeEndingFileSeparator(dir); } + String s = getFileName(dir); + if(s != null) info.setName(toNonEscapedFileName(s)); + s = getParentDirectory(dir); + if(s != null) info.setParentDirectoryPath(s); return info; } @@ -3926,9 +4024,11 @@ public synchronized DbDirectoryInfo[] getDbDirectories(String dir) throws IOException, LscpException, LSException { String[] dirS = getDbDirectoryNames(dir); - if(dir.charAt(dir.length() - 1) != '/') dir += "/"; + if(!hasEndingFileSeparator(dir)) dir += "/"; DbDirectoryInfo[] infoS = new DbDirectoryInfo[dirS.length]; - for(int i = 0; i < dirS.length; i++) infoS[i] = getDbDirectoryInfo(dir + dirS[i]); + for(int i = 0; i < dirS.length; i++) { + infoS[i] = getDbDirectoryInfo(dir + toEscapedFileName(dirS[i])); + } return infoS; } @@ -3993,6 +4093,7 @@ public synchronized void renameDbDirectory(String dir, String name) throws IOException, LSException, LscpException { verifyConnection(); + name = toEscapedString(name); out.writeLine("SET DB_INSTRUMENT_DIRECTORY NAME '" + dir + "' '" + name + "'"); if(getPrintOnlyMode()) return; @@ -4085,7 +4186,7 @@ verifyConnection(); String s = "SET DB_INSTRUMENT_DIRECTORY DESCRIPTION '"; - out.writeLine(s + dir + "' '" + desc + "'"); + out.writeLine(s + dir + "' '" + toEscapedString(desc) + "'"); if(getPrintOnlyMode()) return; ResultSet rs = getEmptyResultSet(); @@ -4264,7 +4365,8 @@ break; } - sb.append(" '").append(dbDir).append("' '").append(fsDir).append("'"); + sb.append(" '").append(dbDir).append("' '"); + sb.append(fsDir).append("'"); out.writeLine(sb.toString()); if(getPrintOnlyMode()) return -1; @@ -4360,7 +4462,11 @@ out.writeLine("LIST DB_INSTRUMENTS '" + dir + "'"); if(getPrintOnlyMode()) return null; - return parseQuotedStringList(getSingleLineResultSet().getResult()); + String[] names = parseEscapedStringList(getSingleLineResultSet().getResult()); + for(int i = 0; i < names.length; i++) { + names[i] = toNonEscapedString(names[i]); + } + return names; } /** @@ -4380,12 +4486,10 @@ ResultSet rs = getMultiLineResultSet(); DbInstrumentInfo info = new DbInstrumentInfo(rs.getMultiLineResult()); - int i = instr.lastIndexOf('/'); - if(i != -1 && i < instr.length() - 1) { - info.setName(instr.substring(i + 1)); - if(i == 0) info.setDirectoryPath("/"); - else info.setDirectoryPath(instr.substring(0, i)); - } + String s = getParentDirectory(instr); + if(s != null) info.setDirectoryPath(s); + s = getFileName(instr); + if(s != null) info.setName(toNonEscapedFileName(s)); return info; } @@ -4402,11 +4506,11 @@ public synchronized DbInstrumentInfo[] getDbInstruments(String dir) throws IOException, LscpException, LSException { String[] instrS = getDbInstrumentNames(dir); - if(dir.charAt(dir.length() - 1) != '/') dir += "/"; + if(!hasEndingFileSeparator(dir)) dir += "/"; DbInstrumentInfo[] infoS = new DbInstrumentInfo[instrS.length]; for(int i = 0; i < instrS.length; i++) { - infoS[i] = getDbInstrumentInfo(dir + instrS[i]); + infoS[i] = getDbInstrumentInfo(dir + toEscapedFileName(instrS[i])); } return infoS; } @@ -4474,6 +4578,7 @@ throws IOException, LSException, LscpException { verifyConnection(); + name = toEscapedString(name); out.writeLine("SET DB_INSTRUMENT NAME '" + instr + "' '" + name + "'"); if(getPrintOnlyMode()) return; @@ -4565,6 +4670,7 @@ throws IOException, LSException, LscpException { verifyConnection(); + desc = toEscapedString(desc); out.writeLine("SET DB_INSTRUMENT DESCRIPTION '" + instr + "' '" + desc + "'"); if(getPrintOnlyMode()) return; @@ -4612,7 +4718,7 @@ sb.append(" '").append(dir).append("'"); if(query.name != null && query.name.length() > 0) { - sb.append(" NAME='").append(query.name).append("'"); + sb.append(" NAME='").append(toEscapedString(query.name)).append("'"); } String s = query.getCreatedAfter(); @@ -4636,13 +4742,14 @@ } if(query.description != null && query.description.length() > 0) { - sb.append(" DESCRIPTION='").append(query.description).append("'"); + sb.append(" DESCRIPTION='"); + sb.append(toEscapedString(query.description)).append("'"); } out.writeLine(sb.toString()); if(getPrintOnlyMode()) return null; - String[] dirS = parseQuotedStringList(getSingleLineResultSet().getResult()); + String[] dirS = parseEscapedStringList(getSingleLineResultSet().getResult()); DbDirectoryInfo[] infoS = new DbDirectoryInfo[dirS.length]; for(int i = 0; i < dirS.length; i++) { @@ -4692,7 +4799,7 @@ sb.append(" '").append(dir).append("'"); if(query.name != null && query.name.length() > 0) { - sb.append(" NAME='").append(query.name).append("'"); + sb.append(" NAME='").append(toEscapedString(query.name)).append("'"); } if(query.formatFamilies.size() > 0) { @@ -4732,7 +4839,8 @@ } if(query.description != null && query.description.length() > 0) { - sb.append(" DESCRIPTION='").append(query.description).append("'"); + sb.append(" DESCRIPTION='"); + sb.append(toEscapedString(query.description)).append("'"); } if(query.instrumentType != DbSearchQuery.InstrumentType.BOTH) { @@ -4745,21 +4853,22 @@ } if(query.product != null && query.product.length() > 0) { - sb.append(" PRODUCT='").append(query.product).append("'"); + sb.append(" PRODUCT='").append(toEscapedString(query.product)).append("'"); } if(query.artists != null && query.artists.length() > 0) { - sb.append(" ARTISTS='").append(query.artists).append("'"); + sb.append(" ARTISTS='").append(toEscapedString(query.artists)).append("'"); } if(query.keywords != null && query.keywords.length() > 0) { - sb.append(" KEYWORDS='").append(query.keywords).append("'"); + sb.append(" KEYWORDS='"); + sb.append(toEscapedString(query.keywords)).append("'"); } out.writeLine(sb.toString()); if(getPrintOnlyMode()) return null; - String[] instrS = parseQuotedStringList(getSingleLineResultSet().getResult()); + String[] instrS = parseEscapedStringList(getSingleLineResultSet().getResult()); DbInstrumentInfo[] infoS = new DbInstrumentInfo[instrS.length]; for(int i = 0; i < instrS.length; i++) { @@ -4790,6 +4899,22 @@ } /** + * Removes all instruments and directories and re-creates + * the instruments database structure. + * @throws IOException If some I/O error occurs. + * @throws LscpException If LSCP protocol corruption occurs. + * @throws LSException If the formatting of the instruments database failed. + */ + public synchronized void + formatInstrumentsDb() throws IOException, LscpException, LSException { + verifyConnection(); + out.writeLine("FORMAT INSTRUMENTS_DB"); + if(getPrintOnlyMode()) return; + + ResultSet rs = getEmptyResultSet(); + } + + /** * Resets the specified sampler channel. * * @param samplerChn The sampler channel number. @@ -4826,6 +4951,23 @@ } /** + * Gets the current number of all active streams. + * @return The current number of all active streams. + * @throws IOException If some I/O error occurs. + * @throws LscpException If LSCP protocol corruption occurs. + * @throws LSException If some other error occurs. + */ + public synchronized int + getTotalStreamCount() throws IOException, LscpException, LSException { + verifyConnection(); + out.writeLine("GET TOTAL_STREAM_COUNT"); + if(getPrintOnlyMode()) return -1; + + String s = getSingleLineResultSet().getResult(); + return parseInt(s); + } + + /** * Gets the current number of all active voices. * @return The current number of all active voices. * @throws IOException If some I/O error occurs. @@ -4914,6 +5056,86 @@ ResultSet rs = getEmptyResultSet(); } + /** + * Gets the number of instruments in the specified instrument file. + * @param filename The absolute path name of the instrument file. + * @return The number of instruments in the specified instrument file. + * @throws IOException If some I/O error occurs. + * @throws LscpException If LSCP protocol corruption occurs. + * @throws LSException If the file is not found, or other error occur. + */ + public synchronized int + getFileInstrumentCount(String filename) throws IOException, LscpException, LSException { + verifyConnection(); + out.writeLine("GET FILE INSTRUMENTS '" + filename +"'"); + if(getPrintOnlyMode()) return -1; + + String s = getSingleLineResultSet().getResult(); + return parseInt(s); + } + + /** + * Gets information about the instrument with index + * instrIdx in the specified instrument file. + * @param filename The absolute path name of the instrument file. + * @param instrIdx The index of the instrument in the specified instrument file. + * @throws IOException If some I/O error occurs. + * @throws LscpException If LSCP protocol corruption occurs. + * @throws LSException If failed to retrieve information. + */ + public synchronized Instrument + getFileInstrumentInfo(String filename, int instrIdx) + throws IOException, LscpException, LSException { + + verifyConnection(); + out.writeLine("GET FILE INSTRUMENT INFO '" + filename + "' " + String.valueOf(instrIdx)); + if(getPrintOnlyMode()) return null; + + ResultSet rs = getMultiLineResultSet(); + Instrument instr = new FileInstrument(rs.getMultiLineResult()) { }; + + return instr; + } + + /** + * Gets the list of instruments in the specified instrument file. + * @param filename The absolute path name of the instrument file. + * @return An Instrument array providing + * information about all instruments in the specified instrument file. + * @throws IOException If some I/O error occurs. + * @throws LscpException If LSCP protocol corruption occurs. + * @throws LSException If the specified file name is invalid. + */ + public synchronized Instrument[] + getFileInstruments(String filename) throws IOException, LscpException, LSException { + int l = getFileInstrumentCount(filename); + if(l < 0) return null; + Instrument[] instrS = new FileInstrument[l]; + + for(int i = 0; i < instrS.length; i++) { + instrS[i] = getFileInstrumentInfo(filename, i); + } + return instrS; + } + + private static class FileInstrument extends AbstractInstrument { + FileInstrument(String[] resultSet) throws LscpException { + super(resultSet); + } + + public String + getEngine() { + // TODO: engine lookup? + return getFormatFamily(); + } + + public boolean + parse(String s) throws LscpException { + if(s.startsWith("PRODUCT: ") || s.startsWith("ARTISTS: ")) return true; + return super.parse(s); + } + } + private void getEmptyResultSets(int count, String err) throws LSException { StringBuffer sb = new StringBuffer();