/[svn]/jlscp/trunk/src/org/linuxsampler/lscp/Client.java
ViewVC logotype

Diff of /jlscp/trunk/src/org/linuxsampler/lscp/Client.java

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 784 by iliev, Mon Oct 10 14:55:44 2005 UTC revision 2242 by iliev, Wed Aug 17 09:06:46 2011 UTC
# Line 1  Line 1 
1  /*  /*
2   *   jlscp - a java LinuxSampler control protocol API   *   jlscp - a java LinuxSampler control protocol API
3   *   *
4   *   Copyright (C) 2005 Grigor Kirilov Iliev   *   Copyright (C) 2005-2011 Grigor Iliev <grigor@grigoriliev.com>
5   *   *
6   *   This file is part of jlscp.   *   This file is part of jlscp.
7   *   *
# Line 23  Line 23 
23  package org.linuxsampler.lscp;  package org.linuxsampler.lscp;
24    
25  import java.io.IOException;  import java.io.IOException;
26    import java.io.OutputStream;
27    
28  import java.net.InetSocketAddress;  import java.net.InetSocketAddress;
29  import java.net.Socket;  import java.net.Socket;
30  import java.net.SocketTimeoutException;  import java.net.SocketTimeoutException;
 import java.net.UnknownHostException;  
31    
32    import java.util.ArrayList;
33    import java.util.TreeMap;
34  import java.util.Vector;  import java.util.Vector;
35  import java.util.logging.Level;  import java.util.logging.Level;
36  import java.util.logging.Logger;  import java.util.logging.Logger;
37    
 import static org.linuxsampler.lscp.Parser.*;  
38  import org.linuxsampler.lscp.event.*;  import org.linuxsampler.lscp.event.*;
39    
40    import static org.linuxsampler.lscp.Parser.*;
41    
42    
43  /**  /**
44   * This class is the abstraction representing a client endpoint for communication with LinuxSampler   * This class is the abstraction representing a client endpoint for communication with LinuxSampler
45   * instance. Since it implements all commands specified in the LSCP protocol v1.0, for more   * instance. Since it implements all commands specified in the LSCP protocol v1.5, for more
46   * information look at the   * information look at the
47   * <a href=http://www.linuxsampler.org/api/lscp-1.0.html>LSCP</a> specification.   * <a href=http://www.linuxsampler.org/api/lscp-1.5.html>LSCP</a> specification.
48   *   *
49   * <p> The following code establishes connection to LinuxSampler instance and gets the   * <p> The following code establishes connection to LinuxSampler instance and gets the
50   * LinuxSampler version:   * LinuxSampler version:
# Line 68  public class Client { Line 71  public class Client {
71          private String address;          private String address;
72          private int port;          private int port;
73          private Socket sock = null;          private Socket sock = null;
74          private int soTimeout = 10000;          private int soTimeout = 20000;
75                    
76          private LscpInputStream in = null;          private LscpInputStream in = null;
77          private LscpOutputStream out = null;          private LscpOutputStream out = null;
78                    
79          private EventThread eventThread;          private EventThread eventThread;
80                    
81            private boolean printOnlyMode = false;
82    
83            public enum ResultSetType {
84                    EMPTY, SINGLE_LINE, MULTI_LINE
85            }
86            
87            private static class ResultSetEntry {
88                    public ResultSetType type;
89                    
90                    public
91                    ResultSetEntry(ResultSetType type) {
92                            this.type = type;
93                    }
94            }
95    
96            private Vector<ResultSetEntry> resultSetQueue = new Vector<ResultSetEntry>();
97            
98            /* Used for caching the engines' info */
99            private final TreeMap<String, SamplerEngine> engineMap = new TreeMap<String, SamplerEngine>();
100            
101          class EventThread extends Thread {          class EventThread extends Thread {
102                    private Vector<String> queue = new Vector<String>();
103                  private boolean terminate = false;                  private boolean terminate = false;
104                                    
105                  EventThread() { super("LSCP-Event-Thread"); }                  EventThread() { super("LSCP-Event-Thread"); }
106                                    
107                    @Override
108                  public void                  public void
109                  run() {                  run() {
110                          while(!mustTerminate()) {                          while(!mustTerminate()) {
111                                  try { processNotifications(); }                                  try {
112                                  catch(Exception x) {                                          processQueue();
113                                            processNotifications();
114                                    } catch(Exception x) {
115                                          getLogger().log(Level.FINE, x.getMessage(), x);                                          getLogger().log(Level.FINE, x.getMessage(), x);
116                                  }                                  }
117                                  try { synchronized(this) { wait(100); } }                                  try { synchronized(this) { wait(100); } }
# Line 102  public class Client { Line 129  public class Client {
129                          terminate = true;                          terminate = true;
130                          this.notifyAll();                          this.notifyAll();
131                  }                  }
132                    
133                    public synchronized void
134                    scheduleNotification(String s) { queue.add(s); }
135                    
136                    private void
137                    processQueue() {
138                            String[] notifications = popAllNotifications();
139                            for(String n : notifications) fireEvent(n);
140                    }
141                    
142                    private synchronized String[]
143                    popAllNotifications() {
144                            String[] notifications = queue.toArray(new String[queue.size()]);
145                            queue.removeAllElements();
146                            return notifications;
147                    }
148          }          }
149                    
150          /**          /**
# Line 133  public class Client { Line 176  public class Client {
176          }          }
177                    
178          /**          /**
179             * Creates a new instance of Client.
180             * @param printOnlyMode Determines whether the client will be in print-only mode.
181             */
182            public
183            Client(boolean printOnlyMode) {
184                    if(printOnlyMode) setPrintOnlyMode(true);
185            }
186            
187            private boolean extendedCharacterEscaping = true;
188            
189            /**
190             * Sets whether strings sent to LinuxSampler should be more aggressively escaped.
191             */
192            public synchronized void
193            setExtendedCharacterEscaping(boolean b) { extendedCharacterEscaping = b; }
194            
195            /**
196             * Determines whether strings sent to LinuxSampler should be more aggressively escaped.
197             */
198            public synchronized boolean
199            getExtendedCharacterEscaping() { return extendedCharacterEscaping; }
200            
201            /**
202             * @see java.net.Socket#setSoTimeout
203             */
204            public synchronized void
205            setSoTimeout(int timeout) {
206                    soTimeout = timeout;
207                    
208                    try { if(sock != null) sock.setSoTimeout(timeout); }
209                    catch(Exception x) { getLogger().log(Level.INFO, "Unable to set timeout", x); }
210            }
211            
212            private String
213            toEscapedText(String s) {
214                    s = toEscapedString(s);
215                    return conv(s);
216            }
217            
218            private String
219            toEscapedFsEntry(String s) {
220                    s = toEscapedFileName(s);
221                    return conv(s);
222            }
223            
224            /**
225             * Applies an extended character escaping to the specified string if needed.
226             */
227            private String
228            conv(String s) {
229                    return getExtendedCharacterEscaping() ? toExtendedEscapeSequence(s) : s;
230            }
231            
232            /**
233             * Determines whether the client is in print-only mode.
234             * Print-only mode means that the client will just print all
235             * LSCP commands to the specified output stream or to the standard output stream
236             * (<code>java.lang.System.out</code>) if no output stream is specified,
237             * without taking any further actions. Thus, in print-only mode all returned
238             * values by <code>Client</code>'s methods are meaningless and should be discarded.
239             * @return <code>true</code> if the client is in
240             * print-only mode, <code>false</code> otherwise.
241             * @see #setPrintOnlyModeOutputStream
242             */
243            public synchronized boolean
244            getPrintOnlyMode() { return printOnlyMode; }
245            
246            /**
247             * Sets the print-only mode. Note that in print-only mode all returned
248             * values by <code>Client</code>'s methods are meaningless and should be discarded.
249             * The default output stream in print-only mode is <code>java.lang.System.out</code>.
250             * @param b If <code>true</code> all LSCP commands will be sent
251             * to the specified output stream or to the standard output stream
252             * (<code>java.lang.System.out</code>) if no output stream is specified,
253             * and no further actions will be taken.
254             * @throws IllegalStateException If the client is connected.
255             * @see #setPrintOnlyModeOutputStream
256             */
257            public synchronized void
258            setPrintOnlyMode(boolean b) {
259                    if(printOnlyMode == b) return;
260                    if(isConnected()) throw new IllegalStateException();
261                    
262                    printOnlyMode = b;
263                    if(b) out = new LscpOutputStream(System.out);
264            }
265            
266            /**
267             * Sets the output stream to be used in print-only mode.
268             * @param out The output stream to be used in print-only mode.
269             * @throws IllegalStateException If the client is not in print-only mode.
270             * @throws IllegalArgumentException if <code>out</code> is <code>null</code>.
271             * @see #setPrintOnlyMode
272             */
273            public synchronized void
274            setPrintOnlyModeOutputStream(OutputStream out) {
275                    if(!getPrintOnlyMode()) throw new IllegalStateException("Not in print-only mode");
276                    if(out == null) throw new IllegalArgumentException("out must be non-null");
277                    this.out = new LscpOutputStream(out);
278            }
279            
280            /**
281           * Specifies the jlscp version.           * Specifies the jlscp version.
282           * @return The jlscp version.           * @return The jlscp version.
283           */           */
# Line 180  public class Client { Line 325  public class Client {
325          public synchronized void          public synchronized void
326          connect() throws LscpException {          connect() throws LscpException {
327                  if(sock != null) disconnect();                  if(sock != null) disconnect();
328                    if(getPrintOnlyMode()) return;
329                    
330                    engineMap.clear();
331                                    
332                  // Initializing LSCP event thread                  // Initializing LSCP event thread
333                  if(eventThread.isAlive()) {                  if(eventThread.isAlive()) {
# Line 252  public class Client { Line 400  public class Client {
400                  if(hasSubscriptions()) eventThread.start();                  if(hasSubscriptions()) eventThread.start();
401                                    
402                  if(!llM.isEmpty()) subscribe("MISCELLANEOUS");                  if(!llM.isEmpty()) subscribe("MISCELLANEOUS");
403                    if(!llAODC.isEmpty()) subscribe("AUDIO_OUTPUT_DEVICE_COUNT");
404                    if(!llAODI.isEmpty()) subscribe("AUDIO_OUTPUT_DEVICE_INFO");
405                    if(!llMIDC.isEmpty()) subscribe("MIDI_INPUT_DEVICE_COUNT");
406                    if(!llMIDI.isEmpty()) subscribe("MIDI_INPUT_DEVICE_INFO");
407                  if(!llBF.isEmpty()) subscribe("BUFFER_FILL");                  if(!llBF.isEmpty()) subscribe("BUFFER_FILL");
408                  if(!llCC.isEmpty()) subscribe("CHANNEL_COUNT");                  if(!llCC.isEmpty()) subscribe("CHANNEL_COUNT");
409                  if(!llCI.isEmpty()) subscribe("CHANNEL_INFO");                  if(!llCI.isEmpty()) subscribe("CHANNEL_INFO");
410                    if(!llFSC.isEmpty()) subscribe("FX_SEND_COUNT");
411                    if(!llFSI.isEmpty()) subscribe("FX_SEND_INFO");
412                  if(!llSC.isEmpty()) subscribe("STREAM_COUNT");                  if(!llSC.isEmpty()) subscribe("STREAM_COUNT");
413                  if(!llVC.isEmpty()) subscribe("VOICE_COUNT");                  if(!llVC.isEmpty()) subscribe("VOICE_COUNT");
414                    if(!llTSC.isEmpty()) subscribe("TOTAL_STREAM_COUNT");
415                  if(!llTVC.isEmpty()) subscribe("TOTAL_VOICE_COUNT");                  if(!llTVC.isEmpty()) subscribe("TOTAL_VOICE_COUNT");
416                    if(!llMIMC.isEmpty()) subscribe("MIDI_INSTRUMENT_MAP_COUNT");
417                    if(!llMIMI.isEmpty()) subscribe("MIDI_INSTRUMENT_MAP_INFO");
418                    if(!llMIC.isEmpty()) subscribe("MIDI_INSTRUMENT_COUNT");
419                    if(!llMII.isEmpty()) subscribe("MIDI_INSTRUMENT_INFO");
420                    if(!llDMD.isEmpty()) subscribe("DEVICE_MIDI");
421                    if(!llCMD.isEmpty()) subscribe("CHANNEL_MIDI");
422                    if(!llID.isEmpty()) {
423                            subscribe("DB_INSTRUMENT_DIRECTORY_COUNT");
424                            subscribe("DB_INSTRUMENT_DIRECTORY_INFO");
425                            subscribe("DB_INSTRUMENT_COUNT");
426                            subscribe("DB_INSTRUMENT_INFO");
427                            subscribe("DB_INSTRUMENTS_JOB_INFO");
428                    }
429                    if(!llGI.isEmpty()) subscribe("GLOBAL_INFO");
430                    if(!llEIC.isEmpty()) subscribe("EFFECT_INSTANCE_COUNT");
431                    if(!llEII.isEmpty()) subscribe("EFFECT_INSTANCE_INFO");
432                    if(!llSECC.isEmpty()) subscribe("SEND_EFFECT_CHAIN_COUNT");
433                    if(!llSECI.isEmpty()) subscribe("SEND_EFFECT_CHAIN_INFO");
434          }          }
435                    
436          /**          /**
# Line 265  public class Client { Line 438  public class Client {
438           */           */
439          public synchronized void          public synchronized void
440          disconnect() {          disconnect() {
441                    if(getPrintOnlyMode()) return;
442                  try { if(sock != null) sock.close(); }                  try { if(sock != null) sock.close(); }
443                  catch(Exception x) { getLogger().log(Level.FINE, x.getMessage(), x); }                  catch(Exception x) { getLogger().log(Level.FINE, x.getMessage(), x); }
444                  sock = null;                  sock = null;
# Line 273  public class Client { Line 447  public class Client {
447                          eventThread.terminate();                          eventThread.terminate();
448                          eventThread = new EventThread();                          eventThread = new EventThread();
449                  }                  }
450                    
451                    engineMap.clear();
452          }          }
453                    
454          /**          /**
# Line 292  public class Client { Line 468  public class Client {
468           */           */
469          private void          private void
470          verifyConnection() throws IOException {          verifyConnection() throws IOException {
471                    if(getPrintOnlyMode()) return;
472                    
473                  if(!isConnected())                  if(!isConnected())
474                          throw new IOException(LscpI18n.getLogMsg("Client.notConnected!"));                          throw new IOException(LscpI18n.getLogMsg("Client.notConnected!"));
475          }          }
# Line 301  public class Client { Line 479  public class Client {
479                  String s;                  String s;
480                  for(;;) {                  for(;;) {
481                          s = in.readLine();                          s = in.readLine();
482                          if(s.startsWith("NOTIFY:")) fireEvent(s.substring("NOTIFY:".length()));                          if(s.startsWith("NOTIFY:")) {
483                                    eventThread.scheduleNotification(s.substring("NOTIFY:".length()));
484                            }
485                          else break;                          else break;
486                  }                  }
487                  return s;                  return s;
488          }          }
489                    
490          /** Processes the notifications send by LinuxSampler */          /** Processes the notifications sent by LinuxSampler */
491          private synchronized void          private synchronized void
492          processNotifications() throws IOException, LscpException {          processNotifications() throws IOException, LscpException {
493                  while(in.available() > 0) {                  while(in.available() > 0) {
# Line 316  public class Client { Line 496  public class Client {
496                          else getLogger().severe("Unknown notification format: " + s);                          else getLogger().severe("Unknown notification format: " + s);
497                  }                  }
498          }          }
499    
500            private synchronized void
501            processResultSetQueue() {
502                    for(int i = 0; i < resultSetQueue.size(); i++) {
503                            try {
504                                    switch(resultSetQueue.get(i).type) {
505                                            case EMPTY:
506                                                    getEmptyResultSet();
507                                                    break;
508                                            case SINGLE_LINE:
509                                                    getSingleLineResultSet();
510                                                    break;
511                                            case MULTI_LINE:
512                                                    getMultiLineResultSet();
513                                                    break;
514                                            default:
515                                                    getLogger().severe("Unknown result set type");
516                                    }
517                            } catch(Exception x) {
518                                    getLogger().log(Level.FINE, "Error while processing result set queue", x);
519                            }
520                    }
521    
522                    resultSetQueue.removeAllElements();
523            }
524                    
525          /**          /**
526           * Gets empty result set.           * Gets empty result set.
527           * @return <code>ResultSet</code> instance.           * @return <code>ResultSet</code> instance.
528           */           */
529          private ResultSet          private ResultSet
530          getEmptyResultSet() throws IOException, LscpException, LSException {          getEmptyResultSet() throws IOException, LscpException, LSException {
531                    processResultSetQueue();
532                  return parseEmptyResultSet(getLine());                  return parseEmptyResultSet(getLine());
533          }          }
534                    
535          private ResultSet          private ResultSet
536          getSingleLineResultSet() throws IOException, LscpException, LSException {          getSingleLineResultSet() throws IOException, LscpException, LSException {
537                    processResultSetQueue();
538                  ResultSet rs = new ResultSet();                  ResultSet rs = new ResultSet();
539                  String ln = getLine();                  String ln = getLine();
540                                    
# Line 346  public class Client { Line 553  public class Client {
553                    
554          private ResultSet          private ResultSet
555          getMultiLineResultSet() throws IOException, LscpException, LSException {          getMultiLineResultSet() throws IOException, LscpException, LSException {
556                    processResultSetQueue();
557                  ResultSet rs = new ResultSet();                  ResultSet rs = new ResultSet();
558                  String ln = getLine();                  String ln = getLine();
559                                    
# Line 366  public class Client { Line 574  public class Client {
574                  return rs;                  return rs;
575          }          }
576                    
577            /** Audio output device count listeners */
578            private final Vector<ItemCountListener> llAODC = new Vector<ItemCountListener>();
579            /** Audio output device info listeners */
580            private final Vector<ItemInfoListener> llAODI = new Vector<ItemInfoListener>();
581          private final Vector<BufferFillListener> llBF = new Vector<BufferFillListener>();          private final Vector<BufferFillListener> llBF = new Vector<BufferFillListener>();
582          private final Vector<ChannelCountListener> llCC = new Vector<ChannelCountListener>();          private final Vector<ChannelCountListener> llCC = new Vector<ChannelCountListener>();
583          private final Vector<ChannelInfoListener> llCI = new Vector<ChannelInfoListener>();          private final Vector<ChannelInfoListener> llCI = new Vector<ChannelInfoListener>();
584            private final Vector<FxSendCountListener> llFSC = new Vector<FxSendCountListener>();
585            private final Vector<FxSendInfoListener> llFSI = new Vector<FxSendInfoListener>();
586          private final Vector<MiscellaneousListener> llM = new Vector<MiscellaneousListener>();          private final Vector<MiscellaneousListener> llM = new Vector<MiscellaneousListener>();
587            /** MIDI input device count listeners */
588            private final Vector<ItemCountListener> llMIDC = new Vector<ItemCountListener>();
589            /** MIDI input device info listeners */
590            private final Vector<ItemInfoListener> llMIDI = new Vector<ItemInfoListener>();
591          private final Vector<StreamCountListener> llSC = new Vector<StreamCountListener>();          private final Vector<StreamCountListener> llSC = new Vector<StreamCountListener>();
592          private final Vector<VoiceCountListener> llVC = new Vector<VoiceCountListener>();          private final Vector<VoiceCountListener> llVC = new Vector<VoiceCountListener>();
593            private final Vector<TotalStreamCountListener> llTSC = new Vector<TotalStreamCountListener>();
594          private final Vector<TotalVoiceCountListener> llTVC = new Vector<TotalVoiceCountListener>();          private final Vector<TotalVoiceCountListener> llTVC = new Vector<TotalVoiceCountListener>();
595                    
596            /** MIDI instrument map count listeners */
597            private final Vector<ItemCountListener> llMIMC = new Vector<ItemCountListener>();
598            /** MIDI instrument map info listeners */
599            private final Vector<ItemInfoListener> llMIMI = new Vector<ItemInfoListener>();
600            /** MIDI instrument count listeners */
601            private final Vector<MidiInstrumentCountListener> llMIC =
602                    new Vector<MidiInstrumentCountListener>();
603            /** MIDI instrument info listeners */
604            private final Vector<MidiInstrumentInfoListener> llMII =
605                    new Vector<MidiInstrumentInfoListener>();
606            private final Vector<DeviceMidiDataListener> llDMD = new Vector<DeviceMidiDataListener>();
607            private final Vector<ChannelMidiDataListener> llCMD = new Vector<ChannelMidiDataListener>();
608            private final Vector<InstrumentsDbListener> llID = new Vector<InstrumentsDbListener>();
609            private final Vector<GlobalInfoListener> llGI = new Vector<GlobalInfoListener>();
610            private final ArrayList<EffectInstanceCountListener> llEIC = new ArrayList<EffectInstanceCountListener>();
611            private final Vector<EffectInstanceInfoListener> llEII = new Vector<EffectInstanceInfoListener>();
612            private final Vector<SendEffectChainCountListener> llSECC = new Vector<SendEffectChainCountListener>();
613            private final Vector<SendEffectChainInfoListener> llSECI = new Vector<SendEffectChainInfoListener>();
614            
615            
616          /**          /**
617           * Determines whether there is at least one subscription for notification events.           * Determines whether there is at least one subscription for notification events.
618           * Do not forget to check for additional listeners if the LSCP specification           * Do not forget to check for additional listeners if the LSCP specification
# Line 383  public class Client { Line 622  public class Client {
622           */           */
623          private boolean          private boolean
624          hasSubscriptions() {          hasSubscriptions() {
625                  return  !llBF.isEmpty() ||                  return  !llAODC.isEmpty() ||
626                          !llCC.isEmpty() ||                          !llAODI.isEmpty() ||
627                          !llCI.isEmpty() ||                          !llBF.isEmpty()   ||
628                          !llM.isEmpty()  ||                          !llCC.isEmpty()   ||
629                          !llSC.isEmpty() ||                          !llCI.isEmpty()   ||
630                          !llVC.isEmpty() ||                          !llFSC.isEmpty()  ||
631                          !llTVC.isEmpty();                          !llFSI.isEmpty()  ||
632                            !llM.isEmpty()    ||
633                            !llMIDC.isEmpty() ||
634                            !llMIDI.isEmpty() ||
635                            !llSC.isEmpty()   ||
636                            !llVC.isEmpty()   ||
637                            !llTSC.isEmpty()  ||
638                            !llTVC.isEmpty()  ||
639                            !llMIMC.isEmpty() ||
640                            !llMIMI.isEmpty() ||
641                            !llMIC.isEmpty()  ||
642                            !llMII.isEmpty()  ||
643                            !llDMD.isEmpty()  ||
644                            !llCMD.isEmpty()  ||
645                            !llID.isEmpty()   ||
646                            !llGI.isEmpty()   ||
647                            !llEIC.isEmpty()  ||
648                            !llEII.isEmpty()  ||
649                            !llSECC.isEmpty() ||
650                            !llSECI.isEmpty();
651          }          }
652                    
653          private void          private synchronized void
654            fireDeviceMidiDataEvent(String s) {
655                    try {
656                            String[] list = parseList(s, ' ');
657                            if(list.length != 5) {
658                                    getLogger().warning("Unknown DEVICE_MIDI format");
659                                    return;
660                            }
661                            
662                            int dev = parseInt(list[0]);
663                            int port = parseInt(list[1]);
664                            
665                            MidiDataEvent.Type type = parseMidiDataType(list[2]);
666                            if(type == null) return;
667                            
668                            int note = parseInt(list[3]);
669                            int velocity = parseInt(list[4]);
670                            
671                            DeviceMidiDataEvent e = new DeviceMidiDataEvent(this, type, note, velocity);
672                            e.setDeviceId(dev);
673                            e.setPortId(port);
674                            for(DeviceMidiDataListener l : llDMD) l.midiDataArrived(e);
675                    } catch(LscpException x) {
676                            getLogger().log (
677                                    Level.WARNING, LscpI18n.getLogMsg("CommandFailed!"), x
678                            );
679                    }
680            }
681            
682            private synchronized void
683            fireChannelMidiDataEvent(String s) {
684                    try {
685                            String[] list = parseList(s, ' ');
686                            if(list.length != 4) {
687                                    getLogger().warning("Unknown CHANNEL_MIDI format");
688                                    return;
689                            }
690                            
691                            int channel = parseInt(list[0]);
692                            
693                            MidiDataEvent.Type type = parseMidiDataType(list[1]);
694                            if(type == null) return;
695                            
696                            int note = parseInt(list[2]);
697                            int velocity = parseInt(list[3]);
698                            
699                            ChannelMidiDataEvent e = new ChannelMidiDataEvent(this, type, note, velocity);
700                            e.setChannelId(channel);
701                            for(ChannelMidiDataListener l : llCMD) l.midiDataArrived(e);
702                    } catch(LscpException x) {
703                            getLogger().log (
704                                    Level.WARNING, LscpI18n.getLogMsg("CommandFailed!"), x
705                            );
706                    }
707            }
708            
709            private MidiDataEvent.Type
710            parseMidiDataType(String s) {
711                    if("NOTE_ON".equals(s)) return MidiDataEvent.Type.NOTE_ON;
712                    if("NOTE_OFF".equals(s)) return MidiDataEvent.Type.NOTE_OFF;
713                    if("CC".equals(s)) return MidiDataEvent.Type.CC;
714                    
715                    getLogger().warning("Unknown MIDI data type: " + s);
716                    return null;
717            }
718            
719            private synchronized void
720          fireEvent(String s) {          fireEvent(String s) {
721                  if(s.startsWith("CHANNEL_COUNT:")) {                  // Sort by priority
722                    
723                     if(s.startsWith("CHANNEL_MIDI:")) {
724                            s = s.substring("CHANNEL_MIDI:".length());
725                            fireChannelMidiDataEvent(s);
726                    } else if(s.startsWith("DEVICE_MIDI:")) {
727                            s = s.substring("DEVICE_MIDI:".length());
728                            fireDeviceMidiDataEvent(s);
729                    } else if(s.startsWith("DB_INSTRUMENT_DIRECTORY_COUNT:")) {
730                            s = s.substring("DB_INSTRUMENT_DIRECTORY_COUNT:".length());
731                            InstrumentsDbEvent e = new InstrumentsDbEvent(this, s);
732                            for(InstrumentsDbListener l : llID) l.directoryCountChanged(e);
733                    } else if(s.startsWith("DB_INSTRUMENT_DIRECTORY_INFO:")) {
734                            InstrumentsDbEvent e;
735                            s = s.substring("DB_INSTRUMENT_DIRECTORY_INFO:".length());
736                            if(s.startsWith("NAME ")) {
737                                    String[] list;
738                                    try {
739                                            s = s.substring("NAME ".length());
740                                            list = parseEscapedStringList(s, ' ');
741                                            if(list.length != 2) throw new LscpException();
742                                            list[1] = toNonEscapedString(list[1]);
743                                            e = new InstrumentsDbEvent(this, list[0], list[1]);
744                                            for(InstrumentsDbListener l : llID) {
745                                                    l.directoryNameChanged(e);
746                                            }
747                                    } catch(LscpException x) {
748                                            getLogger().log (
749                                                    Level.WARNING,
750                                                    LscpI18n.getLogMsg("CommandFailed!"),
751                                                    x
752                                            );
753                                    }
754                            } else {
755                                    e = new InstrumentsDbEvent(this, s);
756                                    for(InstrumentsDbListener l : llID) l.directoryInfoChanged(e);
757                            }
758                    } else if(s.startsWith("DB_INSTRUMENT_COUNT:")) {
759                            s = s.substring("DB_INSTRUMENT_COUNT:".length());
760                            InstrumentsDbEvent e = new InstrumentsDbEvent(this, s);
761                            for(InstrumentsDbListener l : llID) l.instrumentCountChanged(e);
762                    } else if(s.startsWith("DB_INSTRUMENT_INFO:")) {
763                            InstrumentsDbEvent e;
764                            s = s.substring("DB_INSTRUMENT_INFO:".length());
765                            if(s.startsWith("NAME ")) {
766                                    String[] list;
767                                    try {
768                                            s = s.substring("NAME ".length());
769                                            list = parseEscapedStringList(s, ' ');
770                                            if(list.length != 2) throw new LscpException();
771                                            list[1] = toNonEscapedString(list[1]);
772                                            e = new InstrumentsDbEvent(this, list[0], list[1]);
773                                            for(InstrumentsDbListener l : llID) {
774                                                    l.instrumentNameChanged(e);
775                                            }
776                                    } catch(LscpException x) {
777                                            getLogger().log (
778                                                    Level.WARNING,
779                                                    LscpI18n.getLogMsg("CommandFailed!"),
780                                                    x
781                                            );
782                                    }
783                            } else {
784                                    e = new InstrumentsDbEvent(this, s);
785                                    for(InstrumentsDbListener l : llID) l.instrumentInfoChanged(e);
786                            }
787                    } else if(s.startsWith("DB_INSTRUMENTS_JOB_INFO:")) {
788                            s = s.substring("DB_INSTRUMENTS_JOB_INFO:".length());
789                            try {
790                                    int i = Integer.parseInt(s);
791                                    InstrumentsDbEvent e = new InstrumentsDbEvent(this, i);
792                                    for(InstrumentsDbListener l : llID) l.jobStatusChanged(e);
793                            } catch(NumberFormatException x) {
794                                    s = "Unknown DB_INSTRUMENTS_JOB_INFO format";
795                                    getLogger().log(Level.WARNING, s, x);
796                            }
797                            
798                    } else if(s.startsWith("CHANNEL_COUNT:")) {
799                          try {                          try {
800                                  int i = Integer.parseInt(s.substring("CHANNEL_COUNT:".length()));                                  int i = Integer.parseInt(s.substring("CHANNEL_COUNT:".length()));
801                                  ChannelCountEvent e = new ChannelCountEvent(this, i);                                  ChannelCountEvent e = new ChannelCountEvent(this, i);
# Line 407  public class Client { Line 808  public class Client {
808                  } else if(s.startsWith("VOICE_COUNT:")) {                  } else if(s.startsWith("VOICE_COUNT:")) {
809                          try {                          try {
810                                  s = s.substring("VOICE_COUNT:".length());                                  s = s.substring("VOICE_COUNT:".length());
811                                  int i = s.indexOf(' ');                                  Integer[] i = parseIntList(s, ' ');
812                                  if(i == -1) {                                  if(i.length != 2) {
813                                          getLogger().warning("Unknown VOICE_COUNT format");                                          getLogger().warning("Unknown VOICE_COUNT format");
814                                          return;                                          return;
815                                  }                                  }
816                                  int j = Integer.parseInt(s.substring(0, i));                                  VoiceCountEvent e = new VoiceCountEvent(this, i[0], i[1]);
                                 i = Integer.parseInt(s.substring(i + 1));  
                                 VoiceCountEvent e = new VoiceCountEvent(this, j, i);  
817                                  for(VoiceCountListener l : llVC) l.voiceCountChanged(e);                                  for(VoiceCountListener l : llVC) l.voiceCountChanged(e);
818                          } catch(NumberFormatException x) {                          } catch(Exception x) {
819                                  getLogger().log(Level.WARNING, "Unknown VOICE_COUNT format", x);                                  getLogger().log(Level.WARNING, "Unknown VOICE_COUNT format", x);
820                          }                          }
821                  } else if(s.startsWith("STREAM_COUNT:")) {                  } else if(s.startsWith("STREAM_COUNT:")) {
822                          try {                          try {
823                                  s = s.substring("STREAM_COUNT:".length());                                  s = s.substring("STREAM_COUNT:".length());
824                                  int i = s.indexOf(' ');                                  Integer[] i = parseIntList(s, ' ');
825                                  if(i == -1) {                                  if(i.length != 2) {
826                                          getLogger().warning("Unknown STREAM_COUNT format");                                          getLogger().warning("Unknown STREAM_COUNT format");
827                                          return;                                          return;
828                                  }                                  }
829                                  int j = Integer.parseInt(s.substring(0, i));                                  StreamCountEvent e = new StreamCountEvent(this, i[0], i[1]);
                                 i = Integer.parseInt(s.substring(i + 1));  
                                 StreamCountEvent e = new StreamCountEvent(this, j, i);  
830                                  for(StreamCountListener l : llSC) l.streamCountChanged(e);                                  for(StreamCountListener l : llSC) l.streamCountChanged(e);
831                          } catch(NumberFormatException x) {                          } catch(Exception x) {
832                                  getLogger().log(Level.WARNING, "Unknown STREAM_COUNT format", x);                                  getLogger().log(Level.WARNING, "Unknown STREAM_COUNT format", x);
833                          }                          }
834                  } else if(s.startsWith("BUFFER_FILL:")) {                  } else if(s.startsWith("BUFFER_FILL:")) {
# Line 439  public class Client { Line 836  public class Client {
836                                  s = s.substring("BUFFER_FILL:".length());                                  s = s.substring("BUFFER_FILL:".length());
837                                  int i = s.indexOf(' ');                                  int i = s.indexOf(' ');
838                                  if(i == -1) {                                  if(i == -1) {
839                                          getLogger().warning("Unknown STREAM_COUNT format");                                          getLogger().warning("Unknown BUFFER_FILL format");
840                                          return;                                          return;
841                                  }                                  }
842                                  int j = Integer.parseInt(s.substring(0, i));                                  int j = Integer.parseInt(s.substring(0, i));
# Line 448  public class Client { Line 845  public class Client {
845                                  BufferFillEvent e = new BufferFillEvent(this, j, v);                                  BufferFillEvent e = new BufferFillEvent(this, j, v);
846                                  for(BufferFillListener l : llBF) l.bufferFillChanged(e);                                  for(BufferFillListener l : llBF) l.bufferFillChanged(e);
847                          } catch(Exception x) {                          } catch(Exception x) {
848                                  getLogger().log(Level.WARNING, "Unknown STREAM_COUNT format", x);                                  getLogger().log(Level.WARNING, "Unknown BUFFER_FILL format", x);
849                          }                          }
850                  } else if(s.startsWith("CHANNEL_INFO:")) {                  } else if(s.startsWith("CHANNEL_INFO:")) {
851                          try {                          try {
# Line 456  public class Client { Line 853  public class Client {
853                                  ChannelInfoEvent e = new ChannelInfoEvent(this, i);                                  ChannelInfoEvent e = new ChannelInfoEvent(this, i);
854                                  for(ChannelInfoListener l : llCI) l.channelInfoChanged(e);                                  for(ChannelInfoListener l : llCI) l.channelInfoChanged(e);
855                          } catch(NumberFormatException x) {                          } catch(NumberFormatException x) {
856                                  getLogger().log(Level.WARNING, "Unknown STREAM_COUNT format", x);                                  getLogger().log(Level.WARNING, "Unknown CHANNEL_INFO format", x);
857                            }
858                    } else if(s.startsWith("TOTAL_STREAM_COUNT:")) {
859                            try {
860                                    s = s.substring("TOTAL_STREAM_COUNT:".length());
861                                    int i = Integer.parseInt(s);
862                                    TotalStreamCountEvent e = new TotalStreamCountEvent(this, i);
863                                    for(TotalStreamCountListener l : llTSC) l.totalStreamCountChanged(e);
864                            } catch(NumberFormatException x) {
865                                    getLogger().log (
866                                            Level.WARNING, "Unknown TOTAL_STREAM_COUNT format", x
867                                    );
868                          }                          }
869                  } else if(s.startsWith("TOTAL_VOICE_COUNT:")) {                  } else if(s.startsWith("TOTAL_VOICE_COUNT:")) {
870                          try {                          try {
# Line 469  public class Client { Line 877  public class Client {
877                                          Level.WARNING, "Unknown TOTAL_VOICE_COUNT format", x                                          Level.WARNING, "Unknown TOTAL_VOICE_COUNT format", x
878                                  );                                  );
879                          }                          }
880                    } else if(s.startsWith("AUDIO_OUTPUT_DEVICE_COUNT:")) {
881                            try {
882                                    s = s.substring("AUDIO_OUTPUT_DEVICE_COUNT:".length());
883                                    int i = Integer.parseInt(s);
884                                    ItemCountEvent e = new ItemCountEvent(this, i);
885                                    for(ItemCountListener l : llAODC) l.itemCountChanged(e);
886                            } catch(NumberFormatException x) {
887                                    getLogger().log (
888                                            Level.WARNING, "Unknown AUDIO_OUTPUT_DEVICE_COUNT format", x
889                                    );
890                            }
891                    } else if(s.startsWith("AUDIO_OUTPUT_DEVICE_INFO:")) {
892                            try {
893                                    s = s.substring("AUDIO_OUTPUT_DEVICE_INFO:".length());
894                                    int i = Integer.parseInt(s);
895                                    ItemInfoEvent e = new ItemInfoEvent(this, i);
896                                    for(ItemInfoListener l : llAODI) l.itemInfoChanged(e);
897                            } catch(NumberFormatException x) {
898                                    getLogger().log (
899                                            Level.WARNING, "Unknown AUDIO_OUTPUT_DEVICE_INFO format", x
900                                    );
901                            }
902                    } else if(s.startsWith("MIDI_INPUT_DEVICE_COUNT:")) {
903                            try {
904                                    s = s.substring("MIDI_INPUT_DEVICE_COUNT:".length());
905                                    int i = Integer.parseInt(s);
906                                    ItemCountEvent e = new ItemCountEvent(this, i);
907                                    for(ItemCountListener l : llMIDC) l.itemCountChanged(e);
908                            } catch(NumberFormatException x) {
909                                    getLogger().log (
910                                            Level.WARNING, "Unknown MIDI_INPUT_DEVICE_COUNT format", x
911                                    );
912                            }
913                    } else if(s.startsWith("MIDI_INPUT_DEVICE_INFO:")) {
914                            try {
915                                    s = s.substring("MIDI_INPUT_DEVICE_INFO:".length());
916                                    int i = Integer.parseInt(s);
917                                    ItemInfoEvent e = new ItemInfoEvent(this, i);
918                                    for(ItemInfoListener l : llMIDI) l.itemInfoChanged(e);
919                            } catch(NumberFormatException x) {
920                                    getLogger().log (
921                                            Level.WARNING, "Unknown MIDI_INPUT_DEVICE_INFO format", x
922                                    );
923                            }
924                    } else if(s.startsWith("MIDI_INSTRUMENT_MAP_COUNT:")) {
925                            try {
926                                    s = s.substring("MIDI_INSTRUMENT_MAP_COUNT:".length());
927                                    int i = Integer.parseInt(s);
928                                    ItemCountEvent e = new ItemCountEvent(this, i);
929                                    for(ItemCountListener l : llMIMC) l.itemCountChanged(e);
930                            } catch(NumberFormatException x) {
931                                    getLogger().log (
932                                            Level.WARNING, "Unknown MIDI_INSTRUMENT_MAP_COUNT format", x
933                                    );
934                            }
935                    } else if(s.startsWith("MIDI_INSTRUMENT_MAP_INFO:")) {
936                            try {
937                                    s = s.substring("MIDI_INSTRUMENT_MAP_INFO:".length());
938                                    int i = Integer.parseInt(s);
939                                    ItemInfoEvent e = new ItemInfoEvent(this, i);
940                                    for(ItemInfoListener l : llMIMI) l.itemInfoChanged(e);
941                            } catch(NumberFormatException x) {
942                                    getLogger().log (
943                                            Level.WARNING, "Unknown MIDI_INSTRUMENT_MAP_INFO format", x
944                                    );
945                            }
946                    } else if(s.startsWith("MIDI_INSTRUMENT_COUNT:")) {
947                            try {
948                                    s = s.substring("MIDI_INSTRUMENT_COUNT:".length());
949                                    Integer[] i = parseIntList(s, ' ');
950                                    if(i.length != 2) {
951                                            getLogger().warning("Unknown MIDI_INSTRUMENT_COUNT format");
952                                            return;
953                                    }
954                                    
955                                    MidiInstrumentCountEvent e =
956                                            new MidiInstrumentCountEvent(this, i[0], i[1]);
957                                    
958                                    for(MidiInstrumentCountListener l : llMIC) {
959                                            l.instrumentCountChanged(e);
960                                    }
961                            } catch(Exception x) {
962                                    getLogger().log (
963                                            Level.WARNING, "Unknown MIDI_INSTRUMENT_COUNT format", x
964                                    );
965                            }
966                    } else if(s.startsWith("MIDI_INSTRUMENT_INFO:")) {
967                            try {
968                                    s = s.substring("MIDI_INSTRUMENT_INFO:".length());
969                                    Integer[] i = parseIntList(s, ' ');
970                                    if(i.length != 3) {
971                                            getLogger().warning("Unknown MIDI_INSTRUMENT_INFO format");
972                                            return;
973                                    }
974                                    
975                                    MidiInstrumentInfoEvent e =
976                                            new MidiInstrumentInfoEvent(this, i[0], i[1], i[2]);
977                                    for(MidiInstrumentInfoListener l : llMII) {
978                                            l.instrumentInfoChanged(e);
979                                    }
980                            } catch(Exception x) {
981                                    getLogger().log (
982                                            Level.WARNING, "Unknown MIDI_INSTRUMENT_INFO format", x
983                                    );
984                            }
985                    } else if(s.startsWith("FX_SEND_COUNT:")) {
986                            try {
987                                    s = s.substring("FX_SEND_COUNT:".length());
988                                    Integer[] i = parseIntList(s, ' ');
989                                    if(i.length != 2) {
990                                            getLogger().warning("Unknown FX_SEND_COUNT format");
991                                            return;
992                                    }
993                                    
994                                    FxSendCountEvent e = new FxSendCountEvent(this, i[0], i[1]);
995                                    
996                                    for(FxSendCountListener l : llFSC) l.fxSendCountChanged(e);
997                            } catch(Exception x) {
998                                    getLogger().log(Level.WARNING, "Unknown FX_SEND_COUNT format", x);
999                            }
1000                    } else if(s.startsWith("FX_SEND_INFO:")) {
1001                            try {
1002                                    s = s.substring("FX_SEND_INFO:".length());
1003                                    Integer[] i = parseIntList(s, ' ');
1004                                    if(i.length != 2) {
1005                                            getLogger().warning("Unknown FX_SEND_INFO format");
1006                                            return;
1007                                    }
1008                                    
1009                                    FxSendInfoEvent e = new FxSendInfoEvent(this, i[0], i[1]);
1010                                    for(FxSendInfoListener l : llFSI) {
1011                                            l.fxSendInfoChanged(e);
1012                                    }
1013                            } catch(Exception x) {
1014                                    getLogger().log(Level.WARNING, "Unknown FX_SEND_INFO format", x);
1015                            }
1016                    } else if(s.startsWith("EFFECT_INSTANCE_COUNT:")) {
1017                            try {
1018                                    s = s.substring("EFFECT_INSTANCE_COUNT:".length());
1019                                    int i = Integer.parseInt(s);
1020                                    
1021                                    EffectInstanceCountEvent e = new EffectInstanceCountEvent(this, i);
1022                                    for(EffectInstanceCountListener l : llEIC) {
1023                                            l.effectInstanceCountChanged(e);
1024                                    }
1025                            } catch(Exception x) {
1026                                    getLogger().log(Level.WARNING, "Unknown EFFECT_INSTANCE_COUNT format", x);
1027                            }
1028                    } else if(s.startsWith("EFFECT_INSTANCE_INFO:")) {
1029                            try {
1030                                    s = s.substring("EFFECT_INSTANCE_INFO:".length());
1031                                    int i = Integer.parseInt(s);
1032                                    
1033                                    EffectInstanceInfoEvent e = new EffectInstanceInfoEvent(this, i);
1034                                    for(EffectInstanceInfoListener l : llEII) {
1035                                            l.effectInstanceInfoChanged(e);
1036                                    }
1037                            } catch(Exception x) {
1038                                    getLogger().log(Level.WARNING, "Unknown EFFECT_INSTANCE_INFO format", x);
1039                            }
1040                    } else if(s.startsWith("SEND_EFFECT_CHAIN_COUNT:")) {
1041                            try {
1042                                    s = s.substring("SEND_EFFECT_CHAIN_COUNT:".length());
1043                                    Integer[] i = parseIntList(s, ' ');
1044                                    if(i.length != 2) {
1045                                            getLogger().warning("Unknown SEND_EFFECT_CHAIN_COUNT format");
1046                                            return;
1047                                    }
1048                                    
1049                                    SendEffectChainCountEvent e =
1050                                            new SendEffectChainCountEvent(this, i[0], i[1]);
1051                                    
1052                                    for(SendEffectChainCountListener l : llSECC) {
1053                                            l.sendEffectChainCountChanged(e);
1054                                    }
1055                            } catch(Exception x) {
1056                                    getLogger().log(Level.WARNING, "Unknown SEND_EFFECT_CHAIN_COUNT format", x);
1057                            }
1058                    } else if(s.startsWith("SEND_EFFECT_CHAIN_INFO:")) {
1059                            try {
1060                                    s = s.substring("SEND_EFFECT_CHAIN_INFO:".length());
1061                                    Integer[] i = parseIntList(s, ' ');
1062                                    if(i.length != 3) {
1063                                            getLogger().warning("Unknown SEND_EFFECT_CHAIN_INFO format");
1064                                            return;
1065                                    }
1066                                    
1067                                    SendEffectChainInfoEvent e =
1068                                            new SendEffectChainInfoEvent(this, i[0], i[1], i[2]);
1069                                    
1070                                    for(SendEffectChainInfoListener l : llSECI) {
1071                                            l.sendEffectChainInfoChanged(e);
1072                                    }
1073                            } catch(Exception x) {
1074                                    getLogger().log(Level.WARNING, "Unknown SEND_EFFECT_CHAIN_INFO format", x);
1075                            }
1076                    } else if(s.startsWith("GLOBAL_INFO:")) {
1077                            handleGlobalInfoEvent(s.substring("GLOBAL_INFO:".length()));
1078                  } else if(s.startsWith("MISCELLANEOUS:")) {                  } else if(s.startsWith("MISCELLANEOUS:")) {
1079                          s = s.substring("MISCELLANEOUS:".length());                          s = s.substring("MISCELLANEOUS:".length());
1080                          MiscellaneousEvent e = new MiscellaneousEvent(this, s);                          MiscellaneousEvent e = new MiscellaneousEvent(this, s);
# Line 477  public class Client { Line 1083  public class Client {
1083          }          }
1084                    
1085          private void          private void
1086            handleGlobalInfoEvent(String s) {
1087                    try {
1088                            if(s.startsWith("VOLUME ")) {
1089                                    float f = Float.parseFloat(s.substring("VOLUME ".length()));
1090                                    GlobalInfoEvent e = new GlobalInfoEvent(this, f);
1091                                    for(GlobalInfoListener l : llGI) l.volumeChanged(e);
1092                            } else if(s.startsWith("VOICES ")) {
1093                                    int i = Integer.parseInt(s.substring("VOICES ".length()));
1094                                    GlobalInfoEvent e = new GlobalInfoEvent(this, i, -1);
1095                                    for(GlobalInfoListener l : llGI) l.voiceLimitChanged(e);
1096                            } else if(s.startsWith("STREAMS ")) {
1097                                    int i = Integer.parseInt(s.substring("STREAMS ".length()));
1098                                    GlobalInfoEvent e = new GlobalInfoEvent(this, -1, i);
1099                                    for(GlobalInfoListener l : llGI) l.streamLimitChanged(e);
1100                            } else {
1101                                    getLogger().info("Unknown GLOBAL_INFO format: " + s);
1102                            }
1103                    } catch(NumberFormatException x) {
1104                            getLogger().log(Level.WARNING, "Unknown GLOBAL_INFO format", x);
1105                    }
1106            }
1107            
1108            private void
1109          subscribe(String event) {          subscribe(String event) {
1110                  if(!isConnected()) return;                  if(!getPrintOnlyMode()) {
1111                            if(!isConnected()) return;
1112                                    
1113                  if(!eventThread.isAlive()) eventThread.start();                          if(!eventThread.isAlive()) eventThread.start();
1114                    }
1115                                    
1116                  try {                  try {
1117                          out.writeLine("SUBSCRIBE " + event);                          out.writeLine("SUBSCRIBE " + event);
1118                          ResultSet rs = getEmptyResultSet();                          if(!getPrintOnlyMode()) getEmptyResultSet();
1119                  } catch(Exception x) {                  } catch(Exception x) {
1120                          getLogger().log (                          getLogger().log (
1121                                  Level.WARNING,                                  Level.WARNING,
# Line 496  public class Client { Line 1127  public class Client {
1127                    
1128          private void          private void
1129          unsubscribe(String event) {          unsubscribe(String event) {
1130                  if(!isConnected()) return;                  if(!getPrintOnlyMode() && !isConnected()) return;
1131                                    
1132                  try {                  try {
1133                          out.writeLine("UNSUBSCRIBE " + event);                          out.writeLine("UNSUBSCRIBE " + event);
1134                          ResultSet rs = getEmptyResultSet();                          if(!getPrintOnlyMode()) getEmptyResultSet();
1135                  } catch(Exception x) {                  } catch(Exception x) {
1136                          getLogger().log (                          getLogger().log (
1137                                  Level.WARNING,                                  Level.WARNING,
# Line 512  public class Client { Line 1143  public class Client {
1143                    
1144          /**          /**
1145           * Registers the specified listener for receiving event messages.           * Registers the specified listener for receiving event messages.
1146             * Listeners can be registered regardless of the connection state.
1147             * @param l The <code>ItemCountListener</code> to register.
1148             */
1149            public synchronized void
1150            addAudioDeviceCountListener(ItemCountListener l) {
1151                    if(llAODC.isEmpty()) subscribe("AUDIO_OUTPUT_DEVICE_COUNT");
1152                    llAODC.add(l);
1153            }
1154            
1155            /**
1156             * Removes the specified listener.
1157             * Listeners can be removed regardless of the connection state.
1158             * @param l The <code>ItemCountListener</code> to remove.
1159             */
1160            public synchronized void
1161            removeAudioDeviceCountListener(ItemCountListener l) {
1162                    boolean b = llAODC.remove(l);
1163                    if(b && llAODC.isEmpty()) unsubscribe("AUDIO_OUTPUT_DEVICE_COUNT");
1164            }
1165            
1166            /**
1167             * Registers the specified listener for receiving event messages.
1168             * Listeners can be registered regardless of the connection state.
1169             * @param l The <code>ItemInfoListener</code> to register.
1170             */
1171            public synchronized void
1172            addAudioDeviceInfoListener(ItemInfoListener l) {
1173                    if(llAODI.isEmpty()) subscribe("AUDIO_OUTPUT_DEVICE_INFO");
1174                    llAODI.add(l);
1175            }
1176            
1177            /**
1178             * Removes the specified listener.
1179             * Listeners can be removed regardless of the connection state.
1180             * @param l The <code>ItemInfoListener</code> to remove.
1181             */
1182            public synchronized void
1183            removeAudioDeviceInfoListener(ItemInfoListener l) {
1184                    boolean b = llAODI.remove(l);
1185                    if(b && llAODI.isEmpty()) unsubscribe("AUDIO_OUTPUT_DEVICE_INFO");
1186            }
1187            
1188            /**
1189             * Registers the specified listener for receiving event messages.
1190           * Listeners can be removed regardless of the connection state.           * Listeners can be removed regardless of the connection state.
1191           * @param l The <code>BufferFillListener</code> to register.           * @param l The <code>BufferFillListener</code> to register.
1192           */           */
# Line 579  public class Client { Line 1254  public class Client {
1254          /**          /**
1255           * Registers the specified listener for receiving event messages.           * Registers the specified listener for receiving event messages.
1256           * Listeners can be registered regardless of the connection state.           * Listeners can be registered regardless of the connection state.
1257             * @param l The <code>FxSendCountListener</code> to register.
1258             */
1259            public synchronized void
1260            addFxSendCountListener(FxSendCountListener l) {
1261                    if(llFSC.isEmpty()) subscribe("FX_SEND_COUNT");
1262                    llFSC.add(l);
1263            }
1264            
1265            /**
1266             * Removes the specified listener.
1267             * Listeners can be removed regardless of the connection state.
1268             * @param l The <code>FxSendCountListener</code> to remove.
1269             */
1270            public synchronized void
1271            removeFxSendCountListener(FxSendCountListener l) {
1272                    boolean b = llFSC.remove(l);
1273                    if(b && llFSC.isEmpty()) unsubscribe("FX_SEND_COUNT");
1274            }
1275            
1276            /**
1277             * Registers the specified listener for receiving event messages.
1278             * Listeners can be registered regardless of the connection state.
1279             * @param l The <code>FxSendInfoListener</code> to register.
1280             */
1281            public synchronized void
1282            addFxSendInfoListener(FxSendInfoListener l) {
1283                    if(llFSI.isEmpty()) subscribe("FX_SEND_INFO");
1284                    llFSI.add(l);
1285            }
1286            
1287            /**
1288             * Removes the specified listener.
1289             * Listeners can be removed regardless of the connection state.
1290             * @param l The <code>FxSendInfoListener</code> to remove.
1291             */
1292            public synchronized void
1293            removeFxSendInfoListener(FxSendInfoListener l) {
1294                    boolean b = llFSI.remove(l);
1295                    if(b && llFSI.isEmpty()) unsubscribe("FX_SEND_INFO");
1296            }
1297            
1298            /**
1299             * Registers the specified listener for receiving event messages.
1300             * Listeners can be registered regardless of the connection state.
1301             * @param l The <code>ItemCountListener</code> to register.
1302             */
1303            public synchronized void
1304            addMidiDeviceCountListener(ItemCountListener l) {
1305                    if(llMIDC.isEmpty()) subscribe("MIDI_INPUT_DEVICE_COUNT");
1306                    llMIDC.add(l);
1307            }
1308            
1309            /**
1310             * Removes the specified listener.
1311             * Listeners can be removed regardless of the connection state.
1312             * @param l The <code>ItemCountListener</code> to remove.
1313             */
1314            public synchronized void
1315            removeMidiDeviceCountListener(ItemCountListener l) {
1316                    boolean b = llMIDC.remove(l);
1317                    if(b && llMIDC.isEmpty()) unsubscribe("MIDI_INPUT_DEVICE_COUNT");
1318            }
1319            
1320            /**
1321             * Registers the specified listener for receiving event messages.
1322             * Listeners can be registered regardless of the connection state.
1323             * @param l The <code>ItemInfoListener</code> to register.
1324             */
1325            public synchronized void
1326            addMidiDeviceInfoListener(ItemInfoListener l) {
1327                    if(llMIDI.isEmpty()) subscribe("MIDI_INPUT_DEVICE_INFO");
1328                    llMIDI.add(l);
1329            }
1330            
1331            /**
1332             * Removes the specified listener.
1333             * Listeners can be removed regardless of the connection state.
1334             * @param l The <code>ItemInfoListener</code> to remove.
1335             */
1336            public synchronized void
1337            removeMidiDeviceInfoListener(ItemInfoListener l) {
1338                    boolean b = llMIDI.remove(l);
1339                    if(b && llMIDI.isEmpty()) unsubscribe("MIDI_INPUT_DEVICE_INFO");
1340            }
1341            
1342            /**
1343             * Registers the specified listener for receiving event messages.
1344             * Listeners can be registered regardless of the connection state.
1345           * @param l The <code>MiscellaneousListener</code> to register.           * @param l The <code>MiscellaneousListener</code> to register.
1346           */           */
1347          public synchronized void          public synchronized void
# Line 645  public class Client { Line 1408  public class Client {
1408          /**          /**
1409           * Registers the specified listener for receiving event messages.           * Registers the specified listener for receiving event messages.
1410           * Listeners can be registered regardless of the connection state.           * Listeners can be registered regardless of the connection state.
1411             * @param l The <code>TotalStreamCountListener</code> to register.
1412             */
1413            public synchronized void
1414            addTotalStreamCountListener(TotalStreamCountListener l) {
1415                    if(llTSC.isEmpty()) subscribe("TOTAL_STREAM_COUNT");
1416                    llTSC.add(l);
1417            }
1418            
1419            /**
1420             * Removes the specified listener.
1421             * Listeners can be removed regardless of the connection state.
1422             * @param l The <code>TotalStreamCountListener</code> to remove.
1423             */
1424            public synchronized void
1425            removeTotalStreamCountListener(TotalStreamCountListener l) {
1426                    boolean b = llTSC.remove(l);
1427                    if(b && llTSC.isEmpty()) unsubscribe("TOTAL_STREAM_COUNT");
1428            }
1429            
1430            /**
1431             * Registers the specified listener for receiving event messages.
1432             * Listeners can be registered regardless of the connection state.
1433           * @param l The <code>TotalVoiceCountListener</code> to register.           * @param l The <code>TotalVoiceCountListener</code> to register.
1434           */           */
1435          public synchronized void          public synchronized void
# Line 665  public class Client { Line 1450  public class Client {
1450          }          }
1451                    
1452          /**          /**
1453             * Registers the specified listener for receiving event messages.
1454             * Listeners can be registered regardless of the connection state.
1455             * @param l The <code>ItemCountListener</code> to register.
1456             */
1457            public synchronized void
1458            addMidiInstrumentMapCountListener(ItemCountListener l) {
1459                    if(llMIMC.isEmpty()) subscribe("MIDI_INSTRUMENT_MAP_COUNT");
1460                    llMIMC.add(l);
1461            }
1462            
1463            /**
1464             * Removes the specified listener.
1465             * Listeners can be removed regardless of the connection state.
1466             * @param l The <code>ItemCountListener</code> to remove.
1467             */
1468            public synchronized void
1469            removeMidiInstrumentMapCountListener(ItemCountListener l) {
1470                    boolean b = llMIMC.remove(l);
1471                    if(b && llMIMC.isEmpty()) unsubscribe("MIDI_INSTRUMENT_MAP_COUNT");
1472            }
1473            
1474            /**
1475             * Registers the specified listener for receiving event messages.
1476             * Listeners can be registered regardless of the connection state.
1477             * @param l The <code>ItemInfoListener</code> to register.
1478             */
1479            public synchronized void
1480            addMidiInstrumentMapInfoListener(ItemInfoListener l) {
1481                    if(llMIMI.isEmpty()) subscribe("MIDI_INSTRUMENT_MAP_INFO");
1482                    llMIMI.add(l);
1483            }
1484            
1485            /**
1486             * Removes the specified listener.
1487             * Listeners can be removed regardless of the connection state.
1488             * @param l The <code>ItemInfoListener</code> to remove.
1489             */
1490            public synchronized void
1491            removeMidiInstrumentMapInfoListener(ItemInfoListener l) {
1492                    boolean b = llMIMI.remove(l);
1493                    if(b && llMIMI.isEmpty()) unsubscribe("MIDI_INSTRUMENT_MAP_INFO");
1494            }
1495            
1496            /**
1497             * Registers the specified listener for receiving event messages.
1498             * Listeners can be registered regardless of the connection state.
1499             * @param l The <code>MidiInstrumentCountListener</code> to register.
1500             */
1501            public synchronized void
1502            addMidiInstrumentCountListener(MidiInstrumentCountListener l) {
1503                    if(llMIC.isEmpty()) subscribe("MIDI_INSTRUMENT_COUNT");
1504                    llMIC.add(l);
1505            }
1506            
1507            /**
1508             * Removes the specified listener.
1509             * Listeners can be removed regardless of the connection state.
1510             * @param l The <code>MidiInstrumentCountListener</code> to remove.
1511             */
1512            public synchronized void
1513            removeMidiInstrumentCountListener(MidiInstrumentCountListener l) {
1514                    boolean b = llMIC.remove(l);
1515                    if(b && llMIC.isEmpty()) unsubscribe("MIDI_INSTRUMENT_COUNT");
1516            }
1517            
1518            /**
1519             * Registers the specified listener for receiving event messages.
1520             * Listeners can be registered regardless of the connection state.
1521             * @param l The <code>MidiInstrumentInfoListener</code> to register.
1522             */
1523            public synchronized void
1524            addMidiInstrumentInfoListener(MidiInstrumentInfoListener l) {
1525                    if(llMII.isEmpty()) subscribe("MIDI_INSTRUMENT_INFO");
1526                    llMII.add(l);
1527            }
1528            
1529            /**
1530             * Removes the specified listener.
1531             * Listeners can be removed regardless of the connection state.
1532             * @param l The <code>MidiInstrumentInfoListener</code> to remove.
1533             */
1534            public synchronized void
1535            removeMidiInstrumentInfoListener(MidiInstrumentInfoListener l) {
1536                    boolean b = llMII.remove(l);
1537                    if(b && llMII.isEmpty()) unsubscribe("MIDI_INSTRUMENT_INFO");
1538            }
1539            
1540            /**
1541             * Registers the specified listener for receiving event messages.
1542             * Listeners can be registered regardless of the connection state.
1543             * @param l The <code>DeviceMidiDataListener</code> to register.
1544             */
1545            public synchronized void
1546            addDeviceMidiDataListener(DeviceMidiDataListener l) {
1547                    if(llDMD.isEmpty()) subscribe("DEVICE_MIDI");
1548                    llDMD.add(l);
1549            }
1550            
1551            /**
1552             * Removes the specified listener.
1553             * Listeners can be removed regardless of the connection state.
1554             * @param l The <code>DeviceMidiDataListener</code> to remove.
1555             */
1556            public synchronized void
1557            removeDeviceMidiDataListener(DeviceMidiDataListener l) {
1558                    boolean b = llDMD.remove(l);
1559                    if(b && llDMD.isEmpty()) unsubscribe("DEVICE_MIDI");
1560            }
1561            
1562            /**
1563             * Registers the specified listener for receiving event messages.
1564             * Listeners can be registered regardless of the connection state.
1565             * @param l The <code>ChannelMidiDataListener</code> to register.
1566             */
1567            public synchronized void
1568            addChannelMidiDataListener(ChannelMidiDataListener l) {
1569                    if(llCMD.isEmpty()) subscribe("CHANNEL_MIDI");
1570                    llCMD.add(l);
1571            }
1572            
1573            /**
1574             * Removes the specified listener.
1575             * Listeners can be removed regardless of the connection state.
1576             * @param l The <code>ChannelMidiDataListener</code> to remove.
1577             */
1578            public synchronized void
1579            removeChannelMidiDataListener(ChannelMidiDataListener l) {
1580                    boolean b = llCMD.remove(l);
1581                    if(b && llCMD.isEmpty()) unsubscribe("CHANNEL_MIDI");
1582            }
1583            
1584            /**
1585             * Registers the specified listener for receiving event messages.
1586             * Listeners can be registered regardless of the connection state.
1587             * @param l The <code>InstrumentsDbListener</code> to register.
1588             */
1589            public synchronized void
1590            addInstrumentsDbListener(InstrumentsDbListener l) {
1591                    if(llID.isEmpty()) {
1592                            subscribe("DB_INSTRUMENT_DIRECTORY_COUNT");
1593                            subscribe("DB_INSTRUMENT_DIRECTORY_INFO");
1594                            subscribe("DB_INSTRUMENT_COUNT");
1595                            subscribe("DB_INSTRUMENT_INFO");
1596                            subscribe("DB_INSTRUMENTS_JOB_INFO");
1597                    }
1598                    llID.add(l);
1599            }
1600            
1601            /**
1602             * Removes the specified listener.
1603             * Listeners can be removed regardless of the connection state.
1604             * @param l The <code>InstrumentsDbListener</code> to remove.
1605             */
1606            public synchronized void
1607            removeInstrumentsDbListener(InstrumentsDbListener l) {
1608                    boolean b = llID.remove(l);
1609                    if(b && llID.isEmpty()) {
1610                            unsubscribe("DB_INSTRUMENT_DIRECTORY_COUNT");
1611                            unsubscribe("DB_INSTRUMENT_DIRECTORY_INFO");
1612                            unsubscribe("DB_INSTRUMENT_COUNT");
1613                            unsubscribe("DB_INSTRUMENT_INFO");
1614                            unsubscribe("DB_INSTRUMENTS_JOB_INFO");
1615                    }
1616            }
1617            
1618            /**
1619             * Registers the specified listener for receiving event messages.
1620             * Listeners can be registered regardless of the connection state.
1621             * @param l The <code>GlobalInfoListener</code> to register.
1622             */
1623            public synchronized void
1624            addGlobalInfoListener(GlobalInfoListener l) {
1625                    if(llGI.isEmpty()) subscribe("GLOBAL_INFO");
1626                    llGI.add(l);
1627            }
1628            
1629            /**
1630             * Removes the specified listener.
1631             * Listeners can be removed regardless of the connection state.
1632             * @param l The <code>GlobalInfoListener</code> to remove.
1633             */
1634            public synchronized void
1635            removeGlobalInfoListener(GlobalInfoListener l) {
1636                    boolean b = llGI.remove(l);
1637                    if(b && llGI.isEmpty()) unsubscribe("GLOBAL_INFO");
1638            }
1639            
1640            /**
1641             * Registers the specified listener for receiving event messages.
1642             * Listeners can be registered regardless of the connection state.
1643             * @param l The <code>EffectInstanceCountListener</code> to register.
1644             */
1645            public synchronized void
1646            addEffectInstanceCountListener(EffectInstanceCountListener l) {
1647                    if(llEIC.isEmpty()) subscribe("EFFECT_INSTANCE_COUNT");
1648                    llEIC.add(l);
1649            }
1650            
1651            /**
1652             * Removes the specified listener.
1653             * Listeners can be removed regardless of the connection state.
1654             * @param l The <code>EffectInstanceCountListener</code> to remove.
1655             */
1656            public synchronized void
1657            removeEffectInstanceCountListener(EffectInstanceCountListener l) {
1658                    boolean b = llEIC.remove(l);
1659                    if(b && llEIC.isEmpty()) unsubscribe("EFFECT_INSTANCE_COUNT");
1660            }
1661            
1662            /**
1663             * Registers the specified listener for receiving event messages.
1664             * Listeners can be registered regardless of the connection state.
1665             * @param l The <code>EffectInstanceInfoListener</code> to register.
1666             */
1667            public synchronized void
1668            addEffectInstanceInfoListener(EffectInstanceInfoListener l) {
1669                    if(llEII.isEmpty()) subscribe("EFFECT_INSTANCE_INFO");
1670                    llEII.add(l);
1671            }
1672            
1673            /**
1674             * Removes the specified listener.
1675             * Listeners can be removed regardless of the connection state.
1676             * @param l The <code>EffectInstanceInfoListener</code> to remove.
1677             */
1678            public synchronized void
1679            removeEffectInstanceInfoListener(EffectInstanceInfoListener l) {
1680                    boolean b = llEII.remove(l);
1681                    if(b && llEII.isEmpty()) unsubscribe("EFFECT_INSTANCE_INFO");
1682            }
1683            
1684            /**
1685             * Registers the specified listener for receiving event messages.
1686             * Listeners can be registered regardless of the connection state.
1687             * @param l The <code>SendEffectChainCountListener</code> to register.
1688             */
1689            public synchronized void
1690            addSendEffectChainCountListener(SendEffectChainCountListener l) {
1691                    if(llSECC.isEmpty()) subscribe("SEND_EFFECT_CHAIN_COUNT");
1692                    llSECC.add(l);
1693            }
1694            
1695            /**
1696             * Removes the specified listener.
1697             * Listeners can be removed regardless of the connection state.
1698             * @param l The <code>SendEffectChainCountListener</code> to remove.
1699             */
1700            public synchronized void
1701            removeSendEffectChainCountListener(SendEffectChainCountListener l) {
1702                    boolean b = llSECC.remove(l);
1703                    if(b && llSECC.isEmpty()) unsubscribe("SEND_EFFECT_CHAIN_COUNT");
1704            }
1705            
1706            /**
1707             * Registers the specified listener for receiving event messages.
1708             * Listeners can be registered regardless of the connection state.
1709             * @param l The <code>SendEffectChainInfoListener</code> to register.
1710             */
1711            public synchronized void
1712            addSendEffectChainInfoListener(SendEffectChainInfoListener l) {
1713                    if(llSECI.isEmpty()) subscribe("SEND_EFFECT_CHAIN_INFO");
1714                    llSECI.add(l);
1715            }
1716            
1717            /**
1718             * Removes the specified listener.
1719             * Listeners can be removed regardless of the connection state.
1720             * @param l The <code>SendEffectChainInfoListener</code> to remove.
1721             */
1722            public synchronized void
1723            removeSendEffectChainInfoListener(SendEffectChainInfoListener l) {
1724                    boolean b = llSECI.remove(l);
1725                    if(b && llSECI.isEmpty()) unsubscribe("SEND_EFFECT_CHAIN_INFO");
1726            }
1727            
1728            /**
1729           * Gets the number of all audio output drivers currently           * Gets the number of all audio output drivers currently
1730           * available for the LinuxSampler instance.           * available for the LinuxSampler instance.
1731           * @return The number of all audio output drivers currently           * @return The number of all audio output drivers currently
1732           * available for the LinuxSampler instance.           * available for the LinuxSampler instance or -1 if in "print only" mode.
1733           * @throws IOException If some I/O error occurs.           * @throws IOException If some I/O error occurs.
1734           * @throws LscpException If LSCP protocol corruption occurs.           * @throws LscpException If LSCP protocol corruption occurs.
1735           * @throws LSException If some other error occurs.           * @throws LSException If some other error occurs.
1736           */           */
1737          public synchronized int          public synchronized int
1738          getAudioOutputDriverCount() throws IOException, LscpException, LSException {          getAudioOutputDriverCount() throws IOException, LscpException, LSException {
1739                  verifyConnection();                  return retrieveInt("GET AVAILABLE_AUDIO_OUTPUT_DRIVERS");
                 out.writeLine("GET AVAILABLE_AUDIO_OUTPUT_DRIVERS");  
                 String s = getSingleLineResultSet().getResult();  
                 return parseInt(s);  
1740          }          }
1741                    
1742          /**          /**
# Line 694  public class Client { Line 1752  public class Client {
1752          public synchronized AudioOutputDriver[]          public synchronized AudioOutputDriver[]
1753          getAudioOutputDrivers() throws IOException, LscpException, LSException {          getAudioOutputDrivers() throws IOException, LscpException, LSException {
1754                  String[] drivers = getAudioOutputDriverNames();                  String[] drivers = getAudioOutputDriverNames();
1755                    if(getPrintOnlyMode()) return null;
1756                    
1757                  AudioOutputDriver[] aod = new AudioOutputDriver[drivers.length];                  AudioOutputDriver[] aod = new AudioOutputDriver[drivers.length];
1758                                    
1759                  for(int i = 0; i < aod.length; i++) aod[i] = getAudioOutputDriverInfo(drivers[i]);                  for(int i = 0; i < aod.length; i++) aod[i] = getAudioOutputDriverInfo(drivers[i]);
# Line 715  public class Client { Line 1775  public class Client {
1775          getAudioOutputDriverNames() throws IOException, LscpException, LSException {          getAudioOutputDriverNames() throws IOException, LscpException, LSException {
1776                  verifyConnection();                  verifyConnection();
1777                  out.writeLine("LIST AVAILABLE_AUDIO_OUTPUT_DRIVERS");                  out.writeLine("LIST AVAILABLE_AUDIO_OUTPUT_DRIVERS");
1778                    if(getPrintOnlyMode()) return null;
1779                  return parseList(getSingleLineResultSet().getResult());                  return parseList(getSingleLineResultSet().getResult());
1780          }          }
1781                    
1782          /**          /**
1783           * Gets detailed information about a specific audio output driver.           * Gets detailed information about a specific audio output driver.
1784           * @param driverName The name of the audio output driver.           * @param driverName The name of the audio output driver.
1785           *           * @param depList An optional list of dependences parameters.
1786           * @return An <code>AudioOutputDriver</code> object containing           * @return An <code>AudioOutputDriver</code> object containing
1787           * information about the specified audio output driver.           * information about the specified audio output driver.
1788           *           *
# Line 731  public class Client { Line 1792  public class Client {
1792           *           *
1793           * @see #getAudioOutputDriverNames           * @see #getAudioOutputDriverNames
1794           */           */
1795          private synchronized AudioOutputDriver          public synchronized AudioOutputDriver
1796          getAudioOutputDriverInfo(String driverName) throws IOException, LscpException, LSException {          getAudioOutputDriverInfo(String driverName, Parameter... depList)
1797                  verifyConnection();                                          throws IOException, LscpException, LSException {
1798                  out.writeLine("GET AUDIO_OUTPUT_DRIVER INFO " + driverName);  
1799                  ResultSet rs = getMultiLineResultSet();                  AudioOutputDriver aod = new AudioOutputDriver();
1800                  AudioOutputDriver aod = new AudioOutputDriver(rs.getMultiLineResult());                  if(!retrieveInfo("GET AUDIO_OUTPUT_DRIVER INFO " + driverName, aod)) return null;
1801                  aod.setName(driverName);                  aod.setName(driverName);
1802                                    
1803                  for(String s : aod.getParameterNames())                  for(String s : aod.getParameterNames())
1804                          aod.addParameter(getAudioOutputDriverParameterInfo(driverName, s));                          aod.addParameter(getAudioOutputDriverParameterInfo(driverName, s, depList));
1805                                    
1806                  return aod;                  return aod;
1807          }          }
# Line 774  public class Client { Line 1835  public class Client {
1835                  StringBuffer args = new StringBuffer(driver);                  StringBuffer args = new StringBuffer(driver);
1836                  args.append(' ').append(param);                  args.append(' ').append(param);
1837                                    
1838                  for(Parameter p : deplist)                  for(Parameter p : deplist) {
1839                            if(p == null || p.getName() == null || p.getValue() == null) continue;
1840                          args.append(' ').append(p.getName()).append('=').append(p.getStringValue());                          args.append(' ').append(p.getName()).append('=').append(p.getStringValue());
1841                    }
1842                                    
1843                  out.writeLine("GET AUDIO_OUTPUT_DRIVER_PARAMETER INFO " + args.toString());                  out.writeLine("GET AUDIO_OUTPUT_DRIVER_PARAMETER INFO " + args.toString());
1844                    if(getPrintOnlyMode()) return null;
1845                                    
1846                  ResultSet rs = getMultiLineResultSet();                  ResultSet rs = getMultiLineResultSet();
1847                                    
# Line 832  public class Client { Line 1896  public class Client {
1896          createAudioOutputDevice(String aoDriver, Parameter... paramList)          createAudioOutputDevice(String aoDriver, Parameter... paramList)
1897                                          throws IOException, LSException, LscpException {                                          throws IOException, LSException, LscpException {
1898                                    
                 verifyConnection();  
1899                  StringBuffer args = new StringBuffer(aoDriver);                  StringBuffer args = new StringBuffer(aoDriver);
1900                                    
1901                  for(Parameter p : paramList)                  for(Parameter p : paramList) {
1902                            if(p == null || p.getName() == null || p.getValue() == null) continue;
1903                          args.append(' ').append(p.getName()).append('=').append(p.getStringValue());                          args.append(' ').append(p.getName()).append('=').append(p.getStringValue());
1904                                    }
1905                  out.writeLine("CREATE AUDIO_OUTPUT_DEVICE " + args.toString());  
1906                  ResultSet rs = getEmptyResultSet();                  return retrieveIndex("CREATE AUDIO_OUTPUT_DEVICE " + args.toString());
                   
                 return rs.getIndex();  
1907          }          }
1908                    
1909          /**          /**
1910           * Destroys already created audio output device.           * Destroys already created audio output device.
1911           * @param deviceID The ID of the audio output device to be destroyed.           * @param deviceId The ID of the audio output device to be destroyed.
1912           * @throws IOException If some I/O error occurs.           * @throws IOException If some I/O error occurs.
1913           * @throws LSException If the destroying of the audio output device failed.           * @throws LSException If the destroying of the audio output device failed.
1914           * @throws LscpException If LSCP protocol corruption occurs.           * @throws LscpException If LSCP protocol corruption occurs.
1915           * @see #getAudioOutputDevices           * @see #getAudioOutputDevices
1916           */           */
1917          public synchronized void          public synchronized void
1918          destroyAudioOutputDevice(int deviceID) throws IOException, LSException, LscpException {          destroyAudioOutputDevice(int deviceId) throws IOException, LSException, LscpException {
1919                  verifyConnection();                  retrieveIndex("DESTROY AUDIO_OUTPUT_DEVICE " + deviceId);
                 out.writeLine("DESTROY AUDIO_OUTPUT_DEVICE " + deviceID);  
                 ResultSet rs = getEmptyResultSet();  
1920          }          }
1921                    
1922          /**          /**
1923           * Enables/disables the specified audio output device.           * Enables/disables the specified audio output device.
1924           * @param deviceID The ID of the audio output device to be enabled/disabled.           * @param deviceId The ID of the audio output device to be enabled/disabled.
1925           * @param enable If <code>true</code> the audio output device is enabled,           * @param enable If <code>true</code> the audio output device is enabled,
1926           * else the device is disabled.           * else the device is disabled.
1927           * @throws IOException If some I/O error occurs.           * @throws IOException If some I/O error occurs.
1928           * @throws LSException If there is no audio output           * @throws LSException If there is no audio output
1929           * device with numerical ID <code>deviceID</code>.           * device with numerical ID <code>deviceId</code>.
1930           * @throws LscpException If LSCP protocol corruption occurs.           * @throws LscpException If LSCP protocol corruption occurs.
1931           */           */
1932          public void          public void
1933          enableAudioOutputDevice(int deviceID, boolean enable)          enableAudioOutputDevice(int deviceId, boolean enable)
1934                                  throws IOException, LSException, LscpException {                                  throws IOException, LSException, LscpException {
1935                                    
1936                  setAudioOutputDeviceParameter(deviceID, new BoolParameter("ACTIVE", enable));                  setAudioOutputDeviceParameter(deviceId, new BoolParameter("ACTIVE", enable));
1937          }          }
1938                    
1939          /**          /**
1940           * Gets the current number of all created audio output devices.           * Gets the current number of all created audio output devices.
1941           * @return The current number of all created audio output devices.           * @return The current number of all created audio output devices
1942             *  or -1 if in "print only" mode.
1943           * @throws IOException If some I/O error occurs.           * @throws IOException If some I/O error occurs.
1944           * @throws LscpException If LSCP protocol corruption occurs.           * @throws LscpException If LSCP protocol corruption occurs.
1945           * @throws LSException If some other error occurs.           * @throws LSException If some other error occurs.
1946           */           */
1947          public synchronized int          public synchronized int
1948          getAudioOutputDeviceCount() throws IOException, LscpException, LSException {          getAudioOutputDeviceCount() throws IOException, LscpException, LSException {
1949                  verifyConnection();                  return retrieveInt("GET AUDIO_OUTPUT_DEVICES");
                 out.writeLine("GET AUDIO_OUTPUT_DEVICES");  
                 String s = getSingleLineResultSet().getResult();  
                 return parseInt(s);  
1950          }          }
1951                                    
1952          /**          /**
# Line 902  public class Client { Line 1960  public class Client {
1960          public synchronized AudioOutputDevice[]          public synchronized AudioOutputDevice[]
1961          getAudioOutputDevices() throws IOException, LscpException, LSException {          getAudioOutputDevices() throws IOException, LscpException, LSException {
1962                  Integer[] idS = getAudioOutputDeviceIDs();                  Integer[] idS = getAudioOutputDeviceIDs();
1963                    if(getPrintOnlyMode()) return null;
1964                    
1965                  AudioOutputDevice[] devices = new AudioOutputDevice[idS.length];                  AudioOutputDevice[] devices = new AudioOutputDevice[idS.length];
1966                                    
1967                  for(int i = 0; i < devices.length; i++)                  for(int i = 0; i < devices.length; i++)
# Line 920  public class Client { Line 1980  public class Client {
1980           */           */
1981          public synchronized Integer[]          public synchronized Integer[]
1982          getAudioOutputDeviceIDs() throws IOException, LscpException, LSException {          getAudioOutputDeviceIDs() throws IOException, LscpException, LSException {
1983                  verifyConnection();                  return getIntegerList("LIST AUDIO_OUTPUT_DEVICES");
                 out.writeLine("LIST AUDIO_OUTPUT_DEVICES");  
                 return parseIntList(getSingleLineResultSet().getResult());  
1984          }          }
1985                    
1986          /**          /**
1987           * Gets the current settings of a specific, already created audio output device.           * Gets the current settings of a specific, already created audio output device.
1988           *           *
1989           * @param deviceID Specifies the numerical ID of the audio output device.           * @param deviceId Specifies the numerical ID of the audio output device.
1990           *           *
1991           * @return An <code>AudioOutputDevice</code> instance containing information           * @return An <code>AudioOutputDevice</code> instance containing information
1992           * about the specified device.           * about the specified device.
# Line 936  public class Client { Line 1994  public class Client {
1994           * @throws IOException If some I/O error occurs.           * @throws IOException If some I/O error occurs.
1995           * @throws LscpException If LSCP protocol corruption occurs.           * @throws LscpException If LSCP protocol corruption occurs.
1996           * @throws LSException If there is no audio output device           * @throws LSException If there is no audio output device
1997           * with device id <code>deviceID</code>.           * with device id <code>deviceId</code>.
1998           *           *
1999           * @see #getAudioOutputDevices           * @see #getAudioOutputDevices
2000           */           */
2001          public synchronized AudioOutputDevice          public synchronized AudioOutputDevice
2002          getAudioOutputDeviceInfo(int deviceID) throws IOException, LscpException, LSException {          getAudioOutputDeviceInfo(int deviceId) throws IOException, LscpException, LSException {
2003                  verifyConnection();                  verifyConnection();
2004                  out.writeLine("GET AUDIO_OUTPUT_DEVICE INFO " + deviceID);                  out.writeLine("GET AUDIO_OUTPUT_DEVICE INFO " + deviceId);
2005                    if(getPrintOnlyMode()) return null;
2006                                    
2007                  ResultSet rs = getMultiLineResultSet();                  ResultSet rs = getMultiLineResultSet();
2008                                    
2009                  String[] lnS = rs.getMultiLineResult();                  String[] lnS = rs.getMultiLineResult();
2010                                    
2011                  AudioOutputDevice aod = new AudioOutputDevice();                  AudioOutputDevice aod = new AudioOutputDevice();
2012                  aod.setDeviceID(deviceID);                  aod.setDeviceId(deviceId);
2013                  Parameter<Integer> channels;                  Parameter<Integer> channels;
2014                  Parameter<Integer> samplerate;                  Parameter<Integer> samplerate;
2015                                    
# Line 968  public class Client { Line 2027  public class Client {
2027                                  int count = channels.getValue() > 0 ? channels.getValue() : 0;                                  int count = channels.getValue() > 0 ? channels.getValue() : 0;
2028                                  AudioOutputChannel[] aoc = new AudioOutputChannel[count];                                  AudioOutputChannel[] aoc = new AudioOutputChannel[count];
2029                                  for(int i = 0; i < count; i++) {                                  for(int i = 0; i < count; i++) {
2030                                          aoc[i] = this.getAudioOutputChannelInfo(deviceID, i);                                          aoc[i] = getAudioOutputChannelInfo(deviceId, i);
2031                                  }                                  }
2032                                  aod.setAudioChannels(aoc);                                  aod.setAudioChannels(aoc);
2033                          } else if(s.startsWith("SAMPLERATE: ")) {                          } else if(s.startsWith("SAMPLERATE: ")) {
# Line 1005  public class Client { Line 2064  public class Client {
2064          /**          /**
2065           * Alters a specific setting of a created audio output device.           * Alters a specific setting of a created audio output device.
2066           *           *
2067           * @param deviceID The numerical ID of the audio output device.           * @param deviceId The numerical ID of the audio output device.
2068           * @param prm A <code>Parameter</code> instance containing the name of the parameter           * @param prm A <code>Parameter</code> instance containing the name of the parameter
2069           * and the new value for this parameter.           * and the new value for this parameter.
2070           *           *
# Line 1013  public class Client { Line 2072  public class Client {
2072           * @throws LscpException If LSCP protocol corruption occurs.           * @throws LscpException If LSCP protocol corruption occurs.
2073           * @throws LSException If           * @throws LSException If
2074           * <ul>           * <ul>
2075           * <li>There is no audio output device with numerical ID <code>deviceID</code>;           * <li>There is no audio output device with numerical ID <code>deviceId</code>;
2076           * <li>There is no device parameter with the specified name;           * <li>There is no device parameter with the specified name;
2077           * <li>The device parameter is readonly;           * <li>The device parameter is readonly;
2078           * <li>The device parameter is from different type.           * <li>The device parameter is from different type.
# Line 1023  public class Client { Line 2082  public class Client {
2082           * @see #getAudioOutputDeviceInfo           * @see #getAudioOutputDeviceInfo
2083           */           */
2084          public synchronized void          public synchronized void
2085          setAudioOutputDeviceParameter(int deviceID, Parameter prm)          setAudioOutputDeviceParameter(int deviceId, Parameter prm)
2086                                                  throws IOException, LscpException, LSException {                                          throws IOException, LscpException, LSException
2087                            {
                 verifyConnection();  
2088                  String kv = prm.getName() + '=' + prm.getStringValue();                  String kv = prm.getName() + '=' + prm.getStringValue();
2089                  out.writeLine("SET AUDIO_OUTPUT_DEVICE_PARAMETER " + deviceID + ' ' + kv);                  retrieveIndex("SET AUDIO_OUTPUT_DEVICE_PARAMETER " + deviceId + ' ' + kv);
                   
                 ResultSet rs = getEmptyResultSet();  
2090          }          }
2091                    
2092          /**          /**
2093           * Changes the channels number of the speicifed audio output device.           * Changes the channel number of the speicifed audio output device.
2094           * @param deviceID The numerical ID of the audio output device.           * @param deviceId The numerical ID of the audio output device.
2095           * @param channels The new number of audio output channels.           * @param channels The new number of audio output channels.
2096           *           *
2097           * @throws IOException If an I/O error occurs.           * @throws IOException If an I/O error occurs.
2098           * @throws LscpException If LSCP protocol corruption occurs.           * @throws LscpException If LSCP protocol corruption occurs.
2099           * @throws LSException If there is no device with ID <code>deviceID</code> or           * @throws LSException If there is no device with ID <code>deviceId</code> or
2100           * if <code>channels</code> number is out of range.           * if <code>channels</code> number is out of range.
2101           *           *
2102           * @see #getAudioOutputChannelInfo           * @see #getAudioOutputChannelInfo
2103           */           */
2104          public synchronized void          public synchronized void
2105          setAudioOutputChannelCount(int deviceID, int channels)          setAudioOutputChannelCount(int deviceId, int channels)
2106                                          throws IOException, LscpException, LSException {                                          throws IOException, LscpException, LSException {
2107                                    
2108                  setAudioOutputDeviceParameter(deviceID, new IntParameter("CHANNELS", channels));                  setAudioOutputDeviceParameter(deviceId, new IntParameter("CHANNELS", channels));
2109          }          }
2110                    
2111          /**          /**
2112           * Gets information about an audio channel.           * Gets information about an audio channel.
2113           *           *
2114           * @param deviceID The numerical ID of the audio output device.           * @param deviceId The numerical ID of the audio output device.
2115           * @param audioChn The audio channel number.           * @param audioChn The audio channel number.
2116           *           *
2117           * @return An <code>AudioOutputChannel</code> instance containing the           * @return An <code>AudioOutputChannel</code> instance containing the
# Line 1065  public class Client { Line 2121  public class Client {
2121           * @throws LscpException If LSCP protocol corruption occurs.           * @throws LscpException If LSCP protocol corruption occurs.
2122           * @throws LSException If           * @throws LSException If
2123           * <ul>           * <ul>
2124           * <li>There is no audio output device with numerical ID <code>deviceID</code>;           * <li>There is no audio output device with numerical ID <code>deviceId</code>;
2125           * <li><code>audioChn</code> is not a valid channel number;           * <li><code>audioChn</code> is not a valid channel number;
2126           * </ul>           * </ul>
2127           *           *
# Line 1073  public class Client { Line 2129  public class Client {
2129           * @see #getAudioOutputDeviceInfo           * @see #getAudioOutputDeviceInfo
2130           */           */
2131          public synchronized AudioOutputChannel          public synchronized AudioOutputChannel
2132          getAudioOutputChannelInfo(int deviceID, int audioChn)          getAudioOutputChannelInfo(int deviceId, int audioChn)
2133                                                  throws IOException, LscpException, LSException {                                                  throws IOException, LscpException, LSException {
2134                                    
2135                  verifyConnection();                  verifyConnection();
2136                  out.writeLine("GET AUDIO_OUTPUT_CHANNEL INFO " + deviceID + ' ' + audioChn);                  out.writeLine("GET AUDIO_OUTPUT_CHANNEL INFO " + deviceId + ' ' + audioChn);
2137                    if(getPrintOnlyMode()) return null;
2138                                    
2139                  ResultSet rs = getMultiLineResultSet();                  ResultSet rs = getMultiLineResultSet();
2140                                    
# Line 1088  public class Client { Line 2145  public class Client {
2145                          if(s.startsWith("NAME: ")) {                          if(s.startsWith("NAME: ")) {
2146                                  s = s.substring("NAME: ".length());                                  s = s.substring("NAME: ".length());
2147                                  Parameter<String> prm = getAudioOutputChannelParameterInfo (                                  Parameter<String> prm = getAudioOutputChannelParameterInfo (
2148                                          deviceID, audioChn, "NAME"                                          deviceId, audioChn, "NAME"
2149                                  );                                  );
2150                                  prm.setValue(removeQuotation(s));                                  prm.setValue(removeQuotation(s));
2151                                  aoc.setNameParameter(prm);                                  aoc.setNameParameter(prm);
2152                          } else if(s.startsWith("IS_MIX_CHANNEL: ")) {                          } else if(s.startsWith("IS_MIX_CHANNEL: ")) {
2153                                  s = s.substring("IS_MIX_CHANNEL: ".length());                                  s = s.substring("IS_MIX_CHANNEL: ".length());
2154                                  Parameter<Boolean> prm = getAudioOutputChannelParameterInfo (                                  Parameter<Boolean> prm = getAudioOutputChannelParameterInfo (
2155                                          deviceID, audioChn, "IS_MIX_CHANNEL"                                          deviceId, audioChn, "IS_MIX_CHANNEL"
2156                                  );                                  );
2157                                  prm.setValue(Boolean.parseBoolean(s));                                  prm.setValue(Boolean.parseBoolean(s));
2158                                  aoc.setMixChannelParameter(prm);                                  aoc.setMixChannelParameter(prm);
2159                          } else if(s.startsWith("MIX_CHANNEL_DESTINATION: ")) {                          } else if(s.startsWith("MIX_CHANNEL_DESTINATION: ")) {
2160                                  s = s.substring("MIX_CHANNEL_DESTINATION: ".length());                                  s = s.substring("MIX_CHANNEL_DESTINATION: ".length());
2161                                  Parameter<Integer> prm = getAudioOutputChannelParameterInfo (                                  Parameter<Integer> prm = getAudioOutputChannelParameterInfo (
2162                                          deviceID, audioChn, "MIX_CHANNEL_DESTINATION"                                          deviceId, audioChn, "MIX_CHANNEL_DESTINATION"
2163                                  );                                  );
2164                                  prm.setValue(parseInt(s));                                  prm.setValue(parseInt(s));
2165                                  aoc.setMixChannelDestParameter(prm);                                  aoc.setMixChannelDestParameter(prm);
# Line 1113  public class Client { Line 2170  public class Client {
2170                                  );                                  );
2171                                                                    
2172                                  Parameter prm = getAudioOutputChannelParameterInfo (                                  Parameter prm = getAudioOutputChannelParameterInfo (
2173                                          deviceID, audioChn, s.substring(0, i)                                          deviceId, audioChn, s.substring(0, i)
2174                                  );                                  );
2175                                                                    
2176                                  s = s.substring(i + 2);                                  s = s.substring(i + 2);
# Line 1129  public class Client { Line 2186  public class Client {
2186          /**          /**
2187           * Gets detailed information about a specific audio output channel parameter.           * Gets detailed information about a specific audio output channel parameter.
2188           *           *
2189           * @param devID The numerical ID of the audio output device.           * @param devId The numerical ID of the audio output device.
2190           * @param chan The audio channel number.           * @param chan The audio channel number.
2191           * @param param a specific channel parameter name for which information should be obtained.           * @param param a specific channel parameter name for which information should be obtained.
2192           *           *
# Line 1140  public class Client { Line 2197  public class Client {
2197           * @throws LscpException If LSCP protocol corruption occurs.           * @throws LscpException If LSCP protocol corruption occurs.
2198           * @throws LSException If           * @throws LSException If
2199           * <ul>           * <ul>
2200           * <li><code>devID</code> is not a valid device ID;           * <li><code>devId</code> is not a valid device ID;
2201           * <li><code>chan</code> is not a valid channel number;           * <li><code>chan</code> is not a valid channel number;
2202           * <li>There is no channel parameter with the specified name.           * <li>There is no channel parameter with the specified name.
2203           * </ul>           * </ul>
# Line 1149  public class Client { Line 2206  public class Client {
2206           * @see #getAudioOutputChannelInfo           * @see #getAudioOutputChannelInfo
2207           */           */
2208          public synchronized Parameter          public synchronized Parameter
2209          getAudioOutputChannelParameterInfo(int devID, int chan, String param)          getAudioOutputChannelParameterInfo(int devId, int chan, String param)
2210                                                  throws IOException, LscpException, LSException {                                                  throws IOException, LscpException, LSException {
2211                                    
2212                  verifyConnection();                  verifyConnection();
2213                  String args = devID + " " + chan + " " + param;                  String args = devId + " " + chan + " " + param;
2214                  out.writeLine("GET AUDIO_OUTPUT_CHANNEL_PARAMETER INFO " + args);                  out.writeLine("GET AUDIO_OUTPUT_CHANNEL_PARAMETER INFO " + args);
2215                    if(getPrintOnlyMode()) return null;
2216                                    
2217                  ResultSet rs = getMultiLineResultSet();                  ResultSet rs = getMultiLineResultSet();
2218                                    
# Line 1191  public class Client { Line 2249  public class Client {
2249          /**          /**
2250           * Alters a specific setting of an audio output channel.           * Alters a specific setting of an audio output channel.
2251           *           *
2252           * @param devID The numerical ID of the audio device.           * @param devId The numerical ID of the audio device.
2253           * @param chn The audio channel number.           * @param chn The audio channel number.
2254           * @param prm A <code>Parameter</code> instance containing the name of the parameter           * @param prm A <code>Parameter</code> instance containing the name of the parameter
2255           * and the new value for this parameter.           * and the new value for this parameter.
# Line 1200  public class Client { Line 2258  public class Client {
2258           * @throws LscpException If LSCP protocol corruption occurs.           * @throws LscpException If LSCP protocol corruption occurs.
2259           * @throws LSException If           * @throws LSException If
2260           * <ul>           * <ul>
2261           * <li>There is no audio output device with numerical ID <code>devID</code>;           * <li>There is no audio output device with numerical ID <code>devId</code>;
2262           * <li><code>chn</code> is not a valid channel number;           * <li><code>chn</code> is not a valid channel number;
2263           * <li>There is no channel parameter with the specified name;           * <li>There is no channel parameter with the specified name;
2264           * <li>The channel parameter is readonly;           * <li>The channel parameter is readonly;
# Line 1211  public class Client { Line 2269  public class Client {
2269           * @see #getAudioOutputChannelInfo           * @see #getAudioOutputChannelInfo
2270           */           */
2271          public synchronized void          public synchronized void
2272          setAudioOutputChannelParameter(int devID, int chn,  Parameter prm)          setAudioOutputChannelParameter(int devId, int chn,  Parameter prm)
2273                                                  throws IOException, LscpException, LSException {                                                  throws IOException, LscpException, LSException
2274                            {
2275                  verifyConnection();                  String args = devId + " " + chn + " " + prm.getName() + '=' + prm.getStringValue();
2276                  String args = devID + " " + chn + " " + prm.getName() + '=' + prm.getStringValue();                  retrieveIndex("SET AUDIO_OUTPUT_CHANNEL_PARAMETER " + args);
                 out.writeLine("SET AUDIO_OUTPUT_CHANNEL_PARAMETER " + args);  
                   
                 ResultSet rs = getEmptyResultSet();  
2277          }          }
2278                    
2279          /**          /**
2280           * Gets the current number of all MIDI input drivers.           * Gets the current number of all MIDI input drivers.
2281           * @return The current number of all MIDI input drivers.           * @return The current number of all MIDI input drivers or -1 if in "print only" mode.
2282           * @throws IOException If some I/O error occurs.           * @throws IOException If some I/O error occurs.
2283           * @throws LscpException If LSCP protocol corruption occurs.           * @throws LscpException If LSCP protocol corruption occurs.
2284           * @throws LSException If some other error occurs.           * @throws LSException If some other error occurs.
2285           */           */
2286          public synchronized int          public synchronized int
2287          getMidiInputDriverCount() throws IOException, LscpException, LSException {          getMidiInputDriverCount() throws IOException, LscpException, LSException {
2288                  verifyConnection();                  return retrieveInt("GET AVAILABLE_MIDI_INPUT_DRIVERS");
                 out.writeLine("GET AVAILABLE_MIDI_INPUT_DRIVERS");  
                 String s = getSingleLineResultSet().getResult();  
                 return parseInt(s);  
2289          }          }
2290                    
2291          /**          /**
# Line 1249  public class Client { Line 2301  public class Client {
2301          public synchronized MidiInputDriver[]          public synchronized MidiInputDriver[]
2302          getMidiInputDrivers() throws IOException, LscpException, LSException {          getMidiInputDrivers() throws IOException, LscpException, LSException {
2303                  String[] drivers = getMidiInputDriverNames();                  String[] drivers = getMidiInputDriverNames();
2304                    if(getPrintOnlyMode()) return null;
2305                    
2306                  MidiInputDriver[] mid = new MidiInputDriver[drivers.length];                  MidiInputDriver[] mid = new MidiInputDriver[drivers.length];
2307                                    
2308                  for(int i = 0; i < mid.length; i++) mid[i] = getMidiInputDriverInfo(drivers[i]);                  for(int i = 0; i < mid.length; i++) mid[i] = getMidiInputDriverInfo(drivers[i]);
# Line 1270  public class Client { Line 2324  public class Client {
2324          getMidiInputDriverNames() throws IOException, LscpException, LSException {          getMidiInputDriverNames() throws IOException, LscpException, LSException {
2325                  verifyConnection();                  verifyConnection();
2326                  out.writeLine("LIST AVAILABLE_MIDI_INPUT_DRIVERS");                  out.writeLine("LIST AVAILABLE_MIDI_INPUT_DRIVERS");
2327                    if(getPrintOnlyMode()) return null;
2328                    
2329                  return parseList(getSingleLineResultSet().getResult());                  return parseList(getSingleLineResultSet().getResult());
2330          }          }
2331                    
2332          /**          /**
2333           * Gets detailed information about a specific MIDI input driver.           * Gets detailed information about a specific MIDI input driver.
2334           * @param driverName The name of the MIDI input driver.           * @param driverName The name of the MIDI input driver.
2335           *           * @param depList An optional list of dependences parameters.
2336           * @return A <code>MidiInputDriver</code> object containing           * @return A <code>MidiInputDriver</code> object containing
2337           * information about the specified MIDI input driver.           * information about the specified MIDI input driver.
2338           *           *
# Line 1286  public class Client { Line 2342  public class Client {
2342           *           *
2343           * @see #getMidiInputDriverNames           * @see #getMidiInputDriverNames
2344           */           */
2345          private synchronized MidiInputDriver          public synchronized MidiInputDriver
2346          getMidiInputDriverInfo(String driverName) throws IOException, LscpException, LSException {          getMidiInputDriverInfo(String driverName, Parameter... depList)
2347                  verifyConnection();                                          throws IOException, LscpException, LSException {
2348                  out.writeLine("GET MIDI_INPUT_DRIVER INFO " + driverName);  
2349                  ResultSet rs = getMultiLineResultSet();                  MidiInputDriver mid = new MidiInputDriver();
2350                                    if(!retrieveInfo("GET MIDI_INPUT_DRIVER INFO " + driverName, mid)) return null;
                 MidiInputDriver mid = new MidiInputDriver(rs.getMultiLineResult());  
2351                  mid.setName(driverName);                  mid.setName(driverName);
2352                                    
2353                  for(String s : mid.getParameterNames())                  for(String s : mid.getParameterNames())
2354                          mid.addParameter(getMidiInputDriverParameterInfo(driverName, s));                          mid.addParameter(getMidiInputDriverParameterInfo(driverName, s, depList));
2355                                    
2356                  return mid;                  return mid;
2357          }          }
# Line 1330  public class Client { Line 2385  public class Client {
2385                  StringBuffer args = new StringBuffer(driver);                  StringBuffer args = new StringBuffer(driver);
2386                  args.append(' ').append(param);                  args.append(' ').append(param);
2387                                    
2388                  for(Parameter p : deplist)                  for(Parameter p : deplist) {
2389                            if(p == null || p.getName() == null || p.getValue() == null) continue;
2390                          args.append(' ').append(p.getName()).append('=').append(p.getStringValue());                          args.append(' ').append(p.getName()).append('=').append(p.getStringValue());
2391                    }
2392                                    
2393                  out.writeLine("GET MIDI_INPUT_DRIVER_PARAMETER INFO " + args.toString());                  out.writeLine("GET MIDI_INPUT_DRIVER_PARAMETER INFO " + args.toString());
2394                    if(getPrintOnlyMode()) return null;
2395                                    
2396                  ResultSet rs = getMultiLineResultSet();                  ResultSet rs = getMultiLineResultSet();
2397                                    
# Line 1387  public class Client { Line 2445  public class Client {
2445           */           */
2446          public synchronized int          public synchronized int
2447          createMidiInputDevice(String miDriver, Parameter... paramList)          createMidiInputDevice(String miDriver, Parameter... paramList)
2448                                          throws IOException, LSException, LscpException {                                          throws IOException, LSException, LscpException
2449                            {
                 verifyConnection();  
2450                  StringBuffer args = new StringBuffer(miDriver);                  StringBuffer args = new StringBuffer(miDriver);
2451                                    
2452                  for(Parameter p : paramList)                  for(Parameter p : paramList) {
2453                            if(p == null || p.getName() == null || p.getValue() == null) continue;
2454                          args.append(' ').append(p.getName()).append('=').append(p.getStringValue());                          args.append(' ').append(p.getName()).append('=').append(p.getStringValue());
2455                                    }
2456                  out.writeLine("CREATE MIDI_INPUT_DEVICE " + args.toString());  
2457                  ResultSet rs = getEmptyResultSet();                  return retrieveIndex("CREATE MIDI_INPUT_DEVICE " + args.toString());
                   
                 return rs.getIndex();  
2458          }          }
2459                    
2460          /**          /**
2461           * Destroys already created MIDI input device.           * Destroys already created MIDI input device.
2462           * @param deviceID The numerical ID of the MIDI input device to be destroyed.           * @param deviceId The numerical ID of the MIDI input device to be destroyed.
2463           * @throws IOException If some I/O error occurs.           * @throws IOException If some I/O error occurs.
2464           * @throws LSException If the destroying of the MIDI input device failed.           * @throws LSException If the destroying of the MIDI input device failed.
2465           * @throws LscpException If LSCP protocol corruption occurs.           * @throws LscpException If LSCP protocol corruption occurs.
# Line 1411  public class Client { Line 2467  public class Client {
2467           * @see #getMidiInputDevices           * @see #getMidiInputDevices
2468           */           */
2469          public synchronized void          public synchronized void
2470          destroyMidiInputDevice(int deviceID) throws IOException, LSException, LscpException {          destroyMidiInputDevice(int deviceId) throws IOException, LSException, LscpException {
2471                  verifyConnection();                  retrieveIndex("DESTROY MIDI_INPUT_DEVICE " + deviceId);
                 out.writeLine("DESTROY MIDI_INPUT_DEVICE " + deviceID);  
                 ResultSet rs = getEmptyResultSet();  
2472          }          }
2473                    
2474          /**          /**
2475           * Enables/disables the specified MIDI input device.           * Enables/disables the specified MIDI input device.
2476           * @param deviceID The ID of the MIDI input device to be enabled/disabled.           * @param deviceId The ID of the MIDI input device to be enabled/disabled.
2477           * @param enable If <code>true</code> the MIDI input device is enabled,           * @param enable If <code>true</code> the MIDI input device is enabled,
2478           * else the device is disabled.           * else the device is disabled.
2479           * @throws IOException If some I/O error occurs.           * @throws IOException If some I/O error occurs.
2480           * @throws LSException If there is no MIDI input           * @throws LSException If there is no MIDI input
2481           * device with numerical ID <code>deviceID</code>.           * device with numerical ID <code>deviceId</code>.
2482           * @throws LscpException If LSCP protocol corruption occurs.           * @throws LscpException If LSCP protocol corruption occurs.
2483           */           */
2484          public void          public void
2485          enableMidiInputDevice(int deviceID, boolean enable)          enableMidiInputDevice(int deviceId, boolean enable)
2486                                  throws IOException, LSException, LscpException {                                  throws IOException, LSException, LscpException {
2487                                    
2488                  setMidiInputDeviceParameter(deviceID, new BoolParameter("ACTIVE", enable));                  setMidiInputDeviceParameter(deviceId, new BoolParameter("ACTIVE", enable));
2489          }          }
2490                    
2491          /**          /**
2492           * Gets the current number of all created MIDI input devices.           * Gets the current number of all created MIDI input devices.
2493           * @return The current number of all created MIDI input devices.           * @return The current number of all created MIDI input
2494             * devices or -1 if in "print only" mode.
2495           * @throws IOException If some I/O error occurs.           * @throws IOException If some I/O error occurs.
2496           * @throws LscpException If LSCP protocol corruption occurs.           * @throws LscpException If LSCP protocol corruption occurs.
2497           * @throws LSException If some other error occurs.           * @throws LSException If some other error occurs.
2498           */           */
2499          public synchronized int          public synchronized int
2500          getMidiInputDeviceCount() throws IOException, LscpException, LSException {          getMidiInputDeviceCount() throws IOException, LscpException, LSException {
2501                  verifyConnection();                  return retrieveInt("GET MIDI_INPUT_DEVICES");
                 out.writeLine("GET MIDI_INPUT_DEVICES");  
                 String s = getSingleLineResultSet().getResult();  
                 return parseInt(s);  
2502          }          }
2503                    
2504          /**          /**
# Line 1463  public class Client { Line 2515  public class Client {
2515          public synchronized MidiInputDevice[]          public synchronized MidiInputDevice[]
2516          getMidiInputDevices() throws IOException, LscpException, LSException {          getMidiInputDevices() throws IOException, LscpException, LSException {
2517                  Integer[] idS = getMidiInputDeviceIDs();                  Integer[] idS = getMidiInputDeviceIDs();
2518                    if(getPrintOnlyMode()) return null;
2519                    
2520                  MidiInputDevice[] devices = new MidiInputDevice[idS.length];                  MidiInputDevice[] devices = new MidiInputDevice[idS.length];
2521                                    
2522                  for(int i = 0; i < devices.length; i++)                  for(int i = 0; i < devices.length; i++)
# Line 1484  public class Client { Line 2538  public class Client {
2538           */           */
2539          public synchronized Integer[]          public synchronized Integer[]
2540          getMidiInputDeviceIDs() throws IOException, LscpException, LSException {          getMidiInputDeviceIDs() throws IOException, LscpException, LSException {
2541                  verifyConnection();                  return getIntegerList("LIST MIDI_INPUT_DEVICES");
                 out.writeLine("LIST MIDI_INPUT_DEVICES");  
                 return parseIntList(getSingleLineResultSet().getResult());  
2542          }          }
2543                    
2544          /**          /**
2545           * Gets the current settings of a specific, already created MIDI input device.           * Gets the current settings of a specific, already created MIDI input device.
2546           *           *
2547           * @param deviceID Specifies the numerical ID of the MIDI input device.           * @param deviceId Specifies the numerical ID of the MIDI input device.
2548           *           *
2549           * @return An <code>MidiInputDevice</code> instance containing information           * @return A <code>MidiInputDevice</code> instance containing information
2550           * about the specified device.           * about the specified device.
2551           *           *
2552           * @throws IOException If some I/O error occurs.           * @throws IOException If some I/O error occurs.
2553           * @throws LscpException If LSCP protocol corruption occurs.           * @throws LscpException If LSCP protocol corruption occurs.
2554           * @throws LSException If there is no MIDI input device           * @throws LSException If there is no MIDI input device
2555           * with device id <code>deviceID</code>.           * with device id <code>deviceId</code>.
2556           *           *
2557           * @see #getMidiInputDevices           * @see #getMidiInputDevices
2558           */           */
2559          public synchronized MidiInputDevice          public synchronized MidiInputDevice
2560          getMidiInputDeviceInfo(int deviceID) throws IOException, LscpException, LSException {          getMidiInputDeviceInfo(int deviceId) throws IOException, LscpException, LSException {
2561                  verifyConnection();                  verifyConnection();
2562                  out.writeLine("GET MIDI_INPUT_DEVICE INFO " + deviceID);                  out.writeLine("GET MIDI_INPUT_DEVICE INFO " + deviceId);
2563                    if(getPrintOnlyMode()) return null;
2564                                    
2565                  ResultSet rs = getMultiLineResultSet();                  ResultSet rs = getMultiLineResultSet();
2566                                    
2567                  String[] lnS = rs.getMultiLineResult();                  String[] lnS = rs.getMultiLineResult();
2568                                    
2569                  MidiInputDevice mid = new MidiInputDevice();                  MidiInputDevice mid = new MidiInputDevice();
2570                  mid.setDeviceID(deviceID);                  mid.setDeviceId(deviceId);
2571                                    
2572                  String drv = getCategoryInfo(lnS, "DRIVER");                  String drv = getCategoryInfo(lnS, "DRIVER");
2573                  mid.setDriverName(drv);                  mid.setDriverName(drv);
# Line 1527  public class Client { Line 2580  public class Client {
2580                                  mid.setActive(Boolean.parseBoolean(s));                                  mid.setActive(Boolean.parseBoolean(s));
2581                          } else if(s.startsWith("PORTS: ")) {                          } else if(s.startsWith("PORTS: ")) {
2582                                  s = s.substring("PORTS: ".length());                                  s = s.substring("PORTS: ".length());
2583                                  int ports = Parser.parseInt(s);                                  
2584                                  MidiPort[] midiPorts = new MidiPort[ports > 0 ? ports : 0];                                  Parameter<Integer> ports = (Parameter<Integer>)
2585                                            getMidiInputDriverParameterInfo(drv, "PORTS");
2586                                    
2587                                    ports.parseValue(s);
2588                                    mid.setPortsParameter(ports);
2589                                    
2590                                    int j = ports.getValue();
2591                                    MidiPort[] midiPorts = new MidiPort[j > 0 ? j : 0];
2592                                                                    
2593                                  for(int i = 0; i < midiPorts.length; i++)                                  for(int i = 0; i < midiPorts.length; i++)
2594                                          midiPorts[i] = getMidiInputPortInfo(deviceID, i);                                          midiPorts[i] = getMidiInputPortInfo(deviceId, i);
2595                                                                    
2596                                  mid.setMidiPorts(midiPorts);                                  mid.setMidiPorts(midiPorts);
2597                          } else {                          } else {
# Line 1556  public class Client { Line 2616  public class Client {
2616          /**          /**
2617           * Alters a specific setting of a created MIDI input device.           * Alters a specific setting of a created MIDI input device.
2618           *           *
2619           * @param deviceID The numerical ID of the MIDI input device.           * @param deviceId The numerical ID of the MIDI input device.
2620           * @param prm A <code>Parameter</code> instance containing the name of the parameter           * @param prm A <code>Parameter</code> instance containing the name of the parameter
2621           * and the new value for this parameter.           * and the new value for this parameter.
2622           *           *
# Line 1564  public class Client { Line 2624  public class Client {
2624           * @throws LscpException If LSCP protocol corruption occurs.           * @throws LscpException If LSCP protocol corruption occurs.
2625           * @throws LSException If           * @throws LSException If
2626           * <ul>           * <ul>
2627           * <li>There is no MIDI input device with numerical ID <code>deviceID</code>;           * <li>There is no MIDI input device with numerical ID <code>deviceId</code>;
2628           * <li>There is no device parameter with the specified name;           * <li>There is no device parameter with the specified name;
2629           * <li>The device parameter is readonly;           * <li>The device parameter is readonly;
2630           * <li>The device parameter is from different type.           * <li>The device parameter is from different type.
# Line 1574  public class Client { Line 2634  public class Client {
2634           * @see #getMidiInputDeviceInfo           * @see #getMidiInputDeviceInfo
2635           */           */
2636          public synchronized void          public synchronized void
2637          setMidiInputDeviceParameter(int deviceID, Parameter prm)          setMidiInputDeviceParameter(int deviceId, Parameter prm)
2638                                                  throws IOException, LscpException, LSException {                                                  throws IOException, LscpException, LSException
2639                            {
                 verifyConnection();  
2640                  String kv = prm.getName() + '=' + prm.getStringValue();                  String kv = prm.getName() + '=' + prm.getStringValue();
2641                  out.writeLine("SET MIDI_INPUT_DEVICE_PARAMETER " + deviceID + ' ' + kv);                  retrieveIndex("SET MIDI_INPUT_DEVICE_PARAMETER " + deviceId + ' ' + kv);
                   
                 ResultSet rs = getEmptyResultSet();  
2642          }          }
2643                    
2644                    
2645          /**          /**
2646           * Changes the ports number of the speicifed MIDI input device.           * Changes the port number of the specified MIDI input device.
2647           * @param deviceID The numerical ID of the MIDI input device.           * @param deviceId The numerical ID of the MIDI input device.
2648           * @param ports The new number of MIDI input ports.           * @param ports The new number of MIDI input ports.
2649           *           *
2650           * @throws IOException If an I/O error occurs.           * @throws IOException If an I/O error occurs.
2651           * @throws LscpException If LSCP protocol corruption occurs.           * @throws LscpException If LSCP protocol corruption occurs.
2652           * @throws LSException If there is no device with ID <code>deviceID</code> or           * @throws LSException If there is no device with ID <code>deviceId</code> or
2653           * if <code>ports</code> number is out of range.           * if <code>ports</code> number is out of range.
2654           *           *
2655           * @see #getMidiInputPortInfo           * @see #getMidiInputPortInfo
2656           */           */
2657          public synchronized void          public synchronized void
2658          setMidiInputPortCount(int deviceID, int ports)          setMidiInputPortCount(int deviceId, int ports)
2659                                          throws IOException, LscpException, LSException {                                          throws IOException, LscpException, LSException {
2660                                    
2661                  setMidiInputDeviceParameter(deviceID, new IntParameter("PORTS", ports));                  setMidiInputDeviceParameter(deviceId, new IntParameter("PORTS", ports));
2662          }          }
2663                    
2664          /**          /**
2665           * Gets detailed information about a specific MIDI input port.           * Gets detailed information about a specific MIDI input port.
2666           * @param deviceID The numerical ID of the MIDI input device.           * @param deviceId The numerical ID of the MIDI input device.
2667           * @param midiPort The MIDI input port number.           * @param midiPort The MIDI input port number.
2668           *           *
2669           * @return A <code>MidiPort</code> instance containing           * @return A <code>MidiPort</code> instance containing
# Line 1614  public class Client { Line 2671  public class Client {
2671           *           *
2672           * @throws IOException If an I/O error occurs.           * @throws IOException If an I/O error occurs.
2673           * @throws LscpException If LSCP protocol corruption occurs.           * @throws LscpException If LSCP protocol corruption occurs.
2674           * @throws LSException If there is no device with ID <code>deviceID</code> or           * @throws LSException If there is no device with ID <code>deviceId</code> or
2675           * if <code>midiPort</code> is not a valid MIDI port number.           * if <code>midiPort</code> is not a valid MIDI port number.
2676           *           *
2677           * @see #getMidiInputDevices           * @see #getMidiInputDevices
2678           */           */
2679          public synchronized MidiPort          public synchronized MidiPort
2680          getMidiInputPortInfo(int deviceID, int midiPort)          getMidiInputPortInfo(int deviceId, int midiPort)
2681                                          throws IOException, LscpException, LSException {                                          throws IOException, LscpException, LSException {
2682                                    
2683                  verifyConnection();                  verifyConnection();
2684                  out.writeLine("GET MIDI_INPUT_PORT INFO " + deviceID + " " + midiPort);                  out.writeLine("GET MIDI_INPUT_PORT INFO " + deviceId + " " + midiPort);
2685                    if(getPrintOnlyMode()) return null;
2686                    
2687                  ResultSet rs = getMultiLineResultSet();                  ResultSet rs = getMultiLineResultSet();
2688                                    
2689                  MidiPort mp = new MidiPort();                  MidiPort mp = new MidiPort();
# Line 1634  public class Client { Line 2693  public class Client {
2693                          if(s.startsWith("NAME: ")) {                          if(s.startsWith("NAME: ")) {
2694                                  s = s.substring("NAME: ".length());                                  s = s.substring("NAME: ".length());
2695                                  Parameter prm = getMidiInputPortParameterInfo (                                  Parameter prm = getMidiInputPortParameterInfo (
2696                                          deviceID, midiPort, "NAME"                                          deviceId, midiPort, "NAME"
2697                                  );                                  );
2698                                  prm.setValue(removeQuotation(s));                                  prm.setValue(removeQuotation(s));
2699                                  mp.setNameParameter(prm);                                  mp.setNameParameter(prm);
# Line 1645  public class Client { Line 2704  public class Client {
2704                                  );                                  );
2705                                                                    
2706                                  Parameter prm = getMidiInputPortParameterInfo (                                  Parameter prm = getMidiInputPortParameterInfo (
2707                                          deviceID, midiPort, s.substring(0, i)                                          deviceId, midiPort, s.substring(0, i)
2708                                  );                                  );
2709                                                                    
2710                                  s = s.substring(i + 2);                                  s = s.substring(i + 2);
# Line 1661  public class Client { Line 2720  public class Client {
2720          /**          /**
2721           * Gets detailed information about a specific MIDI input port parameter.           * Gets detailed information about a specific MIDI input port parameter.
2722           *           *
2723           * @param deviceID The numerical ID of the MIDI input device.           * @param deviceId The numerical ID of the MIDI input device.
2724           * @param port The MIDI port number.           * @param port The MIDI port number.
2725           * @param param A specific parameter name for which information should be obtained.           * @param param A specific parameter name for which information should be obtained.
2726           *           *
# Line 1672  public class Client { Line 2731  public class Client {
2731           * @throws LscpException If LSCP protocol corruption occurs.           * @throws LscpException If LSCP protocol corruption occurs.
2732           * @throws LSException If           * @throws LSException If
2733           * <ul>           * <ul>
2734           * <li>There is no MIDI input device with numerical ID <code>deviceID</code>;           * <li>There is no MIDI input device with numerical ID <code>deviceId</code>;
2735           * <li> <code>port</code> is not a valid MIDI port number;           * <li> <code>port</code> is not a valid MIDI port number;
2736           * <li><code>param</code> is not a valid parameter for the specified MIDI port.           * <li><code>param</code> is not a valid parameter for the specified MIDI port.
2737           * </ul>           * </ul>
# Line 1681  public class Client { Line 2740  public class Client {
2740           * @see #getMidiInputPortInfo           * @see #getMidiInputPortInfo
2741           */           */
2742          public synchronized Parameter          public synchronized Parameter
2743          getMidiInputPortParameterInfo(int deviceID, int port, String param)          getMidiInputPortParameterInfo(int deviceId, int port, String param)
2744                                                  throws IOException, LscpException, LSException {                                                  throws IOException, LscpException, LSException {
2745                                    
2746                  verifyConnection();                  verifyConnection();
2747                  String args = deviceID + " " + port + " " + param;                  String args = deviceId + " " + port + " " + param;
2748                  out.writeLine("GET MIDI_INPUT_PORT_PARAMETER INFO " + args);                  out.writeLine("GET MIDI_INPUT_PORT_PARAMETER INFO " + args);
2749                    if(getPrintOnlyMode()) return null;
2750                                    
2751                  ResultSet rs = getMultiLineResultSet();                  ResultSet rs = getMultiLineResultSet();
2752                                    
# Line 1723  public class Client { Line 2783  public class Client {
2783          /**          /**
2784           * Alters a specific setting of a MIDI input port.           * Alters a specific setting of a MIDI input port.
2785           *           *
2786           * @param deviceID The numerical ID of the MIDI device.           * @param deviceId The numerical ID of the MIDI device.
2787           * @param port The MIDI port number.           * @param port The MIDI port number.
2788           * @param prm A <code>Parameter</code> instance containing the name of the parameter           * @param prm A <code>Parameter</code> instance containing the name of the parameter
2789           * and the new value for this parameter.           * and the new value for this parameter.
# Line 1732  public class Client { Line 2792  public class Client {
2792           * @throws LscpException If LSCP protocol corruption occurs.           * @throws LscpException If LSCP protocol corruption occurs.
2793           * @throws LSException If           * @throws LSException If
2794           * <ul>           * <ul>
2795           * <li>There is no MIDI device with numerical ID <code>deviceID</code>;           * <li>There is no MIDI device with numerical ID <code>deviceId</code>;
2796           * <li><code>port</code> is not a valid MIDI port number;           * <li><code>port</code> is not a valid MIDI port number;
2797           * <li><code>prm</code> is not a valid parameter;           * <li><code>prm</code> is not a valid parameter;
2798           * <li>The parameter is readonly;           * <li>The parameter is readonly;
# Line 1743  public class Client { Line 2803  public class Client {
2803           * @see #getMidiInputPortInfo           * @see #getMidiInputPortInfo
2804           */           */
2805          public synchronized void          public synchronized void
2806          setMidiInputPortParameter(int deviceID, int port,  Parameter prm)          setMidiInputPortParameter(int deviceId, int port,  Parameter prm)
2807                                                  throws IOException, LscpException, LSException {                                                  throws IOException, LscpException, LSException
2808            {
2809                    String args = deviceId + " " + port + " " +
2810                            prm.getName() + '=' + prm.getStringValue();
2811                    retrieveIndex("SET MIDI_INPUT_PORT_PARAMETER " + args);
2812            }
2813            
2814            /**
2815             * Adds a new MIDI instrument map.
2816             * @param name The name of this MIDI instrument map.
2817             * @return The number of the newly MIDI instrument map.
2818             * @throws IOException If some I/O error occurs.
2819             * @throws LSException If the creation of the new MIDI instrument map failed.
2820             * @throws LscpException If LSCP protocol corruption occurs.
2821             * @see #removeMidiInstrumentMap
2822             */
2823            public synchronized int
2824            addMidiInstrumentMap(String name) throws IOException, LSException, LscpException {
2825                    return retrieveIndex("ADD MIDI_INSTRUMENT_MAP '" + toEscapedText(name) + "'");
2826            }
2827            
2828            /**
2829             * Removes the specified MIDI instrument map.
2830             * @param mapId The numerical ID of the MIDI instrument map to be removed.
2831             * @throws IOException If some I/O error occurs.
2832             * @throws LscpException If LSCP protocol corruption occurs.
2833             * @throws LSException If the removing of the MIDI instrument map failed.
2834             * @see #addMidiInstrumentMap
2835             * @see #getMidiInstrumentMapIDs
2836             */
2837            public synchronized void
2838            removeMidiInstrumentMap(int mapId) throws IOException, LscpException, LSException {
2839                    retrieveIndex("REMOVE MIDI_INSTRUMENT_MAP " + mapId);
2840            }
2841            
2842            /**
2843             * Removes the all MIDI instrument maps.
2844             * @throws IOException If some I/O error occurs.
2845             * @throws LscpException If LSCP protocol corruption occurs.
2846             * @throws LSException If the removing of the MIDI instrument maps failed.
2847             */
2848            public synchronized void
2849            removeAllMidiInstrumentMaps() throws IOException, LscpException, LSException {
2850                    retrieveIndex("REMOVE MIDI_INSTRUMENT_MAP ALL");
2851            }
2852            
2853            /**
2854             * Gets the current number of all MIDI instrument maps.
2855             * @return The current number of all MIDI instrument maps
2856             *  or -1 if in "print only" mode.
2857             * @throws IOException If some I/O error occurs.
2858             * @throws LscpException If LSCP protocol corruption occurs.
2859             * @throws LSException If some other error occurs.
2860             */
2861            public synchronized int
2862            getMidiInstrumentMapCount() throws IOException, LscpException, LSException {
2863                    return retrieveInt("GET MIDI_INSTRUMENT_MAPS");
2864            }
2865            
2866            /**
2867             * Gets a list of numerical IDs of all created MIDI instrument maps.
2868             * @return An <code>Integer</code> array providing the numerical IDs of
2869             * all created MIDI instrument maps.
2870             * @throws IOException If some I/O error occurs.
2871             * @throws LscpException If LSCP protocol corruption occurs.
2872             * @throws LSException If some other error occurs.
2873             * @see #addMidiInstrumentMap
2874             * @see #removeMidiInstrumentMap
2875             */
2876            public synchronized Integer[]
2877            getMidiInstrumentMapIDs() throws IOException, LscpException, LSException {
2878                    return getIntegerList("LIST MIDI_INSTRUMENT_MAPS");
2879            }
2880            
2881            /**
2882             * Gets the current settings of a specific, already created MIDI instrument map.
2883             * @param mapId Specifies the numerical ID of the MIDI instrument map.
2884             * @return A <code>MidiInstrumentMapInfo</code> instance containing information
2885             * about the specified device.
2886             * @throws IOException If some I/O error occurs.
2887             * @throws LscpException If LSCP protocol corruption occurs.
2888             * @throws LSException If there is no MIDI instrument map
2889             * with map id <code>mapId</code>.
2890             * @see #getMidiInstrumentMaps
2891             */
2892            public synchronized MidiInstrumentMapInfo
2893            getMidiInstrumentMapInfo(int mapId) throws IOException, LscpException, LSException {
2894                    verifyConnection();
2895                    out.writeLine("GET MIDI_INSTRUMENT_MAP INFO " + mapId);
2896                    if(getPrintOnlyMode()) return null;
2897                    
2898                    ResultSet rs = getMultiLineResultSet();
2899                    
2900                    String[] lnS = rs.getMultiLineResult();
2901                    
2902                    String name = "";
2903                    boolean b = false;
2904                    
2905                    for(String s : lnS) {
2906                            if(s.startsWith("NAME: ")) {
2907                                    name = toNonEscapedString(s.substring("NAME: ".length()));
2908                            } else if(s.startsWith("DEFAULT: ")) {
2909                                    b = Boolean.parseBoolean(s.substring("DEFAULT: ".length()));
2910                            } else {
2911                                     getLogger().info(LscpI18n.getLogMsg("unknownLine", s));
2912                            }
2913                    }
2914                    
2915                    return new MidiInstrumentMapInfo(mapId, name, b);
2916            }
2917            
2918            /**
2919             * Gets an information of all created MIDI instrument maps.
2920             * @return A <code>MidiInstrumentMap</code> array
2921             * providing information for all created MIDI instrument maps.
2922             * @throws IOException If some I/O error occurs.
2923             * @throws LscpException If LSCP protocol corruption occurs.
2924             * @throws LSException If some other error occurs.
2925             * @see #addMidiInstrumentMap
2926             * @see #removeMidiInstrumentMap
2927             */
2928            public synchronized MidiInstrumentMapInfo[]
2929            getMidiInstrumentMaps() throws IOException, LscpException, LSException {
2930                    Integer[] idS = getMidiInstrumentMapIDs();
2931                    if(getPrintOnlyMode()) return null;
2932                    
2933                    MidiInstrumentMapInfo[] maps = new MidiInstrumentMapInfo[idS.length];
2934                    
2935                    for(int i = 0; i < maps.length; i++)
2936                            maps[i] = getMidiInstrumentMapInfo(idS[i]);
2937                    
2938                    return maps;
2939            }
2940            
2941            /**
2942             * Sets the name of the specified MIDI instrument map.
2943             * @param mapId The numerical ID of the MIDI instrument map.
2944             * @param name The new name for the specified MIDI instrument map.
2945             * @throws IOException If some I/O error occurs.
2946             * @throws LscpException If LSCP protocol corruption occurs.
2947             * @throws LSException If <code>mapId</code> is not a valid MIDI
2948             * instrument map number or <code>name</code> is not a valid name;
2949             */
2950            public synchronized void
2951            setMidiInstrumentMapName(int mapId, String name)
2952                                    throws IOException, LscpException, LSException
2953            {
2954                    name = toEscapedText(name);
2955                    retrieveIndex("SET MIDI_INSTRUMENT_MAP NAME " +  + mapId + " '" + name + "'");
2956            }
2957            
2958            
2959            
2960            /**
2961             * Creates or replaces a MIDI instrument map entry.
2962             * @param mapId The ID of the map, where this instrument should be mapped.
2963             * @param entry Specifies the position of the MIDI instrument in the MIDI instrument map.
2964             * @param info Provides the needed information of the
2965             * MIDI instrument, which will be mapped to the specified MIDI instrument map.
2966             * @throws IOException If some I/O error occurs.
2967             * @throws LSException If the mapping failed.
2968             * @throws LscpException If LSCP protocol corruption occurs.
2969             * @see #unmapMidiInstrument
2970             */
2971            public synchronized void
2972            mapMidiInstrument(int mapId, MidiInstrumentEntry entry, MidiInstrumentInfo info)
2973                                            throws IOException, LSException, LscpException {
2974                    mapMidiInstrument(mapId, entry, info, false);
2975            }
2976            
2977            /**
2978             * Creates or replaces a MIDI instrument map entry.
2979             * @param mapId The ID of the map, where this instrument should be mapped.
2980             * @param entry Specifies the position of the MIDI instrument in the MIDI instrument map.
2981             * @param info Provides the needed information of the
2982             * MIDI instrument, which will be mapped to the specified MIDI instrument map.
2983             * @param nonModal If <code>true</code> the function returns immediately
2984             * and the mapping is established in the background.
2985             * @throws IOException If some I/O error occurs.
2986             * @throws LSException If the mapping failed.
2987             * @throws LscpException If LSCP protocol corruption occurs.
2988             * @see #unmapMidiInstrument
2989             */
2990            public synchronized void
2991            mapMidiInstrument(int mapId, MidiInstrumentEntry entry, MidiInstrumentInfo info, boolean nonModal)
2992                                            throws IOException, LSException, LscpException {
2993                                    
2994                  verifyConnection();                  verifyConnection();
2995                  String args = deviceID + " " + port + " " +                  StringBuffer cmd = new StringBuffer("MAP MIDI_INSTRUMENT ");
2996                          prm.getName() + '=' + prm.getStringValue();                  if(nonModal) cmd.append("NON_MODAL ");
2997                  out.writeLine("SET MIDI_INPUT_PORT_PARAMETER " + args);                  cmd.append(mapId).append(' ');
2998                    cmd.append(entry.getMidiBank()).append(' ');
2999                    cmd.append(entry.getMidiProgram()).append(' ');
3000                    cmd.append(info.getEngine()).append(" '");
3001                    cmd.append(conv(info.getFilePath())).append("' ");
3002                    cmd.append(info.getInstrumentIndex()).append(' ');
3003                    cmd.append(info.getVolume());
3004                    if(!info.getLoadMode().name().equals("DEFAULT")) {
3005                            cmd.append(' ').append(info.getLoadMode().name());
3006                    }
3007                    
3008                    if(info.getName() != null) {
3009                            String s = toEscapedText(info.getName());
3010                            cmd.append(" '").append(s).append("'");
3011                    }
3012                    
3013                    out.writeLine(cmd.toString());
3014                    if(getPrintOnlyMode()) return;
3015                                    
3016                  ResultSet rs = getEmptyResultSet();                  ResultSet rs = getEmptyResultSet();
3017          }          }
3018                    
3019          /**          /**
3020             * Removes an entry MIDI instrument map.
3021             * @param mapId The ID of the map, from which
3022             * the specified MIDI instrument should be removed.
3023             * @param entry The entry to remove from the specified MIDI instrument map.
3024             * @throws IOException If some I/O error occurs.
3025             * @throws LSException If the unmapping failed.
3026             * @throws LscpException If LSCP protocol corruption occurs.
3027             * @see #mapMidiInstrument
3028             */
3029            public synchronized void
3030            unmapMidiInstrument(int mapId, MidiInstrumentEntry entry)
3031                                            throws IOException, LSException, LscpException
3032            {
3033                    StringBuffer cmd = new StringBuffer("UNMAP MIDI_INSTRUMENT ");
3034                    cmd.append(mapId).append(' ');
3035                    cmd.append(entry.getMidiBank()).append(' ');
3036                    cmd.append(entry.getMidiProgram());
3037    
3038                    retrieveIndex(cmd.toString());
3039            }
3040            
3041            /**
3042             * Gets the current number of all MIDI instrument in all maps.
3043             * @return The current number of all MIDI instrument in all maps
3044             * or -1 if in "print only" mode.
3045             * @throws IOException If some I/O error occurs.
3046             * @throws LscpException If LSCP protocol corruption occurs.
3047             * @throws LSException If some other error occurs.
3048             */
3049            public synchronized int
3050            getMidiInstrumentCount() throws IOException, LscpException, LSException {
3051                    return retrieveInt("GET MIDI_INSTRUMENTS ALL");
3052            }
3053            
3054            /**
3055             * Gets the current number of MIDI instrument in the specified map.
3056             * @param mapId The ID of the map.
3057             * @return The current number of MIDI instrument in the
3058             * specified map or -1 if in "print only" mode.
3059             * @throws IOException If some I/O error occurs.
3060             * @throws LscpException If LSCP protocol corruption occurs.
3061             * @throws LSException If some other error occurs.
3062             */
3063            public synchronized int
3064            getMidiInstrumentCount(int mapId) throws IOException, LscpException, LSException {
3065                    return retrieveInt("GET MIDI_INSTRUMENTS " + String.valueOf(mapId));
3066            }
3067            
3068            /**
3069             * Gets all MIDI instrument from all maps.
3070             * @return A <code>MidiInstrumentInfo</code> array providing
3071             * all MIDI instruments from all MIDI instrument maps.
3072             * @throws IOException If some I/O error occurs.
3073             * @throws LscpException If LSCP protocol corruption occurs.
3074             * @throws LSException If some other error occurs.
3075             */
3076            public synchronized MidiInstrumentInfo[]
3077            getMidiInstruments() throws IOException, LscpException, LSException {
3078                    verifyConnection();
3079                    out.writeLine("LIST MIDI_INSTRUMENTS ALL");
3080                    if(getPrintOnlyMode()) return null;
3081                    
3082                    String[] entries = parseArray(getSingleLineResultSet().getResult());
3083                    
3084                    return getMidiInstruments(entries);
3085            }
3086            
3087            /**
3088             * Gets all MIDI instrument entries contained int the specified MIDI instrument map.
3089             * @param mapId The ID of the map, which instruments should be obtained.
3090             * @return An int array providing all MIDI instrument entries
3091             * in the specified MIDI instrument map.
3092             * @throws IOException If some I/O error occurs.
3093             * @throws LscpException If LSCP protocol corruption occurs.
3094             * @throws LSException If some other error occurs.
3095             */
3096            public synchronized int[][]
3097            getMidiInstrumentEntries(int mapId) throws IOException, LscpException, LSException {
3098                    verifyConnection();
3099                    out.writeLine("LIST MIDI_INSTRUMENTS " + String.valueOf(mapId));
3100                    if(getPrintOnlyMode()) return null;
3101                    
3102                    String[] entries = parseArray(getSingleLineResultSet().getResult());
3103                    int[][] e = new int[entries.length][3];
3104                    
3105                    for(int i = 0; i < entries.length; i++) {
3106                            Integer[] vals = parseIntList(entries[i]);
3107                            if(vals.length != 3) {
3108                                    throw new LscpException(LscpI18n.getLogMsg("CommandFailed!"));
3109                            }
3110                            
3111                            e[i][0] = vals[0];
3112                            e[i][1] = vals[1];
3113                            e[i][2] = vals[2];
3114                    }
3115                    
3116                    return e;
3117            }
3118            
3119            /**
3120             * Gets all MIDI instruments contained int the specified MIDI instrument map.
3121             * @param mapId The ID of the map, which instruments should be obtained.
3122             * @return A <code>MidiInstrumentInfo</code> array providing
3123             * all MIDI instruments in the specified MIDI instrument map.
3124             * @throws IOException If some I/O error occurs.
3125             * @throws LscpException If LSCP protocol corruption occurs.
3126             * @throws LSException If some other error occurs.
3127             */
3128            public synchronized MidiInstrumentInfo[]
3129            getMidiInstruments(int mapId) throws IOException, LscpException, LSException {
3130                    verifyConnection();
3131                    out.writeLine("LIST MIDI_INSTRUMENTS " + String.valueOf(mapId));
3132                    if(getPrintOnlyMode()) return null;
3133                    
3134                    String[] entries = parseArray(getSingleLineResultSet().getResult());
3135                    
3136                    return getMidiInstruments(entries);
3137            }
3138            
3139            private MidiInstrumentInfo[]
3140            getMidiInstruments(String[] entries) throws IOException, LscpException, LSException {
3141                    Vector<MidiInstrumentInfo> v = new Vector<MidiInstrumentInfo>();
3142                    
3143                    for(String s : entries) {
3144                            Integer[] vals = parseIntList(s);
3145                            if(vals.length != 3) {
3146                                    throw new LscpException(LscpI18n.getLogMsg("CommandFailed!"));
3147                            }
3148                            
3149                            v.add(getMidiInstrumentInfo(vals[0], vals[1], vals[2]));
3150                    }
3151                    
3152                    return v.toArray(new MidiInstrumentInfo[v.size()]);
3153            }
3154            
3155            /**
3156             * Gets the current settings of the specified MIDI instrument.
3157             * @param mapId The ID of the map.
3158             * @param bank The index of the MIDI bank.
3159             * @param program The MIDI program number of the instrument.
3160             * @return <code>MidiInstrumentInfo</code> instance containing
3161             * the current settings of the specified MIDI instrument.
3162             * @throws IOException If an I/O error occurs.
3163             * @throws LscpException If LSCP protocol corruption occurs.
3164             * @throws LSException If the specified MIDI instrument is missing.
3165             */
3166            public synchronized MidiInstrumentInfo
3167            getMidiInstrumentInfo(int mapId, int bank, int program)
3168                                            throws IOException, LscpException, LSException {
3169            
3170                    verifyConnection();
3171                    requestMidiInstrumentInfo(mapId, bank, program);
3172                    return getMidiInstrumentInfoResponse(mapId, bank, program);
3173            }
3174            
3175            private void
3176            requestMidiInstrumentInfo(int mapId, int bank, int program) throws IOException {
3177                    StringBuffer cmd = new StringBuffer("GET MIDI_INSTRUMENT INFO ");
3178                    cmd.append(mapId).append(' ');
3179                    cmd.append(bank).append(' ');
3180                    cmd.append(program);
3181                    
3182                    out.writeLine(cmd.toString());
3183            }
3184            
3185            private MidiInstrumentInfo
3186            getMidiInstrumentInfoResponse(int mapId, int bank, int program)
3187                                            throws IOException, LscpException, LSException {
3188                    
3189                    if(getPrintOnlyMode()) return null;
3190                    ResultSet rs = getMultiLineResultSet();
3191                    MidiInstrumentEntry entry = new MidiInstrumentEntry(bank, program);
3192                    return new MidiInstrumentInfo(mapId, entry, rs.getMultiLineResult());
3193            }
3194            
3195            /**
3196           * Loads and assigns an instrument to a sampler channel. Notice that this function will           * Loads and assigns an instrument to a sampler channel. Notice that this function will
3197           * return after the instrument is fully loaded and the channel is ready to be used.           * return after the instrument is fully loaded and the channel is ready to be used.
          *    
3198           * @param filename The name of the instrument file           * @param filename The name of the instrument file
3199           * on the LinuxSampler instance's host system.           * on the LinuxSampler instance's host system.
3200           * @param instrIdx The index of the instrument in the instrument file.           * @param instrIdx The index of the instrument in the instrument file.
3201           * @param samplerChn The number of the sampler channel the instrument should be assigned to.           * @param samplerChn The number of the sampler channel the instrument should be assigned to.
          *  
3202           * @throws IOException If some I/O error occurs.           * @throws IOException If some I/O error occurs.
3203           * @throws LscpException If LSCP protocol corruption occurs.           * @throws LscpException If LSCP protocol corruption occurs.
3204           * @throws LSException If the loading of the instrument failed.           * @throws LSException If the loading of the instrument failed.
          *  
3205           * @see #loadInstrument(String, int, int, boolean)           * @see #loadInstrument(String, int, int, boolean)
3206           * @see #getSamplerChannels           * @see #getSamplerChannels
3207           */           */
# Line 1798  public class Client { Line 3233  public class Client {
3233           */           */
3234          public synchronized void          public synchronized void
3235          loadInstrument(String filename, int instrIdx, int samplerChn, boolean nonModal)          loadInstrument(String filename, int instrIdx, int samplerChn, boolean nonModal)
3236                                                  throws IOException, LscpException, LSException {                                                  throws IOException, LscpException, LSException
3237                            {
3238                  String cmd = nonModal ? "LOAD INSTRUMENT NON_MODAL " : "LOAD INSTRUMENT ";                  String cmd = nonModal ? "LOAD INSTRUMENT NON_MODAL " : "LOAD INSTRUMENT ";
3239                  String args = '\'' + filename + "' " + instrIdx + ' ' + samplerChn;                  String args = '\'' + conv(filename) + "' " + instrIdx + ' ' + samplerChn;
3240                    
3241                  out.writeLine(cmd + args);                  retrieveIndex(cmd + args);
                   
                 ResultSet rs = getEmptyResultSet();  
3242          }          }
3243                    
3244          /**          /**
# Line 1822  public class Client { Line 3255  public class Client {
3255           */           */
3256          public synchronized void          public synchronized void
3257          loadSamplerEngine(String engineName, int samplerChn)          loadSamplerEngine(String engineName, int samplerChn)
3258                                          throws IOException, LscpException, LSException {                                          throws IOException, LscpException, LSException
3259                            { retrieveIndex("LOAD ENGINE " + engineName + ' ' + samplerChn); }
                 verifyConnection();  
                 out.writeLine("LOAD ENGINE " + engineName + ' ' + samplerChn);  
                   
                 ResultSet rs = getEmptyResultSet();  
         }  
3260                    
3261          /**          /**
3262           * Gets the current number of all created sampler channels.           * Gets the current number of all created sampler channels.
3263           * @return The current number of all created sampler channels.           * @return The current number of all created sampler
3264             * channels or -1 if in "print only" mode.
3265           * @throws IOException If some I/O error occurs.           * @throws IOException If some I/O error occurs.
3266           * @throws LscpException If LSCP protocol corruption occurs.           * @throws LscpException If LSCP protocol corruption occurs.
3267           * @throws LSException If some other error occurs.           * @throws LSException If some other error occurs.
3268           */           */
3269          public synchronized int          public synchronized int
3270          getSamplerChannelCount() throws IOException, LscpException, LSException {          getSamplerChannelCount() throws IOException, LscpException, LSException {
3271                  verifyConnection();                  return retrieveInt("GET CHANNELS");
                 out.writeLine("GET CHANNELS");  
                 String s = getSingleLineResultSet().getResult();  
                 return parseInt(s);  
3272          }          }
3273                    
3274          /**          /**
# Line 1857  public class Client { Line 3283  public class Client {
3283          public synchronized SamplerChannel[]          public synchronized SamplerChannel[]
3284          getSamplerChannels() throws IOException, LscpException, LSException {          getSamplerChannels() throws IOException, LscpException, LSException {
3285                  Integer[] idS = getSamplerChannelIDs();                  Integer[] idS = getSamplerChannelIDs();
3286                    if(getPrintOnlyMode()) return null;
3287                    
3288                  SamplerChannel[] channels = new SamplerChannel[idS.length];                  SamplerChannel[] channels = new SamplerChannel[idS.length];
3289                                    
3290                  for(int i = 0; i < channels.length; i++)                  for(int i = 0; i < channels.length; i++)
# Line 1864  public class Client { Line 3292  public class Client {
3292                                    
3293                  return channels;                  return channels;
3294          }          }
3295    
3296            /**
3297             * Gets a list of the specified sampler channels.
3298             * @return A <code>SamplerChannel</code> array providing all created sampler channels.
3299             * @throws IOException If some I/O error occurs.
3300             * @throws LscpException If LSCP protocol corruption occurs.
3301             * @throws LSException If some other error occurs.
3302             * @see #addSamplerChannel
3303             * @see #removeSamplerChannel
3304             */
3305            public synchronized SamplerChannel[]
3306            getSamplerChannels(final Integer[] ids) throws IOException, LscpException, LSException {
3307                    verifyConnection();
3308    
3309                    int count = 0;
3310                    for(int i = 0; i < ids.length; i++) {
3311                            if(ids[i] >= 0) {
3312                                    int tmp = ids[i]; // to avoid overlapping
3313                                    ids[i] = -1;
3314                                    ids[count++] = tmp;
3315                            }
3316                    }
3317                    if(getPrintOnlyMode()) return null;
3318    
3319                    final SamplerChannel[] channels = new SamplerChannel[count];
3320    
3321                    new CmdListIterator(count) {
3322                            @Override
3323                            protected void
3324                            writeOutput(int index) throws IOException {
3325                                    channels[index] = new SamplerChannel();
3326                                    out.writeLine("GET CHANNEL INFO " + ids[index]);
3327                                    channels[index].setChannelId(ids[index]);
3328                            }
3329    
3330                            @Override
3331                            protected void
3332                            readInput(int index) throws IOException, LscpException, LSException {
3333                                    if(getPrintOnlyMode()) return;
3334                                    ResultSet rs = getMultiLineResultSet();
3335    
3336                                    for(String s : rs.getMultiLineResult()) {
3337                                            if(!channels[index].parse(s)) {
3338                                                    String msg = LscpI18n.getLogMsg("unknownLine", s);
3339                                                    Client.getLogger().info(msg);
3340                                            }
3341                                    }
3342                            }
3343                    }.run();
3344    
3345    
3346    
3347                    for(SamplerChannel sc : channels) {
3348                            if(sc.getEngine() != null) {
3349                                    sc.setEngine(getEngineInfo(sc.getEngine().getName()));
3350                            }
3351                    }
3352    
3353                    return channels;
3354            }
3355    
3356            private static abstract class CmdListIterator {
3357                    private final int cmdCount;
3358                    private final int cmdsPerStep;
3359    
3360                    CmdListIterator(int cmdCount) {
3361                            this(cmdCount, 100);
3362                    }
3363    
3364                    CmdListIterator(int cmdCount, int cmdsPerStep) {
3365                            this.cmdCount = cmdCount;
3366                            this.cmdsPerStep = cmdsPerStep;
3367                    }
3368    
3369                    public void
3370                    run() throws IOException, LscpException, LSException {
3371                            int currentStep = 0;
3372                            int stepCount = cmdCount / cmdsPerStep;
3373    
3374                            for(currentStep = 0; currentStep < stepCount; currentStep++) {
3375                                    for(int j = 0; j < cmdsPerStep; j++) {
3376                                            int idx = (currentStep * cmdsPerStep) + j;
3377                                            writeOutput(idx);
3378                                    }
3379    
3380                                    for(int j = 0; j < cmdsPerStep; j++) {
3381                                            int idx = (currentStep * cmdsPerStep) + j;
3382                                            readInput(idx);
3383                                    }
3384                            }
3385    
3386                            int cmdsLeft = cmdCount % cmdsPerStep;
3387                            if(cmdsLeft > 0) {
3388                                    for(int j = 0; j < cmdsLeft; j++) {
3389                                            int idx = stepCount * cmdsPerStep + j;
3390                                            writeOutput(idx);
3391                                    }
3392    
3393                                    for(int j = 0; j < cmdsLeft; j++) {
3394                                            int idx = stepCount * cmdsPerStep + j;
3395                                            readInput(idx);
3396                                    }
3397                            }
3398                    }
3399    
3400                    protected abstract void writeOutput(int index) throws IOException;
3401    
3402                    protected abstract void readInput(int index) throws IOException, LscpException, LSException;
3403            }
3404                    
3405          /**          /**
3406           * Gets a list with numerical IDs of all created sampler channels.           * Gets a list with numerical IDs of all created sampler channels.
# Line 1877  public class Client { Line 3414  public class Client {
3414           */           */
3415          public synchronized Integer[]          public synchronized Integer[]
3416          getSamplerChannelIDs() throws IOException, LscpException, LSException {          getSamplerChannelIDs() throws IOException, LscpException, LSException {
3417                  verifyConnection();                  return getIntegerList("LIST CHANNELS");
                 out.writeLine("LIST CHANNELS");  
                 return parseIntList(getSingleLineResultSet().getResult());  
3418          }          }
3419                    
3420          /**          /**
# Line 1894  public class Client { Line 3429  public class Client {
3429           */           */
3430          public synchronized int          public synchronized int
3431          addSamplerChannel() throws IOException, LSException, LscpException {          addSamplerChannel() throws IOException, LSException, LscpException {
3432                  verifyConnection();                  return retrieveIndex("ADD CHANNEL");
                 out.writeLine("ADD CHANNEL");  
                 ResultSet rs = getEmptyResultSet();  
                   
                 return rs.getIndex();  
3433          }          }
3434                    
3435          /**          /**
# Line 1914  public class Client { Line 3445  public class Client {
3445           */           */
3446          public synchronized void          public synchronized void
3447          removeSamplerChannel(int samplerChn) throws IOException, LscpException, LSException {          removeSamplerChannel(int samplerChn) throws IOException, LscpException, LSException {
3448                  verifyConnection();                  retrieveIndex("REMOVE CHANNEL " + samplerChn);
                 out.writeLine("REMOVE CHANNEL " + samplerChn);  
                   
                 ResultSet rs = getEmptyResultSet();  
3449          }          }
3450                    
3451          /**          /**
3452           * Gets the number of all available engines.           * Gets the number of all available engines.
3453           * @return The number of all available engines.           * @return The number of all available engines or -1 if in "print only" mode.
3454           * @throws IOException If some I/O error occurs.           * @throws IOException If some I/O error occurs.
3455           * @throws LscpException If LSCP protocol corruption occurs.           * @throws LscpException If LSCP protocol corruption occurs.
3456           * @throws LSException If some other error occurs.           * @throws LSException If some other error occurs.
3457           */           */
3458          public synchronized int          public synchronized int
3459          getEngineCount() throws IOException, LscpException, LSException {          getEngineCount() throws IOException, LscpException, LSException {
3460                  verifyConnection();                  return retrieveInt("GET AVAILABLE_ENGINES");
                 out.writeLine("GET AVAILABLE_ENGINES");  
                 String s = getSingleLineResultSet().getResult();  
                 return parseInt(s);  
3461          }          }
3462                    
3463          /**          /**
# Line 1946  public class Client { Line 3471  public class Client {
3471          public synchronized SamplerEngine[]          public synchronized SamplerEngine[]
3472          getEngines() throws IOException, LscpException, LSException {          getEngines() throws IOException, LscpException, LSException {
3473                  String[] engines = getEngineNames();                  String[] engines = getEngineNames();
3474                    if(getPrintOnlyMode()) return null;
3475                    
3476                  SamplerEngine[] se = new SamplerEngine[engines.length];                  SamplerEngine[] se = new SamplerEngine[engines.length];
3477                                    
3478                  for(int i = 0; i < engines.length; i++) se[i] = getEngineInfo(engines[i]);                  for(int i = 0; i < engines.length; i++) se[i] = getEngineInfo(engines[i]);
# Line 1965  public class Client { Line 3492  public class Client {
3492          getEngineNames() throws IOException, LscpException, LSException {          getEngineNames() throws IOException, LscpException, LSException {
3493                  verifyConnection();                  verifyConnection();
3494                  out.writeLine("LIST AVAILABLE_ENGINES");                  out.writeLine("LIST AVAILABLE_ENGINES");
3495                    if(getPrintOnlyMode()) return null;
3496                    
3497                  return parseStringList(getSingleLineResultSet().getResult());                  return parseStringList(getSingleLineResultSet().getResult());
3498          }          }
3499                    
# Line 1982  public class Client { Line 3511  public class Client {
3511           */           */
3512          private synchronized SamplerEngine          private synchronized SamplerEngine
3513          getEngineInfo(String engineName) throws IOException, LscpException, LSException {          getEngineInfo(String engineName) throws IOException, LscpException, LSException {
3514                  verifyConnection();                  SamplerEngine se = engineMap.get(engineName);
3515                  out.writeLine("GET ENGINE INFO " + engineName);                  if(se != null) return se;
3516                  ResultSet rs = getMultiLineResultSet();                  
3517                  SamplerEngine se = new SamplerEngine(rs.getMultiLineResult());                  se = new SamplerEngine();
3518                    if(!retrieveInfo("GET ENGINE INFO " + engineName, se)) return null;
3519                  se.setName(engineName);                  se.setName(engineName);
3520                    engineMap.put(engineName, se);
3521    
3522                  return se;                  return se;
3523          }          }
3524                    
# Line 2004  public class Client { Line 3536  public class Client {
3536           */           */
3537          public synchronized SamplerChannel          public synchronized SamplerChannel
3538          getSamplerChannelInfo(int samplerChn) throws IOException, LscpException, LSException {          getSamplerChannelInfo(int samplerChn) throws IOException, LscpException, LSException {
3539                  verifyConnection();                  SamplerChannel sc = new SamplerChannel();
3540                  out.writeLine("GET CHANNEL INFO " + samplerChn);                  if(!retrieveInfo("GET CHANNEL INFO " + samplerChn, sc)) return null;
3541                  ResultSet rs = getMultiLineResultSet();                  sc.setChannelId(samplerChn);
                 SamplerChannel sc = new SamplerChannel(rs.getMultiLineResult());  
                 sc.setChannelID(samplerChn);  
3542                  if(sc.getEngine() != null) sc.setEngine(getEngineInfo(sc.getEngine().getName()));                  if(sc.getEngine() != null) sc.setEngine(getEngineInfo(sc.getEngine().getName()));
3543                                    
3544                  return sc;                  return sc;
# Line 2018  public class Client { Line 3548  public class Client {
3548           * Gets the current number of active voices on the specified sampler channel.           * Gets the current number of active voices on the specified sampler channel.
3549           *           *
3550           * @param samplerChn The sampler channel number.           * @param samplerChn The sampler channel number.
3551           * @return The current number of active voices on the specified sampler channel.           * @return The current number of active voices on the
3552             * specified sampler channel or -1 if in "print only" mode.
3553           * @throws IOException If some I/O error occurs.           * @throws IOException If some I/O error occurs.
3554           * @throws LscpException If LSCP protocol corruption occurs.           * @throws LscpException If LSCP protocol corruption occurs.
3555           * @throws LSException If there is no sampler channel with number <code>samplerChn</code>.           * @throws LSException If there is no sampler channel with number <code>samplerChn</code>.
# Line 2026  public class Client { Line 3557  public class Client {
3557           */           */
3558          public synchronized int          public synchronized int
3559          getChannelVoiceCount(int samplerChn) throws IOException, LscpException, LSException {          getChannelVoiceCount(int samplerChn) throws IOException, LscpException, LSException {
3560                  verifyConnection();                  return retrieveInt("GET CHANNEL VOICE_COUNT " + samplerChn);
                 out.writeLine("GET CHANNEL VOICE_COUNT " + samplerChn);  
                 ResultSet rs = getSingleLineResultSet();  
                   
                 return parseInt(rs.getResult());  
3561          }          }
3562                    
3563          /**          /**
# Line 2048  public class Client { Line 3575  public class Client {
3575          getChannelStreamCount(int samplerChn) throws IOException, LscpException, LSException {          getChannelStreamCount(int samplerChn) throws IOException, LscpException, LSException {
3576                  verifyConnection();                  verifyConnection();
3577                  out.writeLine("GET CHANNEL STREAM_COUNT " + samplerChn);                  out.writeLine("GET CHANNEL STREAM_COUNT " + samplerChn);
3578                    if(getPrintOnlyMode()) return -1;
3579            
3580                  ResultSet rs = getSingleLineResultSet();                  ResultSet rs = getSingleLineResultSet();
3581                                    
3582                  if(rs.getResult().equals("NA")) return -1;                  if(rs.getResult().equals("NA")) return -1;
# Line 2072  public class Client { Line 3601  public class Client {
3601          getChannelBufferFillBytes(int samplerChn) throws IOException, LscpException, LSException {          getChannelBufferFillBytes(int samplerChn) throws IOException, LscpException, LSException {
3602                  verifyConnection();                  verifyConnection();
3603                  out.writeLine("GET CHANNEL BUFFER_FILL BYTES " + samplerChn);                  out.writeLine("GET CHANNEL BUFFER_FILL BYTES " + samplerChn);
3604                    if(getPrintOnlyMode()) return null;
3605                    
3606                  ResultSet rs = getSingleLineResultSet();                  ResultSet rs = getSingleLineResultSet();
3607                                    
3608                  if(rs.getResult().equals("NA")) return null;                  if(rs.getResult().equals("NA")) return null;
# Line 2087  public class Client { Line 3618  public class Client {
3618                          if(i == -1) throw new LscpException(LscpI18n.getLogMsg("CommandFailed!"));                          if(i == -1) throw new LscpException(LscpI18n.getLogMsg("CommandFailed!"));
3619                                                    
3620                          BufferFill bf = new BufferFill();                          BufferFill bf = new BufferFill();
3621                          bf.setStreamID(parseInt(s.substring(1, i)));                          bf.setStreamId(parseInt(s.substring(1, i)));
3622                          bf.setValue(parseInt(s.substring(i + 1)));                          bf.setValue(parseInt(s.substring(i + 1)));
3623                          v.add(bf);                          v.add(bf);
3624                  }                  }
# Line 2114  public class Client { Line 3645  public class Client {
3645                                    
3646                  verifyConnection();                  verifyConnection();
3647                  out.writeLine("GET CHANNEL BUFFER_FILL PERCENTAGE " + samplerChn);                  out.writeLine("GET CHANNEL BUFFER_FILL PERCENTAGE " + samplerChn);
3648                    if(getPrintOnlyMode()) return null;
3649                    
3650                  ResultSet rs = getSingleLineResultSet();                  ResultSet rs = getSingleLineResultSet();
3651                                    
3652                  return getChannelBufferFillPercentage(rs.getResult());                  return getChannelBufferFillPercentage(rs.getResult());
# Line 2137  public class Client { Line 3670  public class Client {
3670                                  throw new LscpException(LscpI18n.getLogMsg("CommandFailed!"));                                  throw new LscpException(LscpI18n.getLogMsg("CommandFailed!"));
3671                                                    
3672                          BufferFill bf = new BufferFill();                          BufferFill bf = new BufferFill();
3673                          bf.setStreamID(parseInt(s.substring(1, i)));                          bf.setStreamId(parseInt(s.substring(1, i)));
3674                          bf.setValue(parseInt(s.substring(i + 1, s.length() - 1)));                          bf.setValue(parseInt(s.substring(i + 1, s.length() - 1)));
3675                          v.add(bf);                          v.add(bf);
3676                  }                  }
# Line 2149  public class Client { Line 3682  public class Client {
3682           * Sets the audio output device on the specified sampler channel.           * Sets the audio output device on the specified sampler channel.
3683           *           *
3684           * @param samplerChn The sampler channel number.           * @param samplerChn The sampler channel number.
3685           * @param devID The numerical ID of the audio output device.           * @param devId The numerical ID of the audio output device.
3686           *           *
3687           * @throws IOException If some I/O error occurs.           * @throws IOException If some I/O error occurs.
3688           * @throws LscpException If LSCP protocol corruption occurs.           * @throws LscpException If LSCP protocol corruption occurs.
3689           * @throws LSException If           * @throws LSException If
3690           * <ul>           * <ul>
3691           * <li><code>samplerChn</code> is not a valid channel number;           * <li><code>samplerChn</code> is not a valid channel number;
3692           * <li><code>devID</code> is not a valid audio output device ID;           * <li><code>devId</code> is not a valid audio output device ID;
3693           * </ul>           * </ul>
3694           *           *
3695           * @see #getSamplerChannels           * @see #getSamplerChannels
3696           * @see #getAudioOutputDevices           * @see #getAudioOutputDevices
3697           */           */
3698          public synchronized void          public synchronized void
3699          setChannelAudioOutputDevice(int samplerChn, int devID)          setChannelAudioOutputDevice(int samplerChn, int devId)
3700                                  throws IOException, LscpException, LSException {                                  throws IOException, LscpException, LSException
3701                            { retrieveIndex("SET CHANNEL AUDIO_OUTPUT_DEVICE " + samplerChn + ' ' + devId); }
                 verifyConnection();  
                 out.writeLine("SET CHANNEL AUDIO_OUTPUT_DEVICE " + samplerChn + ' ' + devID);  
                   
                 ResultSet rs = getEmptyResultSet();  
         }  
3702                    
3703          /**          /**
3704           * Sets the audio output channel on the specified sampler channel.           * Sets the audio output channel on the specified sampler channel.
# Line 2193  public class Client { Line 3721  public class Client {
3721           */           */
3722          public synchronized void          public synchronized void
3723          setChannelAudioOutputChannel(int samplerChn, int audioOut, int audioIn)          setChannelAudioOutputChannel(int samplerChn, int audioOut, int audioIn)
3724                                  throws IOException, LscpException, LSException {                                  throws IOException, LscpException, LSException
3725                            {
                 verifyConnection();  
3726                  String args = " " + samplerChn + ' ' + audioOut + ' ' + audioIn;                  String args = " " + samplerChn + ' ' + audioOut + ' ' + audioIn;
3727                  out.writeLine("SET CHANNEL AUDIO_OUTPUT_CHANNEL" + args);                  retrieveIndex("SET CHANNEL AUDIO_OUTPUT_CHANNEL" + args);
                   
                 ResultSet rs = getEmptyResultSet();  
3728          }          }
3729                    
3730          /**          /**
3731           * Sets the MIDI input device on the specified sampler channel.           * Sets the MIDI input device on the specified sampler channel.
3732           *           *
3733           * @param samplerChn The sampler channel number.           * @param samplerChn The sampler channel number.
3734           * @param devID The numerical ID of the MIDI input device.           * @param devId The numerical ID of the MIDI input device.
3735           *           *
3736           * @throws IOException If some I/O error occurs.           * @throws IOException If some I/O error occurs.
3737           * @throws LscpException If LSCP protocol corruption occurs.           * @throws LscpException If LSCP protocol corruption occurs.
3738           * @throws LSException If           * @throws LSException If
3739           * <ul>           * <ul>
3740           * <li><code>samplerChn</code> is not a valid channel number;           * <li><code>samplerChn</code> is not a valid channel number;
3741           * <li><code>devID</code> is not a valid MIDI input device ID;           * <li><code>devId</code> is not a valid MIDI input device ID;
3742           * </ul>           * </ul>
3743           *           *
3744           * @see #getSamplerChannels           * @see #getSamplerChannels
3745           * @see #getMidiInputDevices           * @see #getMidiInputDevices
3746           */           */
3747          public synchronized void          public synchronized void
3748          setChannelMidiInputDevice(int samplerChn, int devID)          setChannelMidiInputDevice(int samplerChn, int devId)
3749                                  throws IOException, LscpException, LSException {                                  throws IOException, LscpException, LSException
3750                            { retrieveIndex("SET CHANNEL MIDI_INPUT_DEVICE " + samplerChn + ' ' + devId); }
                 verifyConnection();  
                 out.writeLine("SET CHANNEL MIDI_INPUT_DEVICE " + samplerChn + ' ' + devID);  
                   
                 ResultSet rs = getEmptyResultSet();  
         }  
3751                    
3752          /**          /**
3753           * Sets the MIDI input port on the specified sampler channel.           * Sets the MIDI input port on the specified sampler channel.
# Line 2243  public class Client { Line 3763  public class Client {
3763           */           */
3764          public synchronized void          public synchronized void
3765          setChannelMidiInputPort(int samplerChn, int port)          setChannelMidiInputPort(int samplerChn, int port)
3766                                  throws IOException, LscpException, LSException {                                  throws IOException, LscpException, LSException
3767                            { retrieveIndex("SET CHANNEL MIDI_INPUT_PORT " + samplerChn + ' ' + port); }
                 verifyConnection();  
                 out.writeLine("SET CHANNEL MIDI_INPUT_PORT " + samplerChn + ' ' + port);  
                   
                 ResultSet rs = getEmptyResultSet();  
         }  
3768                    
3769          /**          /**
3770           * Sets the MIDI input channel the specified sampler channel should listen to.           * Sets the MIDI input channel the specified sampler channel should listen to.
# Line 2265  public class Client { Line 3780  public class Client {
3780           */           */
3781          public synchronized void          public synchronized void
3782          setChannelMidiInputChannel(int samplerChn, int midiChn)          setChannelMidiInputChannel(int samplerChn, int midiChn)
3783                                  throws IOException, LscpException, LSException {                                  throws IOException, LscpException, LSException
3784                            {
                 verifyConnection();  
3785                  String args = String.valueOf(samplerChn) + ' ';                  String args = String.valueOf(samplerChn) + ' ';
3786                  args += (midiChn == -1 ? "ALL" : String.valueOf(midiChn));                  args += (midiChn == -1 ? "ALL" : String.valueOf(midiChn));
3787                  out.writeLine("SET CHANNEL MIDI_INPUT_CHANNEL " + args);                  retrieveIndex("SET CHANNEL MIDI_INPUT_CHANNEL " + args);
3788                            }
3789                  ResultSet rs = getEmptyResultSet();          
3790            /**
3791             * Sets the MIDI instrument map to be used on the specified sampler channel.
3792             *
3793             * @param samplerChn The sampler channel number.
3794             * @param mapId Specifies the numerical ID of the MIDI instrument
3795             * map to assign. To remove the current map binding use <code>-1</code>.
3796             * To set the current map to be the default map use <code>-2</code>.
3797             *
3798             * @throws IOException If some I/O error occurs.
3799             * @throws LscpException If LSCP protocol corruption occurs.
3800             * @throws LSException If
3801             * <ul>
3802             * <li><code>samplerChn</code> is not a valid channel number;
3803             * <li><code>mapId</code> is not a valid MIDI instrument map ID;
3804             * </ul>
3805             *
3806             * @see #getSamplerChannels
3807             * @see #getMidiInstrumentMaps
3808             */
3809            public synchronized void
3810            setChannelMidiInstrumentMap(int samplerChn, int mapId)
3811                                    throws IOException, LscpException, LSException
3812            {
3813                    String s;
3814                    if(mapId == -1) {
3815                            s = " NONE";
3816                    } else if(mapId == -2) {
3817                            s = " DEFAULT";
3818                    } else {
3819                            s = " " + String.valueOf(mapId);
3820                    }
3821    
3822                    retrieveIndex("SET CHANNEL MIDI_INSTRUMENT_MAP " + samplerChn + s);
3823          }          }
3824                    
3825          /**          /**
# Line 2289  public class Client { Line 3836  public class Client {
3836           */           */
3837          public synchronized void          public synchronized void
3838          setChannelVolume(int samplerChn, float volume)          setChannelVolume(int samplerChn, float volume)
3839                                  throws IOException, LscpException, LSException {                                  throws IOException, LscpException, LSException
3840                    { retrieveIndex("SET CHANNEL VOLUME " + samplerChn + ' ' + volume); }
                 verifyConnection();  
                 out.writeLine("SET CHANNEL VOLUME " + samplerChn + ' ' + volume);  
                   
                 ResultSet rs = getEmptyResultSet();  
         }  
3841                    
3842          /**          /**
3843           * Mute/unmute the specified sampler channel.           * Mute/unmute the specified sampler channel.
# Line 2312  public class Client { Line 3854  public class Client {
3854           */           */
3855          public synchronized void          public synchronized void
3856          setChannelMute(int samplerChn, boolean mute)          setChannelMute(int samplerChn, boolean mute)
3857                                  throws IOException, LscpException, LSException {                                  throws IOException, LscpException, LSException
3858                    { retrieveIndex("SET CHANNEL MUTE " + samplerChn + ' ' + (mute ? 1 : 0)); }
                 verifyConnection();  
                 out.writeLine("SET CHANNEL MUTE " + samplerChn + ' ' + (mute ? 1 : 0));  
                   
                 ResultSet rs = getEmptyResultSet();  
         }  
3859                    
3860          /**          /**
3861           * Solo/unsolo the specified sampler channel.           * Solo/unsolo the specified sampler channel.
# Line 2335  public class Client { Line 3872  public class Client {
3872           */           */
3873          public synchronized void          public synchronized void
3874          setChannelSolo(int samplerChn, boolean solo)          setChannelSolo(int samplerChn, boolean solo)
3875                                  throws IOException, LscpException, LSException {                                  throws IOException, LscpException, LSException
3876            { retrieveIndex("SET CHANNEL SOLO " + samplerChn + ' ' + (solo ? 1 : 0)); }
3877                    
3878                  verifyConnection();          /**
3879                  out.writeLine("SET CHANNEL SOLO " + samplerChn + ' ' + (solo ? 1 : 0));           * Creates an additional effect send on the specified sampler channel.
3880             * @param channel The sampler channel, on which a new effect send should be added.
3881             * @param midiCtrl Defines the MIDI controller, which
3882             * will be able alter the effect send level.
3883             * @return The unique ID of the newly created effect send entity.
3884             * @throws IOException If some I/O error occurs.
3885             * @throws LSException If the creation of the effect send failed.
3886             * @throws LscpException If LSCP protocol corruption occurs.
3887             * @see #destroyFxSend
3888             */
3889            public synchronized int
3890            createFxSend(int channel, int midiCtrl)
3891                            throws IOException, LSException, LscpException {
3892                                    
3893                  ResultSet rs = getEmptyResultSet();                  return createFxSend(channel, midiCtrl, null);
3894            }
3895            
3896            /**
3897             * Creates an additional effect send on the specified sampler channel.
3898             * @param channel The sampler channel, on which the effect send should be created on.
3899             * @param midiCtrl Defines the MIDI controller, which can alter the effect send level.
3900             * @param name The name of the effect send entity. The name does not have to be unique.
3901             * @return The unique ID of the newly created effect send entity.
3902             * @throws IOException If some I/O error occurs.
3903             * @throws LSException If the creation of the effect send failed.
3904             * @throws LscpException If LSCP protocol corruption occurs.
3905             * @see #destroyFxSend
3906             */
3907            public synchronized int
3908            createFxSend(int channel, int midiCtrl, String name)
3909                            throws IOException, LSException, LscpException
3910            {
3911                    String s = String.valueOf(channel) + " " + String.valueOf(midiCtrl);
3912                    if(name != null) s += " '" + toEscapedText(name) + "'";
3913    
3914                    return retrieveIndex("CREATE FX_SEND " + s);
3915            }
3916            
3917            /**
3918             * Destroys the specified effect send on the specified sampler channel.
3919             * @param channel The sampler channel, from which
3920             * the specified effect send should be removed.
3921             * @param fxSend The ID of the effect send that should be removed.
3922             * @throws LSException If some other error occurs.
3923             * @throws LscpException If LSCP protocol corruption occurs.
3924             * @see #createFxSend
3925             */
3926            public synchronized void
3927            destroyFxSend(int channel, int fxSend)
3928                            throws IOException, LSException, LscpException
3929            {
3930                    String s = String.valueOf(channel) + " " + String.valueOf(fxSend);
3931                    retrieveIndex("DESTROY FX_SEND " + s);
3932            }
3933            
3934            /**
3935             * Gets the current number of effect sends on the specified sampler channel.
3936             * @param channel The ID of the sampler channel.
3937             * @return The current number of effect sends on the specified sampler channels.
3938             * @throws IOException If some I/O error occurs.
3939             * @throws LscpException If LSCP protocol corruption occurs.
3940             * @throws LSException If some other error occurs.
3941             */
3942            public synchronized int
3943            getFxSendCount(int channel) throws IOException, LscpException, LSException {
3944                    return retrieveInt("GET FX_SENDS " + String.valueOf(channel));
3945            }
3946            
3947            /**
3948             * Gets a list of all created effect sends on the specified sampler channel.
3949             * @param channel The sampler channel number.
3950             * @return A <code>FxSend</code> array providing all created
3951             * effect sends on the specified sampler channel.
3952             * @throws IOException If some I/O error occurs.
3953             * @throws LscpException If LSCP protocol corruption occurs.
3954             * @throws LSException If <code>channel</code> is not a valid sampler channel ID.
3955             * @see #createFxSend
3956             * @see #destroyFxSend
3957             */
3958            public synchronized FxSend[]
3959            getFxSends(int channel) throws IOException, LscpException, LSException {
3960                    Integer[] idS = getFxSendIDs(channel);
3961                    if(getPrintOnlyMode()) return null;
3962                    
3963                    FxSend[] fxSends = new FxSend[idS.length];
3964                    
3965                    for(int i = 0; i < fxSends.length; i++)
3966                            fxSends[i] = getFxSendInfo(channel, idS[i]);
3967                    
3968                    return fxSends;
3969            }
3970            
3971            /**
3972             * Gets a list of effect sends on the specified sampler channel.
3973             * @param channel The sampler channel number.
3974             * @return An <code>Integer</code> array providing
3975             * the numerical IDs of all effect sends on the specified sampler channel.
3976             * @throws IOException If some I/O error occurs.
3977             * @throws LscpException If LSCP protocol corruption occurs.
3978             * @throws LSException If <code>channel</code> is not a valid sampler channel ID.
3979             * @see #createFxSend
3980             * @see #destroyFxSend
3981             */
3982            public synchronized Integer[]
3983            getFxSendIDs(int channel) throws IOException, LscpException, LSException {
3984                    return getIntegerList("LIST FX_SENDS " + channel);
3985            }
3986            
3987            /**
3988             * Gets the current settings of the specified effect send entity.
3989             * @param channel The sampler channel number.
3990             * @param fxSend The numerical ID of the effect send entity.
3991             * @return <code>FxSend</code> instance containing
3992             * the current settings of the specified effect send entity.
3993             * @throws IOException If an I/O error occurs.
3994             * @throws LscpException If LSCP protocol corruption occurs.
3995             * @throws LSException If the sampler channel and/or the effect send number are invalid.
3996             */
3997            public synchronized FxSend
3998            getFxSendInfo(int channel, int fxSend) throws IOException, LscpException, LSException {
3999                    FxSend fxs = new FxSend();
4000                    String s = String.valueOf(channel) + " " + String.valueOf(fxSend);
4001                    if(!retrieveInfo("GET FX_SEND INFO " + s, fxs)) return null;
4002                    fxs.setFxSendId(fxSend);
4003                    
4004                    return fxs;
4005            }
4006            
4007            /**
4008             * Sets the name of the specified effect send.
4009             * @param channel The sampler channel number.
4010             * @param fxSend The numerical ID of the effect send entity.
4011             * @param name The new name for the specified effect send.
4012             * @throws IOException If some I/O error occurs.
4013             * @throws LscpException If LSCP protocol corruption occurs.
4014             * @throws LSException If <code>channel</code> is not a valid channel
4015             * number or <code>fxSend</code> is not a valid effect send ID;
4016             */
4017            public synchronized void
4018            setFxSendName(int channel, int fxSend, String name)
4019                                    throws IOException, LscpException, LSException
4020            {
4021                    String args = " " + channel + " " + fxSend + " '" + toEscapedText(name) + "'";
4022                    retrieveIndex("SET FX_SEND NAME" + args);
4023            }
4024            
4025            /**
4026             * Sets the destination of an effect send's audio channel in the specified sampler channel.
4027             * @param channel The sampler channel number.
4028             * @param fxSend The numerical ID of the effect send entity to be rerouted.
4029             * @param audioSrc The numerical ID of the effect send's audio output channel,
4030             * which should be rerouted.
4031             * @param audioDst The audio channel of the selected audio output device
4032             * where <code>audioSrc</code> should be routed to.
4033             * @throws IOException If some I/O error occurs.
4034             * @throws LscpException If LSCP protocol corruption occurs.
4035             * @throws LSException If
4036             * <ul>
4037             * <li><code>channel</code> is not a valid channel number;
4038             * <li><code>fxSend</code> is not a valid effect send ID;
4039             * <li>There is no engine assigned yet to the specified sampler channel;
4040             * <li>There is no audio output device connected to the specified sampler channel.
4041             * </ul>
4042             */
4043            public synchronized void
4044            setFxSendAudioOutputChannel(int channel, int fxSend, int audioSrc, int audioDst)
4045                                    throws IOException, LscpException, LSException
4046            {
4047                    String args = " " + channel + " " + fxSend + " " + audioSrc + " " + audioDst;
4048                    retrieveIndex("SET FX_SEND AUDIO_OUTPUT_CHANNEL" + args);
4049            }
4050    
4051            /**
4052             * Assign a destination effect to an effect send.
4053             * @param channel The sampler channel number.
4054             * @param fxSend The numerical ID of the effect send entity.
4055             * @param fxChainId The numerical ID of the destination effect chain.
4056             * @param chainPos The exact effect chain position in the effect
4057             * chain which hosts the actual destination effect.
4058             * @throws IOException If some I/O error occurs.
4059             * @throws LscpException If LSCP protocol corruption occurs.
4060             * @throws LSException If
4061             * <ul>
4062             * <li><code>channel</code> is not a valid channel number;
4063             * <li><code>fxSend</code> is not a valid effect send ID;
4064             * <li><code>fxChainId</code> is not a valid effect chain ID;
4065             * <li><code>chainPos</code> is out of bounds;
4066             * <li>There is no engine assigned yet to the specified sampler channel;
4067             * <li>There is no audio output device connected to the specified sampler channel.
4068             * </ul>
4069             */
4070            public synchronized void
4071            setFxSendEffect(int channel, int fxSend, int fxChainId, int chainPos)
4072                                    throws IOException, LscpException, LSException
4073            {
4074                    String args = " " + channel + " " + fxSend + " " + fxChainId + " " + chainPos;
4075                    retrieveIndex("SET FX_SEND EFFECT" + args);
4076            }
4077    
4078            /**
4079             * Removes destination effect from an effect send.
4080             * @param channel The sampler channel number.
4081             * @param fxSend The numerical ID of the effect send entity.
4082             * @throws IOException If some I/O error occurs.
4083             * @throws LscpException If LSCP protocol corruption occurs.
4084             * @throws LSException If other error occurs.
4085             */
4086            public synchronized void
4087            removeFxSendEffect(int channel, int fxSend) throws IOException, LscpException, LSException {
4088                    String args = " " + channel + " " + fxSend;
4089                    retrieveIndex("REMOVE FX_SEND EFFECT" + args);
4090            }
4091            
4092            /**
4093             * Sets the MIDI controller, which will be able to modify
4094             * the send level of the specified effect send in the specified sampler channel.
4095             * @param channel The sampler channel number.
4096             * @param fxSend The numerical ID of the effect send entity.
4097             * @param midiCtrl The MIDI controller which shall be
4098             * able to modify the effect send's send level.
4099             * @throws IOException If some I/O error occurs.
4100             * @throws LscpException If LSCP protocol corruption occurs.
4101             * @throws LSException If
4102             * <ul>
4103             * <li><code>channel</code> is not a valid channel number;
4104             * <li><code>fxSend</code> is not a valid effect send ID;
4105             * <li><code>midiCtrl</code> is not a valid controller;
4106             * </ul>
4107             */
4108            public synchronized void
4109            setFxSendMidiController(int channel, int fxSend, int midiCtrl)
4110                                    throws IOException, LscpException, LSException
4111            {
4112                    String args = " " + channel + " " + fxSend + " " + midiCtrl;
4113                    retrieveIndex("SET FX_SEND MIDI_CONTROLLER" + args);
4114            }
4115            
4116            /**
4117             * Sets the current send level of the specified
4118             * effect send entity in the specified sampler channel.
4119             * @param channel The sampler channel number.
4120             * @param fxSend The numerical ID of the effect send entity.
4121             * @param volume The new volume value (a value smaller than 1.0 means
4122             * attenuation, whereas a value greater than 1.0 means amplification).
4123             * @throws IOException If some I/O error occurs.
4124             * @throws LscpException If LSCP protocol corruption occurs.
4125             * @throws LSException If some other error occurs.
4126             */
4127            public synchronized void
4128            setFxSendLevel(int channel, int fxSend, float volume)
4129                                    throws IOException, LscpException, LSException
4130            {
4131                    String args = " " + channel + " " + fxSend + " " + String.valueOf(volume);
4132                    retrieveIndex("SET FX_SEND LEVEL" + args);
4133            }
4134    
4135    
4136            /**
4137             * Gets the current amount of internal effects available to the sampler.
4138             * @return The current amount of internal effects available to the sampler.
4139             * @throws IOException If some I/O error occurs.
4140             * @throws LscpException If LSCP protocol corruption occurs.
4141             * @throws LSException If some other error occurs.
4142             */
4143            public synchronized int
4144            getEffectCount() throws IOException, LscpException, LSException
4145            { return retrieveInt("GET AVAILABLE_EFFECTS"); }
4146    
4147            /**
4148             * Gets the list of internal effects available to the sampler.
4149             * Note that the set of available internal effects can change at runtime.
4150             * @return An <code>Effect</code> array providing the current list of internal effects.
4151             * @throws IOException If some I/O error occurs.
4152             * @throws LscpException If LSCP protocol corruption occurs.
4153             */
4154            public synchronized Effect[]
4155            getEffects() throws IOException, LscpException, LSException {
4156                    Integer[] idS = getEffectIDs();
4157                    if(getPrintOnlyMode()) return null;
4158    
4159                    Effect[] effects = new Effect[idS.length];
4160    
4161                    for(int i = 0; i < effects.length; i++)
4162                            effects[i] = getEffectInfo(idS[i]);
4163    
4164                    return effects;
4165            }
4166    
4167            /**
4168             * Retrieves the list of available internal effects.
4169             * Note that the set of available internal effects can change at runtime.
4170             * @return An <code>Integer</code> array providing
4171             * the numerical IDs of all available internal effects.
4172             * @throws IOException If some I/O error occurs.
4173             * @throws LscpException If LSCP protocol corruption occurs.
4174             */
4175            public synchronized Integer[]
4176            getEffectIDs() throws IOException, LscpException, LSException
4177            { return getIntegerList("LIST AVAILABLE_EFFECTS"); }
4178    
4179            /**
4180             * Gets general informations about the specified effect.
4181             * @param effect The numerical ID of the effect entity.
4182             * @return <code>Effect</code> instance containing
4183             * general informations about the specified effect.
4184             * @throws IOException If an I/O error occurs.
4185             * @throws LscpException If LSCP protocol corruption occurs.
4186             * @throws LSException If the effect ID is invalid.
4187             */
4188            public synchronized Effect
4189            getEffectInfo(int effect) throws IOException, LscpException, LSException {
4190                    Effect e = new Effect();
4191                    if(!retrieveInfo("GET EFFECT INFO " + effect, e)) return null;
4192                    e.setEffectId(effect);
4193    
4194                    return e;
4195            }
4196    
4197            /**
4198             * Creates an instance of the desired effect.
4199             * @param id The unique ID of the effect.
4200             * @return The unique ID of the newly created effect instance.
4201             * @throws IOException If some I/O error occurs.
4202             * @throws LSException If the creation of the effect instance failed.
4203             * @throws LscpException If LSCP protocol corruption occurs.
4204             * @see #getEffectIDs
4205             * @see #getEffectInfo
4206             * @see #destroyEffectInstance
4207             */
4208            public synchronized int
4209            createEffectInstanceById(int id) throws IOException, LSException, LscpException
4210            { return retrieveIndex("CREATE EFFECT_INSTANCE " + String.valueOf(id)); }
4211    
4212            /**
4213             * Creates an instance of the desired effect.
4214             * @return The unique ID of the newly created effect instance.
4215             * @throws IOException If some I/O error occurs.
4216             * @throws LSException If the creation of the effect instance failed.
4217             * @throws LscpException If LSCP protocol corruption occurs.
4218             * @see #getEffectInfo
4219             * @see #destroyEffectInstance
4220             */
4221            public synchronized int
4222            createEffectInstance(Effect effect) throws IOException, LSException, LscpException
4223            { return createEffectInstanceById(effect.getEffectId()); }
4224    
4225            /**
4226             * Creates an instance of the desired effect.
4227             * @return The unique ID of the newly created effect instance.
4228             * @throws IOException If some I/O error occurs.
4229             * @throws LSException If the creation of the effect instance failed.
4230             * @throws LscpException If LSCP protocol corruption occurs.
4231             * @see #getEffectInfo
4232             * @see #destroyEffectInstance
4233             */
4234            public synchronized int
4235            createEffectInstance(String system, String module, String name)
4236                            throws IOException, LSException, LscpException
4237            {
4238                    String s = system + " '" + toEscapedText(module) + "' '" + toEscapedText(name) + "'";
4239                    return retrieveIndex("CREATE EFFECT_INSTANCE " + s);
4240            }
4241    
4242            /**
4243             * Destroys the specified unused effect instance.
4244             * @param instanceId The numerical ID of the effect instance.
4245             * @throws LscpException If LSCP protocol corruption occurs.
4246             * @throws LSException If some other error occurs.
4247             * @see #createEffectInstance
4248             */
4249            public synchronized void
4250            destroyEffectInstance(int instanceId) throws IOException, LSException, LscpException
4251            { retrieveIndex("DESTROY EFFECT_INSTANCE " + String.valueOf(instanceId)); }
4252            /**
4253             * Gets the current amount of effect instances available to the sampler.
4254             * @return The current amount of effect instances available to the sampler.
4255             * @throws IOException If some I/O error occurs.
4256             * @throws LscpException If LSCP protocol corruption occurs.
4257             * @throws LSException If some other error occurs.
4258             */
4259            public synchronized int
4260            getEffectInstanceCount() throws IOException, LscpException, LSException
4261            { return retrieveInt("GET EFFECT_INSTANCES"); }
4262    
4263            /**
4264             * Gets the current list of effect instances.
4265             * @return An <code>EffectInstanceInfo</code> array
4266             * providing the current list of effect instances.
4267             * @throws IOException If some I/O error occurs.
4268             * @throws LscpException If LSCP protocol corruption occurs.
4269             */
4270            public synchronized EffectInstanceInfo[]
4271            getEffectInstances() throws IOException, LscpException, LSException {
4272                    Integer[] idS = getEffectInscanceIDs();
4273                    if(getPrintOnlyMode()) return null;
4274    
4275                    EffectInstanceInfo[] eis = new EffectInstanceInfo[idS.length];
4276    
4277                    for(int i = 0; i < eis.length; i++)
4278                            eis[i] = getEffectInstanceInfo(idS[i]);
4279    
4280                    return eis;
4281            }
4282    
4283            /**
4284             * Retrieves the current list of effect instances.
4285             * @return An <code>Integer</code> array providing
4286             * the numerical IDs of all available effect instances.
4287             * @throws IOException If some I/O error occurs.
4288             * @throws LscpException If LSCP protocol corruption occurs.
4289             */
4290            public synchronized Integer[]
4291            getEffectInscanceIDs() throws IOException, LscpException, LSException
4292            { return getIntegerList("LIST EFFECT_INSTANCES"); }
4293    
4294            /**
4295             * Gets the current informations about the specified effect instance.
4296             * @param id The numerical ID of the effect instance.
4297             * @return <code>EffectInstanceInfo</code> object containing
4298             * the current informations about the specified effect instance.
4299             * @throws IOException If an I/O error occurs.
4300             * @throws LscpException If LSCP protocol corruption occurs.
4301             * @throws LSException If the effect instance ID is invalid.
4302             */
4303            public synchronized EffectInstanceInfo
4304            getEffectInstanceInfo(int id) throws IOException, LscpException, LSException {
4305                    EffectInstanceInfo ei = new EffectInstanceInfo();
4306                    if(!retrieveInfo("GET EFFECT_INSTANCE INFO " + id, ei)) return null;
4307                    ei.setInstanceId(id);
4308    
4309                    for(int i = 0; i < ei.getParameterCount(); i++) {
4310                            ei.addParameter(getEffectInstanceParameterInfo(id, i));
4311                    }
4312    
4313                    return ei;
4314            }
4315    
4316            /**
4317             * Gets information about the specified effect parameter.
4318             * @param id The numerical ID of the effect instance.
4319             * @param parameter The parameter index.
4320             * @return <code>EffectParameter</code> object containing
4321             * information about the specified effect parameter.
4322             * Note that only the following fields are used - description,
4323             * value, rangeMin, rangeMax, possibilities and default.
4324             * @throws IOException If an I/O error occurs.
4325             * @throws LscpException If LSCP protocol corruption occurs.
4326             * @throws LSException If the effect instance ID or the parameter index is invalid.
4327             */
4328            public synchronized EffectParameter
4329            getEffectInstanceParameterInfo(int instanceId, int parameter)
4330                                    throws IOException, LscpException, LSException
4331            {
4332                    EffectParameter prm = new EffectParameter(instanceId, parameter);
4333                    String s = String.valueOf(instanceId) + " " + String.valueOf(parameter);
4334                    if(!retrieveInfo("GET EFFECT_INSTANCE_INPUT_CONTROL INFO " + s, prm)) return null;
4335    
4336                    return prm;
4337            }
4338    
4339            /**
4340             * Alters the current value of an effect parameter.
4341             * @param instanceId The numerical ID of the effect instance.
4342             * @param prmIndex The index of the parameter to alter.
4343             * @param value The new value for this parameter.
4344             * @throws IOException If some I/O error occurs.
4345             * @throws LscpException If LSCP protocol corruption occurs.
4346             * @throws LSException If
4347             * <ul>
4348             * <li>There is no effect instance with numerical ID <code>instanceId</code>;
4349             * <li>There parameter index is invalid;
4350             * <li>The new value is out of range;
4351             * </ul>
4352             *
4353             * @see #getEffectInstanceInfo
4354             * @see #getEffectInstanceParameterInfo
4355             */
4356            public synchronized void
4357            setEffectInstanceParameter(int instanceId, int prmIndex, float value)
4358                                            throws IOException, LscpException, LSException
4359            {
4360                    String s = " " + instanceId + " " + prmIndex + " " + value;
4361                    retrieveIndex("SET EFFECT_INSTANCE_INPUT_CONTROL VALUE" + s);
4362            }
4363            /**
4364             * Gets the current amount of send effect chains on the specified audio output device.
4365             * @param audioDeviceId numerical ID of the audio output device.
4366             * @return The current amount of send effect chains or -1 if in "print only" mode.
4367             * @throws IOException If some I/O error occurs.
4368             * @throws LscpException If LSCP protocol corruption occurs.
4369             * @throws LSException If some other error occurs.
4370             */
4371            public synchronized int
4372            getSendEffectChainCount(int audioDeviceId) throws IOException, LscpException, LSException
4373            { return retrieveInt("GET SEND_EFFECT_CHAINS " + audioDeviceId); }
4374    
4375            /**
4376             * Gets the current list of send effect chains on the specified audio output device.
4377             * @param audioDeviceId The numerical ID of the audio output device.
4378             * @return An <code>EffectInstanceInfo</code> array
4379             * providing the current list of effect instances.
4380             * @throws IOException If some I/O error occurs.
4381             * @throws LscpException If LSCP protocol corruption occurs.
4382             */
4383            public synchronized EffectChainInfo[]
4384            getSendEffectChains(int audioDeviceId) throws IOException, LscpException, LSException {
4385                    Integer[] idS = getSendEffectChainIDs(audioDeviceId);
4386                    if(getPrintOnlyMode()) return null;
4387    
4388                    EffectChainInfo[] ecs = new EffectChainInfo[idS.length];
4389    
4390                    for(int i = 0; i < ecs.length; i++) {
4391                            ecs[i] = getSendEffectChainInfo(audioDeviceId, idS[i]);
4392                            ecs[i].setChainId(idS[i]);
4393                    }
4394    
4395                    return ecs;
4396            }
4397    
4398            /**
4399             * Retrieves the current list of send effect
4400             * chains on the specified audio output device.
4401             * @param audioDeviceId The numerical ID of the audio output device.
4402             * @return An <code>Integer</code> array providing the numerical
4403             * IDs of all send effect chains on the specified audio output device.
4404             * @throws IOException If some I/O error occurs.
4405             * @throws LscpException If LSCP protocol corruption occurs.
4406             */
4407            public synchronized Integer[]
4408            getSendEffectChainIDs(int audioDeviceId) throws IOException, LscpException, LSException
4409            { return getIntegerList("LIST SEND_EFFECT_CHAINS " + audioDeviceId); }
4410    
4411            /**
4412             * Adds a send effect chain to the specified audio output device.
4413             * @param audioDeviceId The numerical ID of the audio output device.
4414             * @return The numerical ID of the new send effect chain.
4415             * @throws IOException If some I/O error occurs.
4416             * @throws LSException If the creation of the effect chain failed.
4417             * @throws LscpException If LSCP protocol corruption occurs.
4418             * @see #removeSendEffectChain
4419             * @see #getSendEffectChainInfo
4420             */
4421            public synchronized int
4422            addSendEffectChain(int audioDeviceId) throws IOException, LSException, LscpException
4423            { return retrieveIndex("ADD SEND_EFFECT_CHAIN " + audioDeviceId); }
4424    
4425            /**
4426             * Removes a send effect chain from an audio output device.
4427             * @param audioDeviceId The numerical ID of the audio output device.
4428             * @param chainId The numerical ID of the send effect chain to remove.
4429             * @throws LscpException If LSCP protocol corruption occurs.
4430             * @throws LSException If some other error occurs.
4431             * @see #addSendEffectChain
4432             */
4433            public synchronized void
4434            removeSendEffectChain(int audioDeviceId, int chainId) throws IOException, LSException, LscpException
4435            { retrieveIndex("REMOVE SEND_EFFECT_CHAIN " + audioDeviceId + " " + chainId); }
4436    
4437            /**
4438             * Gets the current information of a send effect chain.
4439             * @param audioDeviceId The numerical ID of the audio output device.
4440             * @param chainId The numerical ID of the send effect chain.
4441             * @return <code>EffectChainInfo</code> object containing
4442             * the current informations about the specified effect chain.
4443             * @throws IOException If an I/O error occurs.
4444             * @throws LscpException If LSCP protocol corruption occurs.
4445             * @throws LSException If the audio device ID or the effect chain ID is invalid.
4446             */
4447            public synchronized EffectChainInfo
4448            getSendEffectChainInfo(int audioDeviceId, int chainId)
4449                                    throws IOException, LscpException, LSException
4450            {
4451                    verifyConnection();
4452                    String str = " " + audioDeviceId + " " + chainId;
4453                    out.writeLine("GET SEND_EFFECT_CHAIN INFO" + str);
4454                    if(getPrintOnlyMode()) return null;
4455    
4456                    ResultSet rs = getMultiLineResultSet();
4457                    EffectChainInfo chain = null;
4458    
4459                    for(String s : rs.getMultiLineResult()) {
4460                            if(s.startsWith("EFFECT_SEQUENCE: ")) {
4461                                    s = s.substring("EFFECT_SEQUENCE: ".length());
4462                                    Integer[] eis = parseIntList(s);
4463                                    EffectInstanceInfo[] instances = new EffectInstanceInfo[eis.length];
4464                                    for(int i = 0; i < eis.length; i++) {
4465                                            instances[i] = getEffectInstanceInfo(eis[i]);
4466                                    }
4467                                    chain = new EffectChainInfo(instances);
4468                                    chain.setChainId(chainId);
4469                            }
4470                    }
4471    
4472                    return chain;
4473            }
4474    
4475            /**
4476             * Adds an unused effect instance to the end of a send effect chain.
4477             * @param audioDeviceId The numerical ID of the audio output device.
4478             * @param chainId The numerical ID of the send effect chain.
4479             * @param fxInstanceId The numerical ID of the effect instance to add.
4480             * @throws IOException If some I/O error occurs.
4481             * @throws LSException If invalid index is specified.
4482             * @throws LscpException If LSCP protocol corruption occurs.
4483             * @see #addSendEffectChain
4484             * @see #createEffectInstance
4485             */
4486            public synchronized void
4487            appendEffectInstance(int audioDeviceId, int chainId, int fxInstanceId)
4488                            throws IOException, LSException, LscpException
4489            {
4490                    String s = " " + audioDeviceId + " " + chainId + " " + fxInstanceId;
4491                    retrieveIndex("APPEND SEND_EFFECT_CHAIN EFFECT" + s);
4492            }
4493    
4494            /**
4495             * Adds an unused effect instance at a certain position of a send effect chain.
4496             * @param audioDeviceId The numerical ID of the audio output device.
4497             * @param chainId The numerical ID of the send effect chain.
4498             * @param pos The exact position in the effect chain where
4499             * the supplied effect shall be inserted to.
4500             * @param fxInstanceId The numerical ID of the effect instance to insert.
4501             * @throws IOException If some I/O error occurs.
4502             * @throws LSException If invalid index is specified.
4503             * @throws LscpException If LSCP protocol corruption occurs.
4504             * @see #addSendEffectChain
4505             * @see #createEffectInstance
4506             */
4507            public synchronized void
4508            insertEffectInstance(int audioDeviceId, int chainId, int pos, int fxInstanceId)
4509                            throws IOException, LSException, LscpException
4510            {
4511                    String s = " " + audioDeviceId + " " + chainId + " " + pos + " " + fxInstanceId;
4512                    retrieveIndex("INSERT SEND_EFFECT_CHAIN EFFECT" + s);
4513            }
4514    
4515            /**
4516             * Removes an effect instance from a certain position of a send effect chain.
4517             * @param audioDeviceId The numerical ID of the audio output device.
4518             * @param chainId The numerical ID of the send effect chain.
4519             * @param pos The exact position of the effect
4520             * instance to be removed from the effect chain.
4521             * @throws IOException If some I/O error occurs.
4522             * @throws LscpException If LSCP protocol corruption occurs.
4523             * @throws LSException If invalid index is specified.
4524             * @see #appendEffectInstance
4525             * @see #insertEffectInstance
4526             */
4527            public synchronized void
4528            removeEffectInstanceFromChain(int audioDeviceId, int chainId, int pos)
4529                            throws IOException, LSException, LscpException
4530            {
4531                    String s = " " + audioDeviceId + " " + chainId + " " + pos;
4532                    retrieveIndex("REMOVE SEND_EFFECT_CHAIN EFFECT" + s);
4533            }
4534            
4535            /**
4536             * Starts an instrument editor for editing the loaded instrument
4537             * on the specified sampler channel.
4538             * @param samplerChn The sampler channel number.
4539             * @throws IOException If some I/O error occurs.
4540             * @throws LscpException If LSCP protocol corruption occurs.
4541             * @throws LSException If <code>samplerChn</code> is not a valid channel number or if
4542             * there is no instrument loaded on the specified sampler channel.
4543             * @see #getSamplerChannels
4544             */
4545            public synchronized void
4546            editChannelInstrument(int samplerChn) throws IOException, LscpException, LSException
4547            { retrieveIndex("EDIT CHANNEL INSTRUMENT " + samplerChn); }
4548            
4549            /**
4550             * Sends a MIDI event to this sampler channel.
4551             * @param samplerChn The sampler channel number.
4552             * @param type The type of MIDI message to send.
4553             * @throws IOException If some I/O error occurs.
4554             * @throws LscpException If LSCP protocol corruption occurs.
4555             * @throws LSException If <code>samplerChn</code> is not a valid channel number or if
4556             * there is no instrument loaded on the specified sampler channel.
4557             * @see #getSamplerChannels
4558             */
4559            public synchronized void
4560            sendChannelMidiData(int samplerChn, MidiDataEvent.Type type, int arg1, int arg2)
4561                                                    throws IOException, LscpException, LSException
4562            {
4563                    StringBuffer sb = new StringBuffer();
4564                    sb.append("SEND CHANNEL MIDI_DATA ");
4565                    sb.append(type).append(" ").append(samplerChn).append(" ");
4566                    sb.append(arg1).append(" ").append(arg2);
4567    
4568                    retrieveIndex(sb.toString());
4569          }          }
4570                    
4571          /**          /**
# Line 2355  public class Client { Line 4580  public class Client {
4580           * @see #getSamplerChannels           * @see #getSamplerChannels
4581           */           */
4582          public synchronized void          public synchronized void
4583          resetChannel(int samplerChn) throws IOException, LscpException, LSException {          resetChannel(int samplerChn) throws IOException, LscpException, LSException
4584            { retrieveIndex("RESET CHANNEL " + samplerChn); }
4585            
4586            
4587            
4588            /**
4589             * Adds the specified directory to the instruments database.
4590             * @param dir The absolute (escaped) path name of the directory to add.
4591             * @throws IOException If some I/O error occurs.
4592             * @throws LSException If the creation of the directory failed.
4593             * @throws LscpException If LSCP protocol corruption occurs.
4594             */
4595            public synchronized void
4596            addDbDirectory(String dir) throws IOException, LSException, LscpException
4597            { retrieveIndex("ADD DB_INSTRUMENT_DIRECTORY '" + conv(dir) + "'"); }
4598            
4599            /**
4600             * Removes the specified directory from the instruments database.
4601             * @param dir The absolute (escaped) path name of the directory to remove.
4602             * @throws IOException If some I/O error occurs.
4603             * @throws LscpException If LSCP protocol corruption occurs.
4604             * @throws LSException If the specified directory is not
4605             * empty or if the removal of the directory failed.
4606             */
4607            public synchronized void
4608            removeDbDirectory(String dir) throws IOException, LscpException, LSException
4609            { removeDbDirectory(dir, false); }
4610            
4611            /**
4612             * Removes the specified directory from the instruments database.
4613             * @param dir The absolute path name of the directory to remove.
4614             * @param force If <code>true</code> forces the removal of non-empty
4615             * directory and all its content.
4616             * @throws IOException If some I/O error occurs.
4617             * @throws LscpException If LSCP protocol corruption occurs.
4618             * @throws LSException If the removing of the directory failed.
4619             */
4620            public synchronized void
4621            removeDbDirectory(String dir, boolean force)
4622                                    throws IOException, LscpException, LSException
4623            {
4624                    String s = "REMOVE DB_INSTRUMENT_DIRECTORY ";
4625                    if(force) s += "FORCE ";
4626                    retrieveIndex(s + "'" + conv(dir) + "'");
4627            }
4628            
4629            /**
4630             * Removes the specified directories from the instruments database.
4631             * @param dirs The absolute (escaped) path names of the directories to remove.
4632             * @param force If <code>true</code> forces the removal of non-empty
4633             * directories.
4634             * @throws IOException If some I/O error occurs.
4635             * @throws LscpException If LSCP protocol corruption occurs.
4636             * @throws LSException If the removing of the directores failed.
4637             */
4638            public synchronized void
4639            removeDbDirectories(String[] dirs, boolean force)
4640                                    throws IOException, LscpException, LSException {
4641                    
4642                  verifyConnection();                  verifyConnection();
4643                  out.writeLine("RESET CHANNEL " + samplerChn);                  String cmd = "REMOVE DB_INSTRUMENT_DIRECTORY ";
4644                    if(force) cmd += "FORCE ";
4645                                    
4646                  ResultSet rs = getEmptyResultSet();                  for(String s : dirs) out.writeLine(cmd + "'" + conv(s) + "'");
4647                    
4648                    if(getPrintOnlyMode()) return;
4649                    
4650                    getEmptyResultSets(dirs.length, "Client.dirDeletionFailed!");
4651            }
4652            
4653            /**
4654             * Gets the number of directories in the specified directory.
4655             * @return The current number of directories in the specified directory.
4656             * @param dir The absolute path name of the directory.
4657             * @throws IOException If some I/O error occurs.
4658             * @throws LscpException If LSCP protocol corruption occurs.
4659             * @throws LSException If some other error occurs.
4660             */
4661            public synchronized int
4662            getDbDirectoryCount(String dir) throws IOException, LscpException, LSException {
4663                    return getDbDirectoryCount(dir, false);
4664            }
4665            
4666            /**
4667             * Gets the number of directories in the specified directory.
4668             * @return The current number of directories in the specified directory.
4669             * @param dir The absolute path name of the directory.
4670             * @param recursive If <code>true</code>, the number of all directories
4671             * in the specified subtree will be returned.
4672             * @throws IOException If some I/O error occurs.
4673             * @throws LscpException If LSCP protocol corruption occurs.
4674             * @throws LSException If some other error occurs.
4675             */
4676            public synchronized int
4677            getDbDirectoryCount(String dir, boolean recursive)
4678                                    throws IOException, LscpException, LSException {
4679                    
4680                    verifyConnection();
4681                    String s;
4682                    if(recursive) s = "GET DB_INSTRUMENT_DIRECTORIES RECURSIVE '";
4683                    else s = "GET DB_INSTRUMENT_DIRECTORIES '";
4684                    out.writeLine(s + conv(dir) + "'");
4685                    if(getPrintOnlyMode()) return -1;
4686                    
4687                    s = getSingleLineResultSet().getResult();
4688                    return parseInt(s);
4689            }
4690            
4691            /**
4692             * Gets the list of directories in the specified directory.
4693             * @param dir The absolute path name of the directory.
4694             * @return A <code>String</code> array providing the names of
4695             * all directories in the specified directory.
4696             * @throws IOException If some I/O error occurs.
4697             * @throws LscpException If LSCP protocol corruption occurs.
4698             * @throws LSException If the specified path name is invalid.
4699             */
4700            public synchronized String[]
4701            getDbDirectoryNames(String dir) throws IOException, LscpException, LSException {
4702                    verifyConnection();
4703                    out.writeLine("LIST DB_INSTRUMENT_DIRECTORIES '" + conv(dir) + "'");
4704                    if(getPrintOnlyMode()) return null;
4705                    
4706                    String[] names = parseEscapedStringList(getSingleLineResultSet().getResult());
4707                    for(int i = 0; i < names.length; i++) {
4708                            names[i] = toNonEscapedString(names[i]);
4709                    }
4710                    return names;
4711            }
4712            
4713            /**
4714             * Gets information about the specified directory.
4715             * @param dir The absolute path name of the directory.
4716             * @return A <code>DbDirectoryInfo</code> instance providing information
4717             * about the specified directory.
4718             * @throws IOException If some I/O error occurs.
4719             * @throws LscpException If LSCP protocol corruption occurs.
4720             * @throws LSException If the specified directory is not found.
4721             */
4722            public synchronized DbDirectoryInfo
4723            getDbDirectoryInfo(String dir) throws IOException, LscpException, LSException {
4724                    DbDirectoryInfo info = new DbDirectoryInfo();
4725                    if(!retrieveInfo("GET DB_INSTRUMENT_DIRECTORY INFO '" + conv(dir) + "'", info)) return null;
4726    
4727                    if(dir.equals("/")) {
4728                            info.setName("/");
4729                    } else {
4730                            dir = removeEndingFileSeparator(dir);
4731                    }
4732                    String s = getFileName(dir);
4733                    if(s != null) info.setName(toNonEscapedFileName(s));
4734                    s = getParentDirectory(dir);
4735                    if(s != null) info.setParentDirectoryPath(s);
4736                    
4737                    return info;
4738            }
4739            
4740            /**
4741             * Gets the list of directories in the specified directory.
4742             * @param dir The absolute path name of the directory.
4743             * @return A <code>DbDirectoryInfo</code> array providing
4744             * information about all directories in the specified directory.
4745             * @throws IOException If some I/O error occurs.
4746             * @throws LscpException If LSCP protocol corruption occurs.
4747             * @throws LSException If the specified path name is invalid.
4748             */
4749            public synchronized DbDirectoryInfo[]
4750            getDbDirectories(String dir) throws IOException, LscpException, LSException {
4751                    String[] dirS = getDbDirectoryNames(dir);
4752                    if(!hasEndingFileSeparator(dir)) dir += "/";
4753                    DbDirectoryInfo[] infoS = new DbDirectoryInfo[dirS.length];
4754                    for(int i = 0; i < dirS.length; i++) {
4755                            infoS[i] = getDbDirectoryInfo(conv(dir) + toEscapedFsEntry(dirS[i]));
4756                    }
4757                    return infoS;
4758            }
4759            
4760            /**
4761             * Gets the list of directories in the specified directory.
4762             * @param dir The absolute path name of the directory.
4763             * @return A <code>DbDirectoryInfo</code> array providing
4764             * information about all directories in the specified directory.
4765             * @throws IOException If some I/O error occurs.
4766             * @throws LscpException If LSCP protocol corruption occurs.
4767             * @throws LSException If the specified path name is invalid.
4768             *
4769            public synchronized DbDirectoryInfo[]
4770            getDbDirectories(String dir) throws IOException, LscpException, LSException {
4771                    String[] dirS = getDbDirectoryNames(conv(dir));
4772                    if(dirS.length == 0) return new DbDirectoryInfo[0];
4773                    
4774                    if(dir.charAt(dir.length() - 1) != '/') dir += "/"; // FIXME:
4775                    
4776                    for(int i = 0; i < dirS.length; i++) {
4777                            out.writeLine("GET DB_INSTRUMENT_DIRECTORY INFO '" + conv(dir + dirS[i]) + "'");
4778                    }
4779                    
4780                    if(getPrintOnlyMode()) return null;
4781                    
4782                    if(dir.length() > 1) dir = dir.substring(0, dir.length() - 1);
4783                    StringBuffer sb = new StringBuffer();
4784                    DbDirectoryInfo[] infoS = new DbDirectoryInfo[dirS.length];
4785                    for(int i = 0; i < dirS.length; i++) {
4786                            try {
4787                                    ResultSet rs = getMultiLineResultSet();
4788                                    infoS[i] = new DbDirectoryInfo(rs.getMultiLineResult());
4789                                    infoS[i].setName(dirS[i]);
4790                                    infoS[i].setParentDirectoryPath(dir);
4791                            } catch (SocketTimeoutException e) {
4792                                    getLogger().log(Level.FINE, e.getMessage(), e);
4793                                    sb.append(e.getMessage()).append("\n");
4794                                    break;
4795                            } catch (Exception e) {
4796                                    getLogger().log(Level.FINE, e.getMessage(), e);
4797                                    sb.append(e.getMessage()).append("\n");
4798                            }
4799                    }
4800                    
4801                    String details = sb.toString();
4802                    if(details.length() > 0) {
4803                            String err = LscpI18n.getLogMsg("Client.getInstrsInfoFailed!");
4804                            throw new LSException(0, err, details);
4805                    }
4806                    
4807                    return infoS;
4808            }*/
4809            
4810            /**
4811             * Renames the specified directory.
4812             * @param dir The absolute path name of the directory to rename.
4813             * @param name The new name for the directory.
4814             * @throws IOException If some I/O error occurs.
4815             * @throws LSException If the renaming of the directory failed.
4816             * @throws LscpException If LSCP protocol corruption occurs.
4817             */
4818            public synchronized void
4819            renameDbDirectory(String dir, String name) throws IOException, LSException, LscpException {
4820                    name = toEscapedText(name);
4821                    retrieveIndex("SET DB_INSTRUMENT_DIRECTORY NAME '" + conv(dir) + "' '" + conv(name) + "'");
4822            }
4823            
4824            /**
4825             * Moves the specified directory into the specified location.
4826             * @param dir The absolute path name of the directory to move.
4827             * @param dst The location where the directory will be moved to.
4828             * @throws IOException If some I/O error occurs.
4829             * @throws LSException If the operation failed.
4830             * @throws LscpException If LSCP protocol corruption occurs.
4831             */
4832            public synchronized void
4833            moveDbDirectory(String dir, String dst) throws IOException, LSException, LscpException
4834            { retrieveIndex("MOVE DB_INSTRUMENT_DIRECTORY '" + conv(dir) + "' '" + conv(dst) + "'"); }
4835            
4836            /**
4837             * Moves the specified directories into the specified location.
4838             * @param dirs The absolute path names of the directories to move.
4839             * @param dst The location where the directories will be moved to.
4840             * @throws IOException If some I/O error occurs.
4841             * @throws LSException If the operation failed.
4842             * @throws LscpException If LSCP protocol corruption occurs.
4843             */
4844            public synchronized void
4845            moveDbDirectories(String dirs[], String dst) throws IOException, LSException, LscpException {
4846                    verifyConnection();
4847                    for(String s : dirs) {
4848                            out.writeLine("MOVE DB_INSTRUMENT_DIRECTORY '" + conv(s) + "' '" + conv(dst) + "'");
4849                    }
4850                    if(getPrintOnlyMode()) return;
4851                    
4852                    getEmptyResultSets(dirs.length, "Client.dirMovingFailed!");
4853            }
4854            
4855            /**
4856             * Copies the specified directory into the specified location.
4857             * @param dir The absolute path name of the directory to copy.
4858             * @param dst The location where the directory will be copied to.
4859             * @throws IOException If some I/O error occurs.
4860             * @throws LSException If the operation failed.
4861             * @throws LscpException If LSCP protocol corruption occurs.
4862             */
4863            public synchronized void
4864            copyDbDirectory(String dir, String dst) throws IOException, LSException, LscpException
4865            { retrieveIndex("COPY DB_INSTRUMENT_DIRECTORY '" + conv(dir) + "' '" + conv(dst) + "'"); }
4866            
4867            /**
4868             * Copies the specified directories into the specified location.
4869             * @param dirs The absolute path names of the directories to copy.
4870             * @param dst The location where the directories will be copied to.
4871             * @throws IOException If some I/O error occurs.
4872             * @throws LSException If the operation failed.
4873             * @throws LscpException If LSCP protocol corruption occurs.
4874             */
4875            public synchronized void
4876            copyDbDirectories(String[] dirs, String dst) throws IOException, LSException, LscpException {
4877                    verifyConnection();
4878                    for(String s : dirs) {
4879                            out.writeLine("COPY DB_INSTRUMENT_DIRECTORY '" + conv(s) + "' '" + conv(dst) + "'");
4880                    }
4881                    if(getPrintOnlyMode()) return;
4882                    
4883                    getEmptyResultSets(dirs.length, "Client.dirCopyingFailed!");
4884            }
4885            
4886            /**
4887             * Changes the description of the specified directory.
4888             * @param dir The absolute path name of the directory.
4889             * @param desc The new description for the directory.
4890             * @throws IOException If some I/O error occurs.
4891             * @throws LSException If failed to change the description.
4892             * @throws LscpException If LSCP protocol corruption occurs.
4893             */
4894            public synchronized void
4895            setDbDirectoryDescription(String dir, String desc)
4896                                    throws IOException, LSException, LscpException
4897            {
4898                    String s = "SET DB_INSTRUMENT_DIRECTORY DESCRIPTION '";
4899                    retrieveIndex(s + conv(dir) + "' '" + toEscapedText(desc) + "'");
4900            }
4901            
4902            public static enum ScanMode {
4903                    RECURSIVE, NON_RECURSIVE, FLAT
4904            }
4905            
4906            /**
4907             * Adds the specified instrument to the specified instruments database directory.
4908             * @param dbDir The absolute path name of the database directory in which the
4909             * specified instrument will be added.
4910             * @param filePath The absolute path name of the instrument file.
4911             * @param instrIndex The index of the instrument (in the given instrument file) to add.
4912             * @throws IOException If some I/O error occurs.
4913             * @throws LSException If the operation failed.
4914             * @throws LscpException If LSCP protocol corruption occurs.
4915             */
4916            public synchronized void
4917            addDbInstrument(String dbDir, String filePath, int instrIndex)
4918                                            throws IOException, LSException, LscpException {
4919                    
4920                    addDbInstrument(dbDir, filePath, instrIndex, false);
4921            }
4922            
4923            /**
4924             * Adds the specified instrument to the specified instruments database directory.
4925             * @param dbDir The absolute path name of the database directory in which the
4926             * specified instrument will be added.
4927             * @param filePath The absolute path name of the instrument file.
4928             * @param instrIndex The index of the instrument (in the given instrument file) to add.
4929             * @param background If <code>true</code>, the scan will be done
4930             * in background and this method may return before the job is finished.
4931             * @return If <code>background</code> is <code>true</code>, the ID
4932             * of the scan job.
4933             * @throws IOException If some I/O error occurs.
4934             * @throws LSException If the operation failed.
4935             * @throws LscpException If LSCP protocol corruption occurs.
4936             * @see #addInstrumentsDbListener
4937             */
4938            public synchronized int
4939            addDbInstrument(String dbDir, String filePath, int instrIndex, boolean background)
4940                                            throws IOException, LSException, LscpException
4941            {
4942                    String s = "ADD DB_INSTRUMENTS";
4943                    if(background) s += " NON_MODAL";
4944                    s += " '" + conv(dbDir) + "' '" + conv(filePath) + "' ";
4945                    return retrieveIndex(s + String.valueOf(instrIndex));
4946            }
4947            
4948            /**
4949             * Adds the instruments in the specified file to the specified
4950             * instruments database directory.
4951             * @param dbDir The absolute path name of the database directory
4952             * in which the the supported instruments will be added.
4953             * @param filePath The absolute path name of the file to scan for instruments.
4954             * @throws IOException If some I/O error occurs.
4955             * @throws LSException If the operation failed.
4956             * @throws LscpException If LSCP protocol corruption occurs.
4957             */
4958            public synchronized void
4959            addDbInstruments(String dbDir, String filePath)
4960                                            throws IOException, LSException, LscpException {
4961                    
4962                    addDbInstruments(dbDir, filePath, false);
4963            }
4964            
4965            /**
4966             * Adds the instruments in the specified file to the specified
4967             * instruments database directory.
4968             * @param dbDir The absolute path name of the database directory
4969             * in which the the supported instruments will be added.
4970             * @param filePath The absolute path name of the file to scan for instruments.
4971             * @param background If <code>true</code>, the scan will be done
4972             * in background and this method may return before the job is finished.
4973             * @return If <code>background</code> is <code>true</code>, the ID
4974             * of the scan job.
4975             * @throws IOException If some I/O error occurs.
4976             * @throws LSException If the operation failed.
4977             * @throws LscpException If LSCP protocol corruption occurs.
4978             * @see #addInstrumentsDbListener
4979             */
4980            public synchronized int
4981            addDbInstruments(String dbDir, String filePath, boolean background)
4982                                            throws IOException, LSException, LscpException
4983            {
4984                    String s = "ADD DB_INSTRUMENTS";
4985                    if(background) s += " NON_MODAL";
4986                    return retrieveIndex(s + " '" + conv(dbDir) + "' '" + conv(filePath) + "'");
4987            }
4988            
4989            /**
4990             * Adds the instruments in the specified file system directory
4991             * to the specified instruments database directory.
4992             * @param mode Determines the scanning mode. If RECURSIVE is
4993             * specified, all supported instruments in the specified file system
4994             * direcotry will be added to the specified instruments database
4995             * directory, including the instruments in subdirectories
4996             * of the supplied directory. If NON_RECURSIVE is specified,
4997             * the instruments in the subdirectories will not be processed.
4998             * If FLAT is specified, all supported instruments in the specified
4999             * file system direcotry will be added, including the instruments in
5000             * subdirectories of the supplied directory, but the respective
5001             * subdirectory structure will not be recreated in the instruments
5002             * database and all instruments will be added directly in the
5003             * specified database directory.
5004             * @param dbDir The absolute path name of the database directory
5005             * in which the supported instruments will be added.
5006             * @param fsDir The absolute path name of the file system directory.
5007             * @throws IOException If some I/O error occurs.
5008             * @throws LSException If the operation failed.
5009             * @throws LscpException If LSCP protocol corruption occurs.
5010             */
5011            public synchronized void
5012            addDbInstruments(ScanMode mode, String dbDir, String fsDir)
5013                                            throws IOException, LSException, LscpException {
5014                    
5015                    addDbInstruments(mode, dbDir, fsDir, false);
5016            }
5017            
5018            /**
5019             * Adds the instruments in the specified file system directory
5020             * to the specified instruments database directory.
5021             * @param mode Determines the scanning mode. If RECURSIVE is
5022             * specified, all supported instruments in the specified file system
5023             * direcotry will be added to the specified instruments database
5024             * directory, including the instruments in subdirectories
5025             * of the supplied directory. If NON_RECURSIVE is specified,
5026             * the instruments in the subdirectories will not be processed.
5027             * If FLAT is specified, all supported instruments in the specified
5028             * file system direcotry will be added, including the instruments in
5029             * subdirectories of the supplied directory, but the respective
5030             * subdirectory structure will not be recreated in the instruments
5031             * database and all instruments will be added directly in the
5032             * specified database directory.
5033             * @param dbDir The absolute path name of the database directory
5034             * in which the supported instruments will be added.
5035             * @param fsDir The absolute path name of the file system directory.
5036             * @param background If <code>true</code>, the scan will be done
5037             * in background and this method may return before the job is finished.
5038             * @return If <code>background</code> is <code>true</code>, the ID
5039             * of the scan job.
5040             * @throws IOException If some I/O error occurs.
5041             * @throws LSException If the operation failed.
5042             * @throws LscpException If LSCP protocol corruption occurs.
5043             * @see #addInstrumentsDbListener
5044             */
5045            public synchronized int
5046            addDbInstruments(ScanMode mode, String dbDir, String fsDir, boolean background)
5047                                            throws IOException, LSException, LscpException {
5048                    
5049                    return addDbInstruments(mode, dbDir, fsDir, background, false);
5050            }
5051            
5052            /**
5053             * Adds the instruments in the specified file system directory
5054             * to the specified instruments database directory.
5055             * @param mode Determines the scanning mode. If RECURSIVE is
5056             * specified, all supported instruments in the specified file system
5057             * direcotry will be added to the specified instruments database
5058             * directory, including the instruments in subdirectories
5059             * of the supplied directory. If NON_RECURSIVE is specified,
5060             * the instruments in the subdirectories will not be processed.
5061             * If FLAT is specified, all supported instruments in the specified
5062             * file system direcotry will be added, including the instruments in
5063             * subdirectories of the supplied directory, but the respective
5064             * subdirectory structure will not be recreated in the instruments
5065             * database and all instruments will be added directly in the
5066             * specified database directory.
5067             * @param dbDir The absolute path name of the database directory
5068             * in which the supported instruments will be added.
5069             * @param fsDir The absolute path name of the file system directory.
5070             * @param background If <code>true</code>, the scan will be done
5071             * in background and this method may return before the job is finished.
5072             * @param insDir If <code>true</code> a drieectory is created for each
5073             * instrument file.
5074             * @return If <code>background</code> is <code>true</code>, the ID
5075             * of the scan job.
5076             * @throws IOException If some I/O error occurs.
5077             * @throws LSException If the operation failed.
5078             * @throws LscpException If LSCP protocol corruption occurs.
5079             * @see #addInstrumentsDbListener
5080             */
5081            public synchronized int
5082            addDbInstruments(ScanMode mode, String dbDir, String fsDir, boolean background, boolean insDir)
5083                                            throws IOException, LSException, LscpException
5084            {
5085                    StringBuffer sb = new StringBuffer("ADD DB_INSTRUMENTS");
5086                    if(background) sb.append(" NON_MODAL");
5087                    
5088                    switch(mode) {
5089                            case RECURSIVE:
5090                                    sb.append(" RECURSIVE");
5091                                    break;
5092                            case NON_RECURSIVE:
5093                                    sb.append(" NON_RECURSIVE");
5094                                    break;
5095                            case FLAT:
5096                                    sb.append(" FLAT");
5097                                    break;
5098                    }
5099                    if(insDir)
5100                            sb.append(" FILE_AS_DIR");
5101                    
5102                    sb.append(" '").append(conv(dbDir)).append("' '");
5103                    sb.append(conv(fsDir)).append("'");
5104                    return retrieveIndex(sb.toString());
5105            }
5106    
5107            /**
5108             * Removes the specified instrument from the instruments database.
5109             * @param instr The absolute path name of the instrument to remove.
5110             * @throws IOException If some I/O error occurs.
5111             * @throws LscpException If LSCP protocol corruption occurs.
5112             * @throws LSException If the removing of the instrument failed.
5113             */
5114            public synchronized void
5115            removeDbInstrument(String instr) throws IOException, LscpException, LSException
5116            { retrieveIndex("REMOVE DB_INSTRUMENT '" + conv(instr) + "'"); }
5117            
5118            /**
5119             * Removes the specified instruments from the instruments database.
5120             * @param instrs The absolute path names of the instruments to remove.
5121             * @throws IOException If some I/O error occurs.
5122             * @throws LscpException If LSCP protocol corruption occurs.
5123             * @throws LSException If the removing of the instruments failed.
5124             */
5125            public synchronized void
5126            removeDbInstruments(String[] instrs) throws IOException, LscpException, LSException {
5127                    verifyConnection();
5128                    for(String s : instrs) {
5129                            out.writeLine("REMOVE DB_INSTRUMENT '" + conv(s) + "'");
5130                    }
5131                    if(getPrintOnlyMode()) return;
5132                    
5133                    getEmptyResultSets(instrs.length, "Client.instrDeletionFailed!");
5134          }          }
5135                    
5136          /**          /**
5137             * Gets the number of instruments in the specified directory.
5138             * @return The current number of instruments in the specified directory.
5139             * @param dir The absolute path name of the directory.
5140             * @throws IOException If some I/O error occurs.
5141             * @throws LscpException If LSCP protocol corruption occurs.
5142             * @throws LSException If some other error occurs.
5143             */
5144            public synchronized int
5145            getDbInstrumentCount(String dir) throws IOException, LscpException, LSException {
5146                    return getDbInstrumentCount(dir, false);
5147            }
5148            
5149            /**
5150             * Gets the number of instruments in the specified directory.
5151             * @return The current number of instruments in the specified directory.
5152             * @param dir The absolute path name of the directory.
5153             * @param recursive If <code>true</code>, the number of all instruments
5154             * in the specified subtree will be returned.
5155             * @throws IOException If some I/O error occurs.
5156             * @throws LscpException If LSCP protocol corruption occurs.
5157             * @throws LSException If some other error occurs.
5158             */
5159            public synchronized int
5160            getDbInstrumentCount(String dir, boolean recursive)
5161                                    throws IOException, LscpException, LSException {
5162                    
5163                    verifyConnection();
5164                    String s;
5165                    if(recursive) s = "GET DB_INSTRUMENTS RECURSIVE '";
5166                    else s = "GET DB_INSTRUMENTS '";
5167                    out.writeLine(s + conv(dir) + "'");
5168                    if(getPrintOnlyMode()) return -1;
5169                    
5170                    s = getSingleLineResultSet().getResult();
5171                    return parseInt(s);
5172            }
5173            
5174            /**
5175             * Gets the list of instruments in the specified directory.
5176             * @param dir The absolute path name of the directory.
5177             * @return A <code>String</code> array providing the names of
5178             * all instruments in the specified directory.
5179             * @throws IOException If some I/O error occurs.
5180             * @throws LscpException If LSCP protocol corruption occurs.
5181             * @throws LSException If the specified path name is invalid.
5182             */
5183            public synchronized String[]
5184            getDbInstrumentNames(String dir) throws IOException, LscpException, LSException {
5185                    verifyConnection();
5186                    out.writeLine("LIST DB_INSTRUMENTS '" + conv(dir) + "'");
5187                    if(getPrintOnlyMode()) return null;
5188                    
5189                    String[] names = parseEscapedStringList(getSingleLineResultSet().getResult());
5190                    for(int i = 0; i < names.length; i++) {
5191                            names[i] = toNonEscapedString(names[i]);
5192                    }
5193                    return names;
5194            }
5195            
5196            /**
5197             * Gets information about the specified instrument.
5198             * @param instr The absolute path name of the instrument.
5199             * @return A <code>DbInstrumentInfo</code> instance providing information
5200             * about the specified instrument.
5201             * @throws IOException If some I/O error occurs.
5202             * @throws LscpException If LSCP protocol corruption occurs.
5203             * @throws LSException If the specified instrument is not found.
5204             */
5205            public synchronized DbInstrumentInfo
5206            getDbInstrumentInfo(String instr) throws IOException, LscpException, LSException {
5207                    DbInstrumentInfo info = new DbInstrumentInfo();
5208                    if(!retrieveInfo("GET DB_INSTRUMENT INFO '" + conv(instr) + "'", info)) return null;
5209    
5210                    String s = getParentDirectory(instr);
5211                    if(s != null) info.setDirectoryPath(s);
5212                    s = getFileName(instr);
5213                    if(s != null) info.setName(toNonEscapedFileName(s));
5214                    
5215                    return info;
5216            }
5217            
5218            /**
5219             * Gets the list of instruments in the specified directory.
5220             * @param dir The absolute path name of the directory.
5221             * @return A <code>DbInstrumentInfo</code> array providing
5222             * information about all instruments in the specified directory.
5223             * @throws IOException If some I/O error occurs.
5224             * @throws LscpException If LSCP protocol corruption occurs.
5225             * @throws LSException If the specified path name is invalid.
5226             */
5227            public synchronized DbInstrumentInfo[]
5228            getDbInstruments(String dir) throws IOException, LscpException, LSException {
5229                    String[] instrS = getDbInstrumentNames(dir);
5230                    if(!hasEndingFileSeparator(dir)) dir += "/";
5231                    
5232                    DbInstrumentInfo[] infoS = new DbInstrumentInfo[instrS.length];
5233                    for(int i = 0; i < instrS.length; i++) {
5234                            infoS[i] = getDbInstrumentInfo(conv(dir) + toEscapedFsEntry(instrS[i]));
5235                    }
5236                    return infoS;
5237            }
5238            
5239            /**
5240             * Gets the list of instruments in the specified directory.
5241             * @param dir The absolute path name of the directory.
5242             * @return A <code>DbInstrumentInfo</code> array providing
5243             * information about all instruments in the specified directory.
5244             * @throws IOException If some I/O error occurs.
5245             * @throws LscpException If LSCP protocol corruption occurs.
5246             * @throws LSException If the specified path name is invalid.
5247             *
5248            public synchronized DbInstrumentInfo[]
5249            getDbInstruments(String dir) throws IOException, LscpException, LSException {
5250                    String[] instrS = getDbInstrumentNames(dir);
5251                    if(instrS.length == 0) return new DbInstrumentInfo[0];
5252                    
5253                    if(dir.charAt(dir.length() - 1) != '/') dir += "/"; FIXME:
5254                    
5255                    for(int i = 0; i < instrS.length; i++) {
5256                            out.writeLine("GET DB_INSTRUMENT INFO '" + conv(dir) + instrS[i] + "'");
5257                    }
5258                    
5259                    if(getPrintOnlyMode()) return null;
5260                    
5261                    if(dir.length() > 1) dir = dir.substring(0, dir.length() - 1);
5262                    StringBuffer sb = new StringBuffer();
5263                    DbInstrumentInfo[] infoS = new DbInstrumentInfo[instrS.length];
5264                    for(int i = 0; i < instrS.length; i++) {
5265                            try {
5266                                    ResultSet rs = getMultiLineResultSet();
5267                                    infoS[i] = new DbInstrumentInfo(rs.getMultiLineResult());
5268                                    infoS[i].setName(instrS[i]);
5269                                    infoS[i].setDirectoryPath(dir);
5270                            } catch (SocketTimeoutException e) {
5271                                    getLogger().log(Level.FINE, e.getMessage(), e);
5272                                    sb.append(e.getMessage()).append("\n");
5273                                    break;
5274                            } catch (Exception e) {
5275                                    getLogger().log(Level.FINE, e.getMessage(), e);
5276                                    sb.append(e.getMessage()).append("\n");
5277                            }
5278                    }
5279                    
5280                    String details = sb.toString();
5281                    if(details.length() > 0) {
5282                            String err = LscpI18n.getLogMsg("Client.getInstrsInfoFailed!");
5283                            throw new LSException(0, err, details);
5284                    }
5285                    
5286                    return infoS;
5287            }*/
5288            
5289            /**
5290             * Renames the specified instrument.
5291             * @param instr The absolute path name of the instrument to rename.
5292             * @param name The new name for the instrument.
5293             * @throws IOException If some I/O error occurs.
5294             * @throws LSException If the renaming of the instrument failed.
5295             * @throws LscpException If LSCP protocol corruption occurs.
5296             */
5297            public synchronized void
5298            renameDbInstrument(String instr, String name)
5299                                    throws IOException, LSException, LscpException
5300            {
5301                    name = toEscapedText(name);
5302                    retrieveIndex("SET DB_INSTRUMENT NAME '" + conv(instr) + "' '" + conv(name) + "'");
5303            }
5304            
5305            /**
5306             * Moves the specified instrument into the specified location.
5307             * @param instr The absolute path name of the instrument to move.
5308             * @param dst The directory where the specified instrument will be moved to.
5309             * @throws IOException If some I/O error occurs.
5310             * @throws LSException If the operation failed.
5311             * @throws LscpException If LSCP protocol corruption occurs.
5312             */
5313            public synchronized void
5314            moveDbInstrument(String instr, String dst) throws IOException, LSException, LscpException
5315            { retrieveIndex("MOVE DB_INSTRUMENT '" + conv(instr) + "' '" + conv(dst) + "'"); }
5316            
5317            /**
5318             * Moves the specified instruments into the specified location.
5319             * @param instrs The absolute path names of the instruments to move.
5320             * @param dst The directory where the specified instruments will be moved to.
5321             * @throws IOException If some I/O error occurs.
5322             * @throws LSException If the operation failed.
5323             * @throws LscpException If LSCP protocol corruption occurs.
5324             */
5325            public synchronized void
5326            moveDbInstruments(String[] instrs, String dst) throws IOException, LSException, LscpException {
5327                    verifyConnection();
5328                    for(String s : instrs) {
5329                            out.writeLine("MOVE DB_INSTRUMENT '" + conv(s) + "' '" + conv(dst) + "'");
5330                    }
5331                    if(getPrintOnlyMode()) return;
5332                    
5333                    getEmptyResultSets(instrs.length, "Client.instrMovingFailed!");
5334            }
5335            
5336            /**
5337             * Copies the specified instrument into the specified location.
5338             * @param instr The absolute path name of the instrument to copy.
5339             * @param dst The directory where the specified instrument will be copied to.
5340             * @throws IOException If some I/O error occurs.
5341             * @throws LSException If the operation failed.
5342             * @throws LscpException If LSCP protocol corruption occurs.
5343             */
5344            public synchronized void
5345            copyDbInstrument(String instr, String dst) throws IOException, LSException, LscpException
5346            { retrieveIndex("COPY DB_INSTRUMENT '" + conv(instr) + "' '" + conv(dst) + "'"); }
5347            
5348            /**
5349             * Copies the specified instruments into the specified location.
5350             * @param instrs The absolute path name of the instruments to copy.
5351             * @param dst The directory where the specified instruments will be copied to.
5352             * @throws IOException If some I/O error occurs.
5353             * @throws LSException If the operation failed.
5354             * @throws LscpException If LSCP protocol corruption occurs.
5355             */
5356            public synchronized void
5357            copyDbInstruments(String[] instrs, String dst) throws IOException, LSException, LscpException {
5358                    verifyConnection();
5359                    for(String s : instrs) {
5360                            out.writeLine("COPY DB_INSTRUMENT '" + conv(s) + "' '" + conv(dst) + "'");
5361                    }
5362                    if(getPrintOnlyMode()) return;
5363                    
5364                    getEmptyResultSets(instrs.length, "Client.instrCopyingFailed!");
5365            }
5366            
5367            /**
5368             * Changes the description of the specified instrument.
5369             * @param instr The absolute path name of the instrument.
5370             * @param desc The new description for the instrument.
5371             * @throws IOException If some I/O error occurs.
5372             * @throws LSException If failed to change the description.
5373             * @throws LscpException If LSCP protocol corruption occurs.
5374             */
5375            public synchronized void
5376            setDbInstrumentDescription(String instr, String desc)
5377                                    throws IOException, LSException, LscpException
5378            {
5379                    desc = toEscapedText(desc);
5380                    retrieveIndex("SET DB_INSTRUMENT DESCRIPTION '" + conv(instr) + "' '" + desc + "'");
5381            }
5382            
5383            /**
5384             * Substitutes all occurrences of the instrument file
5385             * <code>oldPath</code> in the database, with <code>newPath</code>.
5386             * @param oldPath The absolute path name of the instrument file to substitute.
5387             * @param newPath The new absolute path name.
5388             * @throws IOException If some I/O error occurs.
5389             * @throws LSException If the operation failed.
5390             * @throws LscpException If LSCP protocol corruption occurs.
5391             */
5392            public synchronized void
5393            setDbInstrumentFilePath(String oldPath, String newPath)
5394                                    throws IOException, LSException, LscpException
5395            { retrieveIndex("SET DB_INSTRUMENT FILE_PATH '" + conv(oldPath) + "' '" + conv(newPath) + "'"); }
5396            
5397            /**
5398             * Finds all directories in the specified directory
5399             * that corresponds to the specified search criterias.
5400             * @param dir The absolute path name of the directory to search.
5401             * @param query Provides the search criterias.
5402             * @return A <code>DbDirectoryInfo</code> array providing
5403             * information about all directories that are found in the specified directory.
5404             * @throws IOException If some I/O error occurs.
5405             * @throws LscpException If LSCP protocol corruption occurs.
5406             * @throws LSException If the specified path name is invalid.
5407             */
5408            public synchronized DbDirectoryInfo[]
5409            findDbDirectories(String dir, DbSearchQuery query)
5410                                    throws IOException, LscpException, LSException {
5411                    
5412                    return findDbDirectories(dir, query, false);
5413            }
5414            
5415            /**
5416             * Finds all directories in the specified directory
5417             * that corresponds to the specified search criterias.
5418             * @param dir The absolute path name of the directory to search.
5419             * @param query Provides the search criterias.
5420             * @param nonRecursive If <code>true</code>, the search will be non-recursive.
5421             * @return A <code>DbDirectoryInfo</code> array providing
5422             * information about all directories that are found in the specified directory.
5423             * @throws IOException If some I/O error occurs.
5424             * @throws LscpException If LSCP protocol corruption occurs.
5425             * @throws LSException If the specified path name is invalid.
5426             */
5427            public synchronized DbDirectoryInfo[]
5428            findDbDirectories(String dir, DbSearchQuery query, boolean nonRecursive)
5429                                    throws IOException, LscpException, LSException {
5430                    
5431                    verifyConnection();
5432                    StringBuffer sb = new StringBuffer();
5433                    sb.append("FIND DB_INSTRUMENT_DIRECTORIES");
5434                    if(nonRecursive) sb.append(" NON_RECURSIVE");
5435                    sb.append(" '").append(conv(dir)).append("'");
5436                    
5437                    if(query.name != null && query.name.length() > 0) {
5438                            sb.append(" NAME='").append(toEscapedText(query.name)).append("'");
5439                    }
5440                    
5441                    String s = query.getCreatedAfter();
5442                    String s2 = query.getCreatedBefore();
5443                    if(s != null || s2 != null) {
5444                            sb.append(" CREATED='");
5445                            if(s != null) sb.append(s);
5446                            sb.append("..");
5447                            if(s2 != null) sb.append(s2);
5448                            sb.append("'");
5449                    }
5450                    
5451                    s = query.getModifiedAfter();
5452                    s2 = query.getModifiedBefore();
5453                    if(s != null || s2 != null) {
5454                            sb.append(" MODIFIED='");
5455                            if(s != null) sb.append(s);
5456                            sb.append("..");
5457                            if(s2 != null) sb.append(s2);
5458                            sb.append("'");
5459                    }
5460                    
5461                    if(query.description != null && query.description.length() > 0) {
5462                            sb.append(" DESCRIPTION='");
5463                            sb.append(toEscapedText(query.description)).append("'");
5464                    }
5465                    
5466                    out.writeLine(sb.toString());
5467                    if(getPrintOnlyMode()) return null;
5468                    
5469                    String[] dirS = parseEscapedStringList(getSingleLineResultSet().getResult());
5470                    
5471                    DbDirectoryInfo[] infoS = new DbDirectoryInfo[dirS.length];
5472                    for(int i = 0; i < dirS.length; i++) {
5473                            infoS[i] = getDbDirectoryInfo(dirS[i]);
5474                    }
5475                    return infoS;
5476            }
5477            
5478            /**
5479             * Finds all instruments in the specified directory
5480             * that corresponds to the specified search criterias.
5481             * @param dir The absolute path name of the directory to search.
5482             * @param query Provides the search criterias.
5483             * @return A <code>DbInstrumentInfo</code> array providing
5484             * information about all instruments that are found in the specified directory.
5485             * @throws IOException If some I/O error occurs.
5486             * @throws LscpException If LSCP protocol corruption occurs.
5487             * @throws LSException If the specified path name is invalid.
5488             */
5489            public synchronized DbInstrumentInfo[]
5490            findDbInstruments(String dir, DbSearchQuery query)
5491                                    throws IOException, LscpException, LSException {
5492                    
5493                    return findDbInstruments(dir, query, false);
5494            }
5495            
5496            /**
5497             * Finds all instruments in the specified directory
5498             * that corresponds to the specified search criterias.
5499             * @param dir The absolute path name of the directory to search.
5500             * @param query Provides the search criterias.
5501             * @param nonRecursive If <code>true</code>, the search will be non-recursive.
5502             * @return A <code>DbInstrumentInfo</code> array providing
5503             * information about all instruments that are found in the specified directory.
5504             * @throws IOException If some I/O error occurs.
5505             * @throws LscpException If LSCP protocol corruption occurs.
5506             * @throws LSException If the specified path name is invalid.
5507             */
5508            public synchronized DbInstrumentInfo[]
5509            findDbInstruments(String dir, DbSearchQuery query, boolean nonRecursive)
5510                                    throws IOException, LscpException, LSException {
5511                    
5512                    verifyConnection();
5513                    StringBuffer sb = new StringBuffer();
5514                    sb.append("FIND DB_INSTRUMENTS");
5515                    if(nonRecursive) sb.append(" NON_RECURSIVE");
5516                    sb.append(" '").append(conv(dir)).append("'");
5517                    
5518                    if(query.name != null && query.name.length() > 0) {
5519                            sb.append(" NAME='").append(toEscapedText(query.name)).append("'");
5520                    }
5521                    
5522                    if(query.formatFamilies.size() > 0) {
5523                            sb.append(" FORMAT_FAMILIES='").append(query.formatFamilies.get(0));
5524                            for(int i = 1; i < query.formatFamilies.size(); i++) {
5525                                    sb.append(',').append(query.formatFamilies.get(i));
5526                            }
5527                            sb.append("'");
5528                    }
5529                    
5530                    if(query.minSize != -1 || query.maxSize != -1) {
5531                            sb.append(" SIZE='");
5532                            if(query.minSize != -1) sb.append(query.minSize);
5533                            sb.append("..");
5534                            if(query.maxSize != -1) sb.append(query.maxSize);
5535                            sb.append("'");
5536                    }
5537                    
5538                    String s = query.getCreatedAfter();
5539                    String s2 = query.getCreatedBefore();
5540                    if(s != null || s2 != null) {
5541                            sb.append(" CREATED='");
5542                            if(s != null) sb.append(s);
5543                            sb.append("..");
5544                            if(s2 != null) sb.append(s2);
5545                            sb.append("'");
5546                    }
5547                    
5548                    s = query.getModifiedAfter();
5549                    s2 = query.getModifiedBefore();
5550                    if(s != null || s2 != null) {
5551                            sb.append(" MODIFIED='");
5552                            if(s != null) sb.append(s);
5553                            sb.append("..");
5554                            if(s2 != null) sb.append(s2);
5555                            sb.append("'");
5556                    }
5557                    
5558                    if(query.description != null && query.description.length() > 0) {
5559                            sb.append(" DESCRIPTION='");
5560                            sb.append(toEscapedText(query.description)).append("'");
5561                    }
5562                    
5563                    if(query.instrumentType != DbSearchQuery.InstrumentType.BOTH) {
5564                            sb.append(" IS_DRUM=");
5565                            if(query.instrumentType == DbSearchQuery.InstrumentType.DRUM) {
5566                                    sb.append("'true'");
5567                            } else {
5568                                    sb.append("'false'");
5569                            }
5570                    }
5571                    
5572                    if(query.product != null && query.product.length() > 0) {
5573                            sb.append(" PRODUCT='").append(toEscapedText(query.product)).append("'");
5574                    }
5575                    
5576                    if(query.artists != null && query.artists.length() > 0) {
5577                            sb.append(" ARTISTS='").append(toEscapedText(query.artists)).append("'");
5578                    }
5579                    
5580                    if(query.keywords != null && query.keywords.length() > 0) {
5581                            sb.append(" KEYWORDS='");
5582                            sb.append(toEscapedText(query.keywords)).append("'");
5583                    }
5584                    
5585                    out.writeLine(sb.toString());
5586                    if(getPrintOnlyMode()) return null;
5587                    
5588                    String[] instrS = parseEscapedStringList(getSingleLineResultSet().getResult());
5589                    
5590                    DbInstrumentInfo[] infoS = new DbInstrumentInfo[instrS.length];
5591                    for(int i = 0; i < instrS.length; i++) {
5592                            infoS[i] = getDbInstrumentInfo(instrS[i]);
5593                    }
5594                    return infoS;
5595            }
5596            
5597            /**
5598             * Returns a list of all instrument files in the database
5599             * that that don't exist in the filesystem.
5600             * @throws IOException If some I/O error occurs.
5601             * @throws LscpException If LSCP protocol corruption occurs.
5602             * @throws LSException If other error occurs.
5603             */
5604            public synchronized String[]
5605            findLostDbInstrumentFiles() throws IOException, LscpException, LSException {
5606                    
5607                    verifyConnection();
5608                    out.writeLine("FIND LOST DB_INSTRUMENT_FILES");
5609                    if(getPrintOnlyMode()) return null;
5610                    
5611                    return parseEscapedStringList(getSingleLineResultSet().getResult());
5612            }
5613            
5614            /**
5615             * Gets status information about the specified job.
5616             * @param jobId The ID of the job.
5617             * @return A <code>ScanJobInfo</code> instance providing information
5618             * about the specified job.
5619             * @throws IOException If some I/O error occurs.
5620             * @throws LscpException If LSCP protocol corruption occurs.
5621             * @throws LSException If the specified job is not found.
5622             */
5623            public synchronized ScanJobInfo
5624            getDbInstrumentsJobInfo(int jobId) throws IOException, LscpException, LSException {
5625                    ScanJobInfo info = new ScanJobInfo();
5626                    if(!retrieveInfo("GET DB_INSTRUMENTS_JOB INFO " + String.valueOf(jobId), info)) return null;
5627                    
5628                    return info;
5629            }
5630            
5631            /**
5632             * Removes all instruments and directories and re-creates
5633             * the instruments database structure.
5634             * @throws IOException If some I/O error occurs.
5635             * @throws LscpException If LSCP protocol corruption occurs.
5636             * @throws LSException If the formatting of the instruments database failed.
5637             */
5638            public synchronized void
5639            formatInstrumentsDb() throws IOException, LscpException, LSException
5640            { retrieveIndex("FORMAT INSTRUMENTS_DB"); }
5641            
5642            /**
5643           * Resets the whole sampler.           * Resets the whole sampler.
5644           *           *
5645           * @throws IOException If some I/O error occurs.           * @throws IOException If some I/O error occurs.
# Line 2372  public class Client { Line 5649  public class Client {
5649          resetSampler() throws IOException, LscpException {          resetSampler() throws IOException, LscpException {
5650                  verifyConnection();                  verifyConnection();
5651                  out.writeLine("RESET");                  out.writeLine("RESET");
5652                    if(getPrintOnlyMode()) return;
5653                    
5654                  try { ResultSet rs = getEmptyResultSet(); }                  try { ResultSet rs = getEmptyResultSet(); }
5655                  catch(LSException x) { getLogger().warning(x.getMessage()); }                  catch(LSException x) { getLogger().warning(x.getMessage()); }
5656          }          }
5657                    
5658          /**          /**
5659             * Gets the current number of all active streams.
5660             * @return The current number of all active streams or -1 if in "print only" mode.
5661             * @throws IOException If some I/O error occurs.
5662             * @throws LscpException If LSCP protocol corruption occurs.
5663             * @throws LSException If some other error occurs.
5664             */
5665            public synchronized int
5666            getTotalStreamCount() throws IOException, LscpException, LSException {
5667                    return retrieveInt("GET TOTAL_STREAM_COUNT");
5668            }
5669            
5670            /**
5671           * Gets the current number of all active voices.           * Gets the current number of all active voices.
5672           * @return The current number of all active voices.           * @return The current number of all active voices or -1 if in "print only" mode.
5673           * @throws IOException If some I/O error occurs.           * @throws IOException If some I/O error occurs.
5674           * @throws LscpException If LSCP protocol corruption occurs.           * @throws LscpException If LSCP protocol corruption occurs.
5675           * @throws LSException If some other error occurs.           * @throws LSException If some other error occurs.
5676           */           */
5677          public synchronized int          public synchronized int
5678          getTotalVoiceCount() throws IOException, LscpException, LSException {          getTotalVoiceCount() throws IOException, LscpException, LSException {
5679                  verifyConnection();                  return retrieveInt("GET TOTAL_VOICE_COUNT");
                 out.writeLine("GET TOTAL_VOICE_COUNT");  
                 String s = getSingleLineResultSet().getResult();  
                 return parseInt(s);  
5680          }          }
5681                    
5682          /**          /**
5683           * Gets the maximum number of active voices.           * Gets the maximum number of active voices.
5684           * @return The maximum number of active voices.           * @return The maximum number of active voices or -1 if in "print only" mode.
5685           * @throws IOException If some I/O error occurs.           * @throws IOException If some I/O error occurs.
5686           * @throws LscpException If LSCP protocol corruption occurs.           * @throws LscpException If LSCP protocol corruption occurs.
5687           * @throws LSException If some other error occurs.           * @throws LSException If some other error occurs.
5688           */           */
5689          public synchronized int          public synchronized int
5690          getTotalVoiceCountMax() throws IOException, LscpException, LSException {          getTotalVoiceCountMax() throws IOException, LscpException, LSException {
5691                  verifyConnection();                  return retrieveInt("GET TOTAL_VOICE_COUNT_MAX");
                 out.writeLine("GET TOTAL_VOICE_COUNT_MAX");  
                 String s = getSingleLineResultSet().getResult();  
                 return parseInt(s);  
5692          }          }
5693                    
5694          /**          /**
# Line 2418  public class Client { Line 5703  public class Client {
5703           */           */
5704          public synchronized ServerInfo          public synchronized ServerInfo
5705          getServerInfo() throws IOException, LscpException, LSException {          getServerInfo() throws IOException, LscpException, LSException {
5706                    ServerInfo info = new ServerInfo();
5707                    if(!retrieveInfo("GET SERVER INFO", info)) return null;
5708                    
5709                    return info;
5710            }
5711            
5712            /**
5713             * Gets the global volume of the sampler.
5714             * @return The global volume of the sampler.
5715             * @throws IOException If some I/O error occurs.
5716             * @throws LscpException If LSCP protocol corruption occurs.
5717             * @throws LSException If some other error occurs.
5718             */
5719            public synchronized float
5720            getVolume() throws IOException, LscpException, LSException {
5721                  verifyConnection();                  verifyConnection();
5722                  out.writeLine("GET SERVER INFO");                  out.writeLine("GET VOLUME");
5723                    if(getPrintOnlyMode()) return -1;
5724                    
5725                    String s = getSingleLineResultSet().getResult();
5726                    return parseFloat(s);
5727            }
5728            
5729            /**
5730             * Sets the global volume of the sampler.
5731             * @param volume The new volume value.
5732             * @throws IOException If some I/O error occurs.
5733             * @throws LscpException If LSCP protocol corruption occurs.
5734             * @throws LSException If some other error occurs.
5735             * @see #getVolume
5736             */
5737            public synchronized void
5738            setVolume(float volume) throws IOException, LscpException, LSException
5739            { retrieveIndex("SET VOLUME " + volume); }
5740            
5741            /**
5742             * Gets the global sampler-wide limit of maximum voices.
5743             * @return The global sampler-wide limit of maximum voices or -1 if in "print only" mode.
5744             * @throws IOException If some I/O error occurs.
5745             * @throws LscpException If LSCP protocol corruption occurs.
5746             * @throws LSException If some other error occurs.
5747             */
5748            public synchronized int
5749            getGlobalVoiceLimit() throws IOException, LscpException, LSException {
5750                    return retrieveInt("GET VOICES");
5751            }
5752            
5753            /**
5754             * Sets the global sampler-wide limit of maximum voices.
5755             * @param maxVoices The new global limit of maximum voices.
5756             * @throws IOException If some I/O error occurs.
5757             * @throws LscpException If LSCP protocol corruption occurs.
5758             * @throws LSException If some other error occurs.
5759             * @see #getVolume
5760             */
5761            public synchronized void
5762            setGlobalVoiceLimit(int maxVoices) throws IOException, LscpException, LSException
5763            { retrieveIndex("SET VOICES " + maxVoices); }
5764            
5765            /**
5766             * Gets the global sampler-wide limit of maximum disk streams.
5767             * @return The global sampler-wide limit of maximum disk streams
5768             *  or -1 if in "print only" mode.
5769             * @throws IOException If some I/O error occurs.
5770             * @throws LscpException If LSCP protocol corruption occurs.
5771             * @throws LSException If some other error occurs.
5772             */
5773            public synchronized int
5774            getGlobalStreamLimit() throws IOException, LscpException, LSException {
5775                    return retrieveInt("GET STREAMS");
5776            }
5777            
5778            /**
5779             * Sets the global sampler-wide limit for maximum disk streams.
5780             * @param maxVoices The new global limit of maximum disk streams.
5781             * @throws IOException If some I/O error occurs.
5782             * @throws LscpException If LSCP protocol corruption occurs.
5783             * @throws LSException If some other error occurs.
5784             * @see #getVolume
5785             */
5786            public synchronized void
5787            setGlobalStreamLimit(int maxStreams) throws IOException, LscpException, LSException
5788            { retrieveIndex("SET STREAMS " + maxStreams); }
5789            
5790            /**
5791             * Gets the number of instruments in the specified instrument file.
5792             * @param filename The absolute path name of the instrument file.
5793             * @return The number of instruments in the specified instrument file
5794             *  or -1 if in "print only" mode.
5795             * @throws IOException If some I/O error occurs.
5796             * @throws LscpException If LSCP protocol corruption occurs.
5797             * @throws LSException If the file is not found, or other error occur.
5798             */
5799            public synchronized int
5800            getFileInstrumentCount(String filename) throws IOException, LscpException, LSException {
5801                    return retrieveInt("GET FILE INSTRUMENTS '" + conv(filename) +"'");
5802            }
5803            
5804            /**
5805             * Gets information about the instrument with index
5806             * <code>instrIdx</code> in the specified instrument file.
5807             * @param filename The absolute path name of the instrument file.
5808             * @param instrIdx The index of the instrument in the specified instrument file.
5809             * @throws IOException If some I/O error occurs.
5810             * @throws LscpException If LSCP protocol corruption occurs.
5811             * @throws LSException If failed to retrieve information.
5812             */
5813            public synchronized Instrument
5814            getFileInstrumentInfo(String filename, int instrIdx)
5815                                    throws IOException, LscpException, LSException {
5816    
5817                    FileInstrument instr = new FileInstrument();
5818                    String cmd = "GET FILE INSTRUMENT INFO '" + conv(filename) + "' " + String.valueOf(instrIdx);
5819                    if(!retrieveInfo(cmd, instr)) return null;
5820                    
5821                    return instr;
5822            }
5823            
5824            /**
5825             * Gets the list of instruments in the specified instrument file.
5826             * @param filename The absolute path name of the instrument file.
5827             * @return An <code>Instrument</code> array providing
5828             * information about all instruments in the specified instrument file.
5829             * @throws IOException If some I/O error occurs.
5830             * @throws LscpException If LSCP protocol corruption occurs.
5831             * @throws LSException If the specified file name is invalid.
5832             */
5833            public synchronized Instrument[]
5834            getFileInstruments(String filename) throws IOException, LscpException, LSException {
5835                    int l = getFileInstrumentCount(filename);
5836                    if(l < 0) return null;
5837                    Instrument[] instrS = new FileInstrument[l];
5838                    
5839                    for(int i = 0; i < instrS.length; i++) {
5840                            instrS[i] = getFileInstrumentInfo(filename, i);
5841                    }
5842                    return instrS;
5843            }
5844            
5845            private static class FileInstrument extends AbstractInstrument {
5846                    FileInstrument() { }
5847                    
5848                    public String
5849                    getEngine() {
5850                            // TODO: engine lookup?
5851                            return getFormatFamily();
5852                    }
5853                    
5854                    @Override
5855                    public boolean
5856                    parse(String s) throws LscpException {
5857                            if(s.startsWith("PRODUCT: ") || s.startsWith("ARTISTS: ")) return true;
5858                            return super.parse(s);
5859                    }
5860            }
5861            
5862            private void
5863            getEmptyResultSets(int count, String err) throws LSException {
5864                    StringBuffer sb = new StringBuffer();
5865                    for(int i = 0; i < count; i++) {
5866                            try { getEmptyResultSet(); }
5867                            catch (SocketTimeoutException e) {
5868                                    getLogger().log(Level.FINE, e.getMessage(), e);
5869                                    sb.append(e.getMessage()).append("\n");
5870                                    break;
5871                            } catch (Exception e) {
5872                                    getLogger().log(Level.FINE, e.getMessage(), e);
5873                                    sb.append(e.getMessage()).append("\n");
5874                            }
5875                    }
5876                    
5877                    String details = sb.toString();
5878                    if(details.length() > 0) {
5879                            String s = LscpI18n.getLogMsg(err);
5880                            throw new LSException(0, s, details);
5881                    }
5882            }
5883    
5884            /**
5885             * Retrieves a list of integers.
5886             * @throws IOException If some I/O error occurs.
5887             * @throws LscpException If LSCP protocol corruption occurs.
5888             */
5889            private Integer[]
5890            getIntegerList(String lscpCmd) throws IOException, LscpException, LSException {
5891                    verifyConnection();
5892                    out.writeLine(lscpCmd);
5893                    if(getPrintOnlyMode()) return null;
5894    
5895                    return parseIntList(getSingleLineResultSet().getResult());
5896            }
5897    
5898            private boolean
5899            retrieveInfo(String lscpCmd, Parseable p) throws IOException, LscpException, LSException {
5900                    verifyConnection();
5901                    out.writeLine(lscpCmd);
5902                    if(getPrintOnlyMode()) return false;
5903    
5904                  ResultSet rs = getMultiLineResultSet();                  ResultSet rs = getMultiLineResultSet();
5905                  return new ServerInfo(rs.getMultiLineResult());  
5906                    for(String s : rs.getMultiLineResult()) {
5907                            if(!p.parse(s)) Client.getLogger().info(LscpI18n.getLogMsg("unknownLine", s));
5908                    }
5909    
5910                    return true;
5911            }
5912    
5913            private int
5914            retrieveInt(String lscpCmd) throws IOException, LscpException, LSException {
5915                    verifyConnection();
5916                    out.writeLine(lscpCmd);
5917                    if(getPrintOnlyMode()) return -1;
5918    
5919                    String s = getSingleLineResultSet().getResult();
5920                    return parseInt(s);
5921            }
5922    
5923            private int
5924            retrieveIndex(String lscpCmd) throws IOException, LSException, LscpException {
5925                    verifyConnection();
5926                    out.writeLine(lscpCmd);
5927                    if(getPrintOnlyMode()) return -1;
5928    
5929                    return getEmptyResultSet().getIndex();
5930          }          }
5931                    
5932          /**          /**

Legend:
Removed from v.784  
changed lines
  Added in v.2242

  ViewVC Help
Powered by ViewVC