/* * jlscp - a java LinuxSampler control protocol API * * Copyright (C) 2005-2011 Grigor Iliev * * This file is part of jlscp. * * jlscp is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 * as published by the Free Software Foundation. * * jlscp 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 jlscp; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA */ package org.linuxsampler.lscp; import java.io.IOException; import java.io.OutputStream; import java.net.InetSocketAddress; import java.net.Socket; import java.net.SocketTimeoutException; import java.util.ArrayList; import java.util.TreeMap; import java.util.Vector; import java.util.logging.Level; import java.util.logging.Logger; import org.linuxsampler.lscp.event.*; import static org.linuxsampler.lscp.Parser.*; /** * This class is the abstraction representing a client endpoint for communication with LinuxSampler * instance. Since it implements all commands specified in the LSCP protocol v1.5, for more * information look at the * LSCP specification. * *

The following code establishes connection to LinuxSampler instance and gets the * LinuxSampler version: *

 *	try {
 *		Client client = new Client();
 *		client.connect();
 *		
 *		String version = client.getServerInfo().getVersion();
 *		System.out.println(version);
 *		
 *		client.disconnect();
 *	} catch(Exception x) { x.printStackTrace(); }
 * 
*

* *

For more examples look at the examples directory * located in the jlscp distribution.

* * All methods are thread safe. * @author Grigor Iliev */ public class Client { private String address; private int port; private Socket sock = null; private int soTimeout = 20000; private LscpInputStream in = null; private LscpOutputStream out = null; private EventThread eventThread; private boolean printOnlyMode = false; public enum ResultSetType { EMPTY, SINGLE_LINE, MULTI_LINE } private static class ResultSetEntry { public ResultSetType type; public ResultSetEntry(ResultSetType type) { this.type = type; } } private Vector resultSetQueue = new Vector(); /* Used for caching the engines' info */ private final TreeMap engineMap = new TreeMap(); class EventThread extends Thread { private Vector queue = new Vector(); private boolean terminate = false; EventThread() { super("LSCP-Event-Thread"); } @Override public void run() { while(!mustTerminate()) { try { processQueue(); processNotifications(); } catch(Exception x) { getLogger().log(Level.FINE, x.getMessage(), x); } try { synchronized(this) { wait(100); } } catch(Exception x) { getLogger().log(Level.FINE, x.getMessage(), x); } } } private synchronized boolean mustTerminate() { return terminate; } public synchronized void terminate() { terminate = true; this.notifyAll(); } public synchronized void scheduleNotification(String s) { queue.add(s); } private void processQueue() { String[] notifications = popAllNotifications(); for(String n : notifications) fireEvent(n); } private synchronized String[] popAllNotifications() { String[] notifications = queue.toArray(new String[queue.size()]); queue.removeAllElements(); return notifications; } } /** * Creates a new instance of Client with default server address and port. * The default server address and port are 127.0.0.1:8888. */ public Client() { this("127.0.0.1"); } /** * Creates a new instance of Client with the specified address and default port. * The default port is 8888. * @param address The address of linux sampler server. */ public Client(String address) { this(address, 8888); } /** * Creates a new instance of Client with the specified address and port. * @param address The address of the Linux Sampler. * @param port The Linux Sampler port number. */ public Client(String address, int port) { setServerAddress(address); setServerPort(port); eventThread = new EventThread(); } /** * Creates a new instance of Client. * @param printOnlyMode Determines whether the client will be in print-only mode. */ public Client(boolean printOnlyMode) { if(printOnlyMode) setPrintOnlyMode(true); } private boolean extendedCharacterEscaping = true; /** * Sets whether strings sent to LinuxSampler should be more aggressively escaped. */ public synchronized void setExtendedCharacterEscaping(boolean b) { extendedCharacterEscaping = b; } /** * Determines whether strings sent to LinuxSampler should be more aggressively escaped. */ public synchronized boolean getExtendedCharacterEscaping() { return extendedCharacterEscaping; } /** * @see java.net.Socket#setSoTimeout */ public synchronized void setSoTimeout(int timeout) { soTimeout = timeout; try { if(sock != null) sock.setSoTimeout(timeout); } catch(Exception x) { getLogger().log(Level.INFO, "Unable to set timeout", x); } } private String toEscapedText(String s) { s = toEscapedString(s); return conv(s); } private String toEscapedFsEntry(String s) { s = toEscapedFileName(s); return conv(s); } /** * Applies an extended character escaping to the specified string if needed. */ private String conv(String s) { return getExtendedCharacterEscaping() ? toExtendedEscapeSequence(s) : s; } /** * Determines whether the client is in print-only mode. * Print-only mode means that the client will just print all * LSCP commands to the specified output stream or to the standard output stream * (java.lang.System.out) if no output stream is specified, * without taking any further actions. Thus, in print-only mode all returned * values by Client's methods are meaningless and should be discarded. * @return true if the client is in * print-only mode, false otherwise. * @see #setPrintOnlyModeOutputStream */ public synchronized boolean getPrintOnlyMode() { return printOnlyMode; } /** * Sets the print-only mode. Note that in print-only mode all returned * values by Client's methods are meaningless and should be discarded. * The default output stream in print-only mode is java.lang.System.out. * @param b If true all LSCP commands will be sent * to the specified output stream or to the standard output stream * (java.lang.System.out) if no output stream is specified, * and no further actions will be taken. * @throws IllegalStateException If the client is connected. * @see #setPrintOnlyModeOutputStream */ public synchronized void setPrintOnlyMode(boolean b) { if(printOnlyMode == b) return; if(isConnected()) throw new IllegalStateException(); printOnlyMode = b; if(b) out = new LscpOutputStream(System.out); } /** * Sets the output stream to be used in print-only mode. * @param out The output stream to be used in print-only mode. * @throws IllegalStateException If the client is not in print-only mode. * @throws IllegalArgumentException if out is null. * @see #setPrintOnlyMode */ public synchronized void setPrintOnlyModeOutputStream(OutputStream out) { if(!getPrintOnlyMode()) throw new IllegalStateException("Not in print-only mode"); if(out == null) throw new IllegalArgumentException("out must be non-null"); this.out = new LscpOutputStream(out); } /** * Specifies the jlscp version. * @return The jlscp version. */ public static String getClientVersion() { return Package.getPackage("org.linuxsampler.lscp").getImplementationVersion(); } /** * Gets the Linux Sampler address. * @return The Linux Sampler address. */ public synchronized String getServerAddress() { return address; } /** * Sets the Linux Sampler address. * @param address The Linux Sampler address. * If address is null sets to default address - 127.0.0.1. */ public synchronized void setServerAddress(String address) { this.address = (address == null ? "127.0.0.1" : address); } /** * Gets the Linux Sampler port number. * @return The Linux Sampler port number. */ public synchronized int getServerPort() { return port; } /** * Sets the Linux Sampler port number. * @param port The Linux Sampler port number. */ public synchronized void setServerPort(int port) { this.port = port; } /** * Connects to the LinuxSampler. If there is already established connection then * the currently available connection is closed berfore connecting. * @throws LscpException If timeout occurs or any other I/O exception. */ public synchronized void connect() throws LscpException { if(sock != null) disconnect(); if(getPrintOnlyMode()) return; engineMap.clear(); // Initializing LSCP event thread if(eventThread.isAlive()) { getLogger().warning("LSCP event thread already running!"); eventThread.terminate(); } if(eventThread.getState() != Thread.State.NEW) eventThread = new EventThread(); /////// InetSocketAddress sockAddr = null; try { sockAddr = new InetSocketAddress(address, port); } catch(IllegalArgumentException x) { String s = String.valueOf(port); throw new LscpException(LscpI18n.getLogMsg("Client.invalidPort!", s), x); } if(sockAddr.isUnresolved()) throw new LscpException ( LscpI18n.getLogMsg("Client.unknownHost!", address) ); try { sock = new Socket(); sock.bind(null); sock.connect(sockAddr, soTimeout); sock.setSoTimeout(soTimeout); sock.setTcpNoDelay(true); in = new LscpInputStream(sock.getInputStream()); out = new LscpOutputStream(sock.getOutputStream()); } catch(SocketTimeoutException x) { throw new LscpException(LscpI18n.getLogMsg("Client.conTimeout!"), x); } catch(Exception x) { throw new LscpException ( LscpI18n.getLogMsg("Client.connectionFailed!"), x ); } String s = Package.getPackage("org.linuxsampler.lscp").getSpecificationVersion(); String s2, sv, sv2; try { s2 = s.substring(0, s.indexOf('.')); sv = getServerInfo().getProtocolVersion(); sv2 = sv.substring(0, sv.indexOf('.')); } catch(Exception x) { disconnect(); throw new LscpException ( LscpI18n.getLogMsg("Client.connectionFailed!"), x ); } if(!sv2.equals(s2)) { disconnect(); throw new LscpException ( LscpI18n.getLogMsg("Client.incompatibleLscpVersion!", sv) ); } s2 = s.substring(s.indexOf('.')); sv2 = sv.substring(sv.indexOf('.')); if(sv2.compareToIgnoreCase(s2) < 0) getLogger().info ( LscpI18n.getLogMsg("Client.incompatibleLscpMinVersion!", sv) ); if(hasSubscriptions()) eventThread.start(); if(!llM.isEmpty()) subscribe("MISCELLANEOUS"); if(!llAODC.isEmpty()) subscribe("AUDIO_OUTPUT_DEVICE_COUNT"); if(!llAODI.isEmpty()) subscribe("AUDIO_OUTPUT_DEVICE_INFO"); if(!llMIDC.isEmpty()) subscribe("MIDI_INPUT_DEVICE_COUNT"); if(!llMIDI.isEmpty()) subscribe("MIDI_INPUT_DEVICE_INFO"); if(!llBF.isEmpty()) subscribe("BUFFER_FILL"); if(!llCC.isEmpty()) subscribe("CHANNEL_COUNT"); if(!llCI.isEmpty()) subscribe("CHANNEL_INFO"); if(!llFSC.isEmpty()) subscribe("FX_SEND_COUNT"); 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"); if(!llMIC.isEmpty()) subscribe("MIDI_INSTRUMENT_COUNT"); if(!llMII.isEmpty()) subscribe("MIDI_INSTRUMENT_INFO"); if(!llDMD.isEmpty()) subscribe("DEVICE_MIDI"); if(!llCMD.isEmpty()) subscribe("CHANNEL_MIDI"); if(!llID.isEmpty()) { subscribe("DB_INSTRUMENT_DIRECTORY_COUNT"); subscribe("DB_INSTRUMENT_DIRECTORY_INFO"); subscribe("DB_INSTRUMENT_COUNT"); subscribe("DB_INSTRUMENT_INFO"); subscribe("DB_INSTRUMENTS_JOB_INFO"); } if(!llGI.isEmpty()) subscribe("GLOBAL_INFO"); if(!llEIC.isEmpty()) subscribe("EFFECT_INSTANCE_COUNT"); if(!llEII.isEmpty()) subscribe("EFFECT_INSTANCE_INFO"); if(!llSECC.isEmpty()) subscribe("SEND_EFFECT_CHAIN_COUNT"); if(!llSECI.isEmpty()) subscribe("SEND_EFFECT_CHAIN_INFO"); } /** * Closes the connection to LinuxSampler. */ public synchronized void disconnect() { if(getPrintOnlyMode()) return; try { if(sock != null) sock.close(); } catch(Exception x) { getLogger().log(Level.FINE, x.getMessage(), x); } sock = null; if(eventThread.getState() != Thread.State.NEW) { eventThread.terminate(); eventThread = new EventThread(); } engineMap.clear(); } /** * Determines whether the client is connected. * @return true if there is established connection, * false otherwise. */ public synchronized boolean isConnected() { if(sock == null) return false; else return sock.isConnected(); } /** * Verifies that there is established connection. * @throws IOException If the connection is not established. */ private void verifyConnection() throws IOException { if(getPrintOnlyMode()) return; if(!isConnected()) throw new IOException(LscpI18n.getLogMsg("Client.notConnected!")); } private String getLine() throws IOException, LscpException { String s; for(;;) { s = in.readLine(); if(s.startsWith("NOTIFY:")) { eventThread.scheduleNotification(s.substring("NOTIFY:".length())); } else break; } return s; } /** Processes the notifications sent by LinuxSampler */ private synchronized void processNotifications() throws IOException, LscpException { while(in.available() > 0) { String s = in.readLine(); if(s.startsWith("NOTIFY:")) fireEvent(s.substring("NOTIFY:".length())); else getLogger().severe("Unknown notification format: " + s); } } private synchronized void processResultSetQueue() { for(int i = 0; i < resultSetQueue.size(); i++) { try { switch(resultSetQueue.get(i).type) { case EMPTY: getEmptyResultSet(); break; case SINGLE_LINE: getSingleLineResultSet(); break; case MULTI_LINE: getMultiLineResultSet(); break; default: getLogger().severe("Unknown result set type"); } } catch(Exception x) { getLogger().log(Level.FINE, "Error while processing result set queue", x); } } resultSetQueue.removeAllElements(); } /** * Gets empty result set. * @return ResultSet instance. */ private ResultSet getEmptyResultSet() throws IOException, LscpException, LSException { processResultSetQueue(); return parseEmptyResultSet(getLine()); } private ResultSet getSingleLineResultSet() throws IOException, LscpException, LSException { processResultSetQueue(); ResultSet rs = new ResultSet(); String ln = getLine(); if(ln.startsWith("WRN")) { parseWarning(ln, rs); getLogger().warning(rs.getMessage()); return rs; } else if(ln.startsWith("ERR")) { parseError(ln, rs); throw new LSException(rs.getCode(), rs.getMessage()); } else { rs.setResult(ln); return rs; } } private ResultSet getMultiLineResultSet() throws IOException, LscpException, LSException { processResultSetQueue(); ResultSet rs = new ResultSet(); String ln = getLine(); if(ln.startsWith("WRN")) { parseWarning(ln, rs); getLogger().warning(rs.getMessage()); return rs; } else if(ln.startsWith("ERR")) { parseError(ln, rs); throw new LSException(rs.getCode(), rs.getMessage()); } while(!ln.equals(".")) { rs.addLine(ln); ln = getLine(); } return rs; } /** Audio output device count listeners */ private final Vector llAODC = new Vector(); /** Audio output device info listeners */ private final Vector llAODI = new Vector(); private final Vector llBF = new Vector(); private final Vector llCC = new Vector(); private final Vector llCI = new Vector(); private final Vector llFSC = new Vector(); private final Vector llFSI = new Vector(); private final Vector llM = new Vector(); /** MIDI input device count listeners */ private final Vector llMIDC = new Vector(); /** MIDI input device info listeners */ 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 */ private final Vector llMIMC = new Vector(); /** MIDI instrument map info listeners */ private final Vector llMIMI = new Vector(); /** MIDI instrument count listeners */ private final Vector llMIC = new Vector(); /** MIDI instrument info listeners */ private final Vector llMII = new Vector(); private final Vector llDMD = new Vector(); private final Vector llCMD = new Vector(); private final Vector llID = new Vector(); private final Vector llGI = new Vector(); private final ArrayList llEIC = new ArrayList(); private final Vector llEII = new Vector(); private final Vector llSECC = new Vector(); private final Vector llSECI = new Vector(); /** * Determines whether there is at least one subscription for notification events. * Do not forget to check for additional listeners if the LSCP specification * is extended in the future. * @return true if there is at least one subscription for notification events, * false otherwise. */ private boolean hasSubscriptions() { return !llAODC.isEmpty() || !llAODI.isEmpty() || !llBF.isEmpty() || !llCC.isEmpty() || !llCI.isEmpty() || !llFSC.isEmpty() || !llFSI.isEmpty() || !llM.isEmpty() || !llMIDC.isEmpty() || !llMIDI.isEmpty() || !llSC.isEmpty() || !llVC.isEmpty() || !llTSC.isEmpty() || !llTVC.isEmpty() || !llMIMC.isEmpty() || !llMIMI.isEmpty() || !llMIC.isEmpty() || !llMII.isEmpty() || !llDMD.isEmpty() || !llCMD.isEmpty() || !llID.isEmpty() || !llGI.isEmpty() || !llEIC.isEmpty() || !llEII.isEmpty() || !llSECC.isEmpty() || !llSECI.isEmpty(); } private synchronized void fireDeviceMidiDataEvent(String s) { try { String[] list = parseList(s, ' '); if(list.length != 5) { getLogger().warning("Unknown DEVICE_MIDI format"); return; } int dev = parseInt(list[0]); int port = parseInt(list[1]); MidiDataEvent.Type type = parseMidiDataType(list[2]); if(type == null) return; int note = parseInt(list[3]); int velocity = parseInt(list[4]); DeviceMidiDataEvent e = new DeviceMidiDataEvent(this, type, note, velocity); e.setDeviceId(dev); e.setPortId(port); for(DeviceMidiDataListener l : llDMD) l.midiDataArrived(e); } catch(LscpException x) { getLogger().log ( Level.WARNING, LscpI18n.getLogMsg("CommandFailed!"), x ); } } private synchronized void fireChannelMidiDataEvent(String s) { try { String[] list = parseList(s, ' '); if(list.length != 4) { getLogger().warning("Unknown CHANNEL_MIDI format"); return; } int channel = parseInt(list[0]); MidiDataEvent.Type type = parseMidiDataType(list[1]); if(type == null) return; int note = parseInt(list[2]); int velocity = parseInt(list[3]); ChannelMidiDataEvent e = new ChannelMidiDataEvent(this, type, note, velocity); e.setChannelId(channel); for(ChannelMidiDataListener l : llCMD) l.midiDataArrived(e); } catch(LscpException x) { getLogger().log ( Level.WARNING, LscpI18n.getLogMsg("CommandFailed!"), x ); } } private MidiDataEvent.Type parseMidiDataType(String s) { if("NOTE_ON".equals(s)) return MidiDataEvent.Type.NOTE_ON; if("NOTE_OFF".equals(s)) return MidiDataEvent.Type.NOTE_OFF; if("CC".equals(s)) return MidiDataEvent.Type.CC; getLogger().warning("Unknown MIDI data type: " + s); return null; } private synchronized void fireEvent(String s) { // Sort by priority if(s.startsWith("CHANNEL_MIDI:")) { s = s.substring("CHANNEL_MIDI:".length()); fireChannelMidiDataEvent(s); } else if(s.startsWith("DEVICE_MIDI:")) { s = s.substring("DEVICE_MIDI:".length()); fireDeviceMidiDataEvent(s); } else if(s.startsWith("DB_INSTRUMENT_DIRECTORY_COUNT:")) { s = s.substring("DB_INSTRUMENT_DIRECTORY_COUNT:".length()); InstrumentsDbEvent e = new InstrumentsDbEvent(this, s); for(InstrumentsDbListener l : llID) l.directoryCountChanged(e); } else if(s.startsWith("DB_INSTRUMENT_DIRECTORY_INFO:")) { InstrumentsDbEvent e; s = s.substring("DB_INSTRUMENT_DIRECTORY_INFO:".length()); if(s.startsWith("NAME ")) { String[] list; try { 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); } } catch(LscpException x) { getLogger().log ( Level.WARNING, LscpI18n.getLogMsg("CommandFailed!"), x ); } } else { e = new InstrumentsDbEvent(this, s); for(InstrumentsDbListener l : llID) l.directoryInfoChanged(e); } } else if(s.startsWith("DB_INSTRUMENT_COUNT:")) { s = s.substring("DB_INSTRUMENT_COUNT:".length()); InstrumentsDbEvent e = new InstrumentsDbEvent(this, s); for(InstrumentsDbListener l : llID) l.instrumentCountChanged(e); } else if(s.startsWith("DB_INSTRUMENT_INFO:")) { InstrumentsDbEvent e; s = s.substring("DB_INSTRUMENT_INFO:".length()); if(s.startsWith("NAME ")) { String[] list; try { 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); } } catch(LscpException x) { getLogger().log ( Level.WARNING, LscpI18n.getLogMsg("CommandFailed!"), x ); } } else { e = new InstrumentsDbEvent(this, s); for(InstrumentsDbListener l : llID) l.instrumentInfoChanged(e); } } else if(s.startsWith("DB_INSTRUMENTS_JOB_INFO:")) { s = s.substring("DB_INSTRUMENTS_JOB_INFO:".length()); try { int i = Integer.parseInt(s); InstrumentsDbEvent e = new InstrumentsDbEvent(this, i); for(InstrumentsDbListener l : llID) l.jobStatusChanged(e); } catch(NumberFormatException x) { s = "Unknown DB_INSTRUMENTS_JOB_INFO format"; getLogger().log(Level.WARNING, s, x); } } else if(s.startsWith("CHANNEL_COUNT:")) { try { int i = Integer.parseInt(s.substring("CHANNEL_COUNT:".length())); ChannelCountEvent e = new ChannelCountEvent(this, i); for(ChannelCountListener l : llCC) l.channelCountChanged(e); } catch(NumberFormatException x) { getLogger().log ( Level.WARNING, LscpI18n.getLogMsg("CommandFailed!"), x ); } } else if(s.startsWith("VOICE_COUNT:")) { try { s = s.substring("VOICE_COUNT:".length()); Integer[] i = parseIntList(s, ' '); if(i.length != 2) { getLogger().warning("Unknown VOICE_COUNT format"); return; } VoiceCountEvent e = new VoiceCountEvent(this, i[0], i[1]); for(VoiceCountListener l : llVC) l.voiceCountChanged(e); } catch(Exception x) { getLogger().log(Level.WARNING, "Unknown VOICE_COUNT format", x); } } else if(s.startsWith("STREAM_COUNT:")) { try { s = s.substring("STREAM_COUNT:".length()); Integer[] i = parseIntList(s, ' '); if(i.length != 2) { getLogger().warning("Unknown STREAM_COUNT format"); return; } StreamCountEvent e = new StreamCountEvent(this, i[0], i[1]); for(StreamCountListener l : llSC) l.streamCountChanged(e); } catch(Exception x) { getLogger().log(Level.WARNING, "Unknown STREAM_COUNT format", x); } } else if(s.startsWith("BUFFER_FILL:")) { try { s = s.substring("BUFFER_FILL:".length()); int i = s.indexOf(' '); if(i == -1) { getLogger().warning("Unknown BUFFER_FILL format"); return; } int j = Integer.parseInt(s.substring(0, i)); Vector v = getChannelBufferFillPercentage(s.substring(i + 1)); BufferFillEvent e = new BufferFillEvent(this, j, v); for(BufferFillListener l : llBF) l.bufferFillChanged(e); } catch(Exception x) { getLogger().log(Level.WARNING, "Unknown BUFFER_FILL format", x); } } else if(s.startsWith("CHANNEL_INFO:")) { try { int i = Integer.parseInt(s.substring("CHANNEL_INFO:".length())); ChannelInfoEvent e = new ChannelInfoEvent(this, i); for(ChannelInfoListener l : llCI) l.channelInfoChanged(e); } 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()); int i = Integer.parseInt(s); TotalVoiceCountEvent e = new TotalVoiceCountEvent(this, i); for(TotalVoiceCountListener l : llTVC) l.totalVoiceCountChanged(e); } catch(NumberFormatException x) { getLogger().log ( Level.WARNING, "Unknown TOTAL_VOICE_COUNT format", x ); } } else if(s.startsWith("AUDIO_OUTPUT_DEVICE_COUNT:")) { try { s = s.substring("AUDIO_OUTPUT_DEVICE_COUNT:".length()); int i = Integer.parseInt(s); ItemCountEvent e = new ItemCountEvent(this, i); for(ItemCountListener l : llAODC) l.itemCountChanged(e); } catch(NumberFormatException x) { getLogger().log ( Level.WARNING, "Unknown AUDIO_OUTPUT_DEVICE_COUNT format", x ); } } else if(s.startsWith("AUDIO_OUTPUT_DEVICE_INFO:")) { try { s = s.substring("AUDIO_OUTPUT_DEVICE_INFO:".length()); int i = Integer.parseInt(s); ItemInfoEvent e = new ItemInfoEvent(this, i); for(ItemInfoListener l : llAODI) l.itemInfoChanged(e); } catch(NumberFormatException x) { getLogger().log ( Level.WARNING, "Unknown AUDIO_OUTPUT_DEVICE_INFO format", x ); } } else if(s.startsWith("MIDI_INPUT_DEVICE_COUNT:")) { try { s = s.substring("MIDI_INPUT_DEVICE_COUNT:".length()); int i = Integer.parseInt(s); ItemCountEvent e = new ItemCountEvent(this, i); for(ItemCountListener l : llMIDC) l.itemCountChanged(e); } catch(NumberFormatException x) { getLogger().log ( Level.WARNING, "Unknown MIDI_INPUT_DEVICE_COUNT format", x ); } } else if(s.startsWith("MIDI_INPUT_DEVICE_INFO:")) { try { s = s.substring("MIDI_INPUT_DEVICE_INFO:".length()); int i = Integer.parseInt(s); ItemInfoEvent e = new ItemInfoEvent(this, i); for(ItemInfoListener l : llMIDI) l.itemInfoChanged(e); } catch(NumberFormatException x) { getLogger().log ( Level.WARNING, "Unknown MIDI_INPUT_DEVICE_INFO format", x ); } } else if(s.startsWith("MIDI_INSTRUMENT_MAP_COUNT:")) { try { s = s.substring("MIDI_INSTRUMENT_MAP_COUNT:".length()); int i = Integer.parseInt(s); ItemCountEvent e = new ItemCountEvent(this, i); for(ItemCountListener l : llMIMC) l.itemCountChanged(e); } catch(NumberFormatException x) { getLogger().log ( Level.WARNING, "Unknown MIDI_INSTRUMENT_MAP_COUNT format", x ); } } else if(s.startsWith("MIDI_INSTRUMENT_MAP_INFO:")) { try { s = s.substring("MIDI_INSTRUMENT_MAP_INFO:".length()); int i = Integer.parseInt(s); ItemInfoEvent e = new ItemInfoEvent(this, i); for(ItemInfoListener l : llMIMI) l.itemInfoChanged(e); } catch(NumberFormatException x) { getLogger().log ( Level.WARNING, "Unknown MIDI_INSTRUMENT_MAP_INFO format", x ); } } else if(s.startsWith("MIDI_INSTRUMENT_COUNT:")) { try { s = s.substring("MIDI_INSTRUMENT_COUNT:".length()); Integer[] i = parseIntList(s, ' '); if(i.length != 2) { getLogger().warning("Unknown MIDI_INSTRUMENT_COUNT format"); return; } MidiInstrumentCountEvent e = new MidiInstrumentCountEvent(this, i[0], i[1]); for(MidiInstrumentCountListener l : llMIC) { l.instrumentCountChanged(e); } } catch(Exception x) { getLogger().log ( Level.WARNING, "Unknown MIDI_INSTRUMENT_COUNT format", x ); } } else if(s.startsWith("MIDI_INSTRUMENT_INFO:")) { try { s = s.substring("MIDI_INSTRUMENT_INFO:".length()); Integer[] i = parseIntList(s, ' '); if(i.length != 3) { getLogger().warning("Unknown MIDI_INSTRUMENT_INFO format"); return; } MidiInstrumentInfoEvent e = new MidiInstrumentInfoEvent(this, i[0], i[1], i[2]); for(MidiInstrumentInfoListener l : llMII) { l.instrumentInfoChanged(e); } } catch(Exception x) { getLogger().log ( Level.WARNING, "Unknown MIDI_INSTRUMENT_INFO format", x ); } } else if(s.startsWith("FX_SEND_COUNT:")) { try { s = s.substring("FX_SEND_COUNT:".length()); Integer[] i = parseIntList(s, ' '); if(i.length != 2) { getLogger().warning("Unknown FX_SEND_COUNT format"); return; } FxSendCountEvent e = new FxSendCountEvent(this, i[0], i[1]); for(FxSendCountListener l : llFSC) l.fxSendCountChanged(e); } catch(Exception x) { getLogger().log(Level.WARNING, "Unknown FX_SEND_COUNT format", x); } } else if(s.startsWith("FX_SEND_INFO:")) { try { s = s.substring("FX_SEND_INFO:".length()); Integer[] i = parseIntList(s, ' '); if(i.length != 2) { getLogger().warning("Unknown FX_SEND_INFO format"); return; } FxSendInfoEvent e = new FxSendInfoEvent(this, i[0], i[1]); for(FxSendInfoListener l : llFSI) { l.fxSendInfoChanged(e); } } catch(Exception x) { getLogger().log(Level.WARNING, "Unknown FX_SEND_INFO format", x); } } else if(s.startsWith("EFFECT_INSTANCE_COUNT:")) { try { s = s.substring("EFFECT_INSTANCE_COUNT:".length()); int i = Integer.parseInt(s); EffectInstanceCountEvent e = new EffectInstanceCountEvent(this, i); for(EffectInstanceCountListener l : llEIC) { l.effectInstanceCountChanged(e); } } catch(Exception x) { getLogger().log(Level.WARNING, "Unknown EFFECT_INSTANCE_COUNT format", x); } } else if(s.startsWith("EFFECT_INSTANCE_INFO:")) { try { s = s.substring("EFFECT_INSTANCE_INFO:".length()); int i = Integer.parseInt(s); EffectInstanceInfoEvent e = new EffectInstanceInfoEvent(this, i); for(EffectInstanceInfoListener l : llEII) { l.effectInstanceInfoChanged(e); } } catch(Exception x) { getLogger().log(Level.WARNING, "Unknown EFFECT_INSTANCE_INFO format", x); } } else if(s.startsWith("SEND_EFFECT_CHAIN_COUNT:")) { try { s = s.substring("SEND_EFFECT_CHAIN_COUNT:".length()); Integer[] i = parseIntList(s, ' '); if(i.length != 2) { getLogger().warning("Unknown SEND_EFFECT_CHAIN_COUNT format"); return; } SendEffectChainCountEvent e = new SendEffectChainCountEvent(this, i[0], i[1]); for(SendEffectChainCountListener l : llSECC) { l.sendEffectChainCountChanged(e); } } catch(Exception x) { getLogger().log(Level.WARNING, "Unknown SEND_EFFECT_CHAIN_COUNT format", x); } } else if(s.startsWith("SEND_EFFECT_CHAIN_INFO:")) { try { s = s.substring("SEND_EFFECT_CHAIN_INFO:".length()); Integer[] i = parseIntList(s, ' '); if(i.length != 3) { getLogger().warning("Unknown SEND_EFFECT_CHAIN_INFO format"); return; } SendEffectChainInfoEvent e = new SendEffectChainInfoEvent(this, i[0], i[1], i[2]); for(SendEffectChainInfoListener l : llSECI) { l.sendEffectChainInfoChanged(e); } } catch(Exception x) { getLogger().log(Level.WARNING, "Unknown SEND_EFFECT_CHAIN_INFO format", x); } } else if(s.startsWith("GLOBAL_INFO:")) { handleGlobalInfoEvent(s.substring("GLOBAL_INFO:".length())); } else if(s.startsWith("MISCELLANEOUS:")) { s = s.substring("MISCELLANEOUS:".length()); MiscellaneousEvent e = new MiscellaneousEvent(this, s); for(MiscellaneousListener l : llM) l.miscEventOccured(e); } } private void handleGlobalInfoEvent(String s) { try { if(s.startsWith("VOLUME ")) { float f = Float.parseFloat(s.substring("VOLUME ".length())); GlobalInfoEvent e = new GlobalInfoEvent(this, f); for(GlobalInfoListener l : llGI) l.volumeChanged(e); } else if(s.startsWith("VOICES ")) { int i = Integer.parseInt(s.substring("VOICES ".length())); GlobalInfoEvent e = new GlobalInfoEvent(this, i, -1); for(GlobalInfoListener l : llGI) l.voiceLimitChanged(e); } else if(s.startsWith("STREAMS ")) { int i = Integer.parseInt(s.substring("STREAMS ".length())); GlobalInfoEvent e = new GlobalInfoEvent(this, -1, i); for(GlobalInfoListener l : llGI) l.streamLimitChanged(e); } else { getLogger().info("Unknown GLOBAL_INFO format: " + s); } } catch(NumberFormatException x) { getLogger().log(Level.WARNING, "Unknown GLOBAL_INFO format", x); } } private void subscribe(String event) { if(!getPrintOnlyMode()) { if(!isConnected()) return; if(!eventThread.isAlive()) eventThread.start(); } try { out.writeLine("SUBSCRIBE " + event); if(!getPrintOnlyMode()) getEmptyResultSet(); } catch(Exception x) { getLogger().log ( Level.WARNING, LscpI18n.getLogMsg("Client.subscriptionFailed!", event), x ); } } private void unsubscribe(String event) { if(!getPrintOnlyMode() && !isConnected()) return; try { out.writeLine("UNSUBSCRIBE " + event); if(!getPrintOnlyMode()) getEmptyResultSet(); } catch(Exception x) { getLogger().log ( Level.WARNING, LscpI18n.getLogMsg("Client.unsubscriptionFailed!", event), x ); } } /** * Registers the specified listener for receiving event messages. * Listeners can be registered regardless of the connection state. * @param l The ItemCountListener to register. */ public synchronized void addAudioDeviceCountListener(ItemCountListener l) { if(llAODC.isEmpty()) subscribe("AUDIO_OUTPUT_DEVICE_COUNT"); llAODC.add(l); } /** * Removes the specified listener. * Listeners can be removed regardless of the connection state. * @param l The ItemCountListener to remove. */ public synchronized void removeAudioDeviceCountListener(ItemCountListener l) { boolean b = llAODC.remove(l); if(b && llAODC.isEmpty()) unsubscribe("AUDIO_OUTPUT_DEVICE_COUNT"); } /** * Registers the specified listener for receiving event messages. * Listeners can be registered regardless of the connection state. * @param l The ItemInfoListener to register. */ public synchronized void addAudioDeviceInfoListener(ItemInfoListener l) { if(llAODI.isEmpty()) subscribe("AUDIO_OUTPUT_DEVICE_INFO"); llAODI.add(l); } /** * Removes the specified listener. * Listeners can be removed regardless of the connection state. * @param l The ItemInfoListener to remove. */ public synchronized void removeAudioDeviceInfoListener(ItemInfoListener l) { boolean b = llAODI.remove(l); if(b && llAODI.isEmpty()) unsubscribe("AUDIO_OUTPUT_DEVICE_INFO"); } /** * Registers the specified listener for receiving event messages. * Listeners can be removed regardless of the connection state. * @param l The BufferFillListener to register. */ public synchronized void addBufferFillListener(BufferFillListener l) { if(llBF.isEmpty()) subscribe("BUFFER_FILL"); llBF.add(l); } /** * Removes the specified listener. * Listeners can be removed regardless of the connection state. * @param l The BufferFillListener to remove. */ public synchronized void removeBufferFillListener(BufferFillListener l) { boolean b = llBF.remove(l); if(b && llBF.isEmpty()) unsubscribe("BUFFER_FILL"); } /** * Registers the specified listener for receiving event messages. * Listeners can be registered regardless of the connection state. * @param l The ChannelCountListener to register. */ public synchronized void addChannelCountListener(ChannelCountListener l) { if(llCC.isEmpty()) subscribe("CHANNEL_COUNT"); llCC.add(l); } /** * Removes the specified listener. * Listeners can be removed regardless of the connection state. * @param l The ChannelCountListener to remove. */ public synchronized void removeChannelCountListener(ChannelCountListener l) { boolean b = llCC.remove(l); if(b && llCC.isEmpty()) unsubscribe("CHANNEL_COUNT"); } /** * Registers the specified listener for receiving event messages. * Listeners can be registered regardless of the connection state. * @param l The ChannelInfoListener to register. */ public synchronized void addChannelInfoListener(ChannelInfoListener l) { if(llCI.isEmpty()) subscribe("CHANNEL_INFO"); llCI.add(l); } /** * Removes the specified listener. * Listeners can be removed regardless of the connection state. * @param l The ChannelInfoListener to remove. */ public synchronized void removeChannelInfoListener(ChannelInfoListener l) { boolean b = llCI.remove(l); if(b && llCI.isEmpty()) unsubscribe("CHANNEL_INFO"); } /** * Registers the specified listener for receiving event messages. * Listeners can be registered regardless of the connection state. * @param l The FxSendCountListener to register. */ public synchronized void addFxSendCountListener(FxSendCountListener l) { if(llFSC.isEmpty()) subscribe("FX_SEND_COUNT"); llFSC.add(l); } /** * Removes the specified listener. * Listeners can be removed regardless of the connection state. * @param l The FxSendCountListener to remove. */ public synchronized void removeFxSendCountListener(FxSendCountListener l) { boolean b = llFSC.remove(l); if(b && llFSC.isEmpty()) unsubscribe("FX_SEND_COUNT"); } /** * Registers the specified listener for receiving event messages. * Listeners can be registered regardless of the connection state. * @param l The FxSendInfoListener to register. */ public synchronized void addFxSendInfoListener(FxSendInfoListener l) { if(llFSI.isEmpty()) subscribe("FX_SEND_INFO"); llFSI.add(l); } /** * Removes the specified listener. * Listeners can be removed regardless of the connection state. * @param l The FxSendInfoListener to remove. */ public synchronized void removeFxSendInfoListener(FxSendInfoListener l) { boolean b = llFSI.remove(l); if(b && llFSI.isEmpty()) unsubscribe("FX_SEND_INFO"); } /** * Registers the specified listener for receiving event messages. * Listeners can be registered regardless of the connection state. * @param l The ItemCountListener to register. */ public synchronized void addMidiDeviceCountListener(ItemCountListener l) { if(llMIDC.isEmpty()) subscribe("MIDI_INPUT_DEVICE_COUNT"); llMIDC.add(l); } /** * Removes the specified listener. * Listeners can be removed regardless of the connection state. * @param l The ItemCountListener to remove. */ public synchronized void removeMidiDeviceCountListener(ItemCountListener l) { boolean b = llMIDC.remove(l); if(b && llMIDC.isEmpty()) unsubscribe("MIDI_INPUT_DEVICE_COUNT"); } /** * Registers the specified listener for receiving event messages. * Listeners can be registered regardless of the connection state. * @param l The ItemInfoListener to register. */ public synchronized void addMidiDeviceInfoListener(ItemInfoListener l) { if(llMIDI.isEmpty()) subscribe("MIDI_INPUT_DEVICE_INFO"); llMIDI.add(l); } /** * Removes the specified listener. * Listeners can be removed regardless of the connection state. * @param l The ItemInfoListener to remove. */ public synchronized void removeMidiDeviceInfoListener(ItemInfoListener l) { boolean b = llMIDI.remove(l); if(b && llMIDI.isEmpty()) unsubscribe("MIDI_INPUT_DEVICE_INFO"); } /** * Registers the specified listener for receiving event messages. * Listeners can be registered regardless of the connection state. * @param l The MiscellaneousListener to register. */ public synchronized void addMiscellaneousListener(MiscellaneousListener l) { if(llM.isEmpty()) subscribe("MISCELLANEOUS"); llM.add(l); } /** * Removes the specified listener. * Listeners can be removed regardless of the connection state. * @param l The MiscellaneousListener to remove. */ public synchronized void removeMiscellaneousListener(MiscellaneousListener l) { boolean b = llM.remove(l); if(b && llM.isEmpty()) unsubscribe("MISCELLANEOUS"); } /** * Registers the specified listener for receiving event messages. * Listeners can be registered regardless of the connection state. * @param l The StreamCountListener to register. */ public synchronized void addStreamCountListener(StreamCountListener l) { if(llSC.isEmpty()) subscribe("STREAM_COUNT"); llSC.add(l); } /** * Removes the specified listener. * Listeners can be removed regardless of the connection state. * @param l The StreamCountListener to remove. */ public synchronized void removeStreamCountListener(StreamCountListener l) { boolean b = llSC.remove(l); if(b && llSC.isEmpty()) unsubscribe("STREAM_COUNT"); } /** * Registers the specified listener for receiving event messages. * Listeners can be registered regardless of the connection state. * @param l The VoiceCountListener to register. */ public synchronized void addVoiceCountListener(VoiceCountListener l) { if(llVC.isEmpty()) subscribe("VOICE_COUNT"); llVC.add(l); } /** * Removes the specified listener. * Listeners can be removed regardless of the connection state. * @param l The VoiceCountListener to remove. */ public synchronized void removeVoiceCountListener(VoiceCountListener l) { boolean b = llVC.remove(l); if(b && llVC.isEmpty()) unsubscribe("VOICE_COUNT"); } /** * 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 addTotalVoiceCountListener(TotalVoiceCountListener l) { if(llTVC.isEmpty()) subscribe("TOTAL_VOICE_COUNT"); llTVC.add(l); } /** * Removes the specified listener. * Listeners can be removed regardless of the connection state. * @param l The TotalVoiceCountListener to remove. */ public synchronized void removeTotalVoiceCountListener(TotalVoiceCountListener l) { boolean b = llTVC.remove(l); if(b && llTVC.isEmpty()) unsubscribe("TOTAL_VOICE_COUNT"); } /** * Registers the specified listener for receiving event messages. * Listeners can be registered regardless of the connection state. * @param l The ItemCountListener to register. */ public synchronized void addMidiInstrumentMapCountListener(ItemCountListener l) { if(llMIMC.isEmpty()) subscribe("MIDI_INSTRUMENT_MAP_COUNT"); llMIMC.add(l); } /** * Removes the specified listener. * Listeners can be removed regardless of the connection state. * @param l The ItemCountListener to remove. */ public synchronized void removeMidiInstrumentMapCountListener(ItemCountListener l) { boolean b = llMIMC.remove(l); if(b && llMIMC.isEmpty()) unsubscribe("MIDI_INSTRUMENT_MAP_COUNT"); } /** * Registers the specified listener for receiving event messages. * Listeners can be registered regardless of the connection state. * @param l The ItemInfoListener to register. */ public synchronized void addMidiInstrumentMapInfoListener(ItemInfoListener l) { if(llMIMI.isEmpty()) subscribe("MIDI_INSTRUMENT_MAP_INFO"); llMIMI.add(l); } /** * Removes the specified listener. * Listeners can be removed regardless of the connection state. * @param l The ItemInfoListener to remove. */ public synchronized void removeMidiInstrumentMapInfoListener(ItemInfoListener l) { boolean b = llMIMI.remove(l); if(b && llMIMI.isEmpty()) unsubscribe("MIDI_INSTRUMENT_MAP_INFO"); } /** * Registers the specified listener for receiving event messages. * Listeners can be registered regardless of the connection state. * @param l The MidiInstrumentCountListener to register. */ public synchronized void addMidiInstrumentCountListener(MidiInstrumentCountListener l) { if(llMIC.isEmpty()) subscribe("MIDI_INSTRUMENT_COUNT"); llMIC.add(l); } /** * Removes the specified listener. * Listeners can be removed regardless of the connection state. * @param l The MidiInstrumentCountListener to remove. */ public synchronized void removeMidiInstrumentCountListener(MidiInstrumentCountListener l) { boolean b = llMIC.remove(l); if(b && llMIC.isEmpty()) unsubscribe("MIDI_INSTRUMENT_COUNT"); } /** * Registers the specified listener for receiving event messages. * Listeners can be registered regardless of the connection state. * @param l The MidiInstrumentInfoListener to register. */ public synchronized void addMidiInstrumentInfoListener(MidiInstrumentInfoListener l) { if(llMII.isEmpty()) subscribe("MIDI_INSTRUMENT_INFO"); llMII.add(l); } /** * Removes the specified listener. * Listeners can be removed regardless of the connection state. * @param l The MidiInstrumentInfoListener to remove. */ public synchronized void removeMidiInstrumentInfoListener(MidiInstrumentInfoListener l) { boolean b = llMII.remove(l); if(b && llMII.isEmpty()) unsubscribe("MIDI_INSTRUMENT_INFO"); } /** * Registers the specified listener for receiving event messages. * Listeners can be registered regardless of the connection state. * @param l The DeviceMidiDataListener to register. */ public synchronized void addDeviceMidiDataListener(DeviceMidiDataListener l) { if(llDMD.isEmpty()) subscribe("DEVICE_MIDI"); llDMD.add(l); } /** * Removes the specified listener. * Listeners can be removed regardless of the connection state. * @param l The DeviceMidiDataListener to remove. */ public synchronized void removeDeviceMidiDataListener(DeviceMidiDataListener l) { boolean b = llDMD.remove(l); if(b && llDMD.isEmpty()) unsubscribe("DEVICE_MIDI"); } /** * Registers the specified listener for receiving event messages. * Listeners can be registered regardless of the connection state. * @param l The ChannelMidiDataListener to register. */ public synchronized void addChannelMidiDataListener(ChannelMidiDataListener l) { if(llCMD.isEmpty()) subscribe("CHANNEL_MIDI"); llCMD.add(l); } /** * Removes the specified listener. * Listeners can be removed regardless of the connection state. * @param l The ChannelMidiDataListener to remove. */ public synchronized void removeChannelMidiDataListener(ChannelMidiDataListener l) { boolean b = llCMD.remove(l); if(b && llCMD.isEmpty()) unsubscribe("CHANNEL_MIDI"); } /** * Registers the specified listener for receiving event messages. * Listeners can be registered regardless of the connection state. * @param l The InstrumentsDbListener to register. */ public synchronized void addInstrumentsDbListener(InstrumentsDbListener l) { if(llID.isEmpty()) { subscribe("DB_INSTRUMENT_DIRECTORY_COUNT"); subscribe("DB_INSTRUMENT_DIRECTORY_INFO"); subscribe("DB_INSTRUMENT_COUNT"); subscribe("DB_INSTRUMENT_INFO"); subscribe("DB_INSTRUMENTS_JOB_INFO"); } llID.add(l); } /** * Removes the specified listener. * Listeners can be removed regardless of the connection state. * @param l The InstrumentsDbListener to remove. */ public synchronized void removeInstrumentsDbListener(InstrumentsDbListener l) { boolean b = llID.remove(l); if(b && llID.isEmpty()) { unsubscribe("DB_INSTRUMENT_DIRECTORY_COUNT"); unsubscribe("DB_INSTRUMENT_DIRECTORY_INFO"); unsubscribe("DB_INSTRUMENT_COUNT"); unsubscribe("DB_INSTRUMENT_INFO"); unsubscribe("DB_INSTRUMENTS_JOB_INFO"); } } /** * Registers the specified listener for receiving event messages. * Listeners can be registered regardless of the connection state. * @param l The GlobalInfoListener to register. */ public synchronized void addGlobalInfoListener(GlobalInfoListener l) { if(llGI.isEmpty()) subscribe("GLOBAL_INFO"); llGI.add(l); } /** * Removes the specified listener. * Listeners can be removed regardless of the connection state. * @param l The GlobalInfoListener to remove. */ public synchronized void removeGlobalInfoListener(GlobalInfoListener l) { boolean b = llGI.remove(l); if(b && llGI.isEmpty()) unsubscribe("GLOBAL_INFO"); } /** * Registers the specified listener for receiving event messages. * Listeners can be registered regardless of the connection state. * @param l The EffectInstanceCountListener to register. */ public synchronized void addEffectInstanceCountListener(EffectInstanceCountListener l) { if(llEIC.isEmpty()) subscribe("EFFECT_INSTANCE_COUNT"); llEIC.add(l); } /** * Removes the specified listener. * Listeners can be removed regardless of the connection state. * @param l The EffectInstanceCountListener to remove. */ public synchronized void removeEffectInstanceCountListener(EffectInstanceCountListener l) { boolean b = llEIC.remove(l); if(b && llEIC.isEmpty()) unsubscribe("EFFECT_INSTANCE_COUNT"); } /** * Registers the specified listener for receiving event messages. * Listeners can be registered regardless of the connection state. * @param l The EffectInstanceInfoListener to register. */ public synchronized void addEffectInstanceInfoListener(EffectInstanceInfoListener l) { if(llEII.isEmpty()) subscribe("EFFECT_INSTANCE_INFO"); llEII.add(l); } /** * Removes the specified listener. * Listeners can be removed regardless of the connection state. * @param l The EffectInstanceInfoListener to remove. */ public synchronized void removeEffectInstanceInfoListener(EffectInstanceInfoListener l) { boolean b = llEII.remove(l); if(b && llEII.isEmpty()) unsubscribe("EFFECT_INSTANCE_INFO"); } /** * Registers the specified listener for receiving event messages. * Listeners can be registered regardless of the connection state. * @param l The SendEffectChainCountListener to register. */ public synchronized void addSendEffectChainCountListener(SendEffectChainCountListener l) { if(llSECC.isEmpty()) subscribe("SEND_EFFECT_CHAIN_COUNT"); llSECC.add(l); } /** * Removes the specified listener. * Listeners can be removed regardless of the connection state. * @param l The SendEffectChainCountListener to remove. */ public synchronized void removeSendEffectChainCountListener(SendEffectChainCountListener l) { boolean b = llSECC.remove(l); if(b && llSECC.isEmpty()) unsubscribe("SEND_EFFECT_CHAIN_COUNT"); } /** * Registers the specified listener for receiving event messages. * Listeners can be registered regardless of the connection state. * @param l The SendEffectChainInfoListener to register. */ public synchronized void addSendEffectChainInfoListener(SendEffectChainInfoListener l) { if(llSECI.isEmpty()) subscribe("SEND_EFFECT_CHAIN_INFO"); llSECI.add(l); } /** * Removes the specified listener. * Listeners can be removed regardless of the connection state. * @param l The SendEffectChainInfoListener to remove. */ public synchronized void removeSendEffectChainInfoListener(SendEffectChainInfoListener l) { boolean b = llSECI.remove(l); if(b && llSECI.isEmpty()) unsubscribe("SEND_EFFECT_CHAIN_INFO"); } /** * Gets the number of all audio output drivers currently * available for the LinuxSampler instance. * @return The number of all audio output drivers currently * available for the LinuxSampler instance or -1 if in "print only" mode. * @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 getAudioOutputDriverCount() throws IOException, LscpException, LSException { return retrieveInt("GET AVAILABLE_AUDIO_OUTPUT_DRIVERS"); } /** * Gets all audio output drivers currently available for the LinuxSampler instance. * * @return AudioOutputDriver array containing all audio output drivers * currently available for the LinuxSampler instance. * * @throws IOException If an I/O error occurs. * @throws LscpException If LSCP protocol corruption occurs. * @throws LSException If some other error occurs. */ public synchronized AudioOutputDriver[] getAudioOutputDrivers() throws IOException, LscpException, LSException { String[] drivers = getAudioOutputDriverNames(); if(getPrintOnlyMode()) return null; AudioOutputDriver[] aod = new AudioOutputDriver[drivers.length]; for(int i = 0; i < aod.length; i++) aod[i] = getAudioOutputDriverInfo(drivers[i]); return aod; } /** * Gets all audio output drivers currently available for the LinuxSampler instance. * * @return String array containing all audio output drivers currently * available for the LinuxSampler instance. * * @throws IOException If an I/O error occurs. * @throws LscpException If LSCP protocol corruption occurs. * @throws LSException If some other error occurs. */ private synchronized String[] getAudioOutputDriverNames() throws IOException, LscpException, LSException { verifyConnection(); out.writeLine("LIST AVAILABLE_AUDIO_OUTPUT_DRIVERS"); if(getPrintOnlyMode()) return null; return parseList(getSingleLineResultSet().getResult()); } /** * Gets detailed information about a specific audio output driver. * @param driverName The name of the audio output driver. * @param depList An optional list of dependences parameters. * @return An AudioOutputDriver object containing * information about the specified audio output driver. * * @throws IOException If an I/O error occurs. * @throws LscpException If LSCP protocol corruption occurs. * @throws LSException If there is no driver with name driverName. * * @see #getAudioOutputDriverNames */ public synchronized AudioOutputDriver getAudioOutputDriverInfo(String driverName, Parameter... depList) throws IOException, LscpException, LSException { AudioOutputDriver aod = new AudioOutputDriver(); if(!retrieveInfo("GET AUDIO_OUTPUT_DRIVER INFO " + driverName, aod)) return null; aod.setName(driverName); for(String s : aod.getParameterNames()) aod.addParameter(getAudioOutputDriverParameterInfo(driverName, s, depList)); return aod; } /** * Gets detailed information about a specific audio output driver parameter. * * @param driver The name of the audio output driver. * @param param A specific parameter name for which information should be obtained. * @param deplist An optional list of parameters on which the sought parameter * param depends on. Parameter instances can be * easily created using {@link ParameterFactory} factory. * * @return Parameter object containing * information about the specified audio output driver parameter. * * @throws IOException If an I/O error occurs. * @throws LscpException If LSCP protocol corruption occurs. * @throws LSException If driver is not a valid driver name * or param is not a valid parameter for the specified driver. * * @see #getAudioOutputDrivers * @see #getAudioOutputDriverInfo * @see ParameterFactory */ public synchronized Parameter getAudioOutputDriverParameterInfo(String driver, String param, Parameter... deplist) throws IOException, LscpException, LSException { verifyConnection(); StringBuffer args = new StringBuffer(driver); args.append(' ').append(param); for(Parameter p : deplist) { if(p == null || p.getName() == null || p.getValue() == null) continue; args.append(' ').append(p.getName()).append('=').append(p.getStringValue()); } out.writeLine("GET AUDIO_OUTPUT_DRIVER_PARAMETER INFO " + args.toString()); if(getPrintOnlyMode()) return null; ResultSet rs = getMultiLineResultSet(); String[] lnS = rs.getMultiLineResult(); ParameterType type = parseType(lnS); boolean multi = parseMultiplicity(lnS); Parameter prm; switch(type) { case BOOL: if(!multi) prm = new BoolParameter(lnS); else prm = new BoolListParameter(lnS); prm.setName(param); prm.setValue(prm.getDefault()); return prm; case INT: if(!multi) prm = new IntParameter(lnS); else prm = new IntListParameter(lnS); prm.setName(param); prm.setValue(prm.getDefault()); return prm; case FLOAT: if(!multi) prm = new FloatParameter(lnS); else prm = new FloatListParameter(lnS); prm.setName(param); prm.setValue(prm.getDefault()); return prm; case STRING: if(!multi) prm = new StringParameter(lnS); else prm = new StringListParameter(lnS); prm.setName(param); prm.setValue(prm.getDefault()); return prm; default: throw new LscpException(LscpI18n.getLogMsg("Client.unknownPrmType!")); } } /** * Creates a new audio output device for the desired audio output system. * @param aoDriver The desired audio output system. * @param paramList An optional list of driver specific parameters. Parameter * instances can be easily created using {@link ParameterFactory} factory. * @return The numerical ID of the newly created device. * @throws IOException If some I/O error occurs. * @throws LSException If the creation of the new audio output device failed. * @throws LscpException If LSCP protocol corruption occurs. * @see #getAudioOutputDrivers * @see #getAudioOutputDriverInfo * @see ParameterFactory */ public synchronized int createAudioOutputDevice(String aoDriver, Parameter... paramList) throws IOException, LSException, LscpException { StringBuffer args = new StringBuffer(aoDriver); for(Parameter p : paramList) { if(p == null || p.getName() == null || p.getValue() == null) continue; args.append(' ').append(p.getName()).append('=').append(p.getStringValue()); } return retrieveIndex("CREATE AUDIO_OUTPUT_DEVICE " + args.toString()); } /** * Destroys already created audio output device. * @param deviceId The ID of the audio output device to be destroyed. * @throws IOException If some I/O error occurs. * @throws LSException If the destroying of the audio output device failed. * @throws LscpException If LSCP protocol corruption occurs. * @see #getAudioOutputDevices */ public synchronized void destroyAudioOutputDevice(int deviceId) throws IOException, LSException, LscpException { retrieveIndex("DESTROY AUDIO_OUTPUT_DEVICE " + deviceId); } /** * Enables/disables the specified audio output device. * @param deviceId The ID of the audio output device to be enabled/disabled. * @param enable If true the audio output device is enabled, * else the device is disabled. * @throws IOException If some I/O error occurs. * @throws LSException If there is no audio output * device with numerical ID deviceId. * @throws LscpException If LSCP protocol corruption occurs. */ public void enableAudioOutputDevice(int deviceId, boolean enable) throws IOException, LSException, LscpException { setAudioOutputDeviceParameter(deviceId, new BoolParameter("ACTIVE", enable)); } /** * Gets the current number of all created audio output devices. * @return The current number of all created audio output devices * or -1 if in "print only" mode. * @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 getAudioOutputDeviceCount() throws IOException, LscpException, LSException { return retrieveInt("GET AUDIO_OUTPUT_DEVICES"); } /** * Gets a list of all created audio output devices. * @return An AudioOutputDevice array * providing all created audio output devices. * @throws IOException If some I/O error occurs. * @throws LscpException If LSCP protocol corruption occurs. * @throws LSException If some other error occurs. */ public synchronized AudioOutputDevice[] getAudioOutputDevices() throws IOException, LscpException, LSException { Integer[] idS = getAudioOutputDeviceIDs(); if(getPrintOnlyMode()) return null; AudioOutputDevice[] devices = new AudioOutputDevice[idS.length]; for(int i = 0; i < devices.length; i++) devices[i] = getAudioOutputDeviceInfo(idS[i]); return devices; } /** * Gets a list of numerical IDs of all created audio output devices. * @return An Integer array providing the numerical IDs of * all created audio output devices. * @throws IOException If some I/O error occurs. * @throws LscpException If LSCP protocol corruption occurs. * @throws LSException If some other error occurs. */ public synchronized Integer[] getAudioOutputDeviceIDs() throws IOException, LscpException, LSException { return getIntegerList("LIST AUDIO_OUTPUT_DEVICES"); } /** * Gets the current settings of a specific, already created audio output device. * * @param deviceId Specifies the numerical ID of the audio output device. * * @return An AudioOutputDevice instance containing information * about the specified device. * * @throws IOException If some I/O error occurs. * @throws LscpException If LSCP protocol corruption occurs. * @throws LSException If there is no audio output device * with device id deviceId. * * @see #getAudioOutputDevices */ public synchronized AudioOutputDevice getAudioOutputDeviceInfo(int deviceId) throws IOException, LscpException, LSException { verifyConnection(); out.writeLine("GET AUDIO_OUTPUT_DEVICE INFO " + deviceId); if(getPrintOnlyMode()) return null; ResultSet rs = getMultiLineResultSet(); String[] lnS = rs.getMultiLineResult(); AudioOutputDevice aod = new AudioOutputDevice(); aod.setDeviceId(deviceId); Parameter channels; Parameter samplerate; String drv = getCategoryInfo(lnS, "DRIVER"); aod.setDriverName(drv); for(String s : lnS) { if(s.startsWith("CHANNELS: ")) { channels = (Parameter) getAudioOutputDriverParameterInfo(drv, "CHANNELS"); s = s.substring("CHANNELS: ".length(), s.length()); channels.parseValue(s); aod.setChannelsParameter(channels); int count = channels.getValue() > 0 ? channels.getValue() : 0; AudioOutputChannel[] aoc = new AudioOutputChannel[count]; for(int i = 0; i < count; i++) { aoc[i] = getAudioOutputChannelInfo(deviceId, i); } aod.setAudioChannels(aoc); } else if(s.startsWith("SAMPLERATE: ")) { samplerate = (Parameter) getAudioOutputDriverParameterInfo(drv, "SAMPLERATE"); s = s.substring("SAMPLERATE: ".length(), s.length()); samplerate.parseValue(s); aod.setSampleRateParameter(samplerate); } else if(s.startsWith("ACTIVE: ")) { s = s.substring("ACTIVE: ".length(), s.length()); aod.setActive(Boolean.parseBoolean(s)); } else if(s.startsWith("DRIVER: ")) { } else { int i = s.indexOf(": "); if(i == -1) throw new LscpException ( LscpI18n.getLogMsg("CommandFailed!") ); Parameter prm = getAudioOutputDriverParameterInfo(drv, s.substring(0, i)); s = s.substring(i + 2); prm.parseValue(s); aod.addParameter(prm); } } return aod; } /** * Alters a specific setting of a created audio output device. * * @param deviceId The numerical ID of the audio output device. * @param prm A Parameter instance containing the name of the parameter * and the new value for this parameter. * * @throws IOException If some I/O error occurs. * @throws LscpException If LSCP protocol corruption occurs. * @throws LSException If *
    *
  • There is no audio output device with numerical ID deviceId; *
  • There is no device parameter with the specified name; *
  • The device parameter is readonly; *
  • The device parameter is from different type. *
* * @see #getAudioOutputDevices * @see #getAudioOutputDeviceInfo */ public synchronized void setAudioOutputDeviceParameter(int deviceId, Parameter prm) throws IOException, LscpException, LSException { String kv = prm.getName() + '=' + prm.getStringValue(); retrieveIndex("SET AUDIO_OUTPUT_DEVICE_PARAMETER " + deviceId + ' ' + kv); } /** * Changes the channel number of the speicifed audio output device. * @param deviceId The numerical ID of the audio output device. * @param channels The new number of audio output channels. * * @throws IOException If an I/O error occurs. * @throws LscpException If LSCP protocol corruption occurs. * @throws LSException If there is no device with ID deviceId or * if channels number is out of range. * * @see #getAudioOutputChannelInfo */ public synchronized void setAudioOutputChannelCount(int deviceId, int channels) throws IOException, LscpException, LSException { setAudioOutputDeviceParameter(deviceId, new IntParameter("CHANNELS", channels)); } /** * Gets information about an audio channel. * * @param deviceId The numerical ID of the audio output device. * @param audioChn The audio channel number. * * @return An AudioOutputChannel instance containing the * information about the specified audio output channel. * * @throws IOException If some I/O error occurs. * @throws LscpException If LSCP protocol corruption occurs. * @throws LSException If *
    *
  • There is no audio output device with numerical ID deviceId; *
  • audioChn is not a valid channel number; *
* * @see #getAudioOutputDevices * @see #getAudioOutputDeviceInfo */ public synchronized AudioOutputChannel getAudioOutputChannelInfo(int deviceId, int audioChn) throws IOException, LscpException, LSException { verifyConnection(); out.writeLine("GET AUDIO_OUTPUT_CHANNEL INFO " + deviceId + ' ' + audioChn); if(getPrintOnlyMode()) return null; ResultSet rs = getMultiLineResultSet(); AudioOutputChannel aoc = new AudioOutputChannel(); String[] lnS = rs.getMultiLineResult(); for(String s : lnS) { if(s.startsWith("NAME: ")) { s = s.substring("NAME: ".length()); Parameter prm = getAudioOutputChannelParameterInfo ( deviceId, audioChn, "NAME" ); prm.setValue(removeQuotation(s)); aoc.setNameParameter(prm); } else if(s.startsWith("IS_MIX_CHANNEL: ")) { s = s.substring("IS_MIX_CHANNEL: ".length()); Parameter prm = getAudioOutputChannelParameterInfo ( deviceId, audioChn, "IS_MIX_CHANNEL" ); prm.setValue(Boolean.parseBoolean(s)); aoc.setMixChannelParameter(prm); } else if(s.startsWith("MIX_CHANNEL_DESTINATION: ")) { s = s.substring("MIX_CHANNEL_DESTINATION: ".length()); Parameter prm = getAudioOutputChannelParameterInfo ( deviceId, audioChn, "MIX_CHANNEL_DESTINATION" ); prm.setValue(parseInt(s)); aoc.setMixChannelDestParameter(prm); } else { int i = s.indexOf(": "); if(i == -1) throw new LscpException ( LscpI18n.getLogMsg("CommandFailed!") ); Parameter prm = getAudioOutputChannelParameterInfo ( deviceId, audioChn, s.substring(0, i) ); s = s.substring(i + 2); prm.parseValue(s); aoc.addParameter(prm); } } return aoc; } /** * Gets detailed information about a specific audio output channel parameter. * * @param devId The numerical ID of the audio output device. * @param chan The audio channel number. * @param param a specific channel parameter name for which information should be obtained. * * @return An Parameter instance containing * information about the specified audio output channel parameter. * * @throws IOException If an I/O error occurs. * @throws LscpException If LSCP protocol corruption occurs. * @throws LSException If *
    *
  • devId is not a valid device ID; *
  • chan is not a valid channel number; *
  • There is no channel parameter with the specified name. *
* * @see #getAudioOutputDevices * @see #getAudioOutputChannelInfo */ public synchronized Parameter getAudioOutputChannelParameterInfo(int devId, int chan, String param) throws IOException, LscpException, LSException { verifyConnection(); String args = devId + " " + chan + " " + param; out.writeLine("GET AUDIO_OUTPUT_CHANNEL_PARAMETER INFO " + args); if(getPrintOnlyMode()) return null; ResultSet rs = getMultiLineResultSet(); String[] lnS = rs.getMultiLineResult(); ParameterType type = parseType(lnS); boolean multi = parseMultiplicity(lnS); Parameter prm; switch(type) { case BOOL: if(!multi) prm = new BoolParameter(lnS); else prm = new BoolListParameter(lnS); prm.setName(param); return prm; case INT: if(!multi) prm = new IntParameter(lnS); else prm = new IntListParameter(lnS); prm.setName(param); return prm; case FLOAT: if(!multi) prm = new FloatParameter(lnS); else prm = new FloatListParameter(lnS); prm.setName(param); return prm; case STRING: if(!multi) prm = new StringParameter(lnS); else prm = new StringListParameter(lnS); prm.setName(param); return prm; default: throw new LscpException(LscpI18n.getLogMsg("Client.unknownPrmType!")); } } /** * Alters a specific setting of an audio output channel. * * @param devId The numerical ID of the audio device. * @param chn The audio channel number. * @param prm A Parameter instance containing the name of the parameter * and the new value for this parameter. * * @throws IOException If some I/O error occurs. * @throws LscpException If LSCP protocol corruption occurs. * @throws LSException If *
    *
  • There is no audio output device with numerical ID devId; *
  • chn is not a valid channel number; *
  • There is no channel parameter with the specified name; *
  • The channel parameter is readonly; *
  • The channel parameter is from different type. *
* * @see #getAudioOutputDevices * @see #getAudioOutputChannelInfo */ public synchronized void setAudioOutputChannelParameter(int devId, int chn, Parameter prm) throws IOException, LscpException, LSException { String args = devId + " " + chn + " " + prm.getName() + '=' + prm.getStringValue(); retrieveIndex("SET AUDIO_OUTPUT_CHANNEL_PARAMETER " + args); } /** * Gets the current number of all MIDI input drivers. * @return The current number of all MIDI input drivers or -1 if in "print only" mode. * @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 getMidiInputDriverCount() throws IOException, LscpException, LSException { return retrieveInt("GET AVAILABLE_MIDI_INPUT_DRIVERS"); } /** * Gets all MIDI input drivers currently available for the LinuxSampler instance. * * @return MidiInputDriver array containing all MIDI input drivers currently * available for the LinuxSampler instance. * * @throws IOException If an I/O error occurs. * @throws LscpException If LSCP protocol corruption occurs. * @throws LSException If some other error occurs. */ public synchronized MidiInputDriver[] getMidiInputDrivers() throws IOException, LscpException, LSException { String[] drivers = getMidiInputDriverNames(); if(getPrintOnlyMode()) return null; MidiInputDriver[] mid = new MidiInputDriver[drivers.length]; for(int i = 0; i < mid.length; i++) mid[i] = getMidiInputDriverInfo(drivers[i]); return mid; } /** * Gets all MIDI input drivers currently available for the LinuxSampler instance. * * @return String array containing all MIDI input drivers currently available * for the LinuxSampler instance. * * @throws IOException If an I/O error occurs. * @throws LscpException If LSCP protocol corruption occurs. * @throws LSException If some other error occurs. */ private synchronized String[] getMidiInputDriverNames() throws IOException, LscpException, LSException { verifyConnection(); out.writeLine("LIST AVAILABLE_MIDI_INPUT_DRIVERS"); if(getPrintOnlyMode()) return null; return parseList(getSingleLineResultSet().getResult()); } /** * Gets detailed information about a specific MIDI input driver. * @param driverName The name of the MIDI input driver. * @param depList An optional list of dependences parameters. * @return A MidiInputDriver object containing * information about the specified MIDI input driver. * * @throws IOException If an I/O error occurs. * @throws LscpException If LSCP protocol corruption occurs. * @throws LSException If there is no driver with name driverName. * * @see #getMidiInputDriverNames */ public synchronized MidiInputDriver getMidiInputDriverInfo(String driverName, Parameter... depList) throws IOException, LscpException, LSException { MidiInputDriver mid = new MidiInputDriver(); if(!retrieveInfo("GET MIDI_INPUT_DRIVER INFO " + driverName, mid)) return null; mid.setName(driverName); for(String s : mid.getParameterNames()) mid.addParameter(getMidiInputDriverParameterInfo(driverName, s, depList)); return mid; } /** * Gets detailed information about a specific MIDI input driver parameter. * * @param driver The name of the MIDI input driver. * @param param a specific parameter name for which information should be obtained. * @param deplist An optional list of parameters on which the sought parameter * param depends on. Parameter instances can be * easily created using {@link ParameterFactory} factory. * * @return A Parameter object containing * information about the specified MIDI input driver parameter. * * @throws IOException If an I/O error occurs. * @throws LscpException If LSCP protocol corruption occurs. * @throws LSException If driver is not a valid driver name * or param is not a valid parameter for the specified driver. * * @see #getMidiInputDrivers * @see #getMidiInputDriverInfo * @see ParameterFactory */ public synchronized Parameter getMidiInputDriverParameterInfo(String driver, String param, Parameter... deplist) throws IOException, LscpException, LSException { verifyConnection(); StringBuffer args = new StringBuffer(driver); args.append(' ').append(param); for(Parameter p : deplist) { if(p == null || p.getName() == null || p.getValue() == null) continue; args.append(' ').append(p.getName()).append('=').append(p.getStringValue()); } out.writeLine("GET MIDI_INPUT_DRIVER_PARAMETER INFO " + args.toString()); if(getPrintOnlyMode()) return null; ResultSet rs = getMultiLineResultSet(); String[] lnS = rs.getMultiLineResult(); ParameterType type = parseType(lnS); boolean multi = parseMultiplicity(lnS); Parameter prm; switch(type) { case BOOL: if(!multi) prm = new BoolParameter(lnS); else prm = new BoolListParameter(lnS); prm.setName(param); prm.setValue(prm.getDefault()); return prm; case INT: if(!multi) prm = new IntParameter(lnS); else prm = new IntListParameter(lnS); prm.setName(param); prm.setValue(prm.getDefault()); return prm; case FLOAT: if(!multi) prm = new FloatParameter(lnS); else prm = new FloatListParameter(lnS); prm.setName(param); prm.setValue(prm.getDefault()); return prm; case STRING: if(!multi) prm = new StringParameter(lnS); else prm = new StringListParameter(lnS); prm.setName(param); prm.setValue(prm.getDefault()); return prm; default: throw new LscpException(LscpI18n.getLogMsg("Client.unknownPrmType!")); } } /** * Creates a new MIDI input device. * @param miDriver The desired MIDI input system. * @param paramList An optional list of driver specific parameters. Parameter * instances can be easily created using {@link ParameterFactory} factory. * @return The numerical ID of the newly created device. * @throws IOException If some I/O error occurs. * @throws LSException If the creation of the new MIDI input device failed. * @throws LscpException If LSCP protocol corruption occurs. * * @see #getMidiInputDrivers * @see #getMidiInputDriverInfo * @see ParameterFactory */ public synchronized int createMidiInputDevice(String miDriver, Parameter... paramList) throws IOException, LSException, LscpException { StringBuffer args = new StringBuffer(miDriver); for(Parameter p : paramList) { if(p == null || p.getName() == null || p.getValue() == null) continue; args.append(' ').append(p.getName()).append('=').append(p.getStringValue()); } return retrieveIndex("CREATE MIDI_INPUT_DEVICE " + args.toString()); } /** * Destroys already created MIDI input device. * @param deviceId The numerical ID of the MIDI input device to be destroyed. * @throws IOException If some I/O error occurs. * @throws LSException If the destroying of the MIDI input device failed. * @throws LscpException If LSCP protocol corruption occurs. * @see #createMidiInputDevice * @see #getMidiInputDevices */ public synchronized void destroyMidiInputDevice(int deviceId) throws IOException, LSException, LscpException { retrieveIndex("DESTROY MIDI_INPUT_DEVICE " + deviceId); } /** * Enables/disables the specified MIDI input device. * @param deviceId The ID of the MIDI input device to be enabled/disabled. * @param enable If true the MIDI input device is enabled, * else the device is disabled. * @throws IOException If some I/O error occurs. * @throws LSException If there is no MIDI input * device with numerical ID deviceId. * @throws LscpException If LSCP protocol corruption occurs. */ public void enableMidiInputDevice(int deviceId, boolean enable) throws IOException, LSException, LscpException { setMidiInputDeviceParameter(deviceId, new BoolParameter("ACTIVE", enable)); } /** * Gets the current number of all created MIDI input devices. * @return The current number of all created MIDI input * devices or -1 if in "print only" mode. * @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 getMidiInputDeviceCount() throws IOException, LscpException, LSException { return retrieveInt("GET MIDI_INPUT_DEVICES"); } /** * Gets a list of all created MIDI input devices. * @return A MidiInputDevice array * providing all created MIDI input devices. * @throws IOException If some I/O error occurs. * @throws LscpException If LSCP protocol corruption occurs. * @throws LSException If some other error occurs. * * @see #createMidiInputDevice * @see #destroyMidiInputDevice */ public synchronized MidiInputDevice[] getMidiInputDevices() throws IOException, LscpException, LSException { Integer[] idS = getMidiInputDeviceIDs(); if(getPrintOnlyMode()) return null; MidiInputDevice[] devices = new MidiInputDevice[idS.length]; for(int i = 0; i < devices.length; i++) devices[i] = getMidiInputDeviceInfo(idS[i]); return devices; } /** * Gets a list of numerical IDs of all created MIDI input devices. * @return An Integer array providing the numerical IDs of * all created MIDI input devices. * @throws IOException If some I/O error occurs. * @throws LscpException If LSCP protocol corruption occurs. * @throws LSException If some other error occurs. * * @see #createMidiInputDevice * @see #destroyMidiInputDevice */ public synchronized Integer[] getMidiInputDeviceIDs() throws IOException, LscpException, LSException { return getIntegerList("LIST MIDI_INPUT_DEVICES"); } /** * Gets the current settings of a specific, already created MIDI input device. * * @param deviceId Specifies the numerical ID of the MIDI input device. * * @return A MidiInputDevice instance containing information * about the specified device. * * @throws IOException If some I/O error occurs. * @throws LscpException If LSCP protocol corruption occurs. * @throws LSException If there is no MIDI input device * with device id deviceId. * * @see #getMidiInputDevices */ public synchronized MidiInputDevice getMidiInputDeviceInfo(int deviceId) throws IOException, LscpException, LSException { verifyConnection(); out.writeLine("GET MIDI_INPUT_DEVICE INFO " + deviceId); if(getPrintOnlyMode()) return null; ResultSet rs = getMultiLineResultSet(); String[] lnS = rs.getMultiLineResult(); MidiInputDevice mid = new MidiInputDevice(); mid.setDeviceId(deviceId); String drv = getCategoryInfo(lnS, "DRIVER"); mid.setDriverName(drv); for(String s : lnS) { if(s.startsWith("DRIVER: ")) { } else if(s.startsWith("ACTIVE: ")) { s = s.substring("ACTIVE: ".length()); mid.setActive(Boolean.parseBoolean(s)); } else if(s.startsWith("PORTS: ")) { s = s.substring("PORTS: ".length()); 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); mid.setMidiPorts(midiPorts); } else { int i = s.indexOf(": "); if(i == -1) throw new LscpException ( LscpI18n.getLogMsg("CommandFailed!") ); Parameter prm = getMidiInputDriverParameterInfo(drv, s.substring(0, i)); s = s.substring(i + 2); prm.parseValue(s); mid.addParameter(prm); } } return mid; } /** * Alters a specific setting of a created MIDI input device. * * @param deviceId The numerical ID of the MIDI input device. * @param prm A Parameter instance containing the name of the parameter * and the new value for this parameter. * * @throws IOException If some I/O error occurs. * @throws LscpException If LSCP protocol corruption occurs. * @throws LSException If *
    *
  • There is no MIDI input device with numerical ID deviceId; *
  • There is no device parameter with the specified name; *
  • The device parameter is readonly; *
  • The device parameter is from different type. *
* * @see #getMidiInputDevices * @see #getMidiInputDeviceInfo */ public synchronized void setMidiInputDeviceParameter(int deviceId, Parameter prm) throws IOException, LscpException, LSException { String kv = prm.getName() + '=' + prm.getStringValue(); retrieveIndex("SET MIDI_INPUT_DEVICE_PARAMETER " + deviceId + ' ' + kv); } /** * Changes the port number of the specified MIDI input device. * @param deviceId The numerical ID of the MIDI input device. * @param ports The new number of MIDI input ports. * * @throws IOException If an I/O error occurs. * @throws LscpException If LSCP protocol corruption occurs. * @throws LSException If there is no device with ID deviceId or * if ports number is out of range. * * @see #getMidiInputPortInfo */ public synchronized void setMidiInputPortCount(int deviceId, int ports) throws IOException, LscpException, LSException { setMidiInputDeviceParameter(deviceId, new IntParameter("PORTS", ports)); } /** * Gets detailed information about a specific MIDI input port. * @param deviceId The numerical ID of the MIDI input device. * @param midiPort The MIDI input port number. * * @return A MidiPort instance containing * information about the specified MIDI input port. * * @throws IOException If an I/O error occurs. * @throws LscpException If LSCP protocol corruption occurs. * @throws LSException If there is no device with ID deviceId or * if midiPort is not a valid MIDI port number. * * @see #getMidiInputDevices */ public synchronized MidiPort getMidiInputPortInfo(int deviceId, int midiPort) throws IOException, LscpException, LSException { verifyConnection(); out.writeLine("GET MIDI_INPUT_PORT INFO " + deviceId + " " + midiPort); if(getPrintOnlyMode()) return null; ResultSet rs = getMultiLineResultSet(); MidiPort mp = new MidiPort(); String[] lnS = rs.getMultiLineResult(); for(String s : lnS) { if(s.startsWith("NAME: ")) { s = s.substring("NAME: ".length()); Parameter prm = getMidiInputPortParameterInfo ( deviceId, midiPort, "NAME" ); prm.setValue(removeQuotation(s)); mp.setNameParameter(prm); } else { int i = s.indexOf(": "); if(i == -1) throw new LscpException ( LscpI18n.getLogMsg("CommandFailed!") ); Parameter prm = getMidiInputPortParameterInfo ( deviceId, midiPort, s.substring(0, i) ); s = s.substring(i + 2); prm.parseValue(s); mp.addParameter(prm); } } return mp; } /** * Gets detailed information about a specific MIDI input port parameter. * * @param deviceId The numerical ID of the MIDI input device. * @param port The MIDI port number. * @param param A specific parameter name for which information should be obtained. * * @return A Parameter instance containing * information about the specified MIDI input port parameter. * * @throws IOException If an I/O error occurs. * @throws LscpException If LSCP protocol corruption occurs. * @throws LSException If *
    *
  • There is no MIDI input device with numerical ID deviceId; *
  • port is not a valid MIDI port number; *
  • param is not a valid parameter for the specified MIDI port. *
* * @see #getMidiInputDevices * @see #getMidiInputPortInfo */ public synchronized Parameter getMidiInputPortParameterInfo(int deviceId, int port, String param) throws IOException, LscpException, LSException { verifyConnection(); String args = deviceId + " " + port + " " + param; out.writeLine("GET MIDI_INPUT_PORT_PARAMETER INFO " + args); if(getPrintOnlyMode()) return null; ResultSet rs = getMultiLineResultSet(); String[] lnS = rs.getMultiLineResult(); ParameterType type = parseType(lnS); boolean multi = parseMultiplicity(lnS); Parameter prm; switch(type) { case BOOL: if(!multi) prm = new BoolParameter(lnS); else prm = new BoolListParameter(lnS); prm.setName(param); return prm; case INT: if(!multi) prm = new IntParameter(lnS); else prm = new IntListParameter(lnS); prm.setName(param); return prm; case FLOAT: if(!multi) prm = new FloatParameter(lnS); else prm = new FloatListParameter(lnS); prm.setName(param); return prm; case STRING: if(!multi) prm = new StringParameter(lnS); else prm = new StringListParameter(lnS); prm.setName(param); return prm; default: throw new LscpException(LscpI18n.getLogMsg("Client.unknownPrmType!")); } } /** * Alters a specific setting of a MIDI input port. * * @param deviceId The numerical ID of the MIDI device. * @param port The MIDI port number. * @param prm A Parameter instance containing the name of the parameter * and the new value for this parameter. * * @throws IOException If some I/O error occurs. * @throws LscpException If LSCP protocol corruption occurs. * @throws LSException If *
    *
  • There is no MIDI device with numerical ID deviceId; *
  • port is not a valid MIDI port number; *
  • prm is not a valid parameter; *
  • The parameter is readonly; *
  • The parameter is from different type. *
* * @see #getMidiInputDevices * @see #getMidiInputPortInfo */ public synchronized void setMidiInputPortParameter(int deviceId, int port, Parameter prm) throws IOException, LscpException, LSException { String args = deviceId + " " + port + " " + prm.getName() + '=' + prm.getStringValue(); retrieveIndex("SET MIDI_INPUT_PORT_PARAMETER " + args); } /** * Adds a new MIDI instrument map. * @param name The name of this MIDI instrument map. * @return The number of the newly MIDI instrument map. * @throws IOException If some I/O error occurs. * @throws LSException If the creation of the new MIDI instrument map failed. * @throws LscpException If LSCP protocol corruption occurs. * @see #removeMidiInstrumentMap */ public synchronized int addMidiInstrumentMap(String name) throws IOException, LSException, LscpException { return retrieveIndex("ADD MIDI_INSTRUMENT_MAP '" + toEscapedText(name) + "'"); } /** * Removes the specified MIDI instrument map. * @param mapId The numerical ID of the MIDI instrument map to be removed. * @throws IOException If some I/O error occurs. * @throws LscpException If LSCP protocol corruption occurs. * @throws LSException If the removing of the MIDI instrument map failed. * @see #addMidiInstrumentMap * @see #getMidiInstrumentMapIDs */ public synchronized void removeMidiInstrumentMap(int mapId) throws IOException, LscpException, LSException { retrieveIndex("REMOVE MIDI_INSTRUMENT_MAP " + mapId); } /** * Removes the all MIDI instrument maps. * @throws IOException If some I/O error occurs. * @throws LscpException If LSCP protocol corruption occurs. * @throws LSException If the removing of the MIDI instrument maps failed. */ public synchronized void removeAllMidiInstrumentMaps() throws IOException, LscpException, LSException { retrieveIndex("REMOVE MIDI_INSTRUMENT_MAP ALL"); } /** * Gets the current number of all MIDI instrument maps. * @return The current number of all MIDI instrument maps * or -1 if in "print only" mode. * @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 getMidiInstrumentMapCount() throws IOException, LscpException, LSException { return retrieveInt("GET MIDI_INSTRUMENT_MAPS"); } /** * Gets a list of numerical IDs of all created MIDI instrument maps. * @return An Integer array providing the numerical IDs of * all created MIDI instrument maps. * @throws IOException If some I/O error occurs. * @throws LscpException If LSCP protocol corruption occurs. * @throws LSException If some other error occurs. * @see #addMidiInstrumentMap * @see #removeMidiInstrumentMap */ public synchronized Integer[] getMidiInstrumentMapIDs() throws IOException, LscpException, LSException { return getIntegerList("LIST MIDI_INSTRUMENT_MAPS"); } /** * Gets the current settings of a specific, already created MIDI instrument map. * @param mapId Specifies the numerical ID of the MIDI instrument map. * @return A MidiInstrumentMapInfo instance containing information * about the specified device. * @throws IOException If some I/O error occurs. * @throws LscpException If LSCP protocol corruption occurs. * @throws LSException If there is no MIDI instrument map * with map id mapId. * @see #getMidiInstrumentMaps */ public synchronized MidiInstrumentMapInfo getMidiInstrumentMapInfo(int mapId) throws IOException, LscpException, LSException { verifyConnection(); out.writeLine("GET MIDI_INSTRUMENT_MAP INFO " + mapId); if(getPrintOnlyMode()) return null; ResultSet rs = getMultiLineResultSet(); String[] lnS = rs.getMultiLineResult(); String name = ""; boolean b = false; for(String s : lnS) { if(s.startsWith("NAME: ")) { name = toNonEscapedString(s.substring("NAME: ".length())); } else if(s.startsWith("DEFAULT: ")) { b = Boolean.parseBoolean(s.substring("DEFAULT: ".length())); } else { getLogger().info(LscpI18n.getLogMsg("unknownLine", s)); } } return new MidiInstrumentMapInfo(mapId, name, b); } /** * Gets an information of all created MIDI instrument maps. * @return A MidiInstrumentMap array * providing information for all created MIDI instrument maps. * @throws IOException If some I/O error occurs. * @throws LscpException If LSCP protocol corruption occurs. * @throws LSException If some other error occurs. * @see #addMidiInstrumentMap * @see #removeMidiInstrumentMap */ public synchronized MidiInstrumentMapInfo[] getMidiInstrumentMaps() throws IOException, LscpException, LSException { Integer[] idS = getMidiInstrumentMapIDs(); if(getPrintOnlyMode()) return null; MidiInstrumentMapInfo[] maps = new MidiInstrumentMapInfo[idS.length]; for(int i = 0; i < maps.length; i++) maps[i] = getMidiInstrumentMapInfo(idS[i]); return maps; } /** * Sets the name of the specified MIDI instrument map. * @param mapId The numerical ID of the MIDI instrument map. * @param name The new name for the specified MIDI instrument map. * @throws IOException If some I/O error occurs. * @throws LscpException If LSCP protocol corruption occurs. * @throws LSException If mapId is not a valid MIDI * instrument map number or name is not a valid name; */ public synchronized void setMidiInstrumentMapName(int mapId, String name) throws IOException, LscpException, LSException { name = toEscapedText(name); retrieveIndex("SET MIDI_INSTRUMENT_MAP NAME " + + mapId + " '" + name + "'"); } /** * Creates or replaces a MIDI instrument map entry. * @param mapId The ID of the map, where this instrument should be mapped. * @param entry Specifies the position of the MIDI instrument in the MIDI instrument map. * @param info Provides the needed information of the * MIDI instrument, which will be mapped to the specified MIDI instrument map. * @throws IOException If some I/O error occurs. * @throws LSException If the mapping failed. * @throws LscpException If LSCP protocol corruption occurs. * @see #unmapMidiInstrument */ public synchronized void mapMidiInstrument(int mapId, MidiInstrumentEntry entry, MidiInstrumentInfo info) throws IOException, LSException, LscpException { mapMidiInstrument(mapId, entry, info, false); } /** * Creates or replaces a MIDI instrument map entry. * @param mapId The ID of the map, where this instrument should be mapped. * @param entry Specifies the position of the MIDI instrument in the MIDI instrument map. * @param info Provides the needed information of the * MIDI instrument, which will be mapped to the specified MIDI instrument map. * @param nonModal If true the function returns immediately * and the mapping is established in the background. * @throws IOException If some I/O error occurs. * @throws LSException If the mapping failed. * @throws LscpException If LSCP protocol corruption occurs. * @see #unmapMidiInstrument */ public synchronized void mapMidiInstrument(int mapId, MidiInstrumentEntry entry, MidiInstrumentInfo info, boolean nonModal) throws IOException, LSException, LscpException { verifyConnection(); StringBuffer cmd = new StringBuffer("MAP MIDI_INSTRUMENT "); if(nonModal) cmd.append("NON_MODAL "); cmd.append(mapId).append(' '); cmd.append(entry.getMidiBank()).append(' '); cmd.append(entry.getMidiProgram()).append(' '); cmd.append(info.getEngine()).append(" '"); cmd.append(conv(info.getFilePath())).append("' "); cmd.append(info.getInstrumentIndex()).append(' '); cmd.append(info.getVolume()); if(!info.getLoadMode().name().equals("DEFAULT")) { cmd.append(' ').append(info.getLoadMode().name()); } if(info.getName() != null) { String s = toEscapedText(info.getName()); cmd.append(" '").append(s).append("'"); } out.writeLine(cmd.toString()); if(getPrintOnlyMode()) return; ResultSet rs = getEmptyResultSet(); } /** * Removes an entry MIDI instrument map. * @param mapId The ID of the map, from which * the specified MIDI instrument should be removed. * @param entry The entry to remove from the specified MIDI instrument map. * @throws IOException If some I/O error occurs. * @throws LSException If the unmapping failed. * @throws LscpException If LSCP protocol corruption occurs. * @see #mapMidiInstrument */ public synchronized void unmapMidiInstrument(int mapId, MidiInstrumentEntry entry) throws IOException, LSException, LscpException { StringBuffer cmd = new StringBuffer("UNMAP MIDI_INSTRUMENT "); cmd.append(mapId).append(' '); cmd.append(entry.getMidiBank()).append(' '); cmd.append(entry.getMidiProgram()); retrieveIndex(cmd.toString()); } /** * Gets the current number of all MIDI instrument in all maps. * @return The current number of all MIDI instrument in all maps * or -1 if in "print only" mode. * @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 getMidiInstrumentCount() throws IOException, LscpException, LSException { return retrieveInt("GET MIDI_INSTRUMENTS ALL"); } /** * Gets the current number of MIDI instrument in the specified map. * @param mapId The ID of the map. * @return The current number of MIDI instrument in the * specified map or -1 if in "print only" mode. * @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 getMidiInstrumentCount(int mapId) throws IOException, LscpException, LSException { return retrieveInt("GET MIDI_INSTRUMENTS " + String.valueOf(mapId)); } /** * Gets all MIDI instrument from all maps. * @return A MidiInstrumentInfo array providing * all MIDI instruments from all MIDI instrument maps. * @throws IOException If some I/O error occurs. * @throws LscpException If LSCP protocol corruption occurs. * @throws LSException If some other error occurs. */ public synchronized MidiInstrumentInfo[] getMidiInstruments() throws IOException, LscpException, LSException { verifyConnection(); out.writeLine("LIST MIDI_INSTRUMENTS ALL"); if(getPrintOnlyMode()) return null; String[] entries = parseArray(getSingleLineResultSet().getResult()); return getMidiInstruments(entries); } /** * 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 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 MidiInstrumentInfo[] getMidiInstruments(int mapId) throws IOException, LscpException, LSException { verifyConnection(); out.writeLine("LIST MIDI_INSTRUMENTS " + String.valueOf(mapId)); if(getPrintOnlyMode()) return null; String[] entries = parseArray(getSingleLineResultSet().getResult()); return getMidiInstruments(entries); } private MidiInstrumentInfo[] getMidiInstruments(String[] entries) throws IOException, LscpException, LSException { Vector v = new Vector(); for(String s : entries) { Integer[] vals = parseIntList(s); if(vals.length != 3) { throw new LscpException(LscpI18n.getLogMsg("CommandFailed!")); } v.add(getMidiInstrumentInfo(vals[0], vals[1], vals[2])); } return v.toArray(new MidiInstrumentInfo[v.size()]); } /** * Gets the current settings of the specified MIDI instrument. * @param mapId The ID of the map. * @param bank The index of the MIDI bank. * @param program The MIDI program number of the instrument. * @return MidiInstrumentInfo instance containing * the current settings of the specified MIDI instrument. * @throws IOException If an I/O error occurs. * @throws LscpException If LSCP protocol corruption occurs. * @throws LSException If the specified MIDI instrument is missing. */ public synchronized MidiInstrumentInfo getMidiInstrumentInfo(int mapId, int bank, int program) 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()); } 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()); } /** * Loads and assigns an instrument to a sampler channel. Notice that this function will * return after the instrument is fully loaded and the channel is ready to be used. * @param filename The name of the instrument file * on the LinuxSampler instance's host system. * @param instrIdx The index of the instrument in the instrument file. * @param samplerChn The number of the sampler channel the instrument should be assigned to. * @throws IOException If some I/O error occurs. * @throws LscpException If LSCP protocol corruption occurs. * @throws LSException If the loading of the instrument failed. * @see #loadInstrument(String, int, int, boolean) * @see #getSamplerChannels */ public synchronized void loadInstrument(String filename, int instrIdx, int samplerChn) throws IOException, LscpException, LSException { verifyConnection(); loadInstrument(filename, instrIdx, samplerChn, false); } /** * Loads and assigns an instrument to a sampler channel. * * @param filename The name of the instrument file * on the LinuxSampler instance's host system. * @param instrIdx The index of the instrument in the instrument file. * @param samplerChn The number of the sampler channel the instrument should be assigned to. * @param nonModal If false the function will return after the instrument * has been fully loaded and the channel is ready to be used. If true * the function returns immediately. * * @throws IOException If some I/O error occurs. * @throws LscpException If LSCP protocol corruption occurs. * @throws LSException If the loading of the instrument failed. * * @see #loadInstrument(String, int, int) * @see #getSamplerChannels */ public synchronized void loadInstrument(String filename, int instrIdx, int samplerChn, boolean nonModal) throws IOException, LscpException, LSException { String cmd = nonModal ? "LOAD INSTRUMENT NON_MODAL " : "LOAD INSTRUMENT "; String args = '\'' + conv(filename) + "' " + instrIdx + ' ' + samplerChn; retrieveIndex(cmd + args); } /** * Loads a sampler engine to a specific sampler channel. * @param engineName The name of the engine. * @param samplerChn The number of the sampler channel * the deployed engine should be assigned to. * * @throws IOException If some I/O error occurs. * @throws LscpException If LSCP protocol corruption occurs. * @throws LSException If the loading of the sampler engine failed. * @see #getEngines * @see #getSamplerChannels */ public synchronized void loadSamplerEngine(String engineName, int samplerChn) throws IOException, LscpException, LSException { retrieveIndex("LOAD ENGINE " + engineName + ' ' + samplerChn); } /** * Gets the current number of all created sampler channels. * @return The current number of all created sampler * channels or -1 if in "print only" mode. * @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 getSamplerChannelCount() throws IOException, LscpException, LSException { return retrieveInt("GET CHANNELS"); } /** * Gets a list of all created sampler channels. * @return A SamplerChannel array providing all created sampler channels. * @throws IOException If some I/O error occurs. * @throws LscpException If LSCP protocol corruption occurs. * @throws LSException If some other error occurs. * @see #addSamplerChannel * @see #removeSamplerChannel */ public synchronized SamplerChannel[] getSamplerChannels() throws IOException, LscpException, LSException { Integer[] idS = getSamplerChannelIDs(); if(getPrintOnlyMode()) return null; SamplerChannel[] channels = new SamplerChannel[idS.length]; for(int i = 0; i < channels.length; i++) channels[i] = getSamplerChannelInfo(idS[i]); return channels; } /** * Gets a list of the specified sampler channels. * @return A SamplerChannel array providing all created sampler channels. * @throws IOException If some I/O error occurs. * @throws LscpException If LSCP protocol corruption occurs. * @throws LSException If some other error occurs. * @see #addSamplerChannel * @see #removeSamplerChannel */ public synchronized SamplerChannel[] getSamplerChannels(final Integer[] ids) throws IOException, LscpException, LSException { verifyConnection(); int count = 0; for(int i = 0; i < ids.length; i++) { if(ids[i] >= 0) { int tmp = ids[i]; // to avoid overlapping ids[i] = -1; ids[count++] = tmp; } } if(getPrintOnlyMode()) return null; final SamplerChannel[] channels = new SamplerChannel[count]; new CmdListIterator(count) { @Override protected void writeOutput(int index) throws IOException { channels[index] = new SamplerChannel(); out.writeLine("GET CHANNEL INFO " + ids[index]); channels[index].setChannelId(ids[index]); } @Override protected void readInput(int index) throws IOException, LscpException, LSException { if(getPrintOnlyMode()) return; ResultSet rs = getMultiLineResultSet(); for(String s : rs.getMultiLineResult()) { if(!channels[index].parse(s)) { String msg = LscpI18n.getLogMsg("unknownLine", s); Client.getLogger().info(msg); } } } }.run(); for(SamplerChannel sc : channels) { if(sc.getEngine() != null) { sc.setEngine(getEngineInfo(sc.getEngine().getName())); } } return channels; } private static abstract class CmdListIterator { private final int cmdCount; private final int cmdsPerStep; CmdListIterator(int cmdCount) { this(cmdCount, 100); } CmdListIterator(int cmdCount, int cmdsPerStep) { this.cmdCount = cmdCount; this.cmdsPerStep = cmdsPerStep; } public void run() throws IOException, LscpException, LSException { int currentStep = 0; int stepCount = cmdCount / cmdsPerStep; for(currentStep = 0; currentStep < stepCount; currentStep++) { for(int j = 0; j < cmdsPerStep; j++) { int idx = (currentStep * cmdsPerStep) + j; writeOutput(idx); } for(int j = 0; j < cmdsPerStep; j++) { int idx = (currentStep * cmdsPerStep) + j; readInput(idx); } } int cmdsLeft = cmdCount % cmdsPerStep; if(cmdsLeft > 0) { for(int j = 0; j < cmdsLeft; j++) { int idx = stepCount * cmdsPerStep + j; writeOutput(idx); } for(int j = 0; j < cmdsLeft; j++) { int idx = stepCount * cmdsPerStep + j; readInput(idx); } } } protected abstract void writeOutput(int index) throws IOException; protected abstract void readInput(int index) throws IOException, LscpException, LSException; } /** * Gets a list with numerical IDs of all created sampler channels. * @return An Integer array providing * the numerical IDs of all created sampler channels. * @throws IOException If some I/O error occurs. * @throws LscpException If LSCP protocol corruption occurs. * @throws LSException If some other error occurs. * @see #addSamplerChannel * @see #removeSamplerChannel */ public synchronized Integer[] getSamplerChannelIDs() throws IOException, LscpException, LSException { return getIntegerList("LIST CHANNELS"); } /** * Adds a new sampler channel. This method will increment the sampler channel count by one * and the new sampler channel will be appended to the end of the sampler channel list. * * @return The number of the newly created sampler channel. * @throws IOException If some I/O error occurs. * @throws LSException If the creation of the new sampler channel failed. * @throws LscpException If LSCP protocol corruption occurs. * @see #removeSamplerChannel */ public synchronized int addSamplerChannel() throws IOException, LSException, LscpException { return retrieveIndex("ADD CHANNEL"); } /** * Removes the specified sampler channel. * * @param samplerChn The numerical ID of the sampler channel to be removed. * * @throws IOException If some I/O error occurs. * @throws LscpException If LSCP protocol corruption occurs. * @throws LSException If the removing of the sampler channel failed. * @see #addSamplerChannel * @see #getSamplerChannels */ public synchronized void removeSamplerChannel(int samplerChn) throws IOException, LscpException, LSException { retrieveIndex("REMOVE CHANNEL " + samplerChn); } /** * Gets the number of all available engines. * @return The number of all available engines or -1 if in "print only" mode. * @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 getEngineCount() throws IOException, LscpException, LSException { return retrieveInt("GET AVAILABLE_ENGINES"); } /** * Gets a list of all available engines. * * @return SamplerEngine array containing all available engines. * @throws IOException If some I/O error occurs. * @throws LscpException If LSCP protocol corruption occurs. * @throws LSException If some other error occurs. */ public synchronized SamplerEngine[] getEngines() throws IOException, LscpException, LSException { String[] engines = getEngineNames(); if(getPrintOnlyMode()) return null; SamplerEngine[] se = new SamplerEngine[engines.length]; for(int i = 0; i < engines.length; i++) se[i] = getEngineInfo(engines[i]); return se; } /** * Gets a list of all available engines' names. * * @return String array with all available engines' names. * @throws IOException If some I/O error occurs. * @throws LscpException If LSCP protocol corruption occurs. * @throws LSException If some other error occurs. */ private synchronized String[] getEngineNames() throws IOException, LscpException, LSException { verifyConnection(); out.writeLine("LIST AVAILABLE_ENGINES"); if(getPrintOnlyMode()) return null; return parseStringList(getSingleLineResultSet().getResult()); } /** * Gets information about a specific sampler engine. * @param engineName The name of the sampler engine. * * @return SamplerEngine instance containing * information about the specified sampler engine. * * @throws IOException If an I/O error occurs. * @throws LscpException If LSCP protocol corruption occurs. * @throws LSException If there is no sampler engine with name engineName. * @see #getEngineNames */ private synchronized SamplerEngine getEngineInfo(String engineName) throws IOException, LscpException, LSException { SamplerEngine se = engineMap.get(engineName); if(se != null) return null; se = new SamplerEngine(); if(!retrieveInfo("GET ENGINE INFO " + engineName, se)) return null; se.setName(engineName); engineMap.put(engineName, se); return se; } /** * Gets the current settings of the specified sampler channel. * @param samplerChn The sampler channel number. * * @return SamplerChannel instance containing * the current settings of the specified sampler channel. * * @throws IOException If an I/O error occurs. * @throws LscpException If LSCP protocol corruption occurs. * @throws LSException If there is no sampler channel with samplerChn number. * @see #getSamplerChannels */ public synchronized SamplerChannel getSamplerChannelInfo(int samplerChn) throws IOException, LscpException, LSException { SamplerChannel sc = new SamplerChannel(); if(!retrieveInfo("GET CHANNEL INFO " + samplerChn, sc)) return null; sc.setChannelId(samplerChn); if(sc.getEngine() != null) sc.setEngine(getEngineInfo(sc.getEngine().getName())); return sc; } /** * Gets the current number of active voices on the specified sampler channel. * * @param samplerChn The sampler channel number. * @return The current number of active voices on the * specified sampler channel or -1 if in "print only" mode. * @throws IOException If some I/O error occurs. * @throws LscpException If LSCP protocol corruption occurs. * @throws LSException If there is no sampler channel with number samplerChn. * @see #getSamplerChannels */ public synchronized int getChannelVoiceCount(int samplerChn) throws IOException, LscpException, LSException { return retrieveInt("GET CHANNEL VOICE_COUNT " + samplerChn); } /** * Gets the current number of active disk streams on the specified sampler channel. * * @param samplerChn The sampler channel number. * @return The current number of active disk streams on the specified sampler channel * or -1 if the engine doesn't support disk streaming. * @throws IOException If some I/O error occurs. * @throws LscpException If LSCP protocol corruption occurs. * @throws LSException If there is no sampler channel with number samplerChn. * @see #getSamplerChannels */ public synchronized int getChannelStreamCount(int samplerChn) throws IOException, LscpException, LSException { verifyConnection(); out.writeLine("GET CHANNEL STREAM_COUNT " + samplerChn); if(getPrintOnlyMode()) return -1; ResultSet rs = getSingleLineResultSet(); if(rs.getResult().equals("NA")) return -1; return parseInt(rs.getResult()); } /** * Gets the current fill state of all disk streams on the specified sampler channel * in bytes. * * @param samplerChn The sampler channel number. * @return The current fill state of all disk streams on the specified sampler channel * or null if the engine which is deployed doesn't support disk streaming. * @throws IOException If some I/O error occurs. * @throws LscpException If LSCP protocol corruption occurs. * @throws LSException If there is no sampler channel with number samplerChn. * @see #getChannelBufferFillPercentage * @see #getSamplerChannels */ public synchronized Vector getChannelBufferFillBytes(int samplerChn) throws IOException, LscpException, LSException { verifyConnection(); out.writeLine("GET CHANNEL BUFFER_FILL BYTES " + samplerChn); if(getPrintOnlyMode()) return null; ResultSet rs = getSingleLineResultSet(); if(rs.getResult().equals("NA")) return null; Vector v = new Vector(); String[] args = parseList(rs.getResult()); for(String s : args) { if(s.charAt(0) != '[') throw new LscpException(LscpI18n.getLogMsg("CommandFailed!")); int i = s.indexOf(']'); if(i == -1) throw new LscpException(LscpI18n.getLogMsg("CommandFailed!")); BufferFill bf = new BufferFill(); bf.setStreamId(parseInt(s.substring(1, i))); bf.setValue(parseInt(s.substring(i + 1))); v.add(bf); } return v; } /** * Gets the current fill state of all disk streams on the specified sampler channel * in percent. * * @param samplerChn The sampler channel number. * @return The current fill state of all disk streams on the specified sampler channel * or null if the engine which is deployed doesn't support disk streaming. * @throws IOException If some I/O error occurs. * @throws LscpException If LSCP protocol corruption occurs. * @throws LSException If there is no sampler channel with number samplerChn. * @see #getChannelBufferFillBytes * @see #getSamplerChannels */ public synchronized Vector getChannelBufferFillPercentage(int samplerChn) throws IOException, LscpException, LSException { verifyConnection(); out.writeLine("GET CHANNEL BUFFER_FILL PERCENTAGE " + samplerChn); if(getPrintOnlyMode()) return null; ResultSet rs = getSingleLineResultSet(); return getChannelBufferFillPercentage(rs.getResult()); } private Vector getChannelBufferFillPercentage(String ln) throws LscpException { if(ln.equals("NA")) return null; Vector v = new Vector(); String[] args = parseList(ln); for(String s : args) { if(s.charAt(0) != '[') throw new LscpException(LscpI18n.getLogMsg("CommandFailed!")); int i = s.indexOf(']'); if(i == -1) throw new LscpException(LscpI18n.getLogMsg("CommandFailed!")); if(s.charAt(s.length() - 1) != '%') throw new LscpException(LscpI18n.getLogMsg("CommandFailed!")); BufferFill bf = new BufferFill(); bf.setStreamId(parseInt(s.substring(1, i))); bf.setValue(parseInt(s.substring(i + 1, s.length() - 1))); v.add(bf); } return v; } /** * Sets the audio output device on the specified sampler channel. * * @param samplerChn The sampler channel number. * @param devId The numerical ID of the audio output device. * * @throws IOException If some I/O error occurs. * @throws LscpException If LSCP protocol corruption occurs. * @throws LSException If *
    *
  • samplerChn is not a valid channel number; *
  • devId is not a valid audio output device ID; *
* * @see #getSamplerChannels * @see #getAudioOutputDevices */ public synchronized void setChannelAudioOutputDevice(int samplerChn, int devId) throws IOException, LscpException, LSException { retrieveIndex("SET CHANNEL AUDIO_OUTPUT_DEVICE " + samplerChn + ' ' + devId); } /** * Sets the audio output channel on the specified sampler channel. * * @param samplerChn The sampler channel number. * @param audioOut The sampler channel's audio output channel which should be rerouted. * @param audioIn The audio channel of the selected audio output device * where audioOut should be routed to. * * @throws IOException If some I/O error occurs. * @throws LscpException If LSCP protocol corruption occurs. * @throws LSException If *
    *
  • samplerChn is not a valid channel number; *
  • There is no engine assigned yet to the specified sampler channel. *
  • There is no audio output device connected to the specified sampler channel. *
* * @see #getSamplerChannels */ public synchronized void setChannelAudioOutputChannel(int samplerChn, int audioOut, int audioIn) throws IOException, LscpException, LSException { String args = " " + samplerChn + ' ' + audioOut + ' ' + audioIn; retrieveIndex("SET CHANNEL AUDIO_OUTPUT_CHANNEL" + args); } /** * Sets the MIDI input device on the specified sampler channel. * * @param samplerChn The sampler channel number. * @param devId The numerical ID of the MIDI input device. * * @throws IOException If some I/O error occurs. * @throws LscpException If LSCP protocol corruption occurs. * @throws LSException If *
    *
  • samplerChn is not a valid channel number; *
  • devId is not a valid MIDI input device ID; *
* * @see #getSamplerChannels * @see #getMidiInputDevices */ public synchronized void setChannelMidiInputDevice(int samplerChn, int devId) throws IOException, LscpException, LSException { retrieveIndex("SET CHANNEL MIDI_INPUT_DEVICE " + samplerChn + ' ' + devId); } /** * Sets the MIDI input port on the specified sampler channel. * * @param samplerChn The sampler channel number. * @param port The MIDI input port number of * the MIDI input device connected to the specified sampler channel. * * @throws IOException If some I/O error occurs. * @throws LscpException If LSCP protocol corruption occurs. * @throws LSException If samplerChn is not a valid channel number. * @see #getSamplerChannels */ public synchronized void setChannelMidiInputPort(int samplerChn, int port) throws IOException, LscpException, LSException { retrieveIndex("SET CHANNEL MIDI_INPUT_PORT " + samplerChn + ' ' + port); } /** * Sets the MIDI input channel the specified sampler channel should listen to. * * @param samplerChn The sampler channel number. * @param midiChn The number of the new MIDI input channel where * samplerChn should listen to or -1 to listen on all 16 MIDI channels. * * @throws IOException If some I/O error occurs. * @throws LscpException If LSCP protocol corruption occurs. * @throws LSException If samplerChn is not a valid channel number. * @see #getSamplerChannels */ public synchronized void setChannelMidiInputChannel(int samplerChn, int midiChn) throws IOException, LscpException, LSException { String args = String.valueOf(samplerChn) + ' '; args += (midiChn == -1 ? "ALL" : String.valueOf(midiChn)); retrieveIndex("SET CHANNEL MIDI_INPUT_CHANNEL " + args); } /** * Sets the MIDI instrument map to be used on the specified sampler channel. * * @param samplerChn The sampler channel number. * @param mapId Specifies the numerical ID of the MIDI instrument * map to assign. To remove the current map binding use -1. * To set the current map to be the default map use -2. * * @throws IOException If some I/O error occurs. * @throws LscpException If LSCP protocol corruption occurs. * @throws LSException If *
    *
  • samplerChn is not a valid channel number; *
  • mapId is not a valid MIDI instrument map ID; *
* * @see #getSamplerChannels * @see #getMidiInstrumentMaps */ public synchronized void setChannelMidiInstrumentMap(int samplerChn, int mapId) throws IOException, LscpException, LSException { String s; if(mapId == -1) { s = " NONE"; } else if(mapId == -2) { s = " DEFAULT"; } else { s = " " + String.valueOf(mapId); } retrieveIndex("SET CHANNEL MIDI_INSTRUMENT_MAP " + samplerChn + s); } /** * Sets the volume of the specified sampler channel. * * @param samplerChn The sampler channel number. * @param volume The new volume value. * * @throws IOException If some I/O error occurs. * @throws LscpException If LSCP protocol corruption occurs. * @throws LSException If samplerChn is not a valid channel number or if * there is no engine assigned yet to the specified sampler channel. * @see #getSamplerChannels */ public synchronized void setChannelVolume(int samplerChn, float volume) throws IOException, LscpException, LSException { retrieveIndex("SET CHANNEL VOLUME " + samplerChn + ' ' + volume); } /** * Mute/unmute the specified sampler channel. * * @param samplerChn The sampler channel number. * @param mute If true the specified channel is muted, else the channel * is unmuted. * * @throws IOException If some I/O error occurs. * @throws LscpException If LSCP protocol corruption occurs. * @throws LSException If samplerChn is not a valid channel number or if * there is no engine assigned yet to the specified sampler channel. * @see #getSamplerChannels */ public synchronized void setChannelMute(int samplerChn, boolean mute) throws IOException, LscpException, LSException { retrieveIndex("SET CHANNEL MUTE " + samplerChn + ' ' + (mute ? 1 : 0)); } /** * Solo/unsolo the specified sampler channel. * * @param samplerChn The sampler channel number. * @param solo true to solo the specified channel, false * otherwise. * * @throws IOException If some I/O error occurs. * @throws LscpException If LSCP protocol corruption occurs. * @throws LSException If samplerChn is not a valid channel number or if * there is no engine assigned yet to the specified sampler channel. * @see #getSamplerChannels */ public synchronized void setChannelSolo(int samplerChn, boolean solo) throws IOException, LscpException, LSException { retrieveIndex("SET CHANNEL SOLO " + samplerChn + ' ' + (solo ? 1 : 0)); } /** * Creates an additional effect send on the specified sampler channel. * @param channel The sampler channel, on which a new effect send should be added. * @param midiCtrl Defines the MIDI controller, which * will be able alter the effect send level. * @return The unique ID of the newly created effect send entity. * @throws IOException If some I/O error occurs. * @throws LSException If the creation of the effect send failed. * @throws LscpException If LSCP protocol corruption occurs. * @see #destroyFxSend */ public synchronized int createFxSend(int channel, int midiCtrl) throws IOException, LSException, LscpException { return createFxSend(channel, midiCtrl, null); } /** * Creates an additional effect send on the specified sampler channel. * @param channel The sampler channel, on which the effect send should be created on. * @param midiCtrl Defines the MIDI controller, which can alter the effect send level. * @param name The name of the effect send entity. The name does not have to be unique. * @return The unique ID of the newly created effect send entity. * @throws IOException If some I/O error occurs. * @throws LSException If the creation of the effect send failed. * @throws LscpException If LSCP protocol corruption occurs. * @see #destroyFxSend */ public synchronized int createFxSend(int channel, int midiCtrl, String name) throws IOException, LSException, LscpException { String s = String.valueOf(channel) + " " + String.valueOf(midiCtrl); if(name != null) s += " '" + toEscapedText(name) + "'"; return retrieveIndex("CREATE FX_SEND " + s); } /** * Destroys the specified effect send on the specified sampler channel. * @param channel The sampler channel, from which * the specified effect send should be removed. * @param fxSend The ID of the effect send that should be removed. * @throws LSException If some other error occurs. * @throws LscpException If LSCP protocol corruption occurs. * @see #createFxSend */ public synchronized void destroyFxSend(int channel, int fxSend) throws IOException, LSException, LscpException { String s = String.valueOf(channel) + " " + String.valueOf(fxSend); retrieveIndex("DESTROY FX_SEND " + s); } /** * Gets the current number of effect sends on the specified sampler channel. * @param channel The ID of the sampler channel. * @return The current number of effect sends on the specified sampler channels. * @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 getFxSendCount(int channel) throws IOException, LscpException, LSException { return retrieveInt("GET FX_SENDS " + String.valueOf(channel)); } /** * Gets a list of all created effect sends on the specified sampler channel. * @param channel The sampler channel number. * @return A FxSend array providing all created * effect sends on the specified sampler channel. * @throws IOException If some I/O error occurs. * @throws LscpException If LSCP protocol corruption occurs. * @throws LSException If channel is not a valid sampler channel ID. * @see #createFxSend * @see #destroyFxSend */ public synchronized FxSend[] getFxSends(int channel) throws IOException, LscpException, LSException { Integer[] idS = getFxSendIDs(channel); if(getPrintOnlyMode()) return null; FxSend[] fxSends = new FxSend[idS.length]; for(int i = 0; i < fxSends.length; i++) fxSends[i] = getFxSendInfo(channel, idS[i]); return fxSends; } /** * Gets a list of effect sends on the specified sampler channel. * @param channel The sampler channel number. * @return An Integer array providing * the numerical IDs of all effect sends on the specified sampler channel. * @throws IOException If some I/O error occurs. * @throws LscpException If LSCP protocol corruption occurs. * @throws LSException If channel is not a valid sampler channel ID. * @see #createFxSend * @see #destroyFxSend */ public synchronized Integer[] getFxSendIDs(int channel) throws IOException, LscpException, LSException { return getIntegerList("LIST FX_SENDS " + channel); } /** * Gets the current settings of the specified effect send entity. * @param channel The sampler channel number. * @param fxSend The numerical ID of the effect send entity. * @return FxSend instance containing * the current settings of the specified effect send entity. * @throws IOException If an I/O error occurs. * @throws LscpException If LSCP protocol corruption occurs. * @throws LSException If the sampler channel and/or the effect send number are invalid. */ public synchronized FxSend getFxSendInfo(int channel, int fxSend) throws IOException, LscpException, LSException { FxSend fxs = new FxSend(); String s = String.valueOf(channel) + " " + String.valueOf(fxSend); if(!retrieveInfo("GET FX_SEND INFO " + s, fxs)) return null; fxs.setFxSendId(fxSend); return fxs; } /** * Sets the name of the specified effect send. * @param channel The sampler channel number. * @param fxSend The numerical ID of the effect send entity. * @param name The new name for the specified effect send. * @throws IOException If some I/O error occurs. * @throws LscpException If LSCP protocol corruption occurs. * @throws LSException If channel is not a valid channel * number or fxSend is not a valid effect send ID; */ public synchronized void setFxSendName(int channel, int fxSend, String name) throws IOException, LscpException, LSException { String args = " " + channel + " " + fxSend + " '" + toEscapedText(name) + "'"; retrieveIndex("SET FX_SEND NAME" + args); } /** * Sets the destination of an effect send's audio channel in the specified sampler channel. * @param channel The sampler channel number. * @param fxSend The numerical ID of the effect send entity to be rerouted. * @param audioSrc The numerical ID of the effect send's audio output channel, * which should be rerouted. * @param audioDst The audio channel of the selected audio output device * where audioSrc should be routed to. * @throws IOException If some I/O error occurs. * @throws LscpException If LSCP protocol corruption occurs. * @throws LSException If *
    *
  • channel is not a valid channel number; *
  • fxSend is not a valid effect send ID; *
  • There is no engine assigned yet to the specified sampler channel; *
  • There is no audio output device connected to the specified sampler channel. *
*/ public synchronized void setFxSendAudioOutputChannel(int channel, int fxSend, int audioSrc, int audioDst) throws IOException, LscpException, LSException { String args = " " + channel + " " + fxSend + " " + audioSrc + " " + audioDst; retrieveIndex("SET FX_SEND AUDIO_OUTPUT_CHANNEL" + args); } /** * Assign a destination effect to an effect send. * @param channel The sampler channel number. * @param fxSend The numerical ID of the effect send entity. * @param fxChainId The numerical ID of the destination effect chain. * @param chainPos The exact effect chain position in the effect * chain which hosts the actual destination effect. * @throws IOException If some I/O error occurs. * @throws LscpException If LSCP protocol corruption occurs. * @throws LSException If *
    *
  • channel is not a valid channel number; *
  • fxSend is not a valid effect send ID; *
  • fxChainId is not a valid effect chain ID; *
  • chainPos is out of bounds; *
  • There is no engine assigned yet to the specified sampler channel; *
  • There is no audio output device connected to the specified sampler channel. *
*/ public synchronized void setFxSendEffect(int channel, int fxSend, int fxChainId, int chainPos) throws IOException, LscpException, LSException { String args = " " + channel + " " + fxSend + " " + fxChainId + " " + chainPos; retrieveIndex("SET FX_SEND EFFECT" + args); } /** * Removes destination effect from an effect send. * @param channel The sampler channel number. * @param fxSend The numerical ID of the effect send entity. * @throws IOException If some I/O error occurs. * @throws LscpException If LSCP protocol corruption occurs. * @throws LSException If other error occurs. */ public synchronized void removeFxSendEffect(int channel, int fxSend) throws IOException, LscpException, LSException { String args = " " + channel + " " + fxSend; retrieveIndex("REMOVE FX_SEND EFFECT" + args); } /** * Sets the MIDI controller, which will be able to modify * the send level of the specified effect send in the specified sampler channel. * @param channel The sampler channel number. * @param fxSend The numerical ID of the effect send entity. * @param midiCtrl The MIDI controller which shall be * able to modify the effect send's send level. * @throws IOException If some I/O error occurs. * @throws LscpException If LSCP protocol corruption occurs. * @throws LSException If *
    *
  • channel is not a valid channel number; *
  • fxSend is not a valid effect send ID; *
  • midiCtrl is not a valid controller; *
*/ public synchronized void setFxSendMidiController(int channel, int fxSend, int midiCtrl) throws IOException, LscpException, LSException { String args = " " + channel + " " + fxSend + " " + midiCtrl; retrieveIndex("SET FX_SEND MIDI_CONTROLLER" + args); } /** * Sets the current send level of the specified * effect send entity in the specified sampler channel. * @param channel The sampler channel number. * @param fxSend The numerical ID of the effect send entity. * @param volume The new volume value (a value smaller than 1.0 means * attenuation, whereas a value greater than 1.0 means amplification). * @throws IOException If some I/O error occurs. * @throws LscpException If LSCP protocol corruption occurs. * @throws LSException If some other error occurs. */ public synchronized void setFxSendLevel(int channel, int fxSend, float volume) throws IOException, LscpException, LSException { String args = " " + channel + " " + fxSend + " " + String.valueOf(volume); retrieveIndex("SET FX_SEND LEVEL" + args); } /** * Gets the current amount of internal effects available to the sampler. * @return The current amount of internal effects available to the sampler. * @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 getEffectCount() throws IOException, LscpException, LSException { return retrieveInt("GET AVAILABLE_EFFECTS"); } /** * Gets the list of internal effects available to the sampler. * Note that the set of available internal effects can change at runtime. * @return An Effect array providing the current list of internal effects. * @throws IOException If some I/O error occurs. * @throws LscpException If LSCP protocol corruption occurs. */ public synchronized Effect[] getEffects() throws IOException, LscpException, LSException { Integer[] idS = getEffectIDs(); if(getPrintOnlyMode()) return null; Effect[] effects = new Effect[idS.length]; for(int i = 0; i < effects.length; i++) effects[i] = getEffectInfo(idS[i]); return effects; } /** * Retrieves the list of available internal effects. * Note that the set of available internal effects can change at runtime. * @return An Integer array providing * the numerical IDs of all available internal effects. * @throws IOException If some I/O error occurs. * @throws LscpException If LSCP protocol corruption occurs. */ public synchronized Integer[] getEffectIDs() throws IOException, LscpException, LSException { return getIntegerList("LIST AVAILABLE_EFFECTS"); } /** * Gets general informations about the specified effect. * @param effect The numerical ID of the effect entity. * @return Effect instance containing * general informations about the specified effect. * @throws IOException If an I/O error occurs. * @throws LscpException If LSCP protocol corruption occurs. * @throws LSException If the effect ID is invalid. */ public synchronized Effect getEffectInfo(int effect) throws IOException, LscpException, LSException { Effect e = new Effect(); if(!retrieveInfo("GET EFFECT INFO " + effect, e)) return null; e.setEffectId(effect); return e; } /** * Creates an instance of the desired effect. * @param id The unique ID of the effect. * @return The unique ID of the newly created effect instance. * @throws IOException If some I/O error occurs. * @throws LSException If the creation of the effect instance failed. * @throws LscpException If LSCP protocol corruption occurs. * @see #getEffectIDs * @see #getEffectInfo * @see #destroyEffectInstance */ public synchronized int createEffectInstanceById(int id) throws IOException, LSException, LscpException { return retrieveIndex("CREATE EFFECT_INSTANCE " + String.valueOf(id)); } /** * Creates an instance of the desired effect. * @return The unique ID of the newly created effect instance. * @throws IOException If some I/O error occurs. * @throws LSException If the creation of the effect instance failed. * @throws LscpException If LSCP protocol corruption occurs. * @see #getEffectInfo * @see #destroyEffectInstance */ public synchronized int createEffectInstance(Effect effect) throws IOException, LSException, LscpException { return createEffectInstanceById(effect.getEffectId()); } /** * Creates an instance of the desired effect. * @return The unique ID of the newly created effect instance. * @throws IOException If some I/O error occurs. * @throws LSException If the creation of the effect instance failed. * @throws LscpException If LSCP protocol corruption occurs. * @see #getEffectInfo * @see #destroyEffectInstance */ public synchronized int createEffectInstance(String system, String module, String name) throws IOException, LSException, LscpException { String s = system + " '" + toEscapedText(module) + "' '" + toEscapedText(name) + "'"; return retrieveIndex("CREATE EFFECT_INSTANCE " + s); } /** * Destroys the specified unused effect instance. * @param instanceId The numerical ID of the effect instance. * @throws LscpException If LSCP protocol corruption occurs. * @throws LSException If some other error occurs. * @see #createEffectInstance */ public synchronized void destroyEffectInstance(int instanceId) throws IOException, LSException, LscpException { retrieveIndex("DESTROY EFFECT_INSTANCE " + String.valueOf(instanceId)); } /** * Gets the current amount of effect instances available to the sampler. * @return The current amount of effect instances available to the sampler. * @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 getEffectInstanceCount() throws IOException, LscpException, LSException { return retrieveInt("GET EFFECT_INSTANCES"); } /** * Gets the current list of effect instances. * @return An EffectInstanceInfo array * providing the current list of effect instances. * @throws IOException If some I/O error occurs. * @throws LscpException If LSCP protocol corruption occurs. */ public synchronized EffectInstanceInfo[] getEffectInstances() throws IOException, LscpException, LSException { Integer[] idS = getEffectInscanceIDs(); if(getPrintOnlyMode()) return null; EffectInstanceInfo[] eis = new EffectInstanceInfo[idS.length]; for(int i = 0; i < eis.length; i++) eis[i] = getEffectInstanceInfo(idS[i]); return eis; } /** * Retrieves the current list of effect instances. * @return An Integer array providing * the numerical IDs of all available effect instances. * @throws IOException If some I/O error occurs. * @throws LscpException If LSCP protocol corruption occurs. */ public synchronized Integer[] getEffectInscanceIDs() throws IOException, LscpException, LSException { return getIntegerList("LIST EFFECT_INSTANCES"); } /** * Gets the current informations about the specified effect instance. * @param id The numerical ID of the effect instance. * @return EffectInstanceInfo object containing * the current informations about the specified effect instance. * @throws IOException If an I/O error occurs. * @throws LscpException If LSCP protocol corruption occurs. * @throws LSException If the effect instance ID is invalid. */ public synchronized EffectInstanceInfo getEffectInstanceInfo(int id) throws IOException, LscpException, LSException { EffectInstanceInfo ei = new EffectInstanceInfo(); if(!retrieveInfo("GET EFFECT_INSTANCE INFO " + id, ei)) return null; ei.setInstanceId(id); for(int i = 0; i < ei.getParameterCount(); i++) { ei.addParameter(getEffectInstanceParameterInfo(id, i)); } return ei; } /** * Gets information about the specified effect parameter. * @param id The numerical ID of the effect instance. * @param parameter The parameter index. * @return EffectParameter object containing * information about the specified effect parameter. * Note that only the following fields are used - description, * value, rangeMin, rangeMax, possibilities and default. * @throws IOException If an I/O error occurs. * @throws LscpException If LSCP protocol corruption occurs. * @throws LSException If the effect instance ID or the parameter index is invalid. */ public synchronized EffectParameter getEffectInstanceParameterInfo(int instanceId, int parameter) throws IOException, LscpException, LSException { EffectParameter prm = new EffectParameter(instanceId, parameter); String s = String.valueOf(instanceId) + " " + String.valueOf(parameter); if(!retrieveInfo("GET EFFECT_INSTANCE_INPUT_CONTROL INFO " + s, prm)) return null; return prm; } /** * Alters the current value of an effect parameter. * @param instanceId The numerical ID of the effect instance. * @param prmIndex The index of the parameter to alter. * @param value The new value for this parameter. * @throws IOException If some I/O error occurs. * @throws LscpException If LSCP protocol corruption occurs. * @throws LSException If *
    *
  • There is no effect instance with numerical ID instanceId; *
  • There parameter index is invalid; *
  • The new value is out of range; *
* * @see #getEffectInstanceInfo * @see #getEffectInstanceParameterInfo */ public synchronized void setEffectInstanceParameter(int instanceId, int prmIndex, float value) throws IOException, LscpException, LSException { String s = " " + instanceId + " " + prmIndex + " " + value; retrieveIndex("SET EFFECT_INSTANCE_INPUT_CONTROL VALUE" + s); } /** * Gets the current amount of send effect chains on the specified audio output device. * @param audioDeviceId numerical ID of the audio output device. * @return The current amount of send effect chains or -1 if in "print only" mode. * @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 getSendEffectChainCount(int audioDeviceId) throws IOException, LscpException, LSException { return retrieveInt("GET SEND_EFFECT_CHAINS " + audioDeviceId); } /** * Gets the current list of send effect chains on the specified audio output device. * @param audioDeviceId The numerical ID of the audio output device. * @return An EffectInstanceInfo array * providing the current list of effect instances. * @throws IOException If some I/O error occurs. * @throws LscpException If LSCP protocol corruption occurs. */ public synchronized EffectChainInfo[] getSendEffectChains(int audioDeviceId) throws IOException, LscpException, LSException { Integer[] idS = getSendEffectChainIDs(audioDeviceId); if(getPrintOnlyMode()) return null; EffectChainInfo[] ecs = new EffectChainInfo[idS.length]; for(int i = 0; i < ecs.length; i++) { ecs[i] = getSendEffectChainInfo(audioDeviceId, idS[i]); ecs[i].setChainId(idS[i]); } return ecs; } /** * Retrieves the current list of send effect * chains on the specified audio output device. * @param audioDeviceId The numerical ID of the audio output device. * @return An Integer array providing the numerical * IDs of all send effect chains on the specified audio output device. * @throws IOException If some I/O error occurs. * @throws LscpException If LSCP protocol corruption occurs. */ public synchronized Integer[] getSendEffectChainIDs(int audioDeviceId) throws IOException, LscpException, LSException { return getIntegerList("LIST SEND_EFFECT_CHAINS " + audioDeviceId); } /** * Adds a send effect chain to the specified audio output device. * @param audioDeviceId The numerical ID of the audio output device. * @return The numerical ID of the new send effect chain. * @throws IOException If some I/O error occurs. * @throws LSException If the creation of the effect chain failed. * @throws LscpException If LSCP protocol corruption occurs. * @see #removeSendEffectChain * @see #getSendEffectChainInfo */ public synchronized int addSendEffectChain(int audioDeviceId) throws IOException, LSException, LscpException { return retrieveIndex("ADD SEND_EFFECT_CHAIN " + audioDeviceId); } /** * Removes a send effect chain from an audio output device. * @param audioDeviceId The numerical ID of the audio output device. * @param chainId The numerical ID of the send effect chain to remove. * @throws LscpException If LSCP protocol corruption occurs. * @throws LSException If some other error occurs. * @see #addSendEffectChain */ public synchronized void removeSendEffectChain(int audioDeviceId, int chainId) throws IOException, LSException, LscpException { retrieveIndex("REMOVE SEND_EFFECT_CHAIN " + audioDeviceId + " " + chainId); } /** * Gets the current information of a send effect chain. * @param audioDeviceId The numerical ID of the audio output device. * @param chainId The numerical ID of the send effect chain. * @return EffectChainInfo object containing * the current informations about the specified effect chain. * @throws IOException If an I/O error occurs. * @throws LscpException If LSCP protocol corruption occurs. * @throws LSException If the audio device ID or the effect chain ID is invalid. */ public synchronized EffectChainInfo getSendEffectChainInfo(int audioDeviceId, int chainId) throws IOException, LscpException, LSException { verifyConnection(); String str = " " + audioDeviceId + " " + chainId; out.writeLine("GET SEND_EFFECT_CHAIN INFO" + str); if(getPrintOnlyMode()) return null; ResultSet rs = getMultiLineResultSet(); EffectChainInfo chain = null; for(String s : rs.getMultiLineResult()) { if(s.startsWith("EFFECT_SEQUENCE: ")) { s = s.substring("EFFECT_SEQUENCE: ".length()); Integer[] eis = parseIntList(s); EffectInstanceInfo[] instances = new EffectInstanceInfo[eis.length]; for(int i = 0; i < eis.length; i++) { instances[i] = getEffectInstanceInfo(eis[i]); } chain = new EffectChainInfo(instances); chain.setChainId(chainId); } } return chain; } /** * Adds an unused effect instance to the end of a send effect chain. * @param audioDeviceId The numerical ID of the audio output device. * @param chainId The numerical ID of the send effect chain. * @param fxInstanceId The numerical ID of the effect instance to add. * @throws IOException If some I/O error occurs. * @throws LSException If invalid index is specified. * @throws LscpException If LSCP protocol corruption occurs. * @see #addSendEffectChain * @see #createEffectInstance */ public synchronized void appendEffectInstance(int audioDeviceId, int chainId, int fxInstanceId) throws IOException, LSException, LscpException { String s = " " + audioDeviceId + " " + chainId + " " + fxInstanceId; retrieveIndex("APPEND SEND_EFFECT_CHAIN EFFECT" + s); } /** * Adds an unused effect instance at a certain position of a send effect chain. * @param audioDeviceId The numerical ID of the audio output device. * @param chainId The numerical ID of the send effect chain. * @param pos The exact position in the effect chain where * the supplied effect shall be inserted to. * @param fxInstanceId The numerical ID of the effect instance to insert. * @throws IOException If some I/O error occurs. * @throws LSException If invalid index is specified. * @throws LscpException If LSCP protocol corruption occurs. * @see #addSendEffectChain * @see #createEffectInstance */ public synchronized void insertEffectInstance(int audioDeviceId, int chainId, int pos, int fxInstanceId) throws IOException, LSException, LscpException { String s = " " + audioDeviceId + " " + chainId + " " + pos + " " + fxInstanceId; retrieveIndex("INSERT SEND_EFFECT_CHAIN EFFECT" + s); } /** * Removes an effect instance from a certain position of a send effect chain. * @param audioDeviceId The numerical ID of the audio output device. * @param chainId The numerical ID of the send effect chain. * @param pos The exact position of the effect * instance to be removed from the effect chain. * @throws IOException If some I/O error occurs. * @throws LscpException If LSCP protocol corruption occurs. * @throws LSException If invalid index is specified. * @see #appendEffectInstance * @see #insertEffectInstance */ public synchronized void removeEffectInstanceFromChain(int audioDeviceId, int chainId, int pos) throws IOException, LSException, LscpException { String s = " " + audioDeviceId + " " + chainId + " " + pos; retrieveIndex("REMOVE SEND_EFFECT_CHAIN EFFECT" + s); } /** * Starts an instrument editor for editing the loaded instrument * on the specified sampler channel. * @param samplerChn The sampler channel number. * @throws IOException If some I/O error occurs. * @throws LscpException If LSCP protocol corruption occurs. * @throws LSException If samplerChn is not a valid channel number or if * there is no instrument loaded on the specified sampler channel. * @see #getSamplerChannels */ public synchronized void editChannelInstrument(int samplerChn) throws IOException, LscpException, LSException { retrieveIndex("EDIT CHANNEL INSTRUMENT " + samplerChn); } /** * Sends a MIDI event to this sampler channel. * @param samplerChn The sampler channel number. * @param type The type of MIDI message to send. * @throws IOException If some I/O error occurs. * @throws LscpException If LSCP protocol corruption occurs. * @throws LSException If samplerChn is not a valid channel number or if * there is no instrument loaded on the specified sampler channel. * @see #getSamplerChannels */ public synchronized void sendChannelMidiData(int samplerChn, MidiDataEvent.Type type, int arg1, int arg2) throws IOException, LscpException, LSException { StringBuffer sb = new StringBuffer(); sb.append("SEND CHANNEL MIDI_DATA "); sb.append(type).append(" ").append(samplerChn).append(" "); sb.append(arg1).append(" ").append(arg2); retrieveIndex(sb.toString()); } /** * Resets the specified sampler channel. * * @param samplerChn The sampler channel number. * * @throws IOException If some I/O error occurs. * @throws LscpException If LSCP protocol corruption occurs. * @throws LSException If samplerChn is not a valid channel number or if * there is no engine assigned yet to the specified sampler channel. * @see #getSamplerChannels */ public synchronized void resetChannel(int samplerChn) throws IOException, LscpException, LSException { retrieveIndex("RESET CHANNEL " + samplerChn); } /** * Adds the specified directory to the instruments database. * @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. */ public synchronized void addDbDirectory(String dir) throws IOException, LSException, LscpException { retrieveIndex("ADD DB_INSTRUMENT_DIRECTORY '" + conv(dir) + "'"); } /** * Removes the specified directory from the instruments database. * @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 * empty or if the removal of the directory failed. */ public synchronized void removeDbDirectory(String dir) throws IOException, LscpException, LSException { removeDbDirectory(dir, false); } /** * Removes the specified directory from the instruments database. * @param dir The absolute path name of the directory to remove. * @param force If true forces the removal of non-empty * directory and all its content. * @throws IOException If some I/O error occurs. * @throws LscpException If LSCP protocol corruption occurs. * @throws LSException If the removing of the directory failed. */ public synchronized void removeDbDirectory(String dir, boolean force) throws IOException, LscpException, LSException { String s = "REMOVE DB_INSTRUMENT_DIRECTORY "; if(force) s += "FORCE "; retrieveIndex(s + "'" + conv(dir) + "'"); } /** * Removes the specified directories from the instruments database. * @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. * @throws LscpException If LSCP protocol corruption occurs. * @throws LSException If the removing of the directores failed. */ public synchronized void removeDbDirectories(String[] dirs, boolean force) throws IOException, LscpException, LSException { verifyConnection(); String cmd = "REMOVE DB_INSTRUMENT_DIRECTORY "; if(force) cmd += "FORCE "; for(String s : dirs) out.writeLine(cmd + "'" + conv(s) + "'"); if(getPrintOnlyMode()) return; getEmptyResultSets(dirs.length, "Client.dirDeletionFailed!"); } /** * Gets the number of directories in the specified directory. * @return The current number of directories in the specified directory. * @param dir The absolute path name of the directory. * @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 getDbDirectoryCount(String dir) throws IOException, LscpException, LSException { return getDbDirectoryCount(dir, false); } /** * Gets the number of directories in the specified directory. * @return The current number of directories in the specified directory. * @param dir The absolute path name of the directory. * @param recursive If true, the number of all directories * in the specified subtree will be returned. * @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 getDbDirectoryCount(String dir, boolean recursive) throws IOException, LscpException, LSException { verifyConnection(); String s; if(recursive) s = "GET DB_INSTRUMENT_DIRECTORIES RECURSIVE '"; else s = "GET DB_INSTRUMENT_DIRECTORIES '"; out.writeLine(s + conv(dir) + "'"); if(getPrintOnlyMode()) return -1; s = getSingleLineResultSet().getResult(); return parseInt(s); } /** * Gets the list of directories in the specified directory. * @param dir The absolute path name of the directory. * @return A String array providing the names of * all directories in the specified directory. * @throws IOException If some I/O error occurs. * @throws LscpException If LSCP protocol corruption occurs. * @throws LSException If the specified path name is invalid. */ public synchronized String[] getDbDirectoryNames(String dir) throws IOException, LscpException, LSException { verifyConnection(); out.writeLine("LIST DB_INSTRUMENT_DIRECTORIES '" + conv(dir) + "'"); if(getPrintOnlyMode()) return null; String[] names = parseEscapedStringList(getSingleLineResultSet().getResult()); for(int i = 0; i < names.length; i++) { names[i] = toNonEscapedString(names[i]); } return names; } /** * Gets information about the specified directory. * @param dir The absolute path name of the directory. * @return A DbDirectoryInfo instance providing information * about the specified directory. * @throws IOException If some I/O error occurs. * @throws LscpException If LSCP protocol corruption occurs. * @throws LSException If the specified directory is not found. */ public synchronized DbDirectoryInfo getDbDirectoryInfo(String dir) throws IOException, LscpException, LSException { DbDirectoryInfo info = new DbDirectoryInfo(); if(!retrieveInfo("GET DB_INSTRUMENT_DIRECTORY INFO '" + conv(dir) + "'", info)) return null; if(dir.equals("/")) { info.setName("/"); } 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; } /** * Gets the list of directories in the specified directory. * @param dir The absolute path name of the directory. * @return A DbDirectoryInfo array providing * information about all directories in the specified directory. * @throws IOException If some I/O error occurs. * @throws LscpException If LSCP protocol corruption occurs. * @throws LSException If the specified path name is invalid. */ public synchronized DbDirectoryInfo[] getDbDirectories(String dir) throws IOException, LscpException, LSException { String[] dirS = getDbDirectoryNames(dir); if(!hasEndingFileSeparator(dir)) dir += "/"; DbDirectoryInfo[] infoS = new DbDirectoryInfo[dirS.length]; for(int i = 0; i < dirS.length; i++) { infoS[i] = getDbDirectoryInfo(conv(dir) + toEscapedFsEntry(dirS[i])); } return infoS; } /** * Gets the list of directories in the specified directory. * @param dir The absolute path name of the directory. * @return A DbDirectoryInfo array providing * information about all directories in the specified directory. * @throws IOException If some I/O error occurs. * @throws LscpException If LSCP protocol corruption occurs. * @throws LSException If the specified path name is invalid. * public synchronized DbDirectoryInfo[] getDbDirectories(String dir) throws IOException, LscpException, LSException { String[] dirS = getDbDirectoryNames(conv(dir)); if(dirS.length == 0) return new DbDirectoryInfo[0]; if(dir.charAt(dir.length() - 1) != '/') dir += "/"; // FIXME: for(int i = 0; i < dirS.length; i++) { out.writeLine("GET DB_INSTRUMENT_DIRECTORY INFO '" + conv(dir + dirS[i]) + "'"); } if(getPrintOnlyMode()) return null; if(dir.length() > 1) dir = dir.substring(0, dir.length() - 1); StringBuffer sb = new StringBuffer(); DbDirectoryInfo[] infoS = new DbDirectoryInfo[dirS.length]; for(int i = 0; i < dirS.length; i++) { try { ResultSet rs = getMultiLineResultSet(); infoS[i] = new DbDirectoryInfo(rs.getMultiLineResult()); infoS[i].setName(dirS[i]); infoS[i].setParentDirectoryPath(dir); } catch (SocketTimeoutException e) { getLogger().log(Level.FINE, e.getMessage(), e); sb.append(e.getMessage()).append("\n"); break; } catch (Exception e) { getLogger().log(Level.FINE, e.getMessage(), e); sb.append(e.getMessage()).append("\n"); } } String details = sb.toString(); if(details.length() > 0) { String err = LscpI18n.getLogMsg("Client.getInstrsInfoFailed!"); throw new LSException(0, err, details); } return infoS; }*/ /** * Renames the specified directory. * @param dir The absolute path name of the directory to rename. * @param name The new name for the directory. * @throws IOException If some I/O error occurs. * @throws LSException If the renaming of the directory failed. * @throws LscpException If LSCP protocol corruption occurs. */ public synchronized void renameDbDirectory(String dir, String name) throws IOException, LSException, LscpException { name = toEscapedText(name); retrieveIndex("SET DB_INSTRUMENT_DIRECTORY NAME '" + conv(dir) + "' '" + conv(name) + "'"); } /** * Moves the specified directory into the specified location. * @param dir The absolute path name of the directory to move. * @param dst The location where the directory will be moved to. * @throws IOException If some I/O error occurs. * @throws LSException If the operation failed. * @throws LscpException If LSCP protocol corruption occurs. */ public synchronized void moveDbDirectory(String dir, String dst) throws IOException, LSException, LscpException { retrieveIndex("MOVE DB_INSTRUMENT_DIRECTORY '" + conv(dir) + "' '" + conv(dst) + "'"); } /** * Moves the specified directories into the specified location. * @param dirs The absolute path names of the directories to move. * @param dst The location where the directories will be moved to. * @throws IOException If some I/O error occurs. * @throws LSException If the operation failed. * @throws LscpException If LSCP protocol corruption occurs. */ public synchronized void moveDbDirectories(String dirs[], String dst) throws IOException, LSException, LscpException { verifyConnection(); for(String s : dirs) { out.writeLine("MOVE DB_INSTRUMENT_DIRECTORY '" + conv(s) + "' '" + conv(dst) + "'"); } if(getPrintOnlyMode()) return; getEmptyResultSets(dirs.length, "Client.dirMovingFailed!"); } /** * Copies the specified directory into the specified location. * @param dir The absolute path name of the directory to copy. * @param dst The location where the directory will be copied to. * @throws IOException If some I/O error occurs. * @throws LSException If the operation failed. * @throws LscpException If LSCP protocol corruption occurs. */ public synchronized void copyDbDirectory(String dir, String dst) throws IOException, LSException, LscpException { retrieveIndex("COPY DB_INSTRUMENT_DIRECTORY '" + conv(dir) + "' '" + conv(dst) + "'"); } /** * Copies the specified directories into the specified location. * @param dirs The absolute path names of the directories to copy. * @param dst The location where the directories will be copied to. * @throws IOException If some I/O error occurs. * @throws LSException If the operation failed. * @throws LscpException If LSCP protocol corruption occurs. */ public synchronized void copyDbDirectories(String[] dirs, String dst) throws IOException, LSException, LscpException { verifyConnection(); for(String s : dirs) { out.writeLine("COPY DB_INSTRUMENT_DIRECTORY '" + conv(s) + "' '" + conv(dst) + "'"); } if(getPrintOnlyMode()) return; getEmptyResultSets(dirs.length, "Client.dirCopyingFailed!"); } /** * Changes the description of the specified directory. * @param dir The absolute path name of the directory. * @param desc The new description for the directory. * @throws IOException If some I/O error occurs. * @throws LSException If failed to change the description. * @throws LscpException If LSCP protocol corruption occurs. */ public synchronized void setDbDirectoryDescription(String dir, String desc) throws IOException, LSException, LscpException { String s = "SET DB_INSTRUMENT_DIRECTORY DESCRIPTION '"; retrieveIndex(s + conv(dir) + "' '" + toEscapedText(desc) + "'"); } public static enum ScanMode { RECURSIVE, NON_RECURSIVE, FLAT } /** * Adds the specified instrument to the specified instruments database directory. * @param dbDir The absolute path name of the database directory in which the * specified instrument will be added. * @param filePath The absolute path name of the instrument file. * @param instrIndex The index of the instrument (in the given instrument file) to add. * @throws IOException If some I/O error occurs. * @throws LSException If the operation failed. * @throws LscpException If LSCP protocol corruption occurs. */ public synchronized void addDbInstrument(String dbDir, String filePath, int instrIndex) throws IOException, LSException, LscpException { addDbInstrument(dbDir, filePath, instrIndex, false); } /** * Adds the specified instrument to the specified instruments database directory. * @param dbDir The absolute path name of the database directory in which the * specified instrument will be added. * @param filePath The absolute path name of the instrument file. * @param instrIndex The index of the instrument (in the given instrument file) to add. * @param background If true, the scan will be done * in background and this method may return before the job is finished. * @return If background is true, the ID * of the scan job. * @throws IOException If some I/O error occurs. * @throws LSException If the operation failed. * @throws LscpException If LSCP protocol corruption occurs. * @see #addInstrumentsDbListener */ public synchronized int addDbInstrument(String dbDir, String filePath, int instrIndex, boolean background) throws IOException, LSException, LscpException { String s = "ADD DB_INSTRUMENTS"; if(background) s += " NON_MODAL"; s += " '" + conv(dbDir) + "' '" + conv(filePath) + "' "; return retrieveIndex(s + String.valueOf(instrIndex)); } /** * Adds the instruments in the specified file to the specified * instruments database directory. * @param dbDir The absolute path name of the database directory * in which the the supported instruments will be added. * @param filePath The absolute path name of the file to scan for instruments. * @throws IOException If some I/O error occurs. * @throws LSException If the operation failed. * @throws LscpException If LSCP protocol corruption occurs. */ public synchronized void addDbInstruments(String dbDir, String filePath) throws IOException, LSException, LscpException { addDbInstruments(dbDir, filePath, false); } /** * Adds the instruments in the specified file to the specified * instruments database directory. * @param dbDir The absolute path name of the database directory * in which the the supported instruments will be added. * @param filePath The absolute path name of the file to scan for instruments. * @param background If true, the scan will be done * in background and this method may return before the job is finished. * @return If background is true, the ID * of the scan job. * @throws IOException If some I/O error occurs. * @throws LSException If the operation failed. * @throws LscpException If LSCP protocol corruption occurs. * @see #addInstrumentsDbListener */ public synchronized int addDbInstruments(String dbDir, String filePath, boolean background) throws IOException, LSException, LscpException { String s = "ADD DB_INSTRUMENTS"; if(background) s += " NON_MODAL"; return retrieveIndex(s + " '" + conv(dbDir) + "' '" + conv(filePath) + "'"); } /** * Adds the instruments in the specified file system directory * to the specified instruments database directory. * @param mode Determines the scanning mode. If RECURSIVE is * specified, all supported instruments in the specified file system * direcotry will be added to the specified instruments database * directory, including the instruments in subdirectories * of the supplied directory. If NON_RECURSIVE is specified, * the instruments in the subdirectories will not be processed. * If FLAT is specified, all supported instruments in the specified * file system direcotry will be added, including the instruments in * subdirectories of the supplied directory, but the respective * subdirectory structure will not be recreated in the instruments * database and all instruments will be added directly in the * specified database directory. * @param dbDir The absolute path name of the database directory * in which the supported instruments will be added. * @param fsDir The absolute path name of the file system directory. * @throws IOException If some I/O error occurs. * @throws LSException If the operation failed. * @throws LscpException If LSCP protocol corruption occurs. */ public synchronized void addDbInstruments(ScanMode mode, String dbDir, String fsDir) throws IOException, LSException, LscpException { addDbInstruments(mode, dbDir, fsDir, false); } /** * Adds the instruments in the specified file system directory * to the specified instruments database directory. * @param mode Determines the scanning mode. If RECURSIVE is * specified, all supported instruments in the specified file system * direcotry will be added to the specified instruments database * directory, including the instruments in subdirectories * of the supplied directory. If NON_RECURSIVE is specified, * the instruments in the subdirectories will not be processed. * If FLAT is specified, all supported instruments in the specified * file system direcotry will be added, including the instruments in * subdirectories of the supplied directory, but the respective * subdirectory structure will not be recreated in the instruments * database and all instruments will be added directly in the * specified database directory. * @param dbDir The absolute path name of the database directory * in which the supported instruments will be added. * @param fsDir The absolute path name of the file system directory. * @param background If true, the scan will be done * in background and this method may return before the job is finished. * @return If background is true, the ID * of the scan job. * @throws IOException If some I/O error occurs. * @throws LSException If the operation failed. * @throws LscpException If LSCP protocol corruption occurs. * @see #addInstrumentsDbListener */ public synchronized int addDbInstruments(ScanMode mode, String dbDir, String fsDir, boolean background) throws IOException, LSException, LscpException { return addDbInstruments(mode, dbDir, fsDir, background, false); } /** * Adds the instruments in the specified file system directory * to the specified instruments database directory. * @param mode Determines the scanning mode. If RECURSIVE is * specified, all supported instruments in the specified file system * direcotry will be added to the specified instruments database * directory, including the instruments in subdirectories * of the supplied directory. If NON_RECURSIVE is specified, * the instruments in the subdirectories will not be processed. * If FLAT is specified, all supported instruments in the specified * file system direcotry will be added, including the instruments in * subdirectories of the supplied directory, but the respective * subdirectory structure will not be recreated in the instruments * database and all instruments will be added directly in the * specified database directory. * @param dbDir The absolute path name of the database directory * in which the supported instruments will be added. * @param fsDir The absolute path name of the file system directory. * @param background If true, the scan will be done * in background and this method may return before the job is finished. * @param insDir If true a drieectory is created for each * instrument file. * @return If background is true, the ID * of the scan job. * @throws IOException If some I/O error occurs. * @throws LSException If the operation failed. * @throws LscpException If LSCP protocol corruption occurs. * @see #addInstrumentsDbListener */ public synchronized int addDbInstruments(ScanMode mode, String dbDir, String fsDir, boolean background, boolean insDir) throws IOException, LSException, LscpException { StringBuffer sb = new StringBuffer("ADD DB_INSTRUMENTS"); if(background) sb.append(" NON_MODAL"); switch(mode) { case RECURSIVE: sb.append(" RECURSIVE"); break; case NON_RECURSIVE: sb.append(" NON_RECURSIVE"); break; case FLAT: sb.append(" FLAT"); break; } if(insDir) sb.append(" FILE_AS_DIR"); sb.append(" '").append(conv(dbDir)).append("' '"); sb.append(conv(fsDir)).append("'"); return retrieveIndex(sb.toString()); } /** * Removes the specified instrument from the instruments database. * @param instr The absolute path name of the instrument to remove. * @throws IOException If some I/O error occurs. * @throws LscpException If LSCP protocol corruption occurs. * @throws LSException If the removing of the instrument failed. */ public synchronized void removeDbInstrument(String instr) throws IOException, LscpException, LSException { retrieveIndex("REMOVE DB_INSTRUMENT '" + conv(instr) + "'"); } /** * Removes the specified instruments from the instruments database. * @param instrs The absolute path names of the instruments to remove. * @throws IOException If some I/O error occurs. * @throws LscpException If LSCP protocol corruption occurs. * @throws LSException If the removing of the instruments failed. */ public synchronized void removeDbInstruments(String[] instrs) throws IOException, LscpException, LSException { verifyConnection(); for(String s : instrs) { out.writeLine("REMOVE DB_INSTRUMENT '" + conv(s) + "'"); } if(getPrintOnlyMode()) return; getEmptyResultSets(instrs.length, "Client.instrDeletionFailed!"); } /** * Gets the number of instruments in the specified directory. * @return The current number of instruments in the specified directory. * @param dir The absolute path name of the directory. * @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 getDbInstrumentCount(String dir) throws IOException, LscpException, LSException { return getDbInstrumentCount(dir, false); } /** * Gets the number of instruments in the specified directory. * @return The current number of instruments in the specified directory. * @param dir The absolute path name of the directory. * @param recursive If true, the number of all instruments * in the specified subtree will be returned. * @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 getDbInstrumentCount(String dir, boolean recursive) throws IOException, LscpException, LSException { verifyConnection(); String s; if(recursive) s = "GET DB_INSTRUMENTS RECURSIVE '"; else s = "GET DB_INSTRUMENTS '"; out.writeLine(s + conv(dir) + "'"); if(getPrintOnlyMode()) return -1; s = getSingleLineResultSet().getResult(); return parseInt(s); } /** * Gets the list of instruments in the specified directory. * @param dir The absolute path name of the directory. * @return A String array providing the names of * all instruments in the specified directory. * @throws IOException If some I/O error occurs. * @throws LscpException If LSCP protocol corruption occurs. * @throws LSException If the specified path name is invalid. */ public synchronized String[] getDbInstrumentNames(String dir) throws IOException, LscpException, LSException { verifyConnection(); out.writeLine("LIST DB_INSTRUMENTS '" + conv(dir) + "'"); if(getPrintOnlyMode()) return null; String[] names = parseEscapedStringList(getSingleLineResultSet().getResult()); for(int i = 0; i < names.length; i++) { names[i] = toNonEscapedString(names[i]); } return names; } /** * Gets information about the specified instrument. * @param instr The absolute path name of the instrument. * @return A DbInstrumentInfo instance providing information * about the specified instrument. * @throws IOException If some I/O error occurs. * @throws LscpException If LSCP protocol corruption occurs. * @throws LSException If the specified instrument is not found. */ public synchronized DbInstrumentInfo getDbInstrumentInfo(String instr) throws IOException, LscpException, LSException { DbInstrumentInfo info = new DbInstrumentInfo(); if(!retrieveInfo("GET DB_INSTRUMENT INFO '" + conv(instr) + "'", info)) return null; String s = getParentDirectory(instr); if(s != null) info.setDirectoryPath(s); s = getFileName(instr); if(s != null) info.setName(toNonEscapedFileName(s)); return info; } /** * Gets the list of instruments in the specified directory. * @param dir The absolute path name of the directory. * @return A DbInstrumentInfo array providing * information about all instruments in the specified directory. * @throws IOException If some I/O error occurs. * @throws LscpException If LSCP protocol corruption occurs. * @throws LSException If the specified path name is invalid. */ public synchronized DbInstrumentInfo[] getDbInstruments(String dir) throws IOException, LscpException, LSException { String[] instrS = getDbInstrumentNames(dir); if(!hasEndingFileSeparator(dir)) dir += "/"; DbInstrumentInfo[] infoS = new DbInstrumentInfo[instrS.length]; for(int i = 0; i < instrS.length; i++) { infoS[i] = getDbInstrumentInfo(conv(dir) + toEscapedFsEntry(instrS[i])); } return infoS; } /** * Gets the list of instruments in the specified directory. * @param dir The absolute path name of the directory. * @return A DbInstrumentInfo array providing * information about all instruments in the specified directory. * @throws IOException If some I/O error occurs. * @throws LscpException If LSCP protocol corruption occurs. * @throws LSException If the specified path name is invalid. * public synchronized DbInstrumentInfo[] getDbInstruments(String dir) throws IOException, LscpException, LSException { String[] instrS = getDbInstrumentNames(dir); if(instrS.length == 0) return new DbInstrumentInfo[0]; if(dir.charAt(dir.length() - 1) != '/') dir += "/"; FIXME: for(int i = 0; i < instrS.length; i++) { out.writeLine("GET DB_INSTRUMENT INFO '" + conv(dir) + instrS[i] + "'"); } if(getPrintOnlyMode()) return null; if(dir.length() > 1) dir = dir.substring(0, dir.length() - 1); StringBuffer sb = new StringBuffer(); DbInstrumentInfo[] infoS = new DbInstrumentInfo[instrS.length]; for(int i = 0; i < instrS.length; i++) { try { ResultSet rs = getMultiLineResultSet(); infoS[i] = new DbInstrumentInfo(rs.getMultiLineResult()); infoS[i].setName(instrS[i]); infoS[i].setDirectoryPath(dir); } catch (SocketTimeoutException e) { getLogger().log(Level.FINE, e.getMessage(), e); sb.append(e.getMessage()).append("\n"); break; } catch (Exception e) { getLogger().log(Level.FINE, e.getMessage(), e); sb.append(e.getMessage()).append("\n"); } } String details = sb.toString(); if(details.length() > 0) { String err = LscpI18n.getLogMsg("Client.getInstrsInfoFailed!"); throw new LSException(0, err, details); } return infoS; }*/ /** * Renames the specified instrument. * @param instr The absolute path name of the instrument to rename. * @param name The new name for the instrument. * @throws IOException If some I/O error occurs. * @throws LSException If the renaming of the instrument failed. * @throws LscpException If LSCP protocol corruption occurs. */ public synchronized void renameDbInstrument(String instr, String name) throws IOException, LSException, LscpException { name = toEscapedText(name); retrieveIndex("SET DB_INSTRUMENT NAME '" + conv(instr) + "' '" + conv(name) + "'"); } /** * Moves the specified instrument into the specified location. * @param instr The absolute path name of the instrument to move. * @param dst The directory where the specified instrument will be moved to. * @throws IOException If some I/O error occurs. * @throws LSException If the operation failed. * @throws LscpException If LSCP protocol corruption occurs. */ public synchronized void moveDbInstrument(String instr, String dst) throws IOException, LSException, LscpException { retrieveIndex("MOVE DB_INSTRUMENT '" + conv(instr) + "' '" + conv(dst) + "'"); } /** * Moves the specified instruments into the specified location. * @param instrs The absolute path names of the instruments to move. * @param dst The directory where the specified instruments will be moved to. * @throws IOException If some I/O error occurs. * @throws LSException If the operation failed. * @throws LscpException If LSCP protocol corruption occurs. */ public synchronized void moveDbInstruments(String[] instrs, String dst) throws IOException, LSException, LscpException { verifyConnection(); for(String s : instrs) { out.writeLine("MOVE DB_INSTRUMENT '" + conv(s) + "' '" + conv(dst) + "'"); } if(getPrintOnlyMode()) return; getEmptyResultSets(instrs.length, "Client.instrMovingFailed!"); } /** * Copies the specified instrument into the specified location. * @param instr The absolute path name of the instrument to copy. * @param dst The directory where the specified instrument will be copied to. * @throws IOException If some I/O error occurs. * @throws LSException If the operation failed. * @throws LscpException If LSCP protocol corruption occurs. */ public synchronized void copyDbInstrument(String instr, String dst) throws IOException, LSException, LscpException { retrieveIndex("COPY DB_INSTRUMENT '" + conv(instr) + "' '" + conv(dst) + "'"); } /** * Copies the specified instruments into the specified location. * @param instrs The absolute path name of the instruments to copy. * @param dst The directory where the specified instruments will be copied to. * @throws IOException If some I/O error occurs. * @throws LSException If the operation failed. * @throws LscpException If LSCP protocol corruption occurs. */ public synchronized void copyDbInstruments(String[] instrs, String dst) throws IOException, LSException, LscpException { verifyConnection(); for(String s : instrs) { out.writeLine("COPY DB_INSTRUMENT '" + conv(s) + "' '" + conv(dst) + "'"); } if(getPrintOnlyMode()) return; getEmptyResultSets(instrs.length, "Client.instrCopyingFailed!"); } /** * Changes the description of the specified instrument. * @param instr The absolute path name of the instrument. * @param desc The new description for the instrument. * @throws IOException If some I/O error occurs. * @throws LSException If failed to change the description. * @throws LscpException If LSCP protocol corruption occurs. */ public synchronized void setDbInstrumentDescription(String instr, String desc) throws IOException, LSException, LscpException { desc = toEscapedText(desc); retrieveIndex("SET DB_INSTRUMENT DESCRIPTION '" + conv(instr) + "' '" + desc + "'"); } /** * Substitutes all occurrences of the instrument file * oldPath in the database, with newPath. * @param oldPath The absolute path name of the instrument file to substitute. * @param newPath The new absolute path name. * @throws IOException If some I/O error occurs. * @throws LSException If the operation failed. * @throws LscpException If LSCP protocol corruption occurs. */ public synchronized void setDbInstrumentFilePath(String oldPath, String newPath) throws IOException, LSException, LscpException { retrieveIndex("SET DB_INSTRUMENT FILE_PATH '" + conv(oldPath) + "' '" + conv(newPath) + "'"); } /** * Finds all directories in the specified directory * that corresponds to the specified search criterias. * @param dir The absolute path name of the directory to search. * @param query Provides the search criterias. * @return A DbDirectoryInfo array providing * information about all directories that are found in the specified directory. * @throws IOException If some I/O error occurs. * @throws LscpException If LSCP protocol corruption occurs. * @throws LSException If the specified path name is invalid. */ public synchronized DbDirectoryInfo[] findDbDirectories(String dir, DbSearchQuery query) throws IOException, LscpException, LSException { return findDbDirectories(dir, query, false); } /** * Finds all directories in the specified directory * that corresponds to the specified search criterias. * @param dir The absolute path name of the directory to search. * @param query Provides the search criterias. * @param nonRecursive If true, the search will be non-recursive. * @return A DbDirectoryInfo array providing * information about all directories that are found in the specified directory. * @throws IOException If some I/O error occurs. * @throws LscpException If LSCP protocol corruption occurs. * @throws LSException If the specified path name is invalid. */ public synchronized DbDirectoryInfo[] findDbDirectories(String dir, DbSearchQuery query, boolean nonRecursive) throws IOException, LscpException, LSException { verifyConnection(); StringBuffer sb = new StringBuffer(); sb.append("FIND DB_INSTRUMENT_DIRECTORIES"); if(nonRecursive) sb.append(" NON_RECURSIVE"); sb.append(" '").append(conv(dir)).append("'"); if(query.name != null && query.name.length() > 0) { sb.append(" NAME='").append(toEscapedText(query.name)).append("'"); } String s = query.getCreatedAfter(); String s2 = query.getCreatedBefore(); if(s != null || s2 != null) { sb.append(" CREATED='"); if(s != null) sb.append(s); sb.append(".."); if(s2 != null) sb.append(s2); sb.append("'"); } s = query.getModifiedAfter(); s2 = query.getModifiedBefore(); if(s != null || s2 != null) { sb.append(" MODIFIED='"); if(s != null) sb.append(s); sb.append(".."); if(s2 != null) sb.append(s2); sb.append("'"); } if(query.description != null && query.description.length() > 0) { sb.append(" DESCRIPTION='"); sb.append(toEscapedText(query.description)).append("'"); } out.writeLine(sb.toString()); if(getPrintOnlyMode()) return null; String[] dirS = parseEscapedStringList(getSingleLineResultSet().getResult()); DbDirectoryInfo[] infoS = new DbDirectoryInfo[dirS.length]; for(int i = 0; i < dirS.length; i++) { infoS[i] = getDbDirectoryInfo(dirS[i]); } return infoS; } /** * Finds all instruments in the specified directory * that corresponds to the specified search criterias. * @param dir The absolute path name of the directory to search. * @param query Provides the search criterias. * @return A DbInstrumentInfo array providing * information about all instruments that are found in the specified directory. * @throws IOException If some I/O error occurs. * @throws LscpException If LSCP protocol corruption occurs. * @throws LSException If the specified path name is invalid. */ public synchronized DbInstrumentInfo[] findDbInstruments(String dir, DbSearchQuery query) throws IOException, LscpException, LSException { return findDbInstruments(dir, query, false); } /** * Finds all instruments in the specified directory * that corresponds to the specified search criterias. * @param dir The absolute path name of the directory to search. * @param query Provides the search criterias. * @param nonRecursive If true, the search will be non-recursive. * @return A DbInstrumentInfo array providing * information about all instruments that are found in the specified directory. * @throws IOException If some I/O error occurs. * @throws LscpException If LSCP protocol corruption occurs. * @throws LSException If the specified path name is invalid. */ public synchronized DbInstrumentInfo[] findDbInstruments(String dir, DbSearchQuery query, boolean nonRecursive) throws IOException, LscpException, LSException { verifyConnection(); StringBuffer sb = new StringBuffer(); sb.append("FIND DB_INSTRUMENTS"); if(nonRecursive) sb.append(" NON_RECURSIVE"); sb.append(" '").append(conv(dir)).append("'"); if(query.name != null && query.name.length() > 0) { sb.append(" NAME='").append(toEscapedText(query.name)).append("'"); } if(query.formatFamilies.size() > 0) { sb.append(" FORMAT_FAMILIES='").append(query.formatFamilies.get(0)); for(int i = 1; i < query.formatFamilies.size(); i++) { sb.append(',').append(query.formatFamilies.get(i)); } sb.append("'"); } if(query.minSize != -1 || query.maxSize != -1) { sb.append(" SIZE='"); if(query.minSize != -1) sb.append(query.minSize); sb.append(".."); if(query.maxSize != -1) sb.append(query.maxSize); sb.append("'"); } String s = query.getCreatedAfter(); String s2 = query.getCreatedBefore(); if(s != null || s2 != null) { sb.append(" CREATED='"); if(s != null) sb.append(s); sb.append(".."); if(s2 != null) sb.append(s2); sb.append("'"); } s = query.getModifiedAfter(); s2 = query.getModifiedBefore(); if(s != null || s2 != null) { sb.append(" MODIFIED='"); if(s != null) sb.append(s); sb.append(".."); if(s2 != null) sb.append(s2); sb.append("'"); } if(query.description != null && query.description.length() > 0) { sb.append(" DESCRIPTION='"); sb.append(toEscapedText(query.description)).append("'"); } if(query.instrumentType != DbSearchQuery.InstrumentType.BOTH) { sb.append(" IS_DRUM="); if(query.instrumentType == DbSearchQuery.InstrumentType.DRUM) { sb.append("'true'"); } else { sb.append("'false'"); } } if(query.product != null && query.product.length() > 0) { sb.append(" PRODUCT='").append(toEscapedText(query.product)).append("'"); } if(query.artists != null && query.artists.length() > 0) { sb.append(" ARTISTS='").append(toEscapedText(query.artists)).append("'"); } if(query.keywords != null && query.keywords.length() > 0) { sb.append(" KEYWORDS='"); sb.append(toEscapedText(query.keywords)).append("'"); } out.writeLine(sb.toString()); if(getPrintOnlyMode()) return null; String[] instrS = parseEscapedStringList(getSingleLineResultSet().getResult()); DbInstrumentInfo[] infoS = new DbInstrumentInfo[instrS.length]; for(int i = 0; i < instrS.length; i++) { infoS[i] = getDbInstrumentInfo(instrS[i]); } return infoS; } /** * Returns a list of all instrument files in the database * that that don't exist in the filesystem. * @throws IOException If some I/O error occurs. * @throws LscpException If LSCP protocol corruption occurs. * @throws LSException If other error occurs. */ public synchronized String[] findLostDbInstrumentFiles() throws IOException, LscpException, LSException { verifyConnection(); out.writeLine("FIND LOST DB_INSTRUMENT_FILES"); if(getPrintOnlyMode()) return null; return parseEscapedStringList(getSingleLineResultSet().getResult()); } /** * Gets status information about the specified job. * @param jobId The ID of the job. * @return A ScanJobInfo instance providing information * about the specified job. * @throws IOException If some I/O error occurs. * @throws LscpException If LSCP protocol corruption occurs. * @throws LSException If the specified job is not found. */ public synchronized ScanJobInfo getDbInstrumentsJobInfo(int jobId) throws IOException, LscpException, LSException { ScanJobInfo info = new ScanJobInfo(); if(!retrieveInfo("GET DB_INSTRUMENTS_JOB INFO " + String.valueOf(jobId), info)) return null; return info; } /** * 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 { retrieveIndex("FORMAT INSTRUMENTS_DB"); } /** * Resets the whole sampler. * * @throws IOException If some I/O error occurs. * @throws LscpException If LSCP protocol corruption occurs. */ public synchronized void resetSampler() throws IOException, LscpException { verifyConnection(); out.writeLine("RESET"); if(getPrintOnlyMode()) return; try { ResultSet rs = getEmptyResultSet(); } catch(LSException x) { getLogger().warning(x.getMessage()); } } /** * Gets the current number of all active streams. * @return The current number of all active streams or -1 if in "print only" mode. * @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 { return retrieveInt("GET TOTAL_STREAM_COUNT"); } /** * Gets the current number of all active voices. * @return The current number of all active voices or -1 if in "print only" mode. * @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 getTotalVoiceCount() throws IOException, LscpException, LSException { return retrieveInt("GET TOTAL_VOICE_COUNT"); } /** * Gets the maximum number of active voices. * @return The maximum number of active voices or -1 if in "print only" mode. * @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 getTotalVoiceCountMax() throws IOException, LscpException, LSException { return retrieveInt("GET TOTAL_VOICE_COUNT_MAX"); } /** * Gets information about the LinuxSampler instance. * * @return ServerInfo instance containing * information about the LinuxSampler instance. * * @throws IOException If an I/O error occurs. * @throws LscpException If LSCP protocol corruption occurs. * @throws LSException If some other error occurs. */ public synchronized ServerInfo getServerInfo() throws IOException, LscpException, LSException { ServerInfo info = new ServerInfo(); if(!retrieveInfo("GET SERVER INFO", info)) return null; return info; } /** * Gets the global volume of the sampler. * @return The global volume of the sampler. * @throws IOException If some I/O error occurs. * @throws LscpException If LSCP protocol corruption occurs. * @throws LSException If some other error occurs. */ public synchronized float getVolume() throws IOException, LscpException, LSException { verifyConnection(); out.writeLine("GET VOLUME"); if(getPrintOnlyMode()) return -1; String s = getSingleLineResultSet().getResult(); return parseFloat(s); } /** * Sets the global volume of the sampler. * @param volume The new volume value. * @throws IOException If some I/O error occurs. * @throws LscpException If LSCP protocol corruption occurs. * @throws LSException If some other error occurs. * @see #getVolume */ public synchronized void setVolume(float volume) throws IOException, LscpException, LSException { retrieveIndex("SET VOLUME " + volume); } /** * Gets the global sampler-wide limit of maximum voices. * @return The global sampler-wide limit of maximum voices or -1 if in "print only" mode. * @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 getGlobalVoiceLimit() throws IOException, LscpException, LSException { return retrieveInt("GET VOICES"); } /** * Sets the global sampler-wide limit of maximum voices. * @param maxVoices The new global limit of maximum voices. * @throws IOException If some I/O error occurs. * @throws LscpException If LSCP protocol corruption occurs. * @throws LSException If some other error occurs. * @see #getVolume */ public synchronized void setGlobalVoiceLimit(int maxVoices) throws IOException, LscpException, LSException { retrieveIndex("SET VOICES " + maxVoices); } /** * Gets the global sampler-wide limit of maximum disk streams. * @return The global sampler-wide limit of maximum disk streams * or -1 if in "print only" mode. * @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 getGlobalStreamLimit() throws IOException, LscpException, LSException { return retrieveInt("GET STREAMS"); } /** * Sets the global sampler-wide limit for maximum disk streams. * @param maxVoices The new global limit of maximum disk streams. * @throws IOException If some I/O error occurs. * @throws LscpException If LSCP protocol corruption occurs. * @throws LSException If some other error occurs. * @see #getVolume */ public synchronized void setGlobalStreamLimit(int maxStreams) throws IOException, LscpException, LSException { retrieveIndex("SET STREAMS " + maxStreams); } /** * 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 * or -1 if in "print only" mode. * @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 { return retrieveInt("GET FILE INSTRUMENTS '" + conv(filename) +"'"); } /** * 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 { FileInstrument instr = new FileInstrument(); String cmd = "GET FILE INSTRUMENT INFO '" + conv(filename) + "' " + String.valueOf(instrIdx); if(!retrieveInfo(cmd, instr)) return null; 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() { } public String getEngine() { // TODO: engine lookup? return getFormatFamily(); } @Override 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(); for(int i = 0; i < count; i++) { try { getEmptyResultSet(); } catch (SocketTimeoutException e) { getLogger().log(Level.FINE, e.getMessage(), e); sb.append(e.getMessage()).append("\n"); break; } catch (Exception e) { getLogger().log(Level.FINE, e.getMessage(), e); sb.append(e.getMessage()).append("\n"); } } String details = sb.toString(); if(details.length() > 0) { String s = LscpI18n.getLogMsg(err); throw new LSException(0, s, details); } } /** * Retrieves a list of integers. * @throws IOException If some I/O error occurs. * @throws LscpException If LSCP protocol corruption occurs. */ private Integer[] getIntegerList(String lscpCmd) throws IOException, LscpException, LSException { verifyConnection(); out.writeLine(lscpCmd); if(getPrintOnlyMode()) return null; return parseIntList(getSingleLineResultSet().getResult()); } private boolean retrieveInfo(String lscpCmd, Parseable p) throws IOException, LscpException, LSException { verifyConnection(); out.writeLine(lscpCmd); if(getPrintOnlyMode()) return false; ResultSet rs = getMultiLineResultSet(); for(String s : rs.getMultiLineResult()) { if(!p.parse(s)) Client.getLogger().info(LscpI18n.getLogMsg("unknownLine", s)); } return true; } private int retrieveInt(String lscpCmd) throws IOException, LscpException, LSException { verifyConnection(); out.writeLine(lscpCmd); if(getPrintOnlyMode()) return -1; String s = getSingleLineResultSet().getResult(); return parseInt(s); } private int retrieveIndex(String lscpCmd) throws IOException, LSException, LscpException { verifyConnection(); out.writeLine(lscpCmd); if(getPrintOnlyMode()) return -1; return getEmptyResultSet().getIndex(); } /** * Returns the logger for this library. * @return The logger for this library. */ protected static Logger getLogger() { return Logger.getLogger("org.linuxsampler.lscp"); } }