/[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 1817 by iliev, Wed Dec 24 16:55:54 2008 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-2008 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.Vector;  import java.util.Vector;
33  import java.util.logging.Level;  import java.util.logging.Level;
34  import java.util.logging.Logger;  import java.util.logging.Logger;
35    
 import static org.linuxsampler.lscp.Parser.*;  
36  import org.linuxsampler.lscp.event.*;  import org.linuxsampler.lscp.event.*;
37    
38    import static org.linuxsampler.lscp.Parser.*;
39    
40    
41  /**  /**
42   * 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
43   * 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.3, for more
44   * information look at the   * information look at the
45   * <a href=http://www.linuxsampler.org/api/lscp-1.0.html>LSCP</a> specification.   * <a href=http://www.linuxsampler.org/api/lscp-1.3.html>LSCP</a> specification.
46   *   *
47   * <p> The following code establishes connection to LinuxSampler instance and gets the   * <p> The following code establishes connection to LinuxSampler instance and gets the
48   * LinuxSampler version:   * LinuxSampler version:
# Line 68  public class Client { Line 69  public class Client {
69          private String address;          private String address;
70          private int port;          private int port;
71          private Socket sock = null;          private Socket sock = null;
72          private int soTimeout = 10000;          private int soTimeout = 20000;
73                    
74          private LscpInputStream in = null;          private LscpInputStream in = null;
75          private LscpOutputStream out = null;          private LscpOutputStream out = null;
76                    
77          private EventThread eventThread;          private EventThread eventThread;
78                    
79            private boolean printOnlyMode = false;
80            
81          class EventThread extends Thread {          class EventThread extends Thread {
82                    private Vector<String> queue = new Vector<String>();
83                  private boolean terminate = false;                  private boolean terminate = false;
84                                    
85                  EventThread() { super("LSCP-Event-Thread"); }                  EventThread() { super("LSCP-Event-Thread"); }
86                                    
87                    @Override
88                  public void                  public void
89                  run() {                  run() {
90                          while(!mustTerminate()) {                          while(!mustTerminate()) {
91                                  try { processNotifications(); }                                  try {
92                                  catch(Exception x) {                                          processQueue();
93                                            processNotifications();
94                                    } catch(Exception x) {
95                                          getLogger().log(Level.FINE, x.getMessage(), x);                                          getLogger().log(Level.FINE, x.getMessage(), x);
96                                  }                                  }
97                                  try { synchronized(this) { wait(100); } }                                  try { synchronized(this) { wait(100); } }
# Line 102  public class Client { Line 109  public class Client {
109                          terminate = true;                          terminate = true;
110                          this.notifyAll();                          this.notifyAll();
111                  }                  }
112                    
113                    public synchronized void
114                    scheduleNotification(String s) { queue.add(s); }
115                    
116                    private void
117                    processQueue() {
118                            String[] notifications = popAllNotifications();
119                            for(String n : notifications) fireEvent(n);
120                    }
121                    
122                    private synchronized String[]
123                    popAllNotifications() {
124                            String[] notifications = queue.toArray(new String[queue.size()]);
125                            queue.removeAllElements();
126                            return notifications;
127                    }
128          }          }
129                    
130          /**          /**
# Line 133  public class Client { Line 156  public class Client {
156          }          }
157                    
158          /**          /**
159             * Creates a new instance of Client.
160             * @param printOnlyMode Determines whether the client will be in print-only mode.
161             */
162            public
163            Client(boolean printOnlyMode) {
164                    if(printOnlyMode) setPrintOnlyMode(true);
165            }
166            
167            private boolean extendedCharacterEscaping = true;
168            
169            /**
170             * Sets whether strings sent to LinuxSampler should be more aggressively escaped.
171             */
172            public synchronized void
173            setExtendedCharacterEscaping(boolean b) { extendedCharacterEscaping = b; }
174            
175            /**
176             * Determines whether strings sent to LinuxSampler should be more aggressively escaped.
177             */
178            public synchronized boolean
179            getExtendedCharacterEscaping() { return extendedCharacterEscaping; }
180            
181            /**
182             * @see java.net.Socket#setSoTimeout
183             */
184            public synchronized void
185            setSoTimeout(int timeout) {
186                    soTimeout = timeout;
187                    
188                    try { if(sock != null) sock.setSoTimeout(timeout); }
189                    catch(Exception x) { getLogger().log(Level.INFO, "Unable to set timeout", x); }
190            }
191            
192            private String
193            toEscapedText(String s) {
194                    s = toEscapedString(s);
195                    return conv(s);
196            }
197            
198            private String
199            toEscapedFsEntry(String s) {
200                    s = toEscapedFileName(s);
201                    return conv(s);
202            }
203            
204            /**
205             * Applies an extended character escaping to the specified string if needed.
206             */
207            private String
208            conv(String s) {
209                    return getExtendedCharacterEscaping() ? toExtendedEscapeSequence(s) : s;
210            }
211            
212            /**
213             * Determines whether the client is in print-only mode.
214             * Print-only mode means that the client will just print all
215             * LSCP commands to the specified output stream or to the standard output stream
216             * (<code>java.lang.System.out</code>) if no output stream is specified,
217             * without taking any further actions. Thus, in print-only mode all returned
218             * values by <code>Client</code>'s methods are meaningless and should be discarded.
219             * @return <code>true</code> if the client is in
220             * print-only mode, <code>false</code> otherwise.
221             * @see #setPrintOnlyModeOutputStream
222             */
223            public synchronized boolean
224            getPrintOnlyMode() { return printOnlyMode; }
225            
226            /**
227             * Sets the print-only mode. Note that in print-only mode all returned
228             * values by <code>Client</code>'s methods are meaningless and should be discarded.
229             * The default output stream in print-only mode is <code>java.lang.System.out</code>.
230             * @param b If <code>true</code> all LSCP commands will be sent
231             * to the specified output stream or to the standard output stream
232             * (<code>java.lang.System.out</code>) if no output stream is specified,
233             * and no further actions will be taken.
234             * @throws IllegalStateException If the client is connected.
235             * @see #setPrintOnlyModeOutputStream
236             */
237            public synchronized void
238            setPrintOnlyMode(boolean b) {
239                    if(printOnlyMode == b) return;
240                    if(isConnected()) throw new IllegalStateException();
241                    
242                    printOnlyMode = b;
243                    if(b) out = new LscpOutputStream(System.out);
244            }
245            
246            /**
247             * Sets the output stream to be used in print-only mode.
248             * @param out The output stream to be used in print-only mode.
249             * @throws IllegalStateException If the client is not in print-only mode.
250             * @throws IllegalArgumentException if <code>out</code> is <code>null</code>.
251             * @see #setPrintOnlyMode
252             */
253            public synchronized void
254            setPrintOnlyModeOutputStream(OutputStream out) {
255                    if(!getPrintOnlyMode()) throw new IllegalStateException("Not in print-only mode");
256                    if(out == null) throw new IllegalArgumentException("out must be non-null");
257                    this.out = new LscpOutputStream(out);
258            }
259            
260            /**
261           * Specifies the jlscp version.           * Specifies the jlscp version.
262           * @return The jlscp version.           * @return The jlscp version.
263           */           */
# Line 180  public class Client { Line 305  public class Client {
305          public synchronized void          public synchronized void
306          connect() throws LscpException {          connect() throws LscpException {
307                  if(sock != null) disconnect();                  if(sock != null) disconnect();
308                    if(getPrintOnlyMode()) return;
309                                    
310                  // Initializing LSCP event thread                  // Initializing LSCP event thread
311                  if(eventThread.isAlive()) {                  if(eventThread.isAlive()) {
# Line 252  public class Client { Line 378  public class Client {
378                  if(hasSubscriptions()) eventThread.start();                  if(hasSubscriptions()) eventThread.start();
379                                    
380                  if(!llM.isEmpty()) subscribe("MISCELLANEOUS");                  if(!llM.isEmpty()) subscribe("MISCELLANEOUS");
381                    if(!llAODC.isEmpty()) subscribe("AUDIO_OUTPUT_DEVICE_COUNT");
382                    if(!llAODI.isEmpty()) subscribe("AUDIO_OUTPUT_DEVICE_INFO");
383                    if(!llMIDC.isEmpty()) subscribe("MIDI_INPUT_DEVICE_COUNT");
384                    if(!llMIDI.isEmpty()) subscribe("MIDI_INPUT_DEVICE_INFO");
385                  if(!llBF.isEmpty()) subscribe("BUFFER_FILL");                  if(!llBF.isEmpty()) subscribe("BUFFER_FILL");
386                  if(!llCC.isEmpty()) subscribe("CHANNEL_COUNT");                  if(!llCC.isEmpty()) subscribe("CHANNEL_COUNT");
387                  if(!llCI.isEmpty()) subscribe("CHANNEL_INFO");                  if(!llCI.isEmpty()) subscribe("CHANNEL_INFO");
388                    if(!llFSC.isEmpty()) subscribe("FX_SEND_COUNT");
389                    if(!llFSI.isEmpty()) subscribe("FX_SEND_INFO");
390                  if(!llSC.isEmpty()) subscribe("STREAM_COUNT");                  if(!llSC.isEmpty()) subscribe("STREAM_COUNT");
391                  if(!llVC.isEmpty()) subscribe("VOICE_COUNT");                  if(!llVC.isEmpty()) subscribe("VOICE_COUNT");
392                    if(!llTSC.isEmpty()) subscribe("TOTAL_STREAM_COUNT");
393                  if(!llTVC.isEmpty()) subscribe("TOTAL_VOICE_COUNT");                  if(!llTVC.isEmpty()) subscribe("TOTAL_VOICE_COUNT");
394                    if(!llMIMC.isEmpty()) subscribe("MIDI_INSTRUMENT_MAP_COUNT");
395                    if(!llMIMI.isEmpty()) subscribe("MIDI_INSTRUMENT_MAP_INFO");
396                    if(!llMIC.isEmpty()) subscribe("MIDI_INSTRUMENT_COUNT");
397                    if(!llMII.isEmpty()) subscribe("MIDI_INSTRUMENT_INFO");
398                    if(!llDMD.isEmpty()) subscribe("DEVICE_MIDI");
399                    if(!llCMD.isEmpty()) subscribe("CHANNEL_MIDI");
400                    if(!llID.isEmpty()) {
401                            subscribe("DB_INSTRUMENT_DIRECTORY_COUNT");
402                            subscribe("DB_INSTRUMENT_DIRECTORY_INFO");
403                            subscribe("DB_INSTRUMENT_COUNT");
404                            subscribe("DB_INSTRUMENT_INFO");
405                            subscribe("DB_INSTRUMENTS_JOB_INFO");
406                    }
407                    if(!llGI.isEmpty()) subscribe("GLOBAL_INFO");
408          }          }
409                    
410          /**          /**
# Line 265  public class Client { Line 412  public class Client {
412           */           */
413          public synchronized void          public synchronized void
414          disconnect() {          disconnect() {
415                    if(getPrintOnlyMode()) return;
416                  try { if(sock != null) sock.close(); }                  try { if(sock != null) sock.close(); }
417                  catch(Exception x) { getLogger().log(Level.FINE, x.getMessage(), x); }                  catch(Exception x) { getLogger().log(Level.FINE, x.getMessage(), x); }
418                  sock = null;                  sock = null;
# Line 292  public class Client { Line 440  public class Client {
440           */           */
441          private void          private void
442          verifyConnection() throws IOException {          verifyConnection() throws IOException {
443                    if(getPrintOnlyMode()) return;
444                    
445                  if(!isConnected())                  if(!isConnected())
446                          throw new IOException(LscpI18n.getLogMsg("Client.notConnected!"));                          throw new IOException(LscpI18n.getLogMsg("Client.notConnected!"));
447          }          }
# Line 301  public class Client { Line 451  public class Client {
451                  String s;                  String s;
452                  for(;;) {                  for(;;) {
453                          s = in.readLine();                          s = in.readLine();
454                          if(s.startsWith("NOTIFY:")) fireEvent(s.substring("NOTIFY:".length()));                          if(s.startsWith("NOTIFY:")) {
455                                    eventThread.scheduleNotification(s.substring("NOTIFY:".length()));
456                            }
457                          else break;                          else break;
458                  }                  }
459                  return s;                  return s;
460          }          }
461                    
462          /** Processes the notifications send by LinuxSampler */          /** Processes the notifications sent by LinuxSampler */
463          private synchronized void          private synchronized void
464          processNotifications() throws IOException, LscpException {          processNotifications() throws IOException, LscpException {
465                  while(in.available() > 0) {                  while(in.available() > 0) {
# Line 366  public class Client { Line 518  public class Client {
518                  return rs;                  return rs;
519          }          }
520                    
521            /** Audio output device count listeners */
522            private final Vector<ItemCountListener> llAODC = new Vector<ItemCountListener>();
523            /** Audio output device info listeners */
524            private final Vector<ItemInfoListener> llAODI = new Vector<ItemInfoListener>();
525          private final Vector<BufferFillListener> llBF = new Vector<BufferFillListener>();          private final Vector<BufferFillListener> llBF = new Vector<BufferFillListener>();
526          private final Vector<ChannelCountListener> llCC = new Vector<ChannelCountListener>();          private final Vector<ChannelCountListener> llCC = new Vector<ChannelCountListener>();
527          private final Vector<ChannelInfoListener> llCI = new Vector<ChannelInfoListener>();          private final Vector<ChannelInfoListener> llCI = new Vector<ChannelInfoListener>();
528            private final Vector<FxSendCountListener> llFSC = new Vector<FxSendCountListener>();
529            private final Vector<FxSendInfoListener> llFSI = new Vector<FxSendInfoListener>();
530          private final Vector<MiscellaneousListener> llM = new Vector<MiscellaneousListener>();          private final Vector<MiscellaneousListener> llM = new Vector<MiscellaneousListener>();
531            /** MIDI input device count listeners */
532            private final Vector<ItemCountListener> llMIDC = new Vector<ItemCountListener>();
533            /** MIDI input device info listeners */
534            private final Vector<ItemInfoListener> llMIDI = new Vector<ItemInfoListener>();
535          private final Vector<StreamCountListener> llSC = new Vector<StreamCountListener>();          private final Vector<StreamCountListener> llSC = new Vector<StreamCountListener>();
536          private final Vector<VoiceCountListener> llVC = new Vector<VoiceCountListener>();          private final Vector<VoiceCountListener> llVC = new Vector<VoiceCountListener>();
537            private final Vector<TotalStreamCountListener> llTSC = new Vector<TotalStreamCountListener>();
538          private final Vector<TotalVoiceCountListener> llTVC = new Vector<TotalVoiceCountListener>();          private final Vector<TotalVoiceCountListener> llTVC = new Vector<TotalVoiceCountListener>();
539                    
540            /** MIDI instrument map count listeners */
541            private final Vector<ItemCountListener> llMIMC = new Vector<ItemCountListener>();
542            /** MIDI instrument map info listeners */
543            private final Vector<ItemInfoListener> llMIMI = new Vector<ItemInfoListener>();
544            /** MIDI instrument count listeners */
545            private final Vector<MidiInstrumentCountListener> llMIC =
546                    new Vector<MidiInstrumentCountListener>();
547            /** MIDI instrument info listeners */
548            private final Vector<MidiInstrumentInfoListener> llMII =
549                    new Vector<MidiInstrumentInfoListener>();
550            private final Vector<DeviceMidiDataListener> llDMD = new Vector<DeviceMidiDataListener>();
551            private final Vector<ChannelMidiDataListener> llCMD = new Vector<ChannelMidiDataListener>();
552            private final Vector<InstrumentsDbListener> llID = new Vector<InstrumentsDbListener>();
553            private final Vector<GlobalInfoListener> llGI = new Vector<GlobalInfoListener>();
554            
555            
556          /**          /**
557           * Determines whether there is at least one subscription for notification events.           * Determines whether there is at least one subscription for notification events.
558           * 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 562  public class Client {
562           */           */
563          private boolean          private boolean
564          hasSubscriptions() {          hasSubscriptions() {
565                  return  !llBF.isEmpty() ||                  return  !llAODC.isEmpty() ||
566                          !llCC.isEmpty() ||                          !llAODI.isEmpty() ||
567                          !llCI.isEmpty() ||                          !llBF.isEmpty()   ||
568                          !llM.isEmpty()  ||                          !llCC.isEmpty()   ||
569                          !llSC.isEmpty() ||                          !llCI.isEmpty()   ||
570                          !llVC.isEmpty() ||                          !llFSC.isEmpty()  ||
571                          !llTVC.isEmpty();                          !llFSI.isEmpty()  ||
572                            !llM.isEmpty()    ||
573                            !llMIDC.isEmpty() ||
574                            !llMIDI.isEmpty() ||
575                            !llSC.isEmpty()   ||
576                            !llVC.isEmpty()   ||
577                            !llTSC.isEmpty()  ||
578                            !llTVC.isEmpty()  ||
579                            !llMIMC.isEmpty() ||
580                            !llMIMI.isEmpty() ||
581                            !llMIC.isEmpty()  ||
582                            !llMII.isEmpty()  ||
583                            !llDMD.isEmpty()  ||
584                            !llCMD.isEmpty()  ||
585                            !llID.isEmpty()   ||
586                            !llGI.isEmpty();
587          }          }
588                    
589          private void          private synchronized void
590            fireDeviceMidiDataEvent(String s) {
591                    try {
592                            String[] list = parseList(s, ' ');
593                            if(list.length != 5) {
594                                    getLogger().warning("Unknown DEVICE_MIDI format");
595                                    return;
596                            }
597                            
598                            int dev = parseInt(list[0]);
599                            int port = parseInt(list[1]);
600                            
601                            MidiDataEvent.Type type = parseMidiDataType(list[2]);
602                            if(type == null) return;
603                            
604                            int note = parseInt(list[3]);
605                            int velocity = parseInt(list[4]);
606                            
607                            DeviceMidiDataEvent e = new DeviceMidiDataEvent(this, type, note, velocity);
608                            e.setDeviceId(dev);
609                            e.setPortId(port);
610                            for(DeviceMidiDataListener l : llDMD) l.midiDataArrived(e);
611                    } catch(LscpException x) {
612                            getLogger().log (
613                                    Level.WARNING, LscpI18n.getLogMsg("CommandFailed!"), x
614                            );
615                    }
616            }
617            
618            private synchronized void
619            fireChannelMidiDataEvent(String s) {
620                    try {
621                            String[] list = parseList(s, ' ');
622                            if(list.length != 4) {
623                                    getLogger().warning("Unknown CHANNEL_MIDI format");
624                                    return;
625                            }
626                            
627                            int channel = parseInt(list[0]);
628                            
629                            MidiDataEvent.Type type = parseMidiDataType(list[1]);
630                            if(type == null) return;
631                            
632                            int note = parseInt(list[2]);
633                            int velocity = parseInt(list[3]);
634                            
635                            ChannelMidiDataEvent e = new ChannelMidiDataEvent(this, type, note, velocity);
636                            e.setChannelId(channel);
637                            for(ChannelMidiDataListener l : llCMD) l.midiDataArrived(e);
638                    } catch(LscpException x) {
639                            getLogger().log (
640                                    Level.WARNING, LscpI18n.getLogMsg("CommandFailed!"), x
641                            );
642                    }
643            }
644            
645            private MidiDataEvent.Type
646            parseMidiDataType(String s) {
647                    if("NOTE_ON".equals(s)) return MidiDataEvent.Type.NOTE_ON;
648                    if("NOTE_OFF".equals(s)) return MidiDataEvent.Type.NOTE_OFF;
649                    
650                    getLogger().warning("Unknown MIDI data type: " + s);
651                    return null;
652            }
653            
654            private synchronized void
655          fireEvent(String s) {          fireEvent(String s) {
656                  if(s.startsWith("CHANNEL_COUNT:")) {                  // Sort by priority
657                    
658                     if(s.startsWith("CHANNEL_MIDI:")) {
659                            s = s.substring("CHANNEL_MIDI:".length());
660                            fireChannelMidiDataEvent(s);
661                    } else if(s.startsWith("DEVICE_MIDI:")) {
662                            s = s.substring("DEVICE_MIDI:".length());
663                            fireDeviceMidiDataEvent(s);
664                    } else if(s.startsWith("DB_INSTRUMENT_DIRECTORY_COUNT:")) {
665                            s = s.substring("DB_INSTRUMENT_DIRECTORY_COUNT:".length());
666                            InstrumentsDbEvent e = new InstrumentsDbEvent(this, s);
667                            for(InstrumentsDbListener l : llID) l.directoryCountChanged(e);
668                    } else if(s.startsWith("DB_INSTRUMENT_DIRECTORY_INFO:")) {
669                            InstrumentsDbEvent e;
670                            s = s.substring("DB_INSTRUMENT_DIRECTORY_INFO:".length());
671                            if(s.startsWith("NAME ")) {
672                                    String[] list;
673                                    try {
674                                            s = s.substring("NAME ".length());
675                                            list = parseEscapedStringList(s, ' ');
676                                            if(list.length != 2) throw new LscpException();
677                                            list[1] = toNonEscapedString(list[1]);
678                                            e = new InstrumentsDbEvent(this, list[0], list[1]);
679                                            for(InstrumentsDbListener l : llID) {
680                                                    l.directoryNameChanged(e);
681                                            }
682                                    } catch(LscpException x) {
683                                            getLogger().log (
684                                                    Level.WARNING,
685                                                    LscpI18n.getLogMsg("CommandFailed!"),
686                                                    x
687                                            );
688                                    }
689                            } else {
690                                    e = new InstrumentsDbEvent(this, s);
691                                    for(InstrumentsDbListener l : llID) l.directoryInfoChanged(e);
692                            }
693                    } else if(s.startsWith("DB_INSTRUMENT_COUNT:")) {
694                            s = s.substring("DB_INSTRUMENT_COUNT:".length());
695                            InstrumentsDbEvent e = new InstrumentsDbEvent(this, s);
696                            for(InstrumentsDbListener l : llID) l.instrumentCountChanged(e);
697                    } else if(s.startsWith("DB_INSTRUMENT_INFO:")) {
698                            InstrumentsDbEvent e;
699                            s = s.substring("DB_INSTRUMENT_INFO:".length());
700                            if(s.startsWith("NAME ")) {
701                                    String[] list;
702                                    try {
703                                            s = s.substring("NAME ".length());
704                                            list = parseEscapedStringList(s, ' ');
705                                            if(list.length != 2) throw new LscpException();
706                                            list[1] = toNonEscapedString(list[1]);
707                                            e = new InstrumentsDbEvent(this, list[0], list[1]);
708                                            for(InstrumentsDbListener l : llID) {
709                                                    l.instrumentNameChanged(e);
710                                            }
711                                    } catch(LscpException x) {
712                                            getLogger().log (
713                                                    Level.WARNING,
714                                                    LscpI18n.getLogMsg("CommandFailed!"),
715                                                    x
716                                            );
717                                    }
718                            } else {
719                                    e = new InstrumentsDbEvent(this, s);
720                                    for(InstrumentsDbListener l : llID) l.instrumentInfoChanged(e);
721                            }
722                    } else if(s.startsWith("DB_INSTRUMENTS_JOB_INFO:")) {
723                            s = s.substring("DB_INSTRUMENTS_JOB_INFO:".length());
724                            try {
725                                    int i = Integer.parseInt(s);
726                                    InstrumentsDbEvent e = new InstrumentsDbEvent(this, i);
727                                    for(InstrumentsDbListener l : llID) l.jobStatusChanged(e);
728                            } catch(NumberFormatException x) {
729                                    s = "Unknown DB_INSTRUMENTS_JOB_INFO format";
730                                    getLogger().log(Level.WARNING, s, x);
731                            }
732                            
733                    } else if(s.startsWith("CHANNEL_COUNT:")) {
734                          try {                          try {
735                                  int i = Integer.parseInt(s.substring("CHANNEL_COUNT:".length()));                                  int i = Integer.parseInt(s.substring("CHANNEL_COUNT:".length()));
736                                  ChannelCountEvent e = new ChannelCountEvent(this, i);                                  ChannelCountEvent e = new ChannelCountEvent(this, i);
# Line 407  public class Client { Line 743  public class Client {
743                  } else if(s.startsWith("VOICE_COUNT:")) {                  } else if(s.startsWith("VOICE_COUNT:")) {
744                          try {                          try {
745                                  s = s.substring("VOICE_COUNT:".length());                                  s = s.substring("VOICE_COUNT:".length());
746                                  int i = s.indexOf(' ');                                  Integer[] i = parseIntList(s, ' ');
747                                  if(i == -1) {                                  if(i.length != 2) {
748                                          getLogger().warning("Unknown VOICE_COUNT format");                                          getLogger().warning("Unknown VOICE_COUNT format");
749                                          return;                                          return;
750                                  }                                  }
751                                  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);  
752                                  for(VoiceCountListener l : llVC) l.voiceCountChanged(e);                                  for(VoiceCountListener l : llVC) l.voiceCountChanged(e);
753                          } catch(NumberFormatException x) {                          } catch(Exception x) {
754                                  getLogger().log(Level.WARNING, "Unknown VOICE_COUNT format", x);                                  getLogger().log(Level.WARNING, "Unknown VOICE_COUNT format", x);
755                          }                          }
756                  } else if(s.startsWith("STREAM_COUNT:")) {                  } else if(s.startsWith("STREAM_COUNT:")) {
757                          try {                          try {
758                                  s = s.substring("STREAM_COUNT:".length());                                  s = s.substring("STREAM_COUNT:".length());
759                                  int i = s.indexOf(' ');                                  Integer[] i = parseIntList(s, ' ');
760                                  if(i == -1) {                                  if(i.length != 2) {
761                                          getLogger().warning("Unknown STREAM_COUNT format");                                          getLogger().warning("Unknown STREAM_COUNT format");
762                                          return;                                          return;
763                                  }                                  }
764                                  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);  
765                                  for(StreamCountListener l : llSC) l.streamCountChanged(e);                                  for(StreamCountListener l : llSC) l.streamCountChanged(e);
766                          } catch(NumberFormatException x) {                          } catch(Exception x) {
767                                  getLogger().log(Level.WARNING, "Unknown STREAM_COUNT format", x);                                  getLogger().log(Level.WARNING, "Unknown STREAM_COUNT format", x);
768                          }                          }
769                  } else if(s.startsWith("BUFFER_FILL:")) {                  } else if(s.startsWith("BUFFER_FILL:")) {
# Line 439  public class Client { Line 771  public class Client {
771                                  s = s.substring("BUFFER_FILL:".length());                                  s = s.substring("BUFFER_FILL:".length());
772                                  int i = s.indexOf(' ');                                  int i = s.indexOf(' ');
773                                  if(i == -1) {                                  if(i == -1) {
774                                          getLogger().warning("Unknown STREAM_COUNT format");                                          getLogger().warning("Unknown BUFFER_FILL format");
775                                          return;                                          return;
776                                  }                                  }
777                                  int j = Integer.parseInt(s.substring(0, i));                                  int j = Integer.parseInt(s.substring(0, i));
# Line 448  public class Client { Line 780  public class Client {
780                                  BufferFillEvent e = new BufferFillEvent(this, j, v);                                  BufferFillEvent e = new BufferFillEvent(this, j, v);
781                                  for(BufferFillListener l : llBF) l.bufferFillChanged(e);                                  for(BufferFillListener l : llBF) l.bufferFillChanged(e);
782                          } catch(Exception x) {                          } catch(Exception x) {
783                                  getLogger().log(Level.WARNING, "Unknown STREAM_COUNT format", x);                                  getLogger().log(Level.WARNING, "Unknown BUFFER_FILL format", x);
784                          }                          }
785                  } else if(s.startsWith("CHANNEL_INFO:")) {                  } else if(s.startsWith("CHANNEL_INFO:")) {
786                          try {                          try {
# Line 456  public class Client { Line 788  public class Client {
788                                  ChannelInfoEvent e = new ChannelInfoEvent(this, i);                                  ChannelInfoEvent e = new ChannelInfoEvent(this, i);
789                                  for(ChannelInfoListener l : llCI) l.channelInfoChanged(e);                                  for(ChannelInfoListener l : llCI) l.channelInfoChanged(e);
790                          } catch(NumberFormatException x) {                          } catch(NumberFormatException x) {
791                                  getLogger().log(Level.WARNING, "Unknown STREAM_COUNT format", x);                                  getLogger().log(Level.WARNING, "Unknown CHANNEL_INFO format", x);
792                            }
793                    } else if(s.startsWith("TOTAL_STREAM_COUNT:")) {
794                            try {
795                                    s = s.substring("TOTAL_STREAM_COUNT:".length());
796                                    int i = Integer.parseInt(s);
797                                    TotalStreamCountEvent e = new TotalStreamCountEvent(this, i);
798                                    for(TotalStreamCountListener l : llTSC) l.totalStreamCountChanged(e);
799                            } catch(NumberFormatException x) {
800                                    getLogger().log (
801                                            Level.WARNING, "Unknown TOTAL_STREAM_COUNT format", x
802                                    );
803                          }                          }
804                  } else if(s.startsWith("TOTAL_VOICE_COUNT:")) {                  } else if(s.startsWith("TOTAL_VOICE_COUNT:")) {
805                          try {                          try {
# Line 469  public class Client { Line 812  public class Client {
812                                          Level.WARNING, "Unknown TOTAL_VOICE_COUNT format", x                                          Level.WARNING, "Unknown TOTAL_VOICE_COUNT format", x
813                                  );                                  );
814                          }                          }
815                    } else if(s.startsWith("AUDIO_OUTPUT_DEVICE_COUNT:")) {
816                            try {
817                                    s = s.substring("AUDIO_OUTPUT_DEVICE_COUNT:".length());
818                                    int i = Integer.parseInt(s);
819                                    ItemCountEvent e = new ItemCountEvent(this, i);
820                                    for(ItemCountListener l : llAODC) l.itemCountChanged(e);
821                            } catch(NumberFormatException x) {
822                                    getLogger().log (
823                                            Level.WARNING, "Unknown AUDIO_OUTPUT_DEVICE_COUNT format", x
824                                    );
825                            }
826                    } else if(s.startsWith("AUDIO_OUTPUT_DEVICE_INFO:")) {
827                            try {
828                                    s = s.substring("AUDIO_OUTPUT_DEVICE_INFO:".length());
829                                    int i = Integer.parseInt(s);
830                                    ItemInfoEvent e = new ItemInfoEvent(this, i);
831                                    for(ItemInfoListener l : llAODI) l.itemInfoChanged(e);
832                            } catch(NumberFormatException x) {
833                                    getLogger().log (
834                                            Level.WARNING, "Unknown AUDIO_OUTPUT_DEVICE_INFO format", x
835                                    );
836                            }
837                    } else if(s.startsWith("MIDI_INPUT_DEVICE_COUNT:")) {
838                            try {
839                                    s = s.substring("MIDI_INPUT_DEVICE_COUNT:".length());
840                                    int i = Integer.parseInt(s);
841                                    ItemCountEvent e = new ItemCountEvent(this, i);
842                                    for(ItemCountListener l : llMIDC) l.itemCountChanged(e);
843                            } catch(NumberFormatException x) {
844                                    getLogger().log (
845                                            Level.WARNING, "Unknown MIDI_INPUT_DEVICE_COUNT format", x
846                                    );
847                            }
848                    } else if(s.startsWith("MIDI_INPUT_DEVICE_INFO:")) {
849                            try {
850                                    s = s.substring("MIDI_INPUT_DEVICE_INFO:".length());
851                                    int i = Integer.parseInt(s);
852                                    ItemInfoEvent e = new ItemInfoEvent(this, i);
853                                    for(ItemInfoListener l : llMIDI) l.itemInfoChanged(e);
854                            } catch(NumberFormatException x) {
855                                    getLogger().log (
856                                            Level.WARNING, "Unknown MIDI_INPUT_DEVICE_INFO format", x
857                                    );
858                            }
859                    } else if(s.startsWith("MIDI_INSTRUMENT_MAP_COUNT:")) {
860                            try {
861                                    s = s.substring("MIDI_INSTRUMENT_MAP_COUNT:".length());
862                                    int i = Integer.parseInt(s);
863                                    ItemCountEvent e = new ItemCountEvent(this, i);
864                                    for(ItemCountListener l : llMIMC) l.itemCountChanged(e);
865                            } catch(NumberFormatException x) {
866                                    getLogger().log (
867                                            Level.WARNING, "Unknown MIDI_INSTRUMENT_MAP_COUNT format", x
868                                    );
869                            }
870                    } else if(s.startsWith("MIDI_INSTRUMENT_MAP_INFO:")) {
871                            try {
872                                    s = s.substring("MIDI_INSTRUMENT_MAP_INFO:".length());
873                                    int i = Integer.parseInt(s);
874                                    ItemInfoEvent e = new ItemInfoEvent(this, i);
875                                    for(ItemInfoListener l : llMIMI) l.itemInfoChanged(e);
876                            } catch(NumberFormatException x) {
877                                    getLogger().log (
878                                            Level.WARNING, "Unknown MIDI_INSTRUMENT_MAP_INFO format", x
879                                    );
880                            }
881                    } else if(s.startsWith("MIDI_INSTRUMENT_COUNT:")) {
882                            try {
883                                    s = s.substring("MIDI_INSTRUMENT_COUNT:".length());
884                                    Integer[] i = parseIntList(s, ' ');
885                                    if(i.length != 2) {
886                                            getLogger().warning("Unknown MIDI_INSTRUMENT_COUNT format");
887                                            return;
888                                    }
889                                    
890                                    MidiInstrumentCountEvent e =
891                                            new MidiInstrumentCountEvent(this, i[0], i[1]);
892                                    
893                                    for(MidiInstrumentCountListener l : llMIC) {
894                                            l.instrumentCountChanged(e);
895                                    }
896                            } catch(Exception x) {
897                                    getLogger().log (
898                                            Level.WARNING, "Unknown MIDI_INSTRUMENT_COUNT format", x
899                                    );
900                            }
901                    } else if(s.startsWith("MIDI_INSTRUMENT_INFO:")) {
902                            try {
903                                    s = s.substring("MIDI_INSTRUMENT_INFO:".length());
904                                    Integer[] i = parseIntList(s, ' ');
905                                    if(i.length != 3) {
906                                            getLogger().warning("Unknown MIDI_INSTRUMENT_INFO format");
907                                            return;
908                                    }
909                                    
910                                    MidiInstrumentInfoEvent e =
911                                            new MidiInstrumentInfoEvent(this, i[0], i[1], i[2]);
912                                    for(MidiInstrumentInfoListener l : llMII) {
913                                            l.instrumentInfoChanged(e);
914                                    }
915                            } catch(Exception x) {
916                                    getLogger().log (
917                                            Level.WARNING, "Unknown MIDI_INSTRUMENT_INFO format", x
918                                    );
919                            }
920                    } else if(s.startsWith("FX_SEND_COUNT:")) {
921                            try {
922                                    s = s.substring("FX_SEND_COUNT:".length());
923                                    Integer[] i = parseIntList(s, ' ');
924                                    if(i.length != 2) {
925                                            getLogger().warning("Unknown FX_SEND_COUNT format");
926                                            return;
927                                    }
928                                    
929                                    FxSendCountEvent e = new FxSendCountEvent(this, i[0], i[1]);
930                                    
931                                    for(FxSendCountListener l : llFSC) l.fxSendCountChanged(e);
932                            } catch(Exception x) {
933                                    getLogger().log(Level.WARNING, "Unknown FX_SEND_COUNT format", x);
934                            }
935                    } else if(s.startsWith("FX_SEND_INFO:")) {
936                            try {
937                                    s = s.substring("FX_SEND_INFO:".length());
938                                    Integer[] i = parseIntList(s, ' ');
939                                    if(i.length != 2) {
940                                            getLogger().warning("Unknown FX_SEND_INFO format");
941                                            return;
942                                    }
943                                    
944                                    FxSendInfoEvent e = new FxSendInfoEvent(this, i[0], i[1]);
945                                    for(FxSendInfoListener l : llFSI) {
946                                            l.fxSendInfoChanged(e);
947                                    }
948                            } catch(Exception x) {
949                                    getLogger().log(Level.WARNING, "Unknown FX_SEND_INFO format", x);
950                            }
951                    } else if(s.startsWith("GLOBAL_INFO:")) {
952                            handleGlobalInfoEvent(s.substring("GLOBAL_INFO:".length()));
953                  } else if(s.startsWith("MISCELLANEOUS:")) {                  } else if(s.startsWith("MISCELLANEOUS:")) {
954                          s = s.substring("MISCELLANEOUS:".length());                          s = s.substring("MISCELLANEOUS:".length());
955                          MiscellaneousEvent e = new MiscellaneousEvent(this, s);                          MiscellaneousEvent e = new MiscellaneousEvent(this, s);
# Line 477  public class Client { Line 958  public class Client {
958          }          }
959                    
960          private void          private void
961            handleGlobalInfoEvent(String s) {
962                    try {
963                            if(s.startsWith("VOLUME ")) {
964                                    float f = Float.parseFloat(s.substring("VOLUME ".length()));
965                                    GlobalInfoEvent e = new GlobalInfoEvent(this, f);
966                                    for(GlobalInfoListener l : llGI) l.volumeChanged(e);
967                            } else if(s.startsWith("VOICES ")) {
968                                    int i = Integer.parseInt(s.substring("VOICES ".length()));
969                                    GlobalInfoEvent e = new GlobalInfoEvent(this, i, -1);
970                                    for(GlobalInfoListener l : llGI) l.voiceLimitChanged(e);
971                            } else if(s.startsWith("STREAMS ")) {
972                                    int i = Integer.parseInt(s.substring("STREAMS ".length()));
973                                    GlobalInfoEvent e = new GlobalInfoEvent(this, -1, i);
974                                    for(GlobalInfoListener l : llGI) l.streamLimitChanged(e);
975                            } else {
976                                    getLogger().info("Unknown GLOBAL_INFO format: " + s);
977                            }
978                    } catch(NumberFormatException x) {
979                            getLogger().log(Level.WARNING, "Unknown GLOBAL_INFO format", x);
980                    }
981            }
982            
983            private void
984          subscribe(String event) {          subscribe(String event) {
985                  if(!isConnected()) return;                  if(!getPrintOnlyMode()) {
986                            if(!isConnected()) return;
987                                    
988                  if(!eventThread.isAlive()) eventThread.start();                          if(!eventThread.isAlive()) eventThread.start();
989                    }
990                                    
991                  try {                  try {
992                          out.writeLine("SUBSCRIBE " + event);                          out.writeLine("SUBSCRIBE " + event);
993                          ResultSet rs = getEmptyResultSet();                          if(!getPrintOnlyMode()) getEmptyResultSet();
994                  } catch(Exception x) {                  } catch(Exception x) {
995                          getLogger().log (                          getLogger().log (
996                                  Level.WARNING,                                  Level.WARNING,
# Line 496  public class Client { Line 1002  public class Client {
1002                    
1003          private void          private void
1004          unsubscribe(String event) {          unsubscribe(String event) {
1005                  if(!isConnected()) return;                  if(!getPrintOnlyMode() && !isConnected()) return;
1006                                    
1007                  try {                  try {
1008                          out.writeLine("UNSUBSCRIBE " + event);                          out.writeLine("UNSUBSCRIBE " + event);
1009                          ResultSet rs = getEmptyResultSet();                          if(!getPrintOnlyMode()) getEmptyResultSet();
1010                  } catch(Exception x) {                  } catch(Exception x) {
1011                          getLogger().log (                          getLogger().log (
1012                                  Level.WARNING,                                  Level.WARNING,
# Line 512  public class Client { Line 1018  public class Client {
1018                    
1019          /**          /**
1020           * Registers the specified listener for receiving event messages.           * Registers the specified listener for receiving event messages.
1021             * Listeners can be registered regardless of the connection state.
1022             * @param l The <code>ItemCountListener</code> to register.
1023             */
1024            public synchronized void
1025            addAudioDeviceCountListener(ItemCountListener l) {
1026                    if(llAODC.isEmpty()) subscribe("AUDIO_OUTPUT_DEVICE_COUNT");
1027                    llAODC.add(l);
1028            }
1029            
1030            /**
1031             * Removes the specified listener.
1032             * Listeners can be removed regardless of the connection state.
1033             * @param l The <code>ItemCountListener</code> to remove.
1034             */
1035            public synchronized void
1036            removeAudioDeviceCountListener(ItemCountListener l) {
1037                    boolean b = llAODC.remove(l);
1038                    if(b && llAODC.isEmpty()) unsubscribe("AUDIO_OUTPUT_DEVICE_COUNT");
1039            }
1040            
1041            /**
1042             * Registers the specified listener for receiving event messages.
1043             * Listeners can be registered regardless of the connection state.
1044             * @param l The <code>ItemInfoListener</code> to register.
1045             */
1046            public synchronized void
1047            addAudioDeviceInfoListener(ItemInfoListener l) {
1048                    if(llAODI.isEmpty()) subscribe("AUDIO_OUTPUT_DEVICE_INFO");
1049                    llAODI.add(l);
1050            }
1051            
1052            /**
1053             * Removes the specified listener.
1054             * Listeners can be removed regardless of the connection state.
1055             * @param l The <code>ItemInfoListener</code> to remove.
1056             */
1057            public synchronized void
1058            removeAudioDeviceInfoListener(ItemInfoListener l) {
1059                    boolean b = llAODI.remove(l);
1060                    if(b && llAODI.isEmpty()) unsubscribe("AUDIO_OUTPUT_DEVICE_INFO");
1061            }
1062            
1063            /**
1064             * Registers the specified listener for receiving event messages.
1065           * Listeners can be removed regardless of the connection state.           * Listeners can be removed regardless of the connection state.
1066           * @param l The <code>BufferFillListener</code> to register.           * @param l The <code>BufferFillListener</code> to register.
1067           */           */
# Line 579  public class Client { Line 1129  public class Client {
1129          /**          /**
1130           * Registers the specified listener for receiving event messages.           * Registers the specified listener for receiving event messages.
1131           * Listeners can be registered regardless of the connection state.           * Listeners can be registered regardless of the connection state.
1132             * @param l The <code>FxSendCountListener</code> to register.
1133             */
1134            public synchronized void
1135            addFxSendCountListener(FxSendCountListener l) {
1136                    if(llFSC.isEmpty()) subscribe("FX_SEND_COUNT");
1137                    llFSC.add(l);
1138            }
1139            
1140            /**
1141             * Removes the specified listener.
1142             * Listeners can be removed regardless of the connection state.
1143             * @param l The <code>FxSendCountListener</code> to remove.
1144             */
1145            public synchronized void
1146            removeFxSendCountListener(FxSendCountListener l) {
1147                    boolean b = llFSC.remove(l);
1148                    if(b && llFSC.isEmpty()) unsubscribe("FX_SEND_COUNT");
1149            }
1150            
1151            /**
1152             * Registers the specified listener for receiving event messages.
1153             * Listeners can be registered regardless of the connection state.
1154             * @param l The <code>FxSendInfoListener</code> to register.
1155             */
1156            public synchronized void
1157            addFxSendInfoListener(FxSendInfoListener l) {
1158                    if(llFSI.isEmpty()) subscribe("FX_SEND_INFO");
1159                    llFSI.add(l);
1160            }
1161            
1162            /**
1163             * Removes the specified listener.
1164             * Listeners can be removed regardless of the connection state.
1165             * @param l The <code>FxSendInfoListener</code> to remove.
1166             */
1167            public synchronized void
1168            removeFxSendInfoListener(FxSendInfoListener l) {
1169                    boolean b = llFSI.remove(l);
1170                    if(b && llFSI.isEmpty()) unsubscribe("FX_SEND_INFO");
1171            }
1172            
1173            /**
1174             * Registers the specified listener for receiving event messages.
1175             * Listeners can be registered regardless of the connection state.
1176             * @param l The <code>ItemCountListener</code> to register.
1177             */
1178            public synchronized void
1179            addMidiDeviceCountListener(ItemCountListener l) {
1180                    if(llMIDC.isEmpty()) subscribe("MIDI_INPUT_DEVICE_COUNT");
1181                    llMIDC.add(l);
1182            }
1183            
1184            /**
1185             * Removes the specified listener.
1186             * Listeners can be removed regardless of the connection state.
1187             * @param l The <code>ItemCountListener</code> to remove.
1188             */
1189            public synchronized void
1190            removeMidiDeviceCountListener(ItemCountListener l) {
1191                    boolean b = llMIDC.remove(l);
1192                    if(b && llMIDC.isEmpty()) unsubscribe("MIDI_INPUT_DEVICE_COUNT");
1193            }
1194            
1195            /**
1196             * Registers the specified listener for receiving event messages.
1197             * Listeners can be registered regardless of the connection state.
1198             * @param l The <code>ItemInfoListener</code> to register.
1199             */
1200            public synchronized void
1201            addMidiDeviceInfoListener(ItemInfoListener l) {
1202                    if(llMIDI.isEmpty()) subscribe("MIDI_INPUT_DEVICE_INFO");
1203                    llMIDI.add(l);
1204            }
1205            
1206            /**
1207             * Removes the specified listener.
1208             * Listeners can be removed regardless of the connection state.
1209             * @param l The <code>ItemInfoListener</code> to remove.
1210             */
1211            public synchronized void
1212            removeMidiDeviceInfoListener(ItemInfoListener l) {
1213                    boolean b = llMIDI.remove(l);
1214                    if(b && llMIDI.isEmpty()) unsubscribe("MIDI_INPUT_DEVICE_INFO");
1215            }
1216            
1217            /**
1218             * Registers the specified listener for receiving event messages.
1219             * Listeners can be registered regardless of the connection state.
1220           * @param l The <code>MiscellaneousListener</code> to register.           * @param l The <code>MiscellaneousListener</code> to register.
1221           */           */
1222          public synchronized void          public synchronized void
# Line 645  public class Client { Line 1283  public class Client {
1283          /**          /**
1284           * Registers the specified listener for receiving event messages.           * Registers the specified listener for receiving event messages.
1285           * Listeners can be registered regardless of the connection state.           * Listeners can be registered regardless of the connection state.
1286             * @param l The <code>TotalStreamCountListener</code> to register.
1287             */
1288            public synchronized void
1289            addTotalStreamCountListener(TotalStreamCountListener l) {
1290                    if(llTSC.isEmpty()) subscribe("TOTAL_STREAM_COUNT");
1291                    llTSC.add(l);
1292            }
1293            
1294            /**
1295             * Removes the specified listener.
1296             * Listeners can be removed regardless of the connection state.
1297             * @param l The <code>TotalStreamCountListener</code> to remove.
1298             */
1299            public synchronized void
1300            removeTotalStreamCountListener(TotalStreamCountListener l) {
1301                    boolean b = llTSC.remove(l);
1302                    if(b && llTSC.isEmpty()) unsubscribe("TOTAL_STREAM_COUNT");
1303            }
1304            
1305            /**
1306             * Registers the specified listener for receiving event messages.
1307             * Listeners can be registered regardless of the connection state.
1308           * @param l The <code>TotalVoiceCountListener</code> to register.           * @param l The <code>TotalVoiceCountListener</code> to register.
1309           */           */
1310          public synchronized void          public synchronized void
# Line 665  public class Client { Line 1325  public class Client {
1325          }          }
1326                    
1327          /**          /**
1328             * Registers the specified listener for receiving event messages.
1329             * Listeners can be registered regardless of the connection state.
1330             * @param l The <code>ItemCountListener</code> to register.
1331             */
1332            public synchronized void
1333            addMidiInstrumentMapCountListener(ItemCountListener l) {
1334                    if(llMIMC.isEmpty()) subscribe("MIDI_INSTRUMENT_MAP_COUNT");
1335                    llMIMC.add(l);
1336            }
1337            
1338            /**
1339             * Removes the specified listener.
1340             * Listeners can be removed regardless of the connection state.
1341             * @param l The <code>ItemCountListener</code> to remove.
1342             */
1343            public synchronized void
1344            removeMidiInstrumentMapCountListener(ItemCountListener l) {
1345                    boolean b = llMIMC.remove(l);
1346                    if(b && llMIMC.isEmpty()) unsubscribe("MIDI_INSTRUMENT_MAP_COUNT");
1347            }
1348            
1349            /**
1350             * Registers the specified listener for receiving event messages.
1351             * Listeners can be registered regardless of the connection state.
1352             * @param l The <code>ItemInfoListener</code> to register.
1353             */
1354            public synchronized void
1355            addMidiInstrumentMapInfoListener(ItemInfoListener l) {
1356                    if(llMIMI.isEmpty()) subscribe("MIDI_INSTRUMENT_MAP_INFO");
1357                    llMIMI.add(l);
1358            }
1359            
1360            /**
1361             * Removes the specified listener.
1362             * Listeners can be removed regardless of the connection state.
1363             * @param l The <code>ItemInfoListener</code> to remove.
1364             */
1365            public synchronized void
1366            removeMidiInstrumentMapInfoListener(ItemInfoListener l) {
1367                    boolean b = llMIMI.remove(l);
1368                    if(b && llMIMI.isEmpty()) unsubscribe("MIDI_INSTRUMENT_MAP_INFO");
1369            }
1370            
1371            /**
1372             * Registers the specified listener for receiving event messages.
1373             * Listeners can be registered regardless of the connection state.
1374             * @param l The <code>MidiInstrumentCountListener</code> to register.
1375             */
1376            public synchronized void
1377            addMidiInstrumentCountListener(MidiInstrumentCountListener l) {
1378                    if(llMIC.isEmpty()) subscribe("MIDI_INSTRUMENT_COUNT");
1379                    llMIC.add(l);
1380            }
1381            
1382            /**
1383             * Removes the specified listener.
1384             * Listeners can be removed regardless of the connection state.
1385             * @param l The <code>MidiInstrumentCountListener</code> to remove.
1386             */
1387            public synchronized void
1388            removeMidiInstrumentCountListener(MidiInstrumentCountListener l) {
1389                    boolean b = llMIC.remove(l);
1390                    if(b && llMIC.isEmpty()) unsubscribe("MIDI_INSTRUMENT_COUNT");
1391            }
1392            
1393            /**
1394             * Registers the specified listener for receiving event messages.
1395             * Listeners can be registered regardless of the connection state.
1396             * @param l The <code>MidiInstrumentInfoListener</code> to register.
1397             */
1398            public synchronized void
1399            addMidiInstrumentInfoListener(MidiInstrumentInfoListener l) {
1400                    if(llMII.isEmpty()) subscribe("MIDI_INSTRUMENT_INFO");
1401                    llMII.add(l);
1402            }
1403            
1404            /**
1405             * Removes the specified listener.
1406             * Listeners can be removed regardless of the connection state.
1407             * @param l The <code>MidiInstrumentInfoListener</code> to remove.
1408             */
1409            public synchronized void
1410            removeMidiInstrumentInfoListener(MidiInstrumentInfoListener l) {
1411                    boolean b = llMII.remove(l);
1412                    if(b && llMII.isEmpty()) unsubscribe("MIDI_INSTRUMENT_INFO");
1413            }
1414            
1415            /**
1416             * Registers the specified listener for receiving event messages.
1417             * Listeners can be registered regardless of the connection state.
1418             * @param l The <code>DeviceMidiDataListener</code> to register.
1419             */
1420            public synchronized void
1421            addDeviceMidiDataListener(DeviceMidiDataListener l) {
1422                    if(llDMD.isEmpty()) subscribe("DEVICE_MIDI");
1423                    llDMD.add(l);
1424            }
1425            
1426            /**
1427             * Removes the specified listener.
1428             * Listeners can be removed regardless of the connection state.
1429             * @param l The <code>DeviceMidiDataListener</code> to remove.
1430             */
1431            public synchronized void
1432            removeDeviceMidiDataListener(DeviceMidiDataListener l) {
1433                    boolean b = llDMD.remove(l);
1434                    if(b && llDMD.isEmpty()) unsubscribe("DEVICE_MIDI");
1435            }
1436            
1437            /**
1438             * Registers the specified listener for receiving event messages.
1439             * Listeners can be registered regardless of the connection state.
1440             * @param l The <code>ChannelMidiDataListener</code> to register.
1441             */
1442            public synchronized void
1443            addChannelMidiDataListener(ChannelMidiDataListener l) {
1444                    if(llCMD.isEmpty()) subscribe("CHANNEL_MIDI");
1445                    llCMD.add(l);
1446            }
1447            
1448            /**
1449             * Removes the specified listener.
1450             * Listeners can be removed regardless of the connection state.
1451             * @param l The <code>ChannelMidiDataListener</code> to remove.
1452             */
1453            public synchronized void
1454            removeChannelMidiDataListener(ChannelMidiDataListener l) {
1455                    boolean b = llCMD.remove(l);
1456                    if(b && llCMD.isEmpty()) unsubscribe("CHANNEL_MIDI");
1457            }
1458            
1459            /**
1460             * Registers the specified listener for receiving event messages.
1461             * Listeners can be registered regardless of the connection state.
1462             * @param l The <code>InstrumentsDbListener</code> to register.
1463             */
1464            public synchronized void
1465            addInstrumentsDbListener(InstrumentsDbListener l) {
1466                    if(llID.isEmpty()) {
1467                            subscribe("DB_INSTRUMENT_DIRECTORY_COUNT");
1468                            subscribe("DB_INSTRUMENT_DIRECTORY_INFO");
1469                            subscribe("DB_INSTRUMENT_COUNT");
1470                            subscribe("DB_INSTRUMENT_INFO");
1471                            subscribe("DB_INSTRUMENTS_JOB_INFO");
1472                    }
1473                    llID.add(l);
1474            }
1475            
1476            /**
1477             * Removes the specified listener.
1478             * Listeners can be removed regardless of the connection state.
1479             * @param l The <code>InstrumentsDbListener</code> to remove.
1480             */
1481            public synchronized void
1482            removeInstrumentsDbListener(InstrumentsDbListener l) {
1483                    boolean b = llID.remove(l);
1484                    if(b && llID.isEmpty()) {
1485                            unsubscribe("DB_INSTRUMENT_DIRECTORY_COUNT");
1486                            unsubscribe("DB_INSTRUMENT_DIRECTORY_INFO");
1487                            unsubscribe("DB_INSTRUMENT_COUNT");
1488                            unsubscribe("DB_INSTRUMENT_INFO");
1489                            unsubscribe("DB_INSTRUMENTS_JOB_INFO");
1490                    }
1491            }
1492            
1493            /**
1494             * Registers the specified listener for receiving event messages.
1495             * Listeners can be registered regardless of the connection state.
1496             * @param l The <code>GlobalInfoListener</code> to register.
1497             */
1498            public synchronized void
1499            addGlobalInfoListener(GlobalInfoListener l) {
1500                    if(llGI.isEmpty()) subscribe("GLOBAL_INFO");
1501                    llGI.add(l);
1502            }
1503            
1504            /**
1505             * Removes the specified listener.
1506             * Listeners can be removed regardless of the connection state.
1507             * @param l The <code>GlobalInfoListener</code> to remove.
1508             */
1509            public synchronized void
1510            removeGlobalInfoListener(GlobalInfoListener l) {
1511                    boolean b = llGI.remove(l);
1512                    if(b && llGI.isEmpty()) unsubscribe("GLOBAL_INFO");
1513            }
1514            
1515            /**
1516           * Gets the number of all audio output drivers currently           * Gets the number of all audio output drivers currently
1517           * available for the LinuxSampler instance.           * available for the LinuxSampler instance.
1518           * @return The number of all audio output drivers currently           * @return The number of all audio output drivers currently
# Line 677  public class Client { Line 1525  public class Client {
1525          getAudioOutputDriverCount() throws IOException, LscpException, LSException {          getAudioOutputDriverCount() throws IOException, LscpException, LSException {
1526                  verifyConnection();                  verifyConnection();
1527                  out.writeLine("GET AVAILABLE_AUDIO_OUTPUT_DRIVERS");                  out.writeLine("GET AVAILABLE_AUDIO_OUTPUT_DRIVERS");
1528                    
1529                    if(getPrintOnlyMode()) return -1;
1530                    
1531                  String s = getSingleLineResultSet().getResult();                  String s = getSingleLineResultSet().getResult();
1532                  return parseInt(s);                  return parseInt(s);
1533          }          }
# Line 694  public class Client { Line 1545  public class Client {
1545          public synchronized AudioOutputDriver[]          public synchronized AudioOutputDriver[]
1546          getAudioOutputDrivers() throws IOException, LscpException, LSException {          getAudioOutputDrivers() throws IOException, LscpException, LSException {
1547                  String[] drivers = getAudioOutputDriverNames();                  String[] drivers = getAudioOutputDriverNames();
1548                    if(getPrintOnlyMode()) return null;
1549                    
1550                  AudioOutputDriver[] aod = new AudioOutputDriver[drivers.length];                  AudioOutputDriver[] aod = new AudioOutputDriver[drivers.length];
1551                                    
1552                  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 1568  public class Client {
1568          getAudioOutputDriverNames() throws IOException, LscpException, LSException {          getAudioOutputDriverNames() throws IOException, LscpException, LSException {
1569                  verifyConnection();                  verifyConnection();
1570                  out.writeLine("LIST AVAILABLE_AUDIO_OUTPUT_DRIVERS");                  out.writeLine("LIST AVAILABLE_AUDIO_OUTPUT_DRIVERS");
1571                    if(getPrintOnlyMode()) return null;
1572                  return parseList(getSingleLineResultSet().getResult());                  return parseList(getSingleLineResultSet().getResult());
1573          }          }
1574                    
1575          /**          /**
1576           * Gets detailed information about a specific audio output driver.           * Gets detailed information about a specific audio output driver.
1577           * @param driverName The name of the audio output driver.           * @param driverName The name of the audio output driver.
1578           *           * @param depList An optional list of dependences parameters.
1579           * @return An <code>AudioOutputDriver</code> object containing           * @return An <code>AudioOutputDriver</code> object containing
1580           * information about the specified audio output driver.           * information about the specified audio output driver.
1581           *           *
# Line 731  public class Client { Line 1585  public class Client {
1585           *           *
1586           * @see #getAudioOutputDriverNames           * @see #getAudioOutputDriverNames
1587           */           */
1588          private synchronized AudioOutputDriver          public synchronized AudioOutputDriver
1589          getAudioOutputDriverInfo(String driverName) throws IOException, LscpException, LSException {          getAudioOutputDriverInfo(String driverName, Parameter... depList)
1590                                            throws IOException, LscpException, LSException {
1591                    
1592                  verifyConnection();                  verifyConnection();
1593                  out.writeLine("GET AUDIO_OUTPUT_DRIVER INFO " + driverName);                  out.writeLine("GET AUDIO_OUTPUT_DRIVER INFO " + driverName);
1594                    if(getPrintOnlyMode()) return null;
1595                    
1596                  ResultSet rs = getMultiLineResultSet();                  ResultSet rs = getMultiLineResultSet();
1597                  AudioOutputDriver aod = new AudioOutputDriver(rs.getMultiLineResult());                  AudioOutputDriver aod = new AudioOutputDriver(rs.getMultiLineResult());
1598                  aod.setName(driverName);                  aod.setName(driverName);
1599                                    
1600                  for(String s : aod.getParameterNames())                  for(String s : aod.getParameterNames())
1601                          aod.addParameter(getAudioOutputDriverParameterInfo(driverName, s));                          aod.addParameter(getAudioOutputDriverParameterInfo(driverName, s, depList));
1602                                    
1603                  return aod;                  return aod;
1604          }          }
# Line 774  public class Client { Line 1632  public class Client {
1632                  StringBuffer args = new StringBuffer(driver);                  StringBuffer args = new StringBuffer(driver);
1633                  args.append(' ').append(param);                  args.append(' ').append(param);
1634                                    
1635                  for(Parameter p : deplist)                  for(Parameter p : deplist) {
1636                            if(p == null || p.getName() == null || p.getValue() == null) continue;
1637                          args.append(' ').append(p.getName()).append('=').append(p.getStringValue());                          args.append(' ').append(p.getName()).append('=').append(p.getStringValue());
1638                    }
1639                                    
1640                  out.writeLine("GET AUDIO_OUTPUT_DRIVER_PARAMETER INFO " + args.toString());                  out.writeLine("GET AUDIO_OUTPUT_DRIVER_PARAMETER INFO " + args.toString());
1641                    if(getPrintOnlyMode()) return null;
1642                                    
1643                  ResultSet rs = getMultiLineResultSet();                  ResultSet rs = getMultiLineResultSet();
1644                                    
# Line 835  public class Client { Line 1696  public class Client {
1696                  verifyConnection();                  verifyConnection();
1697                  StringBuffer args = new StringBuffer(aoDriver);                  StringBuffer args = new StringBuffer(aoDriver);
1698                                    
1699                  for(Parameter p : paramList)                  for(Parameter p : paramList) {
1700                            if(p == null || p.getName() == null || p.getValue() == null) continue;
1701                          args.append(' ').append(p.getName()).append('=').append(p.getStringValue());                          args.append(' ').append(p.getName()).append('=').append(p.getStringValue());
1702                    }
1703                                    
1704                  out.writeLine("CREATE AUDIO_OUTPUT_DEVICE " + args.toString());                  out.writeLine("CREATE AUDIO_OUTPUT_DEVICE " + args.toString());
1705                    if(getPrintOnlyMode()) return -1;
1706                    
1707                  ResultSet rs = getEmptyResultSet();                  ResultSet rs = getEmptyResultSet();
1708                                    
1709                  return rs.getIndex();                  return rs.getIndex();
# Line 846  public class Client { Line 1711  public class Client {
1711                    
1712          /**          /**
1713           * Destroys already created audio output device.           * Destroys already created audio output device.
1714           * @param deviceID The ID of the audio output device to be destroyed.           * @param deviceId The ID of the audio output device to be destroyed.
1715           * @throws IOException If some I/O error occurs.           * @throws IOException If some I/O error occurs.
1716           * @throws LSException If the destroying of the audio output device failed.           * @throws LSException If the destroying of the audio output device failed.
1717           * @throws LscpException If LSCP protocol corruption occurs.           * @throws LscpException If LSCP protocol corruption occurs.
1718           * @see #getAudioOutputDevices           * @see #getAudioOutputDevices
1719           */           */
1720          public synchronized void          public synchronized void
1721          destroyAudioOutputDevice(int deviceID) throws IOException, LSException, LscpException {          destroyAudioOutputDevice(int deviceId) throws IOException, LSException, LscpException {
1722                  verifyConnection();                  verifyConnection();
1723                  out.writeLine("DESTROY AUDIO_OUTPUT_DEVICE " + deviceID);                  out.writeLine("DESTROY AUDIO_OUTPUT_DEVICE " + deviceId);
1724                    if(getPrintOnlyMode()) return;
1725                    
1726                  ResultSet rs = getEmptyResultSet();                  ResultSet rs = getEmptyResultSet();
1727          }          }
1728                    
1729          /**          /**
1730           * Enables/disables the specified audio output device.           * Enables/disables the specified audio output device.
1731           * @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.
1732           * @param enable If <code>true</code> the audio output device is enabled,           * @param enable If <code>true</code> the audio output device is enabled,
1733           * else the device is disabled.           * else the device is disabled.
1734           * @throws IOException If some I/O error occurs.           * @throws IOException If some I/O error occurs.
1735           * @throws LSException If there is no audio output           * @throws LSException If there is no audio output
1736           * device with numerical ID <code>deviceID</code>.           * device with numerical ID <code>deviceId</code>.
1737           * @throws LscpException If LSCP protocol corruption occurs.           * @throws LscpException If LSCP protocol corruption occurs.
1738           */           */
1739          public void          public void
1740          enableAudioOutputDevice(int deviceID, boolean enable)          enableAudioOutputDevice(int deviceId, boolean enable)
1741                                  throws IOException, LSException, LscpException {                                  throws IOException, LSException, LscpException {
1742                                    
1743                  setAudioOutputDeviceParameter(deviceID, new BoolParameter("ACTIVE", enable));                  setAudioOutputDeviceParameter(deviceId, new BoolParameter("ACTIVE", enable));
1744          }          }
1745                    
1746          /**          /**
# Line 887  public class Client { Line 1754  public class Client {
1754          getAudioOutputDeviceCount() throws IOException, LscpException, LSException {          getAudioOutputDeviceCount() throws IOException, LscpException, LSException {
1755                  verifyConnection();                  verifyConnection();
1756                  out.writeLine("GET AUDIO_OUTPUT_DEVICES");                  out.writeLine("GET AUDIO_OUTPUT_DEVICES");
1757                    if(getPrintOnlyMode()) return -1;
1758                    
1759                  String s = getSingleLineResultSet().getResult();                  String s = getSingleLineResultSet().getResult();
1760                  return parseInt(s);                  return parseInt(s);
1761          }          }
# Line 902  public class Client { Line 1771  public class Client {
1771          public synchronized AudioOutputDevice[]          public synchronized AudioOutputDevice[]
1772          getAudioOutputDevices() throws IOException, LscpException, LSException {          getAudioOutputDevices() throws IOException, LscpException, LSException {
1773                  Integer[] idS = getAudioOutputDeviceIDs();                  Integer[] idS = getAudioOutputDeviceIDs();
1774                    if(getPrintOnlyMode()) return null;
1775                    
1776                  AudioOutputDevice[] devices = new AudioOutputDevice[idS.length];                  AudioOutputDevice[] devices = new AudioOutputDevice[idS.length];
1777                                    
1778                  for(int i = 0; i < devices.length; i++)                  for(int i = 0; i < devices.length; i++)
# Line 922  public class Client { Line 1793  public class Client {
1793          getAudioOutputDeviceIDs() throws IOException, LscpException, LSException {          getAudioOutputDeviceIDs() throws IOException, LscpException, LSException {
1794                  verifyConnection();                  verifyConnection();
1795                  out.writeLine("LIST AUDIO_OUTPUT_DEVICES");                  out.writeLine("LIST AUDIO_OUTPUT_DEVICES");
1796                    if(getPrintOnlyMode()) return null;
1797                    
1798                  return parseIntList(getSingleLineResultSet().getResult());                  return parseIntList(getSingleLineResultSet().getResult());
1799          }          }
1800                    
1801          /**          /**
1802           * Gets the current settings of a specific, already created audio output device.           * Gets the current settings of a specific, already created audio output device.
1803           *           *
1804           * @param deviceID Specifies the numerical ID of the audio output device.           * @param deviceId Specifies the numerical ID of the audio output device.
1805           *           *
1806           * @return An <code>AudioOutputDevice</code> instance containing information           * @return An <code>AudioOutputDevice</code> instance containing information
1807           * about the specified device.           * about the specified device.
# Line 936  public class Client { Line 1809  public class Client {
1809           * @throws IOException If some I/O error occurs.           * @throws IOException If some I/O error occurs.
1810           * @throws LscpException If LSCP protocol corruption occurs.           * @throws LscpException If LSCP protocol corruption occurs.
1811           * @throws LSException If there is no audio output device           * @throws LSException If there is no audio output device
1812           * with device id <code>deviceID</code>.           * with device id <code>deviceId</code>.
1813           *           *
1814           * @see #getAudioOutputDevices           * @see #getAudioOutputDevices
1815           */           */
1816          public synchronized AudioOutputDevice          public synchronized AudioOutputDevice
1817          getAudioOutputDeviceInfo(int deviceID) throws IOException, LscpException, LSException {          getAudioOutputDeviceInfo(int deviceId) throws IOException, LscpException, LSException {
1818                  verifyConnection();                  verifyConnection();
1819                  out.writeLine("GET AUDIO_OUTPUT_DEVICE INFO " + deviceID);                  out.writeLine("GET AUDIO_OUTPUT_DEVICE INFO " + deviceId);
1820                    if(getPrintOnlyMode()) return null;
1821                                    
1822                  ResultSet rs = getMultiLineResultSet();                  ResultSet rs = getMultiLineResultSet();
1823                                    
1824                  String[] lnS = rs.getMultiLineResult();                  String[] lnS = rs.getMultiLineResult();
1825                                    
1826                  AudioOutputDevice aod = new AudioOutputDevice();                  AudioOutputDevice aod = new AudioOutputDevice();
1827                  aod.setDeviceID(deviceID);                  aod.setDeviceId(deviceId);
1828                  Parameter<Integer> channels;                  Parameter<Integer> channels;
1829                  Parameter<Integer> samplerate;                  Parameter<Integer> samplerate;
1830                                    
# Line 968  public class Client { Line 1842  public class Client {
1842                                  int count = channels.getValue() > 0 ? channels.getValue() : 0;                                  int count = channels.getValue() > 0 ? channels.getValue() : 0;
1843                                  AudioOutputChannel[] aoc = new AudioOutputChannel[count];                                  AudioOutputChannel[] aoc = new AudioOutputChannel[count];
1844                                  for(int i = 0; i < count; i++) {                                  for(int i = 0; i < count; i++) {
1845                                          aoc[i] = this.getAudioOutputChannelInfo(deviceID, i);                                          aoc[i] = getAudioOutputChannelInfo(deviceId, i);
1846                                  }                                  }
1847                                  aod.setAudioChannels(aoc);                                  aod.setAudioChannels(aoc);
1848                          } else if(s.startsWith("SAMPLERATE: ")) {                          } else if(s.startsWith("SAMPLERATE: ")) {
# Line 1005  public class Client { Line 1879  public class Client {
1879          /**          /**
1880           * Alters a specific setting of a created audio output device.           * Alters a specific setting of a created audio output device.
1881           *           *
1882           * @param deviceID The numerical ID of the audio output device.           * @param deviceId The numerical ID of the audio output device.
1883           * @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
1884           * and the new value for this parameter.           * and the new value for this parameter.
1885           *           *
# Line 1013  public class Client { Line 1887  public class Client {
1887           * @throws LscpException If LSCP protocol corruption occurs.           * @throws LscpException If LSCP protocol corruption occurs.
1888           * @throws LSException If           * @throws LSException If
1889           * <ul>           * <ul>
1890           * <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>;
1891           * <li>There is no device parameter with the specified name;           * <li>There is no device parameter with the specified name;
1892           * <li>The device parameter is readonly;           * <li>The device parameter is readonly;
1893           * <li>The device parameter is from different type.           * <li>The device parameter is from different type.
# Line 1023  public class Client { Line 1897  public class Client {
1897           * @see #getAudioOutputDeviceInfo           * @see #getAudioOutputDeviceInfo
1898           */           */
1899          public synchronized void          public synchronized void
1900          setAudioOutputDeviceParameter(int deviceID, Parameter prm)          setAudioOutputDeviceParameter(int deviceId, Parameter prm)
1901                                                  throws IOException, LscpException, LSException {                                                  throws IOException, LscpException, LSException {
1902                                    
1903                  verifyConnection();                  verifyConnection();
1904                  String kv = prm.getName() + '=' + prm.getStringValue();                  String kv = prm.getName() + '=' + prm.getStringValue();
1905                  out.writeLine("SET AUDIO_OUTPUT_DEVICE_PARAMETER " + deviceID + ' ' + kv);                  out.writeLine("SET AUDIO_OUTPUT_DEVICE_PARAMETER " + deviceId + ' ' + kv);
1906                    if(getPrintOnlyMode()) return;
1907                                    
1908                  ResultSet rs = getEmptyResultSet();                  ResultSet rs = getEmptyResultSet();
1909          }          }
1910                    
1911          /**          /**
1912           * Changes the channels number of the speicifed audio output device.           * Changes the channel number of the speicifed audio output device.
1913           * @param deviceID The numerical ID of the audio output device.           * @param deviceId The numerical ID of the audio output device.
1914           * @param channels The new number of audio output channels.           * @param channels The new number of audio output channels.
1915           *           *
1916           * @throws IOException If an I/O error occurs.           * @throws IOException If an I/O error occurs.
1917           * @throws LscpException If LSCP protocol corruption occurs.           * @throws LscpException If LSCP protocol corruption occurs.
1918           * @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
1919           * if <code>channels</code> number is out of range.           * if <code>channels</code> number is out of range.
1920           *           *
1921           * @see #getAudioOutputChannelInfo           * @see #getAudioOutputChannelInfo
1922           */           */
1923          public synchronized void          public synchronized void
1924          setAudioOutputChannelCount(int deviceID, int channels)          setAudioOutputChannelCount(int deviceId, int channels)
1925                                          throws IOException, LscpException, LSException {                                          throws IOException, LscpException, LSException {
1926                                    
1927                  setAudioOutputDeviceParameter(deviceID, new IntParameter("CHANNELS", channels));                  setAudioOutputDeviceParameter(deviceId, new IntParameter("CHANNELS", channels));
1928          }          }
1929                    
1930          /**          /**
1931           * Gets information about an audio channel.           * Gets information about an audio channel.
1932           *           *
1933           * @param deviceID The numerical ID of the audio output device.           * @param deviceId The numerical ID of the audio output device.
1934           * @param audioChn The audio channel number.           * @param audioChn The audio channel number.
1935           *           *
1936           * @return An <code>AudioOutputChannel</code> instance containing the           * @return An <code>AudioOutputChannel</code> instance containing the
# Line 1065  public class Client { Line 1940  public class Client {
1940           * @throws LscpException If LSCP protocol corruption occurs.           * @throws LscpException If LSCP protocol corruption occurs.
1941           * @throws LSException If           * @throws LSException If
1942           * <ul>           * <ul>
1943           * <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>;
1944           * <li><code>audioChn</code> is not a valid channel number;           * <li><code>audioChn</code> is not a valid channel number;
1945           * </ul>           * </ul>
1946           *           *
# Line 1073  public class Client { Line 1948  public class Client {
1948           * @see #getAudioOutputDeviceInfo           * @see #getAudioOutputDeviceInfo
1949           */           */
1950          public synchronized AudioOutputChannel          public synchronized AudioOutputChannel
1951          getAudioOutputChannelInfo(int deviceID, int audioChn)          getAudioOutputChannelInfo(int deviceId, int audioChn)
1952                                                  throws IOException, LscpException, LSException {                                                  throws IOException, LscpException, LSException {
1953                                    
1954                  verifyConnection();                  verifyConnection();
1955                  out.writeLine("GET AUDIO_OUTPUT_CHANNEL INFO " + deviceID + ' ' + audioChn);                  out.writeLine("GET AUDIO_OUTPUT_CHANNEL INFO " + deviceId + ' ' + audioChn);
1956                    if(getPrintOnlyMode()) return null;
1957                                    
1958                  ResultSet rs = getMultiLineResultSet();                  ResultSet rs = getMultiLineResultSet();
1959                                    
# Line 1088  public class Client { Line 1964  public class Client {
1964                          if(s.startsWith("NAME: ")) {                          if(s.startsWith("NAME: ")) {
1965                                  s = s.substring("NAME: ".length());                                  s = s.substring("NAME: ".length());
1966                                  Parameter<String> prm = getAudioOutputChannelParameterInfo (                                  Parameter<String> prm = getAudioOutputChannelParameterInfo (
1967                                          deviceID, audioChn, "NAME"                                          deviceId, audioChn, "NAME"
1968                                  );                                  );
1969                                  prm.setValue(removeQuotation(s));                                  prm.setValue(removeQuotation(s));
1970                                  aoc.setNameParameter(prm);                                  aoc.setNameParameter(prm);
1971                          } else if(s.startsWith("IS_MIX_CHANNEL: ")) {                          } else if(s.startsWith("IS_MIX_CHANNEL: ")) {
1972                                  s = s.substring("IS_MIX_CHANNEL: ".length());                                  s = s.substring("IS_MIX_CHANNEL: ".length());
1973                                  Parameter<Boolean> prm = getAudioOutputChannelParameterInfo (                                  Parameter<Boolean> prm = getAudioOutputChannelParameterInfo (
1974                                          deviceID, audioChn, "IS_MIX_CHANNEL"                                          deviceId, audioChn, "IS_MIX_CHANNEL"
1975                                  );                                  );
1976                                  prm.setValue(Boolean.parseBoolean(s));                                  prm.setValue(Boolean.parseBoolean(s));
1977                                  aoc.setMixChannelParameter(prm);                                  aoc.setMixChannelParameter(prm);
1978                          } else if(s.startsWith("MIX_CHANNEL_DESTINATION: ")) {                          } else if(s.startsWith("MIX_CHANNEL_DESTINATION: ")) {
1979                                  s = s.substring("MIX_CHANNEL_DESTINATION: ".length());                                  s = s.substring("MIX_CHANNEL_DESTINATION: ".length());
1980                                  Parameter<Integer> prm = getAudioOutputChannelParameterInfo (                                  Parameter<Integer> prm = getAudioOutputChannelParameterInfo (
1981                                          deviceID, audioChn, "MIX_CHANNEL_DESTINATION"                                          deviceId, audioChn, "MIX_CHANNEL_DESTINATION"
1982                                  );                                  );
1983                                  prm.setValue(parseInt(s));                                  prm.setValue(parseInt(s));
1984                                  aoc.setMixChannelDestParameter(prm);                                  aoc.setMixChannelDestParameter(prm);
# Line 1113  public class Client { Line 1989  public class Client {
1989                                  );                                  );
1990                                                                    
1991                                  Parameter prm = getAudioOutputChannelParameterInfo (                                  Parameter prm = getAudioOutputChannelParameterInfo (
1992                                          deviceID, audioChn, s.substring(0, i)                                          deviceId, audioChn, s.substring(0, i)
1993                                  );                                  );
1994                                                                    
1995                                  s = s.substring(i + 2);                                  s = s.substring(i + 2);
# Line 1129  public class Client { Line 2005  public class Client {
2005          /**          /**
2006           * Gets detailed information about a specific audio output channel parameter.           * Gets detailed information about a specific audio output channel parameter.
2007           *           *
2008           * @param devID The numerical ID of the audio output device.           * @param devId The numerical ID of the audio output device.
2009           * @param chan The audio channel number.           * @param chan The audio channel number.
2010           * @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.
2011           *           *
# Line 1140  public class Client { Line 2016  public class Client {
2016           * @throws LscpException If LSCP protocol corruption occurs.           * @throws LscpException If LSCP protocol corruption occurs.
2017           * @throws LSException If           * @throws LSException If
2018           * <ul>           * <ul>
2019           * <li><code>devID</code> is not a valid device ID;           * <li><code>devId</code> is not a valid device ID;
2020           * <li><code>chan</code> is not a valid channel number;           * <li><code>chan</code> is not a valid channel number;
2021           * <li>There is no channel parameter with the specified name.           * <li>There is no channel parameter with the specified name.
2022           * </ul>           * </ul>
# Line 1149  public class Client { Line 2025  public class Client {
2025           * @see #getAudioOutputChannelInfo           * @see #getAudioOutputChannelInfo
2026           */           */
2027          public synchronized Parameter          public synchronized Parameter
2028          getAudioOutputChannelParameterInfo(int devID, int chan, String param)          getAudioOutputChannelParameterInfo(int devId, int chan, String param)
2029                                                  throws IOException, LscpException, LSException {                                                  throws IOException, LscpException, LSException {
2030                                    
2031                  verifyConnection();                  verifyConnection();
2032                  String args = devID + " " + chan + " " + param;                  String args = devId + " " + chan + " " + param;
2033                  out.writeLine("GET AUDIO_OUTPUT_CHANNEL_PARAMETER INFO " + args);                  out.writeLine("GET AUDIO_OUTPUT_CHANNEL_PARAMETER INFO " + args);
2034                    if(getPrintOnlyMode()) return null;
2035                                    
2036                  ResultSet rs = getMultiLineResultSet();                  ResultSet rs = getMultiLineResultSet();
2037                                    
# Line 1191  public class Client { Line 2068  public class Client {
2068          /**          /**
2069           * Alters a specific setting of an audio output channel.           * Alters a specific setting of an audio output channel.
2070           *           *
2071           * @param devID The numerical ID of the audio device.           * @param devId The numerical ID of the audio device.
2072           * @param chn The audio channel number.           * @param chn The audio channel number.
2073           * @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
2074           * and the new value for this parameter.           * and the new value for this parameter.
# Line 1200  public class Client { Line 2077  public class Client {
2077           * @throws LscpException If LSCP protocol corruption occurs.           * @throws LscpException If LSCP protocol corruption occurs.
2078           * @throws LSException If           * @throws LSException If
2079           * <ul>           * <ul>
2080           * <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>;
2081           * <li><code>chn</code> is not a valid channel number;           * <li><code>chn</code> is not a valid channel number;
2082           * <li>There is no channel parameter with the specified name;           * <li>There is no channel parameter with the specified name;
2083           * <li>The channel parameter is readonly;           * <li>The channel parameter is readonly;
# Line 1211  public class Client { Line 2088  public class Client {
2088           * @see #getAudioOutputChannelInfo           * @see #getAudioOutputChannelInfo
2089           */           */
2090          public synchronized void          public synchronized void
2091          setAudioOutputChannelParameter(int devID, int chn,  Parameter prm)          setAudioOutputChannelParameter(int devId, int chn,  Parameter prm)
2092                                                  throws IOException, LscpException, LSException {                                                  throws IOException, LscpException, LSException {
2093                                    
2094                  verifyConnection();                  verifyConnection();
2095                  String args = devID + " " + chn + " " + prm.getName() + '=' + prm.getStringValue();                  String args = devId + " " + chn + " " + prm.getName() + '=' + prm.getStringValue();
2096                  out.writeLine("SET AUDIO_OUTPUT_CHANNEL_PARAMETER " + args);                  out.writeLine("SET AUDIO_OUTPUT_CHANNEL_PARAMETER " + args);
2097                    if(getPrintOnlyMode()) return;
2098                                    
2099                  ResultSet rs = getEmptyResultSet();                  ResultSet rs = getEmptyResultSet();
2100          }          }
# Line 1232  public class Client { Line 2110  public class Client {
2110          getMidiInputDriverCount() throws IOException, LscpException, LSException {          getMidiInputDriverCount() throws IOException, LscpException, LSException {
2111                  verifyConnection();                  verifyConnection();
2112                  out.writeLine("GET AVAILABLE_MIDI_INPUT_DRIVERS");                  out.writeLine("GET AVAILABLE_MIDI_INPUT_DRIVERS");
2113                    if(getPrintOnlyMode()) return -1;
2114                    
2115                  String s = getSingleLineResultSet().getResult();                  String s = getSingleLineResultSet().getResult();
2116                  return parseInt(s);                  return parseInt(s);
2117          }          }
# Line 1249  public class Client { Line 2129  public class Client {
2129          public synchronized MidiInputDriver[]          public synchronized MidiInputDriver[]
2130          getMidiInputDrivers() throws IOException, LscpException, LSException {          getMidiInputDrivers() throws IOException, LscpException, LSException {
2131                  String[] drivers = getMidiInputDriverNames();                  String[] drivers = getMidiInputDriverNames();
2132                    if(getPrintOnlyMode()) return null;
2133                    
2134                  MidiInputDriver[] mid = new MidiInputDriver[drivers.length];                  MidiInputDriver[] mid = new MidiInputDriver[drivers.length];
2135                                    
2136                  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 2152  public class Client {
2152          getMidiInputDriverNames() throws IOException, LscpException, LSException {          getMidiInputDriverNames() throws IOException, LscpException, LSException {
2153                  verifyConnection();                  verifyConnection();
2154                  out.writeLine("LIST AVAILABLE_MIDI_INPUT_DRIVERS");                  out.writeLine("LIST AVAILABLE_MIDI_INPUT_DRIVERS");
2155                    if(getPrintOnlyMode()) return null;
2156                    
2157                  return parseList(getSingleLineResultSet().getResult());                  return parseList(getSingleLineResultSet().getResult());
2158          }          }
2159                    
2160          /**          /**
2161           * Gets detailed information about a specific MIDI input driver.           * Gets detailed information about a specific MIDI input driver.
2162           * @param driverName The name of the MIDI input driver.           * @param driverName The name of the MIDI input driver.
2163           *           * @param depList An optional list of dependences parameters.
2164           * @return A <code>MidiInputDriver</code> object containing           * @return A <code>MidiInputDriver</code> object containing
2165           * information about the specified MIDI input driver.           * information about the specified MIDI input driver.
2166           *           *
# Line 1286  public class Client { Line 2170  public class Client {
2170           *           *
2171           * @see #getMidiInputDriverNames           * @see #getMidiInputDriverNames
2172           */           */
2173          private synchronized MidiInputDriver          public synchronized MidiInputDriver
2174          getMidiInputDriverInfo(String driverName) throws IOException, LscpException, LSException {          getMidiInputDriverInfo(String driverName, Parameter... depList)
2175                                            throws IOException, LscpException, LSException {
2176                    
2177                  verifyConnection();                  verifyConnection();
2178                  out.writeLine("GET MIDI_INPUT_DRIVER INFO " + driverName);                  out.writeLine("GET MIDI_INPUT_DRIVER INFO " + driverName);
2179                    if(getPrintOnlyMode()) return null;
2180                    
2181                  ResultSet rs = getMultiLineResultSet();                  ResultSet rs = getMultiLineResultSet();
2182                                    
2183                  MidiInputDriver mid = new MidiInputDriver(rs.getMultiLineResult());                  MidiInputDriver mid = new MidiInputDriver(rs.getMultiLineResult());
2184                  mid.setName(driverName);                  mid.setName(driverName);
2185                                    
2186                  for(String s : mid.getParameterNames())                  for(String s : mid.getParameterNames())
2187                          mid.addParameter(getMidiInputDriverParameterInfo(driverName, s));                          mid.addParameter(getMidiInputDriverParameterInfo(driverName, s, depList));
2188                                    
2189                  return mid;                  return mid;
2190          }          }
# Line 1330  public class Client { Line 2218  public class Client {
2218                  StringBuffer args = new StringBuffer(driver);                  StringBuffer args = new StringBuffer(driver);
2219                  args.append(' ').append(param);                  args.append(' ').append(param);
2220                                    
2221                  for(Parameter p : deplist)                  for(Parameter p : deplist) {
2222                            if(p == null || p.getName() == null || p.getValue() == null) continue;
2223                          args.append(' ').append(p.getName()).append('=').append(p.getStringValue());                          args.append(' ').append(p.getName()).append('=').append(p.getStringValue());
2224                    }
2225                                    
2226                  out.writeLine("GET MIDI_INPUT_DRIVER_PARAMETER INFO " + args.toString());                  out.writeLine("GET MIDI_INPUT_DRIVER_PARAMETER INFO " + args.toString());
2227                    if(getPrintOnlyMode()) return null;
2228                                    
2229                  ResultSet rs = getMultiLineResultSet();                  ResultSet rs = getMultiLineResultSet();
2230                                    
# Line 1392  public class Client { Line 2283  public class Client {
2283                  verifyConnection();                  verifyConnection();
2284                  StringBuffer args = new StringBuffer(miDriver);                  StringBuffer args = new StringBuffer(miDriver);
2285                                    
2286                  for(Parameter p : paramList)                  for(Parameter p : paramList) {
2287                            if(p == null || p.getName() == null || p.getValue() == null) continue;
2288                          args.append(' ').append(p.getName()).append('=').append(p.getStringValue());                          args.append(' ').append(p.getName()).append('=').append(p.getStringValue());
2289                    }
2290                                    
2291                  out.writeLine("CREATE MIDI_INPUT_DEVICE " + args.toString());                  out.writeLine("CREATE MIDI_INPUT_DEVICE " + args.toString());
2292                    if(getPrintOnlyMode()) return -1;
2293                    
2294                  ResultSet rs = getEmptyResultSet();                  ResultSet rs = getEmptyResultSet();
2295                                    
2296                  return rs.getIndex();                  return rs.getIndex();
# Line 1403  public class Client { Line 2298  public class Client {
2298                    
2299          /**          /**
2300           * Destroys already created MIDI input device.           * Destroys already created MIDI input device.
2301           * @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.
2302           * @throws IOException If some I/O error occurs.           * @throws IOException If some I/O error occurs.
2303           * @throws LSException If the destroying of the MIDI input device failed.           * @throws LSException If the destroying of the MIDI input device failed.
2304           * @throws LscpException If LSCP protocol corruption occurs.           * @throws LscpException If LSCP protocol corruption occurs.
# Line 1411  public class Client { Line 2306  public class Client {
2306           * @see #getMidiInputDevices           * @see #getMidiInputDevices
2307           */           */
2308          public synchronized void          public synchronized void
2309          destroyMidiInputDevice(int deviceID) throws IOException, LSException, LscpException {          destroyMidiInputDevice(int deviceId) throws IOException, LSException, LscpException {
2310                  verifyConnection();                  verifyConnection();
2311                  out.writeLine("DESTROY MIDI_INPUT_DEVICE " + deviceID);                  out.writeLine("DESTROY MIDI_INPUT_DEVICE " + deviceId);
2312                    if(getPrintOnlyMode()) return;
2313                    
2314                  ResultSet rs = getEmptyResultSet();                  ResultSet rs = getEmptyResultSet();
2315          }          }
2316                    
2317          /**          /**
2318           * Enables/disables the specified MIDI input device.           * Enables/disables the specified MIDI input device.
2319           * @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.
2320           * @param enable If <code>true</code> the MIDI input device is enabled,           * @param enable If <code>true</code> the MIDI input device is enabled,
2321           * else the device is disabled.           * else the device is disabled.
2322           * @throws IOException If some I/O error occurs.           * @throws IOException If some I/O error occurs.
2323           * @throws LSException If there is no MIDI input           * @throws LSException If there is no MIDI input
2324           * device with numerical ID <code>deviceID</code>.           * device with numerical ID <code>deviceId</code>.
2325           * @throws LscpException If LSCP protocol corruption occurs.           * @throws LscpException If LSCP protocol corruption occurs.
2326           */           */
2327          public void          public void
2328          enableMidiInputDevice(int deviceID, boolean enable)          enableMidiInputDevice(int deviceId, boolean enable)
2329                                  throws IOException, LSException, LscpException {                                  throws IOException, LSException, LscpException {
2330                                    
2331                  setMidiInputDeviceParameter(deviceID, new BoolParameter("ACTIVE", enable));                  setMidiInputDeviceParameter(deviceId, new BoolParameter("ACTIVE", enable));
2332          }          }
2333                    
2334          /**          /**
# Line 1445  public class Client { Line 2342  public class Client {
2342          getMidiInputDeviceCount() throws IOException, LscpException, LSException {          getMidiInputDeviceCount() throws IOException, LscpException, LSException {
2343                  verifyConnection();                  verifyConnection();
2344                  out.writeLine("GET MIDI_INPUT_DEVICES");                  out.writeLine("GET MIDI_INPUT_DEVICES");
2345                    if(getPrintOnlyMode()) return -1;
2346                    
2347                  String s = getSingleLineResultSet().getResult();                  String s = getSingleLineResultSet().getResult();
2348                  return parseInt(s);                  return parseInt(s);
2349          }          }
# Line 1463  public class Client { Line 2362  public class Client {
2362          public synchronized MidiInputDevice[]          public synchronized MidiInputDevice[]
2363          getMidiInputDevices() throws IOException, LscpException, LSException {          getMidiInputDevices() throws IOException, LscpException, LSException {
2364                  Integer[] idS = getMidiInputDeviceIDs();                  Integer[] idS = getMidiInputDeviceIDs();
2365                    if(getPrintOnlyMode()) return null;
2366                    
2367                  MidiInputDevice[] devices = new MidiInputDevice[idS.length];                  MidiInputDevice[] devices = new MidiInputDevice[idS.length];
2368                                    
2369                  for(int i = 0; i < devices.length; i++)                  for(int i = 0; i < devices.length; i++)
# Line 1486  public class Client { Line 2387  public class Client {
2387          getMidiInputDeviceIDs() throws IOException, LscpException, LSException {          getMidiInputDeviceIDs() throws IOException, LscpException, LSException {
2388                  verifyConnection();                  verifyConnection();
2389                  out.writeLine("LIST MIDI_INPUT_DEVICES");                  out.writeLine("LIST MIDI_INPUT_DEVICES");
2390                    if(getPrintOnlyMode()) return null;
2391                    
2392                  return parseIntList(getSingleLineResultSet().getResult());                  return parseIntList(getSingleLineResultSet().getResult());
2393          }          }
2394                    
2395          /**          /**
2396           * Gets the current settings of a specific, already created MIDI input device.           * Gets the current settings of a specific, already created MIDI input device.
2397           *           *
2398           * @param deviceID Specifies the numerical ID of the MIDI input device.           * @param deviceId Specifies the numerical ID of the MIDI input device.
2399           *           *
2400           * @return An <code>MidiInputDevice</code> instance containing information           * @return A <code>MidiInputDevice</code> instance containing information
2401           * about the specified device.           * about the specified device.
2402           *           *
2403           * @throws IOException If some I/O error occurs.           * @throws IOException If some I/O error occurs.
2404           * @throws LscpException If LSCP protocol corruption occurs.           * @throws LscpException If LSCP protocol corruption occurs.
2405           * @throws LSException If there is no MIDI input device           * @throws LSException If there is no MIDI input device
2406           * with device id <code>deviceID</code>.           * with device id <code>deviceId</code>.
2407           *           *
2408           * @see #getMidiInputDevices           * @see #getMidiInputDevices
2409           */           */
2410          public synchronized MidiInputDevice          public synchronized MidiInputDevice
2411          getMidiInputDeviceInfo(int deviceID) throws IOException, LscpException, LSException {          getMidiInputDeviceInfo(int deviceId) throws IOException, LscpException, LSException {
2412                  verifyConnection();                  verifyConnection();
2413                  out.writeLine("GET MIDI_INPUT_DEVICE INFO " + deviceID);                  out.writeLine("GET MIDI_INPUT_DEVICE INFO " + deviceId);
2414                    if(getPrintOnlyMode()) return null;
2415                                    
2416                  ResultSet rs = getMultiLineResultSet();                  ResultSet rs = getMultiLineResultSet();
2417                                    
2418                  String[] lnS = rs.getMultiLineResult();                  String[] lnS = rs.getMultiLineResult();
2419                                    
2420                  MidiInputDevice mid = new MidiInputDevice();                  MidiInputDevice mid = new MidiInputDevice();
2421                  mid.setDeviceID(deviceID);                  mid.setDeviceId(deviceId);
2422                                    
2423                  String drv = getCategoryInfo(lnS, "DRIVER");                  String drv = getCategoryInfo(lnS, "DRIVER");
2424                  mid.setDriverName(drv);                  mid.setDriverName(drv);
# Line 1527  public class Client { Line 2431  public class Client {
2431                                  mid.setActive(Boolean.parseBoolean(s));                                  mid.setActive(Boolean.parseBoolean(s));
2432                          } else if(s.startsWith("PORTS: ")) {                          } else if(s.startsWith("PORTS: ")) {
2433                                  s = s.substring("PORTS: ".length());                                  s = s.substring("PORTS: ".length());
2434                                  int ports = Parser.parseInt(s);                                  
2435                                  MidiPort[] midiPorts = new MidiPort[ports > 0 ? ports : 0];                                  Parameter<Integer> ports = (Parameter<Integer>)
2436                                            getMidiInputDriverParameterInfo(drv, "PORTS");
2437                                    
2438                                    ports.parseValue(s);
2439                                    mid.setPortsParameter(ports);
2440                                    
2441                                    int j = ports.getValue();
2442                                    MidiPort[] midiPorts = new MidiPort[j > 0 ? j : 0];
2443                                                                    
2444                                  for(int i = 0; i < midiPorts.length; i++)                                  for(int i = 0; i < midiPorts.length; i++)
2445                                          midiPorts[i] = getMidiInputPortInfo(deviceID, i);                                          midiPorts[i] = getMidiInputPortInfo(deviceId, i);
2446                                                                    
2447                                  mid.setMidiPorts(midiPorts);                                  mid.setMidiPorts(midiPorts);
2448                          } else {                          } else {
# Line 1556  public class Client { Line 2467  public class Client {
2467          /**          /**
2468           * Alters a specific setting of a created MIDI input device.           * Alters a specific setting of a created MIDI input device.
2469           *           *
2470           * @param deviceID The numerical ID of the MIDI input device.           * @param deviceId The numerical ID of the MIDI input device.
2471           * @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
2472           * and the new value for this parameter.           * and the new value for this parameter.
2473           *           *
# Line 1564  public class Client { Line 2475  public class Client {
2475           * @throws LscpException If LSCP protocol corruption occurs.           * @throws LscpException If LSCP protocol corruption occurs.
2476           * @throws LSException If           * @throws LSException If
2477           * <ul>           * <ul>
2478           * <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>;
2479           * <li>There is no device parameter with the specified name;           * <li>There is no device parameter with the specified name;
2480           * <li>The device parameter is readonly;           * <li>The device parameter is readonly;
2481           * <li>The device parameter is from different type.           * <li>The device parameter is from different type.
# Line 1574  public class Client { Line 2485  public class Client {
2485           * @see #getMidiInputDeviceInfo           * @see #getMidiInputDeviceInfo
2486           */           */
2487          public synchronized void          public synchronized void
2488          setMidiInputDeviceParameter(int deviceID, Parameter prm)          setMidiInputDeviceParameter(int deviceId, Parameter prm)
2489                                                  throws IOException, LscpException, LSException {                                                  throws IOException, LscpException, LSException {
2490                                    
2491                  verifyConnection();                  verifyConnection();
2492                  String kv = prm.getName() + '=' + prm.getStringValue();                  String kv = prm.getName() + '=' + prm.getStringValue();
2493                  out.writeLine("SET MIDI_INPUT_DEVICE_PARAMETER " + deviceID + ' ' + kv);                  out.writeLine("SET MIDI_INPUT_DEVICE_PARAMETER " + deviceId + ' ' + kv);
2494                    if(getPrintOnlyMode()) return;
2495                                    
2496                  ResultSet rs = getEmptyResultSet();                  ResultSet rs = getEmptyResultSet();
2497          }          }
2498                    
2499                    
2500          /**          /**
2501           * Changes the ports number of the speicifed MIDI input device.           * Changes the port number of the speicified MIDI input device.
2502           * @param deviceID The numerical ID of the MIDI input device.           * @param deviceId The numerical ID of the MIDI input device.
2503           * @param ports The new number of MIDI input ports.           * @param ports The new number of MIDI input ports.
2504           *           *
2505           * @throws IOException If an I/O error occurs.           * @throws IOException If an I/O error occurs.
2506           * @throws LscpException If LSCP protocol corruption occurs.           * @throws LscpException If LSCP protocol corruption occurs.
2507           * @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
2508           * if <code>ports</code> number is out of range.           * if <code>ports</code> number is out of range.
2509           *           *
2510           * @see #getMidiInputPortInfo           * @see #getMidiInputPortInfo
2511           */           */
2512          public synchronized void          public synchronized void
2513          setMidiInputPortCount(int deviceID, int ports)          setMidiInputPortCount(int deviceId, int ports)
2514                                          throws IOException, LscpException, LSException {                                          throws IOException, LscpException, LSException {
2515                                    
2516                  setMidiInputDeviceParameter(deviceID, new IntParameter("PORTS", ports));                  setMidiInputDeviceParameter(deviceId, new IntParameter("PORTS", ports));
2517          }          }
2518                    
2519          /**          /**
2520           * Gets detailed information about a specific MIDI input port.           * Gets detailed information about a specific MIDI input port.
2521           * @param deviceID The numerical ID of the MIDI input device.           * @param deviceId The numerical ID of the MIDI input device.
2522           * @param midiPort The MIDI input port number.           * @param midiPort The MIDI input port number.
2523           *           *
2524           * @return A <code>MidiPort</code> instance containing           * @return A <code>MidiPort</code> instance containing
# Line 1614  public class Client { Line 2526  public class Client {
2526           *           *
2527           * @throws IOException If an I/O error occurs.           * @throws IOException If an I/O error occurs.
2528           * @throws LscpException If LSCP protocol corruption occurs.           * @throws LscpException If LSCP protocol corruption occurs.
2529           * @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
2530           * if <code>midiPort</code> is not a valid MIDI port number.           * if <code>midiPort</code> is not a valid MIDI port number.
2531           *           *
2532           * @see #getMidiInputDevices           * @see #getMidiInputDevices
2533           */           */
2534          public synchronized MidiPort          public synchronized MidiPort
2535          getMidiInputPortInfo(int deviceID, int midiPort)          getMidiInputPortInfo(int deviceId, int midiPort)
2536                                          throws IOException, LscpException, LSException {                                          throws IOException, LscpException, LSException {
2537                                    
2538                  verifyConnection();                  verifyConnection();
2539                  out.writeLine("GET MIDI_INPUT_PORT INFO " + deviceID + " " + midiPort);                  out.writeLine("GET MIDI_INPUT_PORT INFO " + deviceId + " " + midiPort);
2540                    if(getPrintOnlyMode()) return null;
2541                    
2542                  ResultSet rs = getMultiLineResultSet();                  ResultSet rs = getMultiLineResultSet();
2543                                    
2544                  MidiPort mp = new MidiPort();                  MidiPort mp = new MidiPort();
# Line 1634  public class Client { Line 2548  public class Client {
2548                          if(s.startsWith("NAME: ")) {                          if(s.startsWith("NAME: ")) {
2549                                  s = s.substring("NAME: ".length());                                  s = s.substring("NAME: ".length());
2550                                  Parameter prm = getMidiInputPortParameterInfo (                                  Parameter prm = getMidiInputPortParameterInfo (
2551                                          deviceID, midiPort, "NAME"                                          deviceId, midiPort, "NAME"
2552                                  );                                  );
2553                                  prm.setValue(removeQuotation(s));                                  prm.setValue(removeQuotation(s));
2554                                  mp.setNameParameter(prm);                                  mp.setNameParameter(prm);
# Line 1645  public class Client { Line 2559  public class Client {
2559                                  );                                  );
2560                                                                    
2561                                  Parameter prm = getMidiInputPortParameterInfo (                                  Parameter prm = getMidiInputPortParameterInfo (
2562                                          deviceID, midiPort, s.substring(0, i)                                          deviceId, midiPort, s.substring(0, i)
2563                                  );                                  );
2564                                                                    
2565                                  s = s.substring(i + 2);                                  s = s.substring(i + 2);
# Line 1661  public class Client { Line 2575  public class Client {
2575          /**          /**
2576           * Gets detailed information about a specific MIDI input port parameter.           * Gets detailed information about a specific MIDI input port parameter.
2577           *           *
2578           * @param deviceID The numerical ID of the MIDI input device.           * @param deviceId The numerical ID of the MIDI input device.
2579           * @param port The MIDI port number.           * @param port The MIDI port number.
2580           * @param param A specific parameter name for which information should be obtained.           * @param param A specific parameter name for which information should be obtained.
2581           *           *
# Line 1672  public class Client { Line 2586  public class Client {
2586           * @throws LscpException If LSCP protocol corruption occurs.           * @throws LscpException If LSCP protocol corruption occurs.
2587           * @throws LSException If           * @throws LSException If
2588           * <ul>           * <ul>
2589           * <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>;
2590           * <li> <code>port</code> is not a valid MIDI port number;           * <li> <code>port</code> is not a valid MIDI port number;
2591           * <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.
2592           * </ul>           * </ul>
# Line 1681  public class Client { Line 2595  public class Client {
2595           * @see #getMidiInputPortInfo           * @see #getMidiInputPortInfo
2596           */           */
2597          public synchronized Parameter          public synchronized Parameter
2598          getMidiInputPortParameterInfo(int deviceID, int port, String param)          getMidiInputPortParameterInfo(int deviceId, int port, String param)
2599                                                  throws IOException, LscpException, LSException {                                                  throws IOException, LscpException, LSException {
2600                                    
2601                  verifyConnection();                  verifyConnection();
2602                  String args = deviceID + " " + port + " " + param;                  String args = deviceId + " " + port + " " + param;
2603                  out.writeLine("GET MIDI_INPUT_PORT_PARAMETER INFO " + args);                  out.writeLine("GET MIDI_INPUT_PORT_PARAMETER INFO " + args);
2604                    if(getPrintOnlyMode()) return null;
2605                                    
2606                  ResultSet rs = getMultiLineResultSet();                  ResultSet rs = getMultiLineResultSet();
2607                                    
# Line 1723  public class Client { Line 2638  public class Client {
2638          /**          /**
2639           * Alters a specific setting of a MIDI input port.           * Alters a specific setting of a MIDI input port.
2640           *           *
2641           * @param deviceID The numerical ID of the MIDI device.           * @param deviceId The numerical ID of the MIDI device.
2642           * @param port The MIDI port number.           * @param port The MIDI port number.
2643           * @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
2644           * and the new value for this parameter.           * and the new value for this parameter.
# Line 1732  public class Client { Line 2647  public class Client {
2647           * @throws LscpException If LSCP protocol corruption occurs.           * @throws LscpException If LSCP protocol corruption occurs.
2648           * @throws LSException If           * @throws LSException If
2649           * <ul>           * <ul>
2650           * <li>There is no MIDI device with numerical ID <code>deviceID</code>;           * <li>There is no MIDI device with numerical ID <code>deviceId</code>;
2651           * <li><code>port</code> is not a valid MIDI port number;           * <li><code>port</code> is not a valid MIDI port number;
2652           * <li><code>prm</code> is not a valid parameter;           * <li><code>prm</code> is not a valid parameter;
2653           * <li>The parameter is readonly;           * <li>The parameter is readonly;
# Line 1743  public class Client { Line 2658  public class Client {
2658           * @see #getMidiInputPortInfo           * @see #getMidiInputPortInfo
2659           */           */
2660          public synchronized void          public synchronized void
2661          setMidiInputPortParameter(int deviceID, int port,  Parameter prm)          setMidiInputPortParameter(int deviceId, int port,  Parameter prm)
2662                                                  throws IOException, LscpException, LSException {                                                  throws IOException, LscpException, LSException {
2663                                    
2664                  verifyConnection();                  verifyConnection();
2665                  String args = deviceID + " " + port + " " +                  String args = deviceId + " " + port + " " +
2666                          prm.getName() + '=' + prm.getStringValue();                          prm.getName() + '=' + prm.getStringValue();
2667                  out.writeLine("SET MIDI_INPUT_PORT_PARAMETER " + args);                  out.writeLine("SET MIDI_INPUT_PORT_PARAMETER " + args);
2668                    if(getPrintOnlyMode()) return;
2669                                    
2670                  ResultSet rs = getEmptyResultSet();                  ResultSet rs = getEmptyResultSet();
2671          }          }
2672                    
2673          /**          /**
2674             * Adds a new MIDI instrument map.
2675             * @param name The name of this MIDI instrument map.
2676             * @return The number of the newly MIDI instrument map.
2677             * @throws IOException If some I/O error occurs.
2678             * @throws LSException If the creation of the new MIDI instrument map failed.
2679             * @throws LscpException If LSCP protocol corruption occurs.
2680             * @see #removeMidiInstrumentMap
2681             */
2682            public synchronized int
2683            addMidiInstrumentMap(String name) throws IOException, LSException, LscpException {
2684                    verifyConnection();
2685                    out.writeLine("ADD MIDI_INSTRUMENT_MAP '" + toEscapedText(name) + "'");
2686                    if(getPrintOnlyMode()) return -1;
2687                    
2688                    ResultSet rs = getEmptyResultSet();
2689                    
2690                    return rs.getIndex();
2691            }
2692            
2693            /**
2694             * Removes the specified MIDI instrument map.
2695             * @param mapId The numerical ID of the MIDI instrument map to be removed.
2696             * @throws IOException If some I/O error occurs.
2697             * @throws LscpException If LSCP protocol corruption occurs.
2698             * @throws LSException If the removing of the MIDI instrument map failed.
2699             * @see #addMidiInstrumentMap
2700             * @see #getMidiInstrumentMapIDs
2701             */
2702            public synchronized void
2703            removeMidiInstrumentMap(int mapId) throws IOException, LscpException, LSException {
2704                    verifyConnection();
2705                    out.writeLine("REMOVE MIDI_INSTRUMENT_MAP " + mapId);
2706                    if(getPrintOnlyMode()) return;
2707                    
2708                    ResultSet rs = getEmptyResultSet();
2709            }
2710            
2711            /**
2712             * Removes the all MIDI instrument maps.
2713             * @throws IOException If some I/O error occurs.
2714             * @throws LscpException If LSCP protocol corruption occurs.
2715             * @throws LSException If the removing of the MIDI instrument maps failed.
2716             */
2717            public synchronized void
2718            removeAllMidiInstrumentMaps() throws IOException, LscpException, LSException {
2719                    verifyConnection();
2720                    out.writeLine("REMOVE MIDI_INSTRUMENT_MAP ALL");
2721                    if(getPrintOnlyMode()) return;
2722                    
2723                    ResultSet rs = getEmptyResultSet();
2724            }
2725            
2726            /**
2727             * Gets the current number of all MIDI instrument maps.
2728             * @return The current number of all MIDI instrument maps.
2729             * @throws IOException If some I/O error occurs.
2730             * @throws LscpException If LSCP protocol corruption occurs.
2731             * @throws LSException If some other error occurs.
2732             */
2733            public synchronized int
2734            getMidiInstrumentMapCount() throws IOException, LscpException, LSException {
2735                    verifyConnection();
2736                    out.writeLine("GET MIDI_INSTRUMENT_MAPS");
2737                    if(getPrintOnlyMode()) return -1;
2738                    
2739                    String s = getSingleLineResultSet().getResult();
2740                    return parseInt(s);
2741            }
2742            
2743            /**
2744             * Gets a list of numerical IDs of all created MIDI instrument maps.
2745             * @return An <code>Integer</code> array providing the numerical IDs of
2746             * all created MIDI instrument maps.
2747             * @throws IOException If some I/O error occurs.
2748             * @throws LscpException If LSCP protocol corruption occurs.
2749             * @throws LSException If some other error occurs.
2750             * @see #addMidiInstrumentMap
2751             * @see #removeMidiInstrumentMap
2752             */
2753            public synchronized Integer[]
2754            getMidiInstrumentMapIDs() throws IOException, LscpException, LSException {
2755                    verifyConnection();
2756                    out.writeLine("LIST MIDI_INSTRUMENT_MAPS");
2757                    if(getPrintOnlyMode()) return null;
2758                    
2759                    return parseIntList(getSingleLineResultSet().getResult());
2760            }
2761            
2762            /**
2763             * Gets the current settings of a specific, already created MIDI instrument map.
2764             * @param mapId Specifies the numerical ID of the MIDI instrument map.
2765             * @return A <code>MidiInstrumentMapInfo</code> instance containing information
2766             * about the specified device.
2767             * @throws IOException If some I/O error occurs.
2768             * @throws LscpException If LSCP protocol corruption occurs.
2769             * @throws LSException If there is no MIDI instrument map
2770             * with map id <code>mapId</code>.
2771             * @see #getMidiInstrumentMaps
2772             */
2773            public synchronized MidiInstrumentMapInfo
2774            getMidiInstrumentMapInfo(int mapId) throws IOException, LscpException, LSException {
2775                    verifyConnection();
2776                    out.writeLine("GET MIDI_INSTRUMENT_MAP INFO " + mapId);
2777                    if(getPrintOnlyMode()) return null;
2778                    
2779                    ResultSet rs = getMultiLineResultSet();
2780                    
2781                    String[] lnS = rs.getMultiLineResult();
2782                    
2783                    String name = "";
2784                    boolean b = false;
2785                    
2786                    for(String s : lnS) {
2787                            if(s.startsWith("NAME: ")) {
2788                                    name = toNonEscapedString(s.substring("NAME: ".length()));
2789                            } else if(s.startsWith("DEFAULT: ")) {
2790                                    b = Boolean.parseBoolean(s.substring("DEFAULT: ".length()));
2791                            } else {
2792                                     getLogger().info(LscpI18n.getLogMsg("unknownLine", s));
2793                            }
2794                    }
2795                    
2796                    return new MidiInstrumentMapInfo(mapId, name, b);
2797            }
2798            
2799            /**
2800             * Gets an information of all created MIDI instrument maps.
2801             * @return A <code>MidiInstrumentMap</code> array
2802             * providing information for all created MIDI instrument maps.
2803             * @throws IOException If some I/O error occurs.
2804             * @throws LscpException If LSCP protocol corruption occurs.
2805             * @throws LSException If some other error occurs.
2806             * @see #addMidiInstrumentMap
2807             * @see #removeMidiInstrumentMap
2808             */
2809            public synchronized MidiInstrumentMapInfo[]
2810            getMidiInstrumentMaps() throws IOException, LscpException, LSException {
2811                    Integer[] idS = getMidiInstrumentMapIDs();
2812                    if(getPrintOnlyMode()) return null;
2813                    
2814                    MidiInstrumentMapInfo[] maps = new MidiInstrumentMapInfo[idS.length];
2815                    
2816                    for(int i = 0; i < maps.length; i++)
2817                            maps[i] = getMidiInstrumentMapInfo(idS[i]);
2818                    
2819                    return maps;
2820            }
2821            
2822            /**
2823             * Sets the name of the specified MIDI instrument map.
2824             * @param mapId The numerical ID of the MIDI instrument map.
2825             * @param name The new name for the specified MIDI instrument map.
2826             * @throws IOException If some I/O error occurs.
2827             * @throws LscpException If LSCP protocol corruption occurs.
2828             * @throws LSException If <code>mapId</code> is not a valid MIDI
2829             * instrument map number or <code>name</code> is not a valid name;
2830             */
2831            public synchronized void
2832            setMidiInstrumentMapName(int mapId, String name)
2833                                    throws IOException, LscpException, LSException {
2834                    
2835                    verifyConnection();
2836                    name = toEscapedText(name);
2837                    out.writeLine("SET MIDI_INSTRUMENT_MAP NAME " +  + mapId + " '" + name + "'");
2838                    if(getPrintOnlyMode()) return;
2839                    
2840                    ResultSet rs = getEmptyResultSet();
2841            }
2842            
2843            
2844            
2845            /**
2846             * Creates or replaces a MIDI instrument map entry.
2847             * @param mapId The ID of the map, where this instrument should be mapped.
2848             * @param entry Specifies the position of the MIDI instrument in the MIDI instrument map.
2849             * @param info Provides the needed information of the
2850             * MIDI instrument, which will be mapped to the specified MIDI instrument map.
2851             * @throws IOException If some I/O error occurs.
2852             * @throws LSException If the mapping failed.
2853             * @throws LscpException If LSCP protocol corruption occurs.
2854             * @see #unmapMidiInstrument
2855             */
2856            public synchronized void
2857            mapMidiInstrument(int mapId, MidiInstrumentEntry entry, MidiInstrumentInfo info)
2858                                            throws IOException, LSException, LscpException {
2859                    mapMidiInstrument(mapId, entry, info, false);
2860            }
2861            
2862            /**
2863             * Creates or replaces a MIDI instrument map entry.
2864             * @param mapId The ID of the map, where this instrument should be mapped.
2865             * @param entry Specifies the position of the MIDI instrument in the MIDI instrument map.
2866             * @param info Provides the needed information of the
2867             * MIDI instrument, which will be mapped to the specified MIDI instrument map.
2868             * @param nonModal If <code>true</code> the function returns immediately
2869             * and the mapping is established in the background.
2870             * @throws IOException If some I/O error occurs.
2871             * @throws LSException If the mapping failed.
2872             * @throws LscpException If LSCP protocol corruption occurs.
2873             * @see #unmapMidiInstrument
2874             */
2875            public synchronized void
2876            mapMidiInstrument(int mapId, MidiInstrumentEntry entry, MidiInstrumentInfo info, boolean nonModal)
2877                                            throws IOException, LSException, LscpException {
2878                    
2879                    verifyConnection();
2880                    StringBuffer cmd = new StringBuffer("MAP MIDI_INSTRUMENT ");
2881                    if(nonModal) cmd.append("NON_MODAL ");
2882                    cmd.append(mapId).append(' ');
2883                    cmd.append(entry.getMidiBank()).append(' ');
2884                    cmd.append(entry.getMidiProgram()).append(' ');
2885                    cmd.append(info.getEngine()).append(" '");
2886                    cmd.append(conv(info.getFilePath())).append("' ");
2887                    cmd.append(info.getInstrumentIndex()).append(' ');
2888                    cmd.append(info.getVolume());
2889                    if(!info.getLoadMode().name().equals("DEFAULT")) {
2890                            cmd.append(' ').append(info.getLoadMode().name());
2891                    }
2892                    
2893                    if(info.getName() != null) {
2894                            String s = toEscapedText(info.getName());
2895                            cmd.append(" '").append(s).append("'");
2896                    }
2897                    
2898                    out.writeLine(cmd.toString());
2899                    if(getPrintOnlyMode()) return;
2900                    
2901                    ResultSet rs = getEmptyResultSet();
2902            }
2903            
2904            /**
2905             * Removes an entry MIDI instrument map.
2906             * @param mapId The ID of the map, from which
2907             * the specified MIDI instrument should be removed.
2908             * @param entry The entry to remove from the specified MIDI instrument map.
2909             * @throws IOException If some I/O error occurs.
2910             * @throws LSException If the unmapping failed.
2911             * @throws LscpException If LSCP protocol corruption occurs.
2912             * @see #mapMidiInstrument
2913             */
2914            public synchronized void
2915            unmapMidiInstrument(int mapId, MidiInstrumentEntry entry)
2916                                            throws IOException, LSException, LscpException {
2917                    
2918                    verifyConnection();
2919                    StringBuffer cmd = new StringBuffer("UNMAP MIDI_INSTRUMENT ");
2920                    cmd.append(mapId).append(' ');
2921                    cmd.append(entry.getMidiBank()).append(' ');
2922                    cmd.append(entry.getMidiProgram());
2923                    
2924                    out.writeLine(cmd.toString());
2925                    if(getPrintOnlyMode()) return;
2926                    
2927                    ResultSet rs = getEmptyResultSet();
2928            }
2929            
2930            /**
2931             * Gets the current number of all MIDI instrument in all maps.
2932             * @return The current number of all MIDI instrument in all maps.
2933             * @throws IOException If some I/O error occurs.
2934             * @throws LscpException If LSCP protocol corruption occurs.
2935             * @throws LSException If some other error occurs.
2936             */
2937            public synchronized int
2938            getMidiInstrumentCount() throws IOException, LscpException, LSException {
2939                    verifyConnection();
2940                    out.writeLine("GET MIDI_INSTRUMENTS ALL");
2941                    if(getPrintOnlyMode()) return -1;
2942                    
2943                    String s = getSingleLineResultSet().getResult();
2944                    return parseInt(s);
2945            }
2946            
2947            /**
2948             * Gets the current number of MIDI instrument in the specified map.
2949             * @param mapId The ID of the map.
2950             * @return The current number of MIDI instrument in the specified map.
2951             * @throws IOException If some I/O error occurs.
2952             * @throws LscpException If LSCP protocol corruption occurs.
2953             * @throws LSException If some other error occurs.
2954             */
2955            public synchronized int
2956            getMidiInstrumentCount(int mapId) throws IOException, LscpException, LSException {
2957                    verifyConnection();
2958                    out.writeLine("GET MIDI_INSTRUMENTS " + String.valueOf(mapId));
2959                    if(getPrintOnlyMode()) return -1;
2960                    
2961                    String s = getSingleLineResultSet().getResult();
2962                    return parseInt(s);
2963            }
2964            
2965            /**
2966             * Gets all MIDI instrument from all maps.
2967             * @return A <code>MidiInstrumentInfo</code> array providing
2968             * all MIDI instruments from all MIDI instrument maps.
2969             * @throws IOException If some I/O error occurs.
2970             * @throws LscpException If LSCP protocol corruption occurs.
2971             * @throws LSException If some other error occurs.
2972             */
2973            public synchronized MidiInstrumentInfo[]
2974            getMidiInstruments() throws IOException, LscpException, LSException {
2975                    verifyConnection();
2976                    out.writeLine("LIST MIDI_INSTRUMENTS ALL");
2977                    if(getPrintOnlyMode()) return null;
2978                    
2979                    String[] entries = parseArray(getSingleLineResultSet().getResult());
2980                    
2981                    return getMidiInstruments(entries);
2982            }
2983            
2984            /**
2985             * Gets all MIDI instrument entries contained int the specified MIDI instrument map.
2986             * @param mapId The ID of the map, which instruments should be obtained.
2987             * @return An int array providing all MIDI instrument entries
2988             * in the specified MIDI instrument map.
2989             * @throws IOException If some I/O error occurs.
2990             * @throws LscpException If LSCP protocol corruption occurs.
2991             * @throws LSException If some other error occurs.
2992             */
2993            public synchronized int[][]
2994            getMidiInstrumentEntries(int mapId) throws IOException, LscpException, LSException {
2995                    verifyConnection();
2996                    out.writeLine("LIST MIDI_INSTRUMENTS " + String.valueOf(mapId));
2997                    if(getPrintOnlyMode()) return null;
2998                    
2999                    String[] entries = parseArray(getSingleLineResultSet().getResult());
3000                    int[][] e = new int[entries.length][3];
3001                    
3002                    for(int i = 0; i < entries.length; i++) {
3003                            Integer[] vals = parseIntList(entries[i]);
3004                            if(vals.length != 3) {
3005                                    throw new LscpException(LscpI18n.getLogMsg("CommandFailed!"));
3006                            }
3007                            
3008                            e[i][0] = vals[0];
3009                            e[i][1] = vals[1];
3010                            e[i][2] = vals[2];
3011                    }
3012                    
3013                    return e;
3014            }
3015            
3016            /**
3017             * Gets all MIDI instruments contained int the specified MIDI instrument map.
3018             * @param mapId The ID of the map, which instruments should be obtained.
3019             * @return A <code>MidiInstrumentInfo</code> array providing
3020             * all MIDI instruments in the specified MIDI instrument map.
3021             * @throws IOException If some I/O error occurs.
3022             * @throws LscpException If LSCP protocol corruption occurs.
3023             * @throws LSException If some other error occurs.
3024             */
3025            public synchronized MidiInstrumentInfo[]
3026            getMidiInstruments(int mapId) throws IOException, LscpException, LSException {
3027                    verifyConnection();
3028                    out.writeLine("LIST MIDI_INSTRUMENTS " + String.valueOf(mapId));
3029                    if(getPrintOnlyMode()) return null;
3030                    
3031                    String[] entries = parseArray(getSingleLineResultSet().getResult());
3032                    
3033                    return getMidiInstruments(entries);
3034            }
3035            
3036            private MidiInstrumentInfo[]
3037            getMidiInstruments(String[] entries) throws IOException, LscpException, LSException {
3038                    Vector<MidiInstrumentInfo> v = new Vector<MidiInstrumentInfo>();
3039                    
3040                    for(String s : entries) {
3041                            Integer[] vals = parseIntList(s);
3042                            if(vals.length != 3) {
3043                                    throw new LscpException(LscpI18n.getLogMsg("CommandFailed!"));
3044                            }
3045                            
3046                            v.add(getMidiInstrumentInfo(vals[0], vals[1], vals[2]));
3047                    }
3048                    
3049                    return v.toArray(new MidiInstrumentInfo[v.size()]);
3050            }
3051            
3052            /**
3053             * Gets the current settings of the specified MIDI instrument.
3054             * @param mapId The ID of the map.
3055             * @param bank The index of the MIDI bank.
3056             * @param program The MIDI program number of the instrument.
3057             * @return <code>MidiInstrumentInfo</code> instance containing
3058             * the current settings of the specified MIDI instrument.
3059             * @throws IOException If an I/O error occurs.
3060             * @throws LscpException If LSCP protocol corruption occurs.
3061             * @throws LSException If the specified MIDI instrument is missing.
3062             */
3063            public synchronized MidiInstrumentInfo
3064            getMidiInstrumentInfo(int mapId, int bank, int program)
3065                                            throws IOException, LscpException, LSException {
3066            
3067                    verifyConnection();
3068                    requestMidiInstrumentInfo(mapId, bank, program);
3069                    return getMidiInstrumentInfoResponse(mapId, bank, program);
3070            }
3071            
3072            private void
3073            requestMidiInstrumentInfo(int mapId, int bank, int program) throws IOException {
3074                    StringBuffer cmd = new StringBuffer("GET MIDI_INSTRUMENT INFO ");
3075                    cmd.append(mapId).append(' ');
3076                    cmd.append(bank).append(' ');
3077                    cmd.append(program);
3078                    
3079                    out.writeLine(cmd.toString());
3080            }
3081            
3082            private MidiInstrumentInfo
3083            getMidiInstrumentInfoResponse(int mapId, int bank, int program)
3084                                            throws IOException, LscpException, LSException {
3085                    
3086                    if(getPrintOnlyMode()) return null;
3087                    ResultSet rs = getMultiLineResultSet();
3088                    MidiInstrumentEntry entry = new MidiInstrumentEntry(bank, program);
3089                    return new MidiInstrumentInfo(mapId, entry, rs.getMultiLineResult());
3090            }
3091            
3092            /**
3093           * 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
3094           * 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.
          *    
3095           * @param filename The name of the instrument file           * @param filename The name of the instrument file
3096           * on the LinuxSampler instance's host system.           * on the LinuxSampler instance's host system.
3097           * @param instrIdx The index of the instrument in the instrument file.           * @param instrIdx The index of the instrument in the instrument file.
3098           * @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.
          *  
3099           * @throws IOException If some I/O error occurs.           * @throws IOException If some I/O error occurs.
3100           * @throws LscpException If LSCP protocol corruption occurs.           * @throws LscpException If LSCP protocol corruption occurs.
3101           * @throws LSException If the loading of the instrument failed.           * @throws LSException If the loading of the instrument failed.
          *  
3102           * @see #loadInstrument(String, int, int, boolean)           * @see #loadInstrument(String, int, int, boolean)
3103           * @see #getSamplerChannels           * @see #getSamplerChannels
3104           */           */
# Line 1801  public class Client { Line 3133  public class Client {
3133                                                  throws IOException, LscpException, LSException {                                                  throws IOException, LscpException, LSException {
3134                                    
3135                  String cmd = nonModal ? "LOAD INSTRUMENT NON_MODAL " : "LOAD INSTRUMENT ";                  String cmd = nonModal ? "LOAD INSTRUMENT NON_MODAL " : "LOAD INSTRUMENT ";
3136                  String args = '\'' + filename + "' " + instrIdx + ' ' + samplerChn;                  String args = '\'' + conv(filename) + "' " + instrIdx + ' ' + samplerChn;
3137                                    
3138                  out.writeLine(cmd + args);                  out.writeLine(cmd + args);
3139                    if(getPrintOnlyMode()) return;
3140                                    
3141                  ResultSet rs = getEmptyResultSet();                  ResultSet rs = getEmptyResultSet();
3142          }          }
# Line 1826  public class Client { Line 3159  public class Client {
3159                                    
3160                  verifyConnection();                  verifyConnection();
3161                  out.writeLine("LOAD ENGINE " + engineName + ' ' + samplerChn);                  out.writeLine("LOAD ENGINE " + engineName + ' ' + samplerChn);
3162                    if(getPrintOnlyMode()) return;
3163                                    
3164                  ResultSet rs = getEmptyResultSet();                  ResultSet rs = getEmptyResultSet();
3165          }          }
# Line 1841  public class Client { Line 3175  public class Client {
3175          getSamplerChannelCount() throws IOException, LscpException, LSException {          getSamplerChannelCount() throws IOException, LscpException, LSException {
3176                  verifyConnection();                  verifyConnection();
3177                  out.writeLine("GET CHANNELS");                  out.writeLine("GET CHANNELS");
3178                    if(getPrintOnlyMode()) return -1;
3179                    
3180                  String s = getSingleLineResultSet().getResult();                  String s = getSingleLineResultSet().getResult();
3181                  return parseInt(s);                  return parseInt(s);
3182          }          }
# Line 1857  public class Client { Line 3193  public class Client {
3193          public synchronized SamplerChannel[]          public synchronized SamplerChannel[]
3194          getSamplerChannels() throws IOException, LscpException, LSException {          getSamplerChannels() throws IOException, LscpException, LSException {
3195                  Integer[] idS = getSamplerChannelIDs();                  Integer[] idS = getSamplerChannelIDs();
3196                    if(getPrintOnlyMode()) return null;
3197                    
3198                  SamplerChannel[] channels = new SamplerChannel[idS.length];                  SamplerChannel[] channels = new SamplerChannel[idS.length];
3199                                    
3200                  for(int i = 0; i < channels.length; i++)                  for(int i = 0; i < channels.length; i++)
# Line 1879  public class Client { Line 3217  public class Client {
3217          getSamplerChannelIDs() throws IOException, LscpException, LSException {          getSamplerChannelIDs() throws IOException, LscpException, LSException {
3218                  verifyConnection();                  verifyConnection();
3219                  out.writeLine("LIST CHANNELS");                  out.writeLine("LIST CHANNELS");
3220                    if(getPrintOnlyMode()) return null;
3221                    
3222                  return parseIntList(getSingleLineResultSet().getResult());                  return parseIntList(getSingleLineResultSet().getResult());
3223          }          }
3224                    
# Line 1896  public class Client { Line 3236  public class Client {
3236          addSamplerChannel() throws IOException, LSException, LscpException {          addSamplerChannel() throws IOException, LSException, LscpException {
3237                  verifyConnection();                  verifyConnection();
3238                  out.writeLine("ADD CHANNEL");                  out.writeLine("ADD CHANNEL");
3239                    if(getPrintOnlyMode()) return -1;
3240                    
3241                  ResultSet rs = getEmptyResultSet();                  ResultSet rs = getEmptyResultSet();
3242                                    
3243                  return rs.getIndex();                  return rs.getIndex();
# Line 1916  public class Client { Line 3258  public class Client {
3258          removeSamplerChannel(int samplerChn) throws IOException, LscpException, LSException {          removeSamplerChannel(int samplerChn) throws IOException, LscpException, LSException {
3259                  verifyConnection();                  verifyConnection();
3260                  out.writeLine("REMOVE CHANNEL " + samplerChn);                  out.writeLine("REMOVE CHANNEL " + samplerChn);
3261                    if(getPrintOnlyMode()) return;
3262                                    
3263                  ResultSet rs = getEmptyResultSet();                  ResultSet rs = getEmptyResultSet();
3264          }          }
# Line 1931  public class Client { Line 3274  public class Client {
3274          getEngineCount() throws IOException, LscpException, LSException {          getEngineCount() throws IOException, LscpException, LSException {
3275                  verifyConnection();                  verifyConnection();
3276                  out.writeLine("GET AVAILABLE_ENGINES");                  out.writeLine("GET AVAILABLE_ENGINES");
3277                    if(getPrintOnlyMode()) return -1;
3278                    
3279                  String s = getSingleLineResultSet().getResult();                  String s = getSingleLineResultSet().getResult();
3280                  return parseInt(s);                  return parseInt(s);
3281          }          }
# Line 1946  public class Client { Line 3291  public class Client {
3291          public synchronized SamplerEngine[]          public synchronized SamplerEngine[]
3292          getEngines() throws IOException, LscpException, LSException {          getEngines() throws IOException, LscpException, LSException {
3293                  String[] engines = getEngineNames();                  String[] engines = getEngineNames();
3294                    if(getPrintOnlyMode()) return null;
3295                    
3296                  SamplerEngine[] se = new SamplerEngine[engines.length];                  SamplerEngine[] se = new SamplerEngine[engines.length];
3297                                    
3298                  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 3312  public class Client {
3312          getEngineNames() throws IOException, LscpException, LSException {          getEngineNames() throws IOException, LscpException, LSException {
3313                  verifyConnection();                  verifyConnection();
3314                  out.writeLine("LIST AVAILABLE_ENGINES");                  out.writeLine("LIST AVAILABLE_ENGINES");
3315                    if(getPrintOnlyMode()) return null;
3316                    
3317                  return parseStringList(getSingleLineResultSet().getResult());                  return parseStringList(getSingleLineResultSet().getResult());
3318          }          }
3319                    
# Line 1984  public class Client { Line 3333  public class Client {
3333          getEngineInfo(String engineName) throws IOException, LscpException, LSException {          getEngineInfo(String engineName) throws IOException, LscpException, LSException {
3334                  verifyConnection();                  verifyConnection();
3335                  out.writeLine("GET ENGINE INFO " + engineName);                  out.writeLine("GET ENGINE INFO " + engineName);
3336                    if(getPrintOnlyMode()) return null;
3337                    
3338                  ResultSet rs = getMultiLineResultSet();                  ResultSet rs = getMultiLineResultSet();
3339                  SamplerEngine se = new SamplerEngine(rs.getMultiLineResult());                  SamplerEngine se = new SamplerEngine(rs.getMultiLineResult());
3340                  se.setName(engineName);                  se.setName(engineName);
# Line 2006  public class Client { Line 3357  public class Client {
3357          getSamplerChannelInfo(int samplerChn) throws IOException, LscpException, LSException {          getSamplerChannelInfo(int samplerChn) throws IOException, LscpException, LSException {
3358                  verifyConnection();                  verifyConnection();
3359                  out.writeLine("GET CHANNEL INFO " + samplerChn);                  out.writeLine("GET CHANNEL INFO " + samplerChn);
3360                    if(getPrintOnlyMode()) return null;
3361                    
3362                  ResultSet rs = getMultiLineResultSet();                  ResultSet rs = getMultiLineResultSet();
3363                  SamplerChannel sc = new SamplerChannel(rs.getMultiLineResult());                  SamplerChannel sc = new SamplerChannel(rs.getMultiLineResult());
3364                  sc.setChannelID(samplerChn);                  sc.setChannelId(samplerChn);
3365                  if(sc.getEngine() != null) sc.setEngine(getEngineInfo(sc.getEngine().getName()));                  if(sc.getEngine() != null) sc.setEngine(getEngineInfo(sc.getEngine().getName()));
3366                                    
3367                  return sc;                  return sc;
# Line 2028  public class Client { Line 3381  public class Client {
3381          getChannelVoiceCount(int samplerChn) throws IOException, LscpException, LSException {          getChannelVoiceCount(int samplerChn) throws IOException, LscpException, LSException {
3382                  verifyConnection();                  verifyConnection();
3383                  out.writeLine("GET CHANNEL VOICE_COUNT " + samplerChn);                  out.writeLine("GET CHANNEL VOICE_COUNT " + samplerChn);
3384                    if(getPrintOnlyMode()) return -1;
3385                    
3386                  ResultSet rs = getSingleLineResultSet();                  ResultSet rs = getSingleLineResultSet();
3387                                    
3388                  return parseInt(rs.getResult());                  return parseInt(rs.getResult());
# Line 2048  public class Client { Line 3403  public class Client {
3403          getChannelStreamCount(int samplerChn) throws IOException, LscpException, LSException {          getChannelStreamCount(int samplerChn) throws IOException, LscpException, LSException {
3404                  verifyConnection();                  verifyConnection();
3405                  out.writeLine("GET CHANNEL STREAM_COUNT " + samplerChn);                  out.writeLine("GET CHANNEL STREAM_COUNT " + samplerChn);
3406                    if(getPrintOnlyMode()) return -1;
3407            
3408                  ResultSet rs = getSingleLineResultSet();                  ResultSet rs = getSingleLineResultSet();
3409                                    
3410                  if(rs.getResult().equals("NA")) return -1;                  if(rs.getResult().equals("NA")) return -1;
# Line 2072  public class Client { Line 3429  public class Client {
3429          getChannelBufferFillBytes(int samplerChn) throws IOException, LscpException, LSException {          getChannelBufferFillBytes(int samplerChn) throws IOException, LscpException, LSException {
3430                  verifyConnection();                  verifyConnection();
3431                  out.writeLine("GET CHANNEL BUFFER_FILL BYTES " + samplerChn);                  out.writeLine("GET CHANNEL BUFFER_FILL BYTES " + samplerChn);
3432                    if(getPrintOnlyMode()) return null;
3433                    
3434                  ResultSet rs = getSingleLineResultSet();                  ResultSet rs = getSingleLineResultSet();
3435                                    
3436                  if(rs.getResult().equals("NA")) return null;                  if(rs.getResult().equals("NA")) return null;
# Line 2087  public class Client { Line 3446  public class Client {
3446                          if(i == -1) throw new LscpException(LscpI18n.getLogMsg("CommandFailed!"));                          if(i == -1) throw new LscpException(LscpI18n.getLogMsg("CommandFailed!"));
3447                                                    
3448                          BufferFill bf = new BufferFill();                          BufferFill bf = new BufferFill();
3449                          bf.setStreamID(parseInt(s.substring(1, i)));                          bf.setStreamId(parseInt(s.substring(1, i)));
3450                          bf.setValue(parseInt(s.substring(i + 1)));                          bf.setValue(parseInt(s.substring(i + 1)));
3451                          v.add(bf);                          v.add(bf);
3452                  }                  }
# Line 2114  public class Client { Line 3473  public class Client {
3473                                    
3474                  verifyConnection();                  verifyConnection();
3475                  out.writeLine("GET CHANNEL BUFFER_FILL PERCENTAGE " + samplerChn);                  out.writeLine("GET CHANNEL BUFFER_FILL PERCENTAGE " + samplerChn);
3476                    if(getPrintOnlyMode()) return null;
3477                    
3478                  ResultSet rs = getSingleLineResultSet();                  ResultSet rs = getSingleLineResultSet();
3479                                    
3480                  return getChannelBufferFillPercentage(rs.getResult());                  return getChannelBufferFillPercentage(rs.getResult());
# Line 2137  public class Client { Line 3498  public class Client {
3498                                  throw new LscpException(LscpI18n.getLogMsg("CommandFailed!"));                                  throw new LscpException(LscpI18n.getLogMsg("CommandFailed!"));
3499                                                    
3500                          BufferFill bf = new BufferFill();                          BufferFill bf = new BufferFill();
3501                          bf.setStreamID(parseInt(s.substring(1, i)));                          bf.setStreamId(parseInt(s.substring(1, i)));
3502                          bf.setValue(parseInt(s.substring(i + 1, s.length() - 1)));                          bf.setValue(parseInt(s.substring(i + 1, s.length() - 1)));
3503                          v.add(bf);                          v.add(bf);
3504                  }                  }
# Line 2149  public class Client { Line 3510  public class Client {
3510           * Sets the audio output device on the specified sampler channel.           * Sets the audio output device on the specified sampler channel.
3511           *           *
3512           * @param samplerChn The sampler channel number.           * @param samplerChn The sampler channel number.
3513           * @param devID The numerical ID of the audio output device.           * @param devId The numerical ID of the audio output device.
3514           *           *
3515           * @throws IOException If some I/O error occurs.           * @throws IOException If some I/O error occurs.
3516           * @throws LscpException If LSCP protocol corruption occurs.           * @throws LscpException If LSCP protocol corruption occurs.
3517           * @throws LSException If           * @throws LSException If
3518           * <ul>           * <ul>
3519           * <li><code>samplerChn</code> is not a valid channel number;           * <li><code>samplerChn</code> is not a valid channel number;
3520           * <li><code>devID</code> is not a valid audio output device ID;           * <li><code>devId</code> is not a valid audio output device ID;
3521           * </ul>           * </ul>
3522           *           *
3523           * @see #getSamplerChannels           * @see #getSamplerChannels
3524           * @see #getAudioOutputDevices           * @see #getAudioOutputDevices
3525           */           */
3526          public synchronized void          public synchronized void
3527          setChannelAudioOutputDevice(int samplerChn, int devID)          setChannelAudioOutputDevice(int samplerChn, int devId)
3528                                  throws IOException, LscpException, LSException {                                  throws IOException, LscpException, LSException {
3529                                    
3530                  verifyConnection();                  verifyConnection();
3531                  out.writeLine("SET CHANNEL AUDIO_OUTPUT_DEVICE " + samplerChn + ' ' + devID);                  out.writeLine("SET CHANNEL AUDIO_OUTPUT_DEVICE " + samplerChn + ' ' + devId);
3532                    if(getPrintOnlyMode()) return;
3533                                    
3534                  ResultSet rs = getEmptyResultSet();                  ResultSet rs = getEmptyResultSet();
3535          }          }
# Line 2198  public class Client { Line 3560  public class Client {
3560                  verifyConnection();                  verifyConnection();
3561                  String args = " " + samplerChn + ' ' + audioOut + ' ' + audioIn;                  String args = " " + samplerChn + ' ' + audioOut + ' ' + audioIn;
3562                  out.writeLine("SET CHANNEL AUDIO_OUTPUT_CHANNEL" + args);                  out.writeLine("SET CHANNEL AUDIO_OUTPUT_CHANNEL" + args);
3563                    if(getPrintOnlyMode()) return;
3564                                    
3565                  ResultSet rs = getEmptyResultSet();                  ResultSet rs = getEmptyResultSet();
3566          }          }
# Line 2206  public class Client { Line 3569  public class Client {
3569           * Sets the MIDI input device on the specified sampler channel.           * Sets the MIDI input device on the specified sampler channel.
3570           *           *
3571           * @param samplerChn The sampler channel number.           * @param samplerChn The sampler channel number.
3572           * @param devID The numerical ID of the MIDI input device.           * @param devId The numerical ID of the MIDI input device.
3573           *           *
3574           * @throws IOException If some I/O error occurs.           * @throws IOException If some I/O error occurs.
3575           * @throws LscpException If LSCP protocol corruption occurs.           * @throws LscpException If LSCP protocol corruption occurs.
3576           * @throws LSException If           * @throws LSException If
3577           * <ul>           * <ul>
3578           * <li><code>samplerChn</code> is not a valid channel number;           * <li><code>samplerChn</code> is not a valid channel number;
3579           * <li><code>devID</code> is not a valid MIDI input device ID;           * <li><code>devId</code> is not a valid MIDI input device ID;
3580           * </ul>           * </ul>
3581           *           *
3582           * @see #getSamplerChannels           * @see #getSamplerChannels
3583           * @see #getMidiInputDevices           * @see #getMidiInputDevices
3584           */           */
3585          public synchronized void          public synchronized void
3586          setChannelMidiInputDevice(int samplerChn, int devID)          setChannelMidiInputDevice(int samplerChn, int devId)
3587                                  throws IOException, LscpException, LSException {                                  throws IOException, LscpException, LSException {
3588                                    
3589                  verifyConnection();                  verifyConnection();
3590                  out.writeLine("SET CHANNEL MIDI_INPUT_DEVICE " + samplerChn + ' ' + devID);                  out.writeLine("SET CHANNEL MIDI_INPUT_DEVICE " + samplerChn + ' ' + devId);
3591                    if(getPrintOnlyMode()) return;
3592                                    
3593                  ResultSet rs = getEmptyResultSet();                  ResultSet rs = getEmptyResultSet();
3594          }          }
# Line 2247  public class Client { Line 3611  public class Client {
3611                                    
3612                  verifyConnection();                  verifyConnection();
3613                  out.writeLine("SET CHANNEL MIDI_INPUT_PORT " + samplerChn + ' ' + port);                  out.writeLine("SET CHANNEL MIDI_INPUT_PORT " + samplerChn + ' ' + port);
3614                    if(getPrintOnlyMode()) return;
3615                                    
3616                  ResultSet rs = getEmptyResultSet();                  ResultSet rs = getEmptyResultSet();
3617          }          }
# Line 2271  public class Client { Line 3636  public class Client {
3636                  String args = String.valueOf(samplerChn) + ' ';                  String args = String.valueOf(samplerChn) + ' ';
3637                  args += (midiChn == -1 ? "ALL" : String.valueOf(midiChn));                  args += (midiChn == -1 ? "ALL" : String.valueOf(midiChn));
3638                  out.writeLine("SET CHANNEL MIDI_INPUT_CHANNEL " + args);                  out.writeLine("SET CHANNEL MIDI_INPUT_CHANNEL " + args);
3639                    if(getPrintOnlyMode()) return;
3640                    
3641                    ResultSet rs = getEmptyResultSet();
3642            }
3643            
3644            /**
3645             * Sets the MIDI instrument map to be used on the specified sampler channel.
3646             *
3647             * @param samplerChn The sampler channel number.
3648             * @param mapId Specifies the numerical ID of the MIDI instrument
3649             * map to assign. To remove the current map binding use <code>-1</code>.
3650             * To set the current map to be the default map use <code>-2</code>.
3651             *
3652             * @throws IOException If some I/O error occurs.
3653             * @throws LscpException If LSCP protocol corruption occurs.
3654             * @throws LSException If
3655             * <ul>
3656             * <li><code>samplerChn</code> is not a valid channel number;
3657             * <li><code>mapId</code> is not a valid MIDI instrument map ID;
3658             * </ul>
3659             *
3660             * @see #getSamplerChannels
3661             * @see #getMidiInstrumentMaps
3662             */
3663            public synchronized void
3664            setChannelMidiInstrumentMap(int samplerChn, int mapId)
3665                                    throws IOException, LscpException, LSException {
3666                    
3667                    verifyConnection();
3668                    String s;
3669                    if(mapId == -1) {
3670                            s = " NONE";
3671                    } else if(mapId == -2) {
3672                            s = " DEFAULT";
3673                    } else {
3674                            s = " " + String.valueOf(mapId);
3675                    }
3676                    out.writeLine("SET CHANNEL MIDI_INSTRUMENT_MAP " + samplerChn + s);
3677                    if(getPrintOnlyMode()) return;
3678                                    
3679                  ResultSet rs = getEmptyResultSet();                  ResultSet rs = getEmptyResultSet();
3680          }          }
# Line 2293  public class Client { Line 3697  public class Client {
3697                    
3698                  verifyConnection();                  verifyConnection();
3699                  out.writeLine("SET CHANNEL VOLUME " + samplerChn + ' ' + volume);                  out.writeLine("SET CHANNEL VOLUME " + samplerChn + ' ' + volume);
3700                    if(getPrintOnlyMode()) return;
3701                                    
3702                  ResultSet rs = getEmptyResultSet();                  ResultSet rs = getEmptyResultSet();
3703          }          }
# Line 2316  public class Client { Line 3721  public class Client {
3721                    
3722                  verifyConnection();                  verifyConnection();
3723                  out.writeLine("SET CHANNEL MUTE " + samplerChn + ' ' + (mute ? 1 : 0));                  out.writeLine("SET CHANNEL MUTE " + samplerChn + ' ' + (mute ? 1 : 0));
3724                    if(getPrintOnlyMode()) return;
3725                                    
3726                  ResultSet rs = getEmptyResultSet();                  ResultSet rs = getEmptyResultSet();
3727          }          }
# Line 2339  public class Client { Line 3745  public class Client {
3745                    
3746                  verifyConnection();                  verifyConnection();
3747                  out.writeLine("SET CHANNEL SOLO " + samplerChn + ' ' + (solo ? 1 : 0));                  out.writeLine("SET CHANNEL SOLO " + samplerChn + ' ' + (solo ? 1 : 0));
3748                    if(getPrintOnlyMode()) return;
3749                    
3750                    ResultSet rs = getEmptyResultSet();
3751            }
3752            
3753            /**
3754             * Creates an additional effect send on the specified sampler channel.
3755             * @param channel The sampler channel, on which a new effect send should be added.
3756             * @param midiCtrl Defines the MIDI controller, which
3757             * will be able alter the effect send level.
3758             * @return The unique ID of the newly created effect send entity.
3759             * @throws IOException If some I/O error occurs.
3760             * @throws LSException If the creation of the effect send failed.
3761             * @throws LscpException If LSCP protocol corruption occurs.
3762             * @see #destroyFxSend
3763             */
3764            public synchronized int
3765            createFxSend(int channel, int midiCtrl)
3766                            throws IOException, LSException, LscpException {
3767                    
3768                    return createFxSend(channel, midiCtrl, null);
3769            }
3770            
3771            /**
3772             * Creates an additional effect send on the specified sampler channel.
3773             * @param channel The sampler channel, on which the effect send should be created on.
3774             * @param midiCtrl Defines the MIDI controller, which can alter the effect send level.
3775             * @param name The name of the effect send entity. The name does not have to be unique.
3776             * @return The unique ID of the newly created effect send entity.
3777             * @throws IOException If some I/O error occurs.
3778             * @throws LSException If the creation of the effect send failed.
3779             * @throws LscpException If LSCP protocol corruption occurs.
3780             * @see #destroyFxSend
3781             */
3782            public synchronized int
3783            createFxSend(int channel, int midiCtrl, String name)
3784                            throws IOException, LSException, LscpException {
3785                    
3786                    verifyConnection();
3787                    String s = String.valueOf(channel) + " " + String.valueOf(midiCtrl);
3788                    if(name != null) s += " '" + toEscapedText(name) + "'";
3789                    out.writeLine("CREATE FX_SEND " + s);
3790                    if(getPrintOnlyMode()) return -1;
3791                    
3792                    ResultSet rs = getEmptyResultSet();
3793                    
3794                    return rs.getIndex();
3795            }
3796            
3797            /**
3798             * Destroys the specified effect send on the specified sampler channel.
3799             * @param channel The sampler channel, from which
3800             * the specified effect send should be removed.
3801             * @param fxSend The ID of the effect send that should be removed.
3802             * @throws LSException If some other error occurs.
3803             * @throws LscpException If LSCP protocol corruption occurs.
3804             * @see #createFxSend
3805             */
3806            public synchronized void
3807            destroyFxSend(int channel, int fxSend)
3808                            throws IOException, LSException, LscpException {
3809                    
3810                    verifyConnection();
3811                    String s = String.valueOf(channel) + " " + String.valueOf(fxSend);
3812                    out.writeLine("DESTROY FX_SEND " + s);
3813                    if(getPrintOnlyMode()) return;
3814                    
3815                    ResultSet rs = getEmptyResultSet();
3816            }
3817            
3818            /**
3819             * Gets the current number of effect sends on the specified sampler channel.
3820             * @param channel The ID of the sampler channel.
3821             * @return The current number of effect sends on the specified sampler channels.
3822             * @throws IOException If some I/O error occurs.
3823             * @throws LscpException If LSCP protocol corruption occurs.
3824             * @throws LSException If some other error occurs.
3825             */
3826            public synchronized int
3827            getFxSoundCount(int channel) throws IOException, LscpException, LSException {
3828                    verifyConnection();
3829                    out.writeLine("GET FX_SENDS " + String.valueOf(channel));
3830                    if(getPrintOnlyMode()) return -1;
3831                    
3832                    String s = getSingleLineResultSet().getResult();
3833                    return parseInt(s);
3834            }
3835            
3836            /**
3837             * Gets a list of all created effect sends on the specified sampler channel.
3838             * @param channel The sampler channel number.
3839             * @return A <code>FxSend</code> array providing all created
3840             * effect sends on the specified sampler channel.
3841             * @throws IOException If some I/O error occurs.
3842             * @throws LscpException If LSCP protocol corruption occurs.
3843             * @throws LSException If <code>channel</code> is not a valid sampler channel ID.
3844             * @see #createFxSend
3845             * @see #destroyFxSend
3846             */
3847            public synchronized FxSend[]
3848            getFxSends(int channel) throws IOException, LscpException, LSException {
3849                    Integer[] idS = getFxSendIDs(channel);
3850                    if(getPrintOnlyMode()) return null;
3851                    
3852                    FxSend[] fxSends = new FxSend[idS.length];
3853                    
3854                    for(int i = 0; i < fxSends.length; i++)
3855                            fxSends[i] = getFxSendInfo(channel, idS[i]);
3856                    
3857                    return fxSends;
3858            }
3859            
3860            /**
3861             * Gets a list of effect sends on the specified sampler channel.
3862             * @param channel The sampler channel number.
3863             * @return An <code>Integer</code> array providing
3864             * the numerical IDs of all effect sends on the specified sampler channel.
3865             * @throws IOException If some I/O error occurs.
3866             * @throws LscpException If LSCP protocol corruption occurs.
3867             * @throws LSException If <code>channel</code> is not a valid sampler channel ID.
3868             * @see #createFxSend
3869             * @see #destroyFxSend
3870             */
3871            public synchronized Integer[]
3872            getFxSendIDs(int channel) throws IOException, LscpException, LSException {
3873                    verifyConnection();
3874                    out.writeLine("LIST FX_SENDS " + channel);
3875                    if(getPrintOnlyMode()) return null;
3876                    
3877                    return parseIntList(getSingleLineResultSet().getResult());
3878            }
3879            
3880            /**
3881             * Gets the current settings of the specified effect send entity.
3882             * @param channel The sampler channel number.
3883             * @param fxSend The numerical ID of the effect send entity.
3884             * @return <code>FxSend</code> instance containing
3885             * the current settings of the specified effect send entity.
3886             * @throws IOException If an I/O error occurs.
3887             * @throws LscpException If LSCP protocol corruption occurs.
3888             * @throws LSException If the sampler channel and/or the effect send number are invalid.
3889             */
3890            public synchronized FxSend
3891            getFxSendInfo(int channel, int fxSend) throws IOException, LscpException, LSException {
3892                    verifyConnection();
3893                    String s = String.valueOf(channel) + " " + String.valueOf(fxSend);
3894                    out.writeLine("GET FX_SEND INFO " + s);
3895                    if(getPrintOnlyMode()) return null;
3896                    
3897                    ResultSet rs = getMultiLineResultSet();
3898                    FxSend fxs = new FxSend(rs.getMultiLineResult());
3899                    fxs.setFxSendId(fxSend);
3900                    
3901                    return fxs;
3902            }
3903            
3904            /**
3905             * Sets the name of the specified effect send.
3906             * @param channel The sampler channel number.
3907             * @param fxSend The numerical ID of the effect send entity.
3908             * @param name The new name for the specified effect send.
3909             * @throws IOException If some I/O error occurs.
3910             * @throws LscpException If LSCP protocol corruption occurs.
3911             * @throws LSException If <code>channel</code> is not a valid channel
3912             * number or <code>fxSend</code> is not a valid effect send ID;
3913             */
3914            public synchronized void
3915            setFxSendName(int channel, int fxSend, String name)
3916                                    throws IOException, LscpException, LSException {
3917                    
3918                    verifyConnection();
3919                    String args = " " + channel + " " + fxSend + " '" + toEscapedText(name) + "'";
3920                    out.writeLine("SET FX_SEND NAME" + args);
3921                    if(getPrintOnlyMode()) return;
3922                    
3923                    ResultSet rs = getEmptyResultSet();
3924            }
3925            
3926            /**
3927             * Sets the destination of an effect send's audio channel in the specified sampler channel.
3928             * @param channel The sampler channel number.
3929             * @param fxSend The numerical ID of the effect send entity to be rerouted.
3930             * @param audioSrc The numerical ID of the effect send's audio output channel,
3931             * which should be rerouted.
3932             * @param audioDst The audio channel of the selected audio output device
3933             * where <code>audioSrc</code> should be routed to.
3934             * @throws IOException If some I/O error occurs.
3935             * @throws LscpException If LSCP protocol corruption occurs.
3936             * @throws LSException If
3937             * <ul>
3938             * <li><code>channel</code> is not a valid channel number;
3939             * <li><code>fxSend</code> is not a valid effect send ID;
3940             * <li>There is no engine assigned yet to the specified sampler channel;
3941             * <li>There is no audio output device connected to the specified sampler channel.
3942             * </ul>
3943             */
3944            public synchronized void
3945            setFxSendAudioOutputChannel(int channel, int fxSend, int audioSrc, int audioDst)
3946                                    throws IOException, LscpException, LSException {
3947                    
3948                    verifyConnection();
3949                    String args = " " + channel + " " + fxSend + " " + audioSrc + " " + audioDst;
3950                    out.writeLine("SET FX_SEND AUDIO_OUTPUT_CHANNEL" + args);
3951                    if(getPrintOnlyMode()) return;
3952                    
3953                    ResultSet rs = getEmptyResultSet();
3954            }
3955            
3956            /**
3957             * Sets the MIDI controller, which will be able to modify
3958             * the send level of the specified effect send in the specified sampler channel.
3959             * @param channel The sampler channel number.
3960             * @param fxSend The numerical ID of the effect send entity.
3961             * @param midiCtrl The MIDI controller which shall be
3962             * able to modify the effect send's send level.
3963             * @throws IOException If some I/O error occurs.
3964             * @throws LscpException If LSCP protocol corruption occurs.
3965             * @throws LSException If
3966             * <ul>
3967             * <li><code>channel</code> is not a valid channel number;
3968             * <li><code>fxSend</code> is not a valid effect send ID;
3969             * <li><code>midiCtrl</code> is not a valid controller;
3970             * </ul>
3971             */
3972            public synchronized void
3973            setFxSendMidiController(int channel, int fxSend, int midiCtrl)
3974                                    throws IOException, LscpException, LSException {
3975                    
3976                    verifyConnection();
3977                    String args = " " + channel + " " + fxSend + " " + midiCtrl;
3978                    out.writeLine("SET FX_SEND MIDI_CONTROLLER" + args);
3979                    if(getPrintOnlyMode()) return;
3980                    
3981                    ResultSet rs = getEmptyResultSet();
3982            }
3983            
3984            /**
3985             * Sets the current send level of the specified
3986             * effect send entity in the specified sampler channel.
3987             * @param channel The sampler channel number.
3988             * @param fxSend The numerical ID of the effect send entity.
3989             * @param volume The new volume value (a value smaller than 1.0 means
3990             * attenuation, whereas a value greater than 1.0 means amplification).
3991             * @throws IOException If some I/O error occurs.
3992             * @throws LscpException If LSCP protocol corruption occurs.
3993             * @throws LSException If some other error occurs.
3994             */
3995            public synchronized void
3996            setFxSendLevel(int channel, int fxSend, float volume)
3997                                    throws IOException, LscpException, LSException {
3998                    
3999                    verifyConnection();
4000                    String args = " " + channel + " " + fxSend + " " + String.valueOf(volume);
4001                    out.writeLine("SET FX_SEND LEVEL" + args);
4002                    if(getPrintOnlyMode()) return;
4003                    
4004                    ResultSet rs = getEmptyResultSet();
4005            }
4006            
4007            /**
4008             * Starts an instrument editor for editing the loaded instrument
4009             * on the specified sampler channel.
4010             * @param samplerChn The sampler channel number.
4011             * @throws IOException If some I/O error occurs.
4012             * @throws LscpException If LSCP protocol corruption occurs.
4013             * @throws LSException If <code>samplerChn</code> is not a valid channel number or if
4014             * there is no instrument loaded on the specified sampler channel.
4015             * @see #getSamplerChannels
4016             */
4017            public synchronized void
4018            editChannelInstrument(int samplerChn) throws IOException, LscpException, LSException {
4019                    verifyConnection();
4020                    out.writeLine("EDIT CHANNEL INSTRUMENT " + samplerChn);
4021                    if(getPrintOnlyMode()) return;
4022                    
4023                    ResultSet rs = getEmptyResultSet();
4024            }
4025            
4026            /**
4027             * Sends a MIDI event to this sampler channel.
4028             * @param samplerChn The sampler channel number.
4029             * @param type The type of MIDI message to send.
4030             * @throws IOException If some I/O error occurs.
4031             * @throws LscpException If LSCP protocol corruption occurs.
4032             * @throws LSException If <code>samplerChn</code> is not a valid channel number or if
4033             * there is no instrument loaded on the specified sampler channel.
4034             * @see #getSamplerChannels
4035             */
4036            public synchronized void
4037            sendChannelMidiData(int samplerChn, MidiDataEvent.Type type, int arg1, int arg2)
4038                                                    throws IOException, LscpException, LSException {
4039                    
4040                    verifyConnection();
4041                    StringBuffer sb = new StringBuffer();
4042                    sb.append("SEND CHANNEL MIDI_DATA ");
4043                    sb.append(type).append(" ").append(samplerChn).append(" ");
4044                    sb.append(arg1).append(" ").append(arg2);
4045                    
4046                    out.writeLine(sb.toString());
4047                    if(getPrintOnlyMode()) return;
4048                                    
4049                  ResultSet rs = getEmptyResultSet();                  ResultSet rs = getEmptyResultSet();
4050          }          }
# Line 2358  public class Client { Line 4064  public class Client {
4064          resetChannel(int samplerChn) throws IOException, LscpException, LSException {          resetChannel(int samplerChn) throws IOException, LscpException, LSException {
4065                  verifyConnection();                  verifyConnection();
4066                  out.writeLine("RESET CHANNEL " + samplerChn);                  out.writeLine("RESET CHANNEL " + samplerChn);
4067                    if(getPrintOnlyMode()) return;
4068                    
4069                    ResultSet rs = getEmptyResultSet();
4070            }
4071            
4072            
4073            
4074            /**
4075             * Adds the specified directory to the instruments database.
4076             * @param dir The absolute (escaped) path name of the directory to add.
4077             * @throws IOException If some I/O error occurs.
4078             * @throws LSException If the creation of the directory failed.
4079             * @throws LscpException If LSCP protocol corruption occurs.
4080             */
4081            public synchronized void
4082            addDbDirectory(String dir) throws IOException, LSException, LscpException {
4083                    verifyConnection();
4084                    out.writeLine("ADD DB_INSTRUMENT_DIRECTORY '" + conv(dir) + "'");
4085                    if(getPrintOnlyMode()) return;
4086                    
4087                    ResultSet rs = getEmptyResultSet();
4088            }
4089            
4090            /**
4091             * Removes the specified directory from the instruments database.
4092             * @param dir The absolute (escaped) path name of the directory to remove.
4093             * @throws IOException If some I/O error occurs.
4094             * @throws LscpException If LSCP protocol corruption occurs.
4095             * @throws LSException If the specified directory is not
4096             * empty or if the removal of the directory failed.
4097             */
4098            public synchronized void
4099            removeDbDirectory(String dir) throws IOException, LscpException, LSException {
4100                    removeDbDirectory(dir, false);
4101            }
4102            
4103            /**
4104             * Removes the specified directory from the instruments database.
4105             * @param dir The absolute path name of the directory to remove.
4106             * @param force If <code>true</code> forces the removal of non-empty
4107             * directory and all its content.
4108             * @throws IOException If some I/O error occurs.
4109             * @throws LscpException If LSCP protocol corruption occurs.
4110             * @throws LSException If the removing of the directory failed.
4111             */
4112            public synchronized void
4113            removeDbDirectory(String dir, boolean force)
4114                                    throws IOException, LscpException, LSException {
4115                    
4116                    verifyConnection();
4117                    String s = "REMOVE DB_INSTRUMENT_DIRECTORY ";
4118                    if(force) s += "FORCE ";
4119                    out.writeLine(s + "'" + conv(dir) + "'");
4120                    if(getPrintOnlyMode()) return;
4121                    
4122                    ResultSet rs = getEmptyResultSet();
4123            }
4124            
4125            /**
4126             * Removes the specified directories from the instruments database.
4127             * @param dirs The absolute (escaped) path names of the directories to remove.
4128             * @param force If <code>true</code> forces the removal of non-empty
4129             * directories.
4130             * @throws IOException If some I/O error occurs.
4131             * @throws LscpException If LSCP protocol corruption occurs.
4132             * @throws LSException If the removing of the directores failed.
4133             */
4134            public synchronized void
4135            removeDbDirectories(String[] dirs, boolean force)
4136                                    throws IOException, LscpException, LSException {
4137                    
4138                    verifyConnection();
4139                    String cmd = "REMOVE DB_INSTRUMENT_DIRECTORY ";
4140                    if(force) cmd += "FORCE ";
4141                    
4142                    for(String s : dirs) out.writeLine(cmd + "'" + conv(s) + "'");
4143                    
4144                    if(getPrintOnlyMode()) return;
4145                    
4146                    getEmptyResultSets(dirs.length, "Client.dirDeletionFailed!");
4147            }
4148            
4149            /**
4150             * Gets the number of directories in the specified directory.
4151             * @return The current number of directories in the specified directory.
4152             * @param dir The absolute path name of the directory.
4153             * @throws IOException If some I/O error occurs.
4154             * @throws LscpException If LSCP protocol corruption occurs.
4155             * @throws LSException If some other error occurs.
4156             */
4157            public synchronized int
4158            getDbDirectoryCount(String dir) throws IOException, LscpException, LSException {
4159                    return getDbDirectoryCount(dir, false);
4160            }
4161            
4162            /**
4163             * Gets the number of directories in the specified directory.
4164             * @return The current number of directories in the specified directory.
4165             * @param dir The absolute path name of the directory.
4166             * @param recursive If <code>true</code>, the number of all directories
4167             * in the specified subtree will be returned.
4168             * @throws IOException If some I/O error occurs.
4169             * @throws LscpException If LSCP protocol corruption occurs.
4170             * @throws LSException If some other error occurs.
4171             */
4172            public synchronized int
4173            getDbDirectoryCount(String dir, boolean recursive)
4174                                    throws IOException, LscpException, LSException {
4175                    
4176                    verifyConnection();
4177                    String s;
4178                    if(recursive) s = "GET DB_INSTRUMENT_DIRECTORIES RECURSIVE '";
4179                    else s = "GET DB_INSTRUMENT_DIRECTORIES '";
4180                    out.writeLine(s + conv(dir) + "'");
4181                    if(getPrintOnlyMode()) return -1;
4182                    
4183                    s = getSingleLineResultSet().getResult();
4184                    return parseInt(s);
4185            }
4186            
4187            /**
4188             * Gets the list of directories in the specified directory.
4189             * @param dir The absolute path name of the directory.
4190             * @return A <code>String</code> array providing the names of
4191             * all directories in the specified directory.
4192             * @throws IOException If some I/O error occurs.
4193             * @throws LscpException If LSCP protocol corruption occurs.
4194             * @throws LSException If the specified path name is invalid.
4195             */
4196            public synchronized String[]
4197            getDbDirectoryNames(String dir) throws IOException, LscpException, LSException {
4198                    verifyConnection();
4199                    out.writeLine("LIST DB_INSTRUMENT_DIRECTORIES '" + conv(dir) + "'");
4200                    if(getPrintOnlyMode()) return null;
4201                    
4202                    String[] names = parseEscapedStringList(getSingleLineResultSet().getResult());
4203                    for(int i = 0; i < names.length; i++) {
4204                            names[i] = toNonEscapedString(names[i]);
4205                    }
4206                    return names;
4207            }
4208            
4209            /**
4210             * Gets information about the specified directory.
4211             * @param dir The absolute path name of the directory.
4212             * @return A <code>DbDirectoryInfo</code> instance providing information
4213             * about the specified directory.
4214             * @throws IOException If some I/O error occurs.
4215             * @throws LscpException If LSCP protocol corruption occurs.
4216             * @throws LSException If the specified directory is not found.
4217             */
4218            public synchronized DbDirectoryInfo
4219            getDbDirectoryInfo(String dir) throws IOException, LscpException, LSException {
4220                    verifyConnection();
4221                    out.writeLine("GET DB_INSTRUMENT_DIRECTORY INFO '" + conv(dir) + "'");
4222                    if(getPrintOnlyMode()) return null;
4223                    
4224                    ResultSet rs = getMultiLineResultSet();
4225                    DbDirectoryInfo info = new DbDirectoryInfo(rs.getMultiLineResult());
4226                    if(dir.equals("/")) {
4227                            info.setName("/");
4228                    } else {
4229                            dir = removeEndingFileSeparator(dir);
4230                    }
4231                    String s = getFileName(dir);
4232                    if(s != null) info.setName(toNonEscapedFileName(s));
4233                    s = getParentDirectory(dir);
4234                    if(s != null) info.setParentDirectoryPath(s);
4235                    
4236                    return info;
4237            }
4238            
4239            /**
4240             * Gets the list of directories in the specified directory.
4241             * @param dir The absolute path name of the directory.
4242             * @return A <code>DbDirectoryInfo</code> array providing
4243             * information about all directories in the specified directory.
4244             * @throws IOException If some I/O error occurs.
4245             * @throws LscpException If LSCP protocol corruption occurs.
4246             * @throws LSException If the specified path name is invalid.
4247             */
4248            public synchronized DbDirectoryInfo[]
4249            getDbDirectories(String dir) throws IOException, LscpException, LSException {
4250                    String[] dirS = getDbDirectoryNames(dir);
4251                    if(!hasEndingFileSeparator(dir)) dir += "/";
4252                    DbDirectoryInfo[] infoS = new DbDirectoryInfo[dirS.length];
4253                    for(int i = 0; i < dirS.length; i++) {
4254                            infoS[i] = getDbDirectoryInfo(conv(dir) + toEscapedFsEntry(dirS[i]));
4255                    }
4256                    return infoS;
4257            }
4258            
4259            /**
4260             * Gets the list of directories in the specified directory.
4261             * @param dir The absolute path name of the directory.
4262             * @return A <code>DbDirectoryInfo</code> array providing
4263             * information about all directories in the specified directory.
4264             * @throws IOException If some I/O error occurs.
4265             * @throws LscpException If LSCP protocol corruption occurs.
4266             * @throws LSException If the specified path name is invalid.
4267             *
4268            public synchronized DbDirectoryInfo[]
4269            getDbDirectories(String dir) throws IOException, LscpException, LSException {
4270                    String[] dirS = getDbDirectoryNames(conv(dir));
4271                    if(dirS.length == 0) return new DbDirectoryInfo[0];
4272                    
4273                    if(dir.charAt(dir.length() - 1) != '/') dir += "/"; // FIXME:
4274                    
4275                    for(int i = 0; i < dirS.length; i++) {
4276                            out.writeLine("GET DB_INSTRUMENT_DIRECTORY INFO '" + conv(dir + dirS[i]) + "'");
4277                    }
4278                    
4279                    if(getPrintOnlyMode()) return null;
4280                    
4281                    if(dir.length() > 1) dir = dir.substring(0, dir.length() - 1);
4282                    StringBuffer sb = new StringBuffer();
4283                    DbDirectoryInfo[] infoS = new DbDirectoryInfo[dirS.length];
4284                    for(int i = 0; i < dirS.length; i++) {
4285                            try {
4286                                    ResultSet rs = getMultiLineResultSet();
4287                                    infoS[i] = new DbDirectoryInfo(rs.getMultiLineResult());
4288                                    infoS[i].setName(dirS[i]);
4289                                    infoS[i].setParentDirectoryPath(dir);
4290                            } catch (SocketTimeoutException e) {
4291                                    getLogger().log(Level.FINE, e.getMessage(), e);
4292                                    sb.append(e.getMessage()).append("\n");
4293                                    break;
4294                            } catch (Exception e) {
4295                                    getLogger().log(Level.FINE, e.getMessage(), e);
4296                                    sb.append(e.getMessage()).append("\n");
4297                            }
4298                    }
4299                    
4300                    String details = sb.toString();
4301                    if(details.length() > 0) {
4302                            String err = LscpI18n.getLogMsg("Client.getInstrsInfoFailed!");
4303                            throw new LSException(0, err, details);
4304                    }
4305                    
4306                    return infoS;
4307            }*/
4308            
4309            /**
4310             * Renames the specified directory.
4311             * @param dir The absolute path name of the directory to rename.
4312             * @param name The new name for the directory.
4313             * @throws IOException If some I/O error occurs.
4314             * @throws LSException If the renaming of the directory failed.
4315             * @throws LscpException If LSCP protocol corruption occurs.
4316             */
4317            public synchronized void
4318            renameDbDirectory(String dir, String name) throws IOException, LSException, LscpException {
4319                    verifyConnection();
4320                    name = toEscapedText(name);
4321                    out.writeLine("SET DB_INSTRUMENT_DIRECTORY NAME '" + conv(dir) + "' '" + conv(name) + "'");
4322                    if(getPrintOnlyMode()) return;
4323                    
4324                    ResultSet rs = getEmptyResultSet();
4325            }
4326            
4327            /**
4328             * Moves the specified directory into the specified location.
4329             * @param dir The absolute path name of the directory to move.
4330             * @param dst The location where the directory will be moved to.
4331             * @throws IOException If some I/O error occurs.
4332             * @throws LSException If the operation failed.
4333             * @throws LscpException If LSCP protocol corruption occurs.
4334             */
4335            public synchronized void
4336            moveDbDirectory(String dir, String dst) throws IOException, LSException, LscpException {
4337                    verifyConnection();
4338                    out.writeLine("MOVE DB_INSTRUMENT_DIRECTORY '" + conv(dir) + "' '" + conv(dst) + "'");
4339                    if(getPrintOnlyMode()) return;
4340                    
4341                    ResultSet rs = getEmptyResultSet();
4342            }
4343            
4344            /**
4345             * Moves the specified directories into the specified location.
4346             * @param dirs The absolute path names of the directories to move.
4347             * @param dst The location where the directories will be moved to.
4348             * @throws IOException If some I/O error occurs.
4349             * @throws LSException If the operation failed.
4350             * @throws LscpException If LSCP protocol corruption occurs.
4351             */
4352            public synchronized void
4353            moveDbDirectories(String dirs[], String dst) throws IOException, LSException, LscpException {
4354                    verifyConnection();
4355                    for(String s : dirs) {
4356                            out.writeLine("MOVE DB_INSTRUMENT_DIRECTORY '" + conv(s) + "' '" + conv(dst) + "'");
4357                    }
4358                    if(getPrintOnlyMode()) return;
4359                    
4360                    getEmptyResultSets(dirs.length, "Client.dirMovingFailed!");
4361            }
4362            
4363            /**
4364             * Copies the specified directory into the specified location.
4365             * @param dir The absolute path name of the directory to copy.
4366             * @param dst The location where the directory will be copied to.
4367             * @throws IOException If some I/O error occurs.
4368             * @throws LSException If the operation failed.
4369             * @throws LscpException If LSCP protocol corruption occurs.
4370             */
4371            public synchronized void
4372            copyDbDirectory(String dir, String dst) throws IOException, LSException, LscpException {
4373                    verifyConnection();
4374                    out.writeLine("COPY DB_INSTRUMENT_DIRECTORY '" + conv(dir) + "' '" + conv(dst) + "'");
4375                    if(getPrintOnlyMode()) return;
4376                    
4377                    ResultSet rs = getEmptyResultSet();
4378            }
4379            
4380            /**
4381             * Copies the specified directories into the specified location.
4382             * @param dirs The absolute path names of the directories to copy.
4383             * @param dst The location where the directories will be copied to.
4384             * @throws IOException If some I/O error occurs.
4385             * @throws LSException If the operation failed.
4386             * @throws LscpException If LSCP protocol corruption occurs.
4387             */
4388            public synchronized void
4389            copyDbDirectories(String[] dirs, String dst) throws IOException, LSException, LscpException {
4390                    verifyConnection();
4391                    for(String s : dirs) {
4392                            out.writeLine("COPY DB_INSTRUMENT_DIRECTORY '" + conv(s) + "' '" + conv(dst) + "'");
4393                    }
4394                    if(getPrintOnlyMode()) return;
4395                    
4396                    getEmptyResultSets(dirs.length, "Client.dirCopyingFailed!");
4397            }
4398            
4399            /**
4400             * Changes the description of the specified directory.
4401             * @param dir The absolute path name of the directory.
4402             * @param desc The new description for the directory.
4403             * @throws IOException If some I/O error occurs.
4404             * @throws LSException If failed to change the description.
4405             * @throws LscpException If LSCP protocol corruption occurs.
4406             */
4407            public synchronized void
4408            setDbDirectoryDescription(String dir, String desc)
4409                                    throws IOException, LSException, LscpException {
4410                    
4411                    verifyConnection();
4412                    String s = "SET DB_INSTRUMENT_DIRECTORY DESCRIPTION '";
4413                    out.writeLine(s + conv(dir) + "' '" + toEscapedText(desc) + "'");
4414                    if(getPrintOnlyMode()) return;
4415                    
4416                    ResultSet rs = getEmptyResultSet();
4417            }
4418            
4419            public static enum ScanMode {
4420                    RECURSIVE, NON_RECURSIVE, FLAT
4421            }
4422            
4423            /**
4424             * Adds the specified instrument to the specified instruments database directory.
4425             * @param dbDir The absolute path name of the database directory in which the
4426             * specified instrument will be added.
4427             * @param filePath The absolute path name of the instrument file.
4428             * @param instrIndex The index of the instrument (in the given instrument file) to add.
4429             * @throws IOException If some I/O error occurs.
4430             * @throws LSException If the operation failed.
4431             * @throws LscpException If LSCP protocol corruption occurs.
4432             */
4433            public synchronized void
4434            addDbInstrument(String dbDir, String filePath, int instrIndex)
4435                                            throws IOException, LSException, LscpException {
4436                    
4437                    addDbInstrument(dbDir, filePath, instrIndex, false);
4438            }
4439            
4440            /**
4441             * Adds the specified instrument to the specified instruments database directory.
4442             * @param dbDir The absolute path name of the database directory in which the
4443             * specified instrument will be added.
4444             * @param filePath The absolute path name of the instrument file.
4445             * @param instrIndex The index of the instrument (in the given instrument file) to add.
4446             * @param background If <code>true</code>, the scan will be done
4447             * in background and this method may return before the job is finished.
4448             * @return If <code>background</code> is <code>true</code>, the ID
4449             * of the scan job.
4450             * @throws IOException If some I/O error occurs.
4451             * @throws LSException If the operation failed.
4452             * @throws LscpException If LSCP protocol corruption occurs.
4453             * @see #addInstrumentsDbListener
4454             */
4455            public synchronized int
4456            addDbInstrument(String dbDir, String filePath, int instrIndex, boolean background)
4457                                            throws IOException, LSException, LscpException {
4458                    
4459                    verifyConnection();
4460                    String s = "ADD DB_INSTRUMENTS";
4461                    if(background) s += " NON_MODAL";
4462                    s += " '" + conv(dbDir) + "' '" + conv(filePath) + "' ";
4463                    out.writeLine(s + String.valueOf(instrIndex));
4464                    if(getPrintOnlyMode()) return -1;
4465                    
4466                    ResultSet rs = getEmptyResultSet();
4467                    return rs.getIndex();
4468            }
4469            
4470            /**
4471             * Adds the instruments in the specified file to the specified
4472             * instruments database directory.
4473             * @param dbDir The absolute path name of the database directory
4474             * in which the the supported instruments will be added.
4475             * @param filePath The absolute path name of the file to scan for instruments.
4476             * @throws IOException If some I/O error occurs.
4477             * @throws LSException If the operation failed.
4478             * @throws LscpException If LSCP protocol corruption occurs.
4479             */
4480            public synchronized void
4481            addDbInstruments(String dbDir, String filePath)
4482                                            throws IOException, LSException, LscpException {
4483                    
4484                    addDbInstruments(dbDir, filePath, false);
4485            }
4486            
4487            /**
4488             * Adds the instruments in the specified file to the specified
4489             * instruments database directory.
4490             * @param dbDir The absolute path name of the database directory
4491             * in which the the supported instruments will be added.
4492             * @param filePath The absolute path name of the file to scan for instruments.
4493             * @param background If <code>true</code>, the scan will be done
4494             * in background and this method may return before the job is finished.
4495             * @return If <code>background</code> is <code>true</code>, the ID
4496             * of the scan job.
4497             * @throws IOException If some I/O error occurs.
4498             * @throws LSException If the operation failed.
4499             * @throws LscpException If LSCP protocol corruption occurs.
4500             * @see #addInstrumentsDbListener
4501             */
4502            public synchronized int
4503            addDbInstruments(String dbDir, String filePath, boolean background)
4504                                            throws IOException, LSException, LscpException {
4505                    
4506                    verifyConnection();
4507                    String s = "ADD DB_INSTRUMENTS";
4508                    if(background) s += " NON_MODAL";
4509                    out.writeLine(s + " '" + conv(dbDir) + "' '" + conv(filePath) + "'");
4510                    if(getPrintOnlyMode()) return -1;
4511                    
4512                    ResultSet rs = getEmptyResultSet();
4513                    return rs.getIndex();
4514            }
4515            
4516            /**
4517             * Adds the instruments in the specified file system directory
4518             * to the specified instruments database directory.
4519             * @param mode Determines the scanning mode. If RECURSIVE is
4520             * specified, all supported instruments in the specified file system
4521             * direcotry will be added to the specified instruments database
4522             * directory, including the instruments in subdirectories
4523             * of the supplied directory. If NON_RECURSIVE is specified,
4524             * the instruments in the subdirectories will not be processed.
4525             * If FLAT is specified, all supported instruments in the specified
4526             * file system direcotry will be added, including the instruments in
4527             * subdirectories of the supplied directory, but the respective
4528             * subdirectory structure will not be recreated in the instruments
4529             * database and all instruments will be added directly in the
4530             * specified database directory.
4531             * @param dbDir The absolute path name of the database directory
4532             * in which the supported instruments will be added.
4533             * @param fsDir The absolute path name of the file system directory.
4534             * @throws IOException If some I/O error occurs.
4535             * @throws LSException If the operation failed.
4536             * @throws LscpException If LSCP protocol corruption occurs.
4537             */
4538            public synchronized void
4539            addDbInstruments(ScanMode mode, String dbDir, String fsDir)
4540                                            throws IOException, LSException, LscpException {
4541                    
4542                    addDbInstruments(mode, dbDir, fsDir, false);
4543            }
4544            
4545            /**
4546             * Adds the instruments in the specified file system directory
4547             * to the specified instruments database directory.
4548             * @param mode Determines the scanning mode. If RECURSIVE is
4549             * specified, all supported instruments in the specified file system
4550             * direcotry will be added to the specified instruments database
4551             * directory, including the instruments in subdirectories
4552             * of the supplied directory. If NON_RECURSIVE is specified,
4553             * the instruments in the subdirectories will not be processed.
4554             * If FLAT is specified, all supported instruments in the specified
4555             * file system direcotry will be added, including the instruments in
4556             * subdirectories of the supplied directory, but the respective
4557             * subdirectory structure will not be recreated in the instruments
4558             * database and all instruments will be added directly in the
4559             * specified database directory.
4560             * @param dbDir The absolute path name of the database directory
4561             * in which the supported instruments will be added.
4562             * @param fsDir The absolute path name of the file system directory.
4563             * @param background If <code>true</code>, the scan will be done
4564             * in background and this method may return before the job is finished.
4565             * @return If <code>background</code> is <code>true</code>, the ID
4566             * of the scan job.
4567             * @throws IOException If some I/O error occurs.
4568             * @throws LSException If the operation failed.
4569             * @throws LscpException If LSCP protocol corruption occurs.
4570             * @see #addInstrumentsDbListener
4571             */
4572            public synchronized int
4573            addDbInstruments(ScanMode mode, String dbDir, String fsDir, boolean background)
4574                                            throws IOException, LSException, LscpException {
4575                    
4576                    return addDbInstruments(mode, dbDir, fsDir, background, false);
4577            }
4578            
4579            /**
4580             * Adds the instruments in the specified file system directory
4581             * to the specified instruments database directory.
4582             * @param mode Determines the scanning mode. If RECURSIVE is
4583             * specified, all supported instruments in the specified file system
4584             * direcotry will be added to the specified instruments database
4585             * directory, including the instruments in subdirectories
4586             * of the supplied directory. If NON_RECURSIVE is specified,
4587             * the instruments in the subdirectories will not be processed.
4588             * If FLAT is specified, all supported instruments in the specified
4589             * file system direcotry will be added, including the instruments in
4590             * subdirectories of the supplied directory, but the respective
4591             * subdirectory structure will not be recreated in the instruments
4592             * database and all instruments will be added directly in the
4593             * specified database directory.
4594             * @param dbDir The absolute path name of the database directory
4595             * in which the supported instruments will be added.
4596             * @param fsDir The absolute path name of the file system directory.
4597             * @param background If <code>true</code>, the scan will be done
4598             * in background and this method may return before the job is finished.
4599             * @param insDir If <code>true</code> a drieectory is created for each
4600             * instrument file.
4601             * @return If <code>background</code> is <code>true</code>, the ID
4602             * of the scan job.
4603             * @throws IOException If some I/O error occurs.
4604             * @throws LSException If the operation failed.
4605             * @throws LscpException If LSCP protocol corruption occurs.
4606             * @see #addInstrumentsDbListener
4607             */
4608            public synchronized int
4609            addDbInstruments(ScanMode mode, String dbDir, String fsDir, boolean background, boolean insDir)
4610                                            throws IOException, LSException, LscpException {
4611                    
4612                    verifyConnection();
4613                    StringBuffer sb = new StringBuffer("ADD DB_INSTRUMENTS");
4614                    if(background) sb.append(" NON_MODAL");
4615                    
4616                    switch(mode) {
4617                            case RECURSIVE:
4618                                    sb.append(" RECURSIVE");
4619                                    break;
4620                            case NON_RECURSIVE:
4621                                    sb.append(" NON_RECURSIVE");
4622                                    break;
4623                            case FLAT:
4624                                    sb.append(" FLAT");
4625                                    break;
4626                    }
4627                    if(insDir)
4628                            sb.append(" FILE_AS_DIR");
4629                    
4630                    sb.append(" '").append(conv(dbDir)).append("' '");
4631                    sb.append(conv(fsDir)).append("'");
4632                    out.writeLine(sb.toString());
4633                    if(getPrintOnlyMode()) return -1;
4634                    
4635                    ResultSet rs = getEmptyResultSet();
4636                    return rs.getIndex();
4637            }
4638    
4639            /**
4640             * Removes the specified instrument from the instruments database.
4641             * @param instr The absolute path name of the instrument to remove.
4642             * @throws IOException If some I/O error occurs.
4643             * @throws LscpException If LSCP protocol corruption occurs.
4644             * @throws LSException If the removing of the instrument failed.
4645             */
4646            public synchronized void
4647            removeDbInstrument(String instr) throws IOException, LscpException, LSException {
4648                    
4649                    verifyConnection();
4650                    out.writeLine("REMOVE DB_INSTRUMENT '" + conv(instr) + "'");
4651                    if(getPrintOnlyMode()) return;
4652                    
4653                    ResultSet rs = getEmptyResultSet();
4654            }
4655            
4656            /**
4657             * Removes the specified instruments from the instruments database.
4658             * @param instrs The absolute path names of the instruments to remove.
4659             * @throws IOException If some I/O error occurs.
4660             * @throws LscpException If LSCP protocol corruption occurs.
4661             * @throws LSException If the removing of the instruments failed.
4662             */
4663            public synchronized void
4664            removeDbInstruments(String[] instrs) throws IOException, LscpException, LSException {
4665                    verifyConnection();
4666                    for(String s : instrs) {
4667                            out.writeLine("REMOVE DB_INSTRUMENT '" + conv(s) + "'");
4668                    }
4669                    if(getPrintOnlyMode()) return;
4670                    
4671                    getEmptyResultSets(instrs.length, "Client.instrDeletionFailed!");
4672            }
4673            
4674            /**
4675             * Gets the number of instruments in the specified directory.
4676             * @return The current number of instruments in the specified directory.
4677             * @param dir The absolute path name of the directory.
4678             * @throws IOException If some I/O error occurs.
4679             * @throws LscpException If LSCP protocol corruption occurs.
4680             * @throws LSException If some other error occurs.
4681             */
4682            public synchronized int
4683            getDbInstrumentCount(String dir) throws IOException, LscpException, LSException {
4684                    return getDbInstrumentCount(dir, false);
4685            }
4686            
4687            /**
4688             * Gets the number of instruments in the specified directory.
4689             * @return The current number of instruments in the specified directory.
4690             * @param dir The absolute path name of the directory.
4691             * @param recursive If <code>true</code>, the number of all instruments
4692             * in the specified subtree will be returned.
4693             * @throws IOException If some I/O error occurs.
4694             * @throws LscpException If LSCP protocol corruption occurs.
4695             * @throws LSException If some other error occurs.
4696             */
4697            public synchronized int
4698            getDbInstrumentCount(String dir, boolean recursive)
4699                                    throws IOException, LscpException, LSException {
4700                    
4701                    verifyConnection();
4702                    String s;
4703                    if(recursive) s = "GET DB_INSTRUMENTS RECURSIVE '";
4704                    else s = "GET DB_INSTRUMENTS '";
4705                    out.writeLine(s + conv(dir) + "'");
4706                    if(getPrintOnlyMode()) return -1;
4707                    
4708                    s = getSingleLineResultSet().getResult();
4709                    return parseInt(s);
4710            }
4711            
4712            /**
4713             * Gets the list of instruments in the specified directory.
4714             * @param dir The absolute path name of the directory.
4715             * @return A <code>String</code> array providing the names of
4716             * all instruments in the specified directory.
4717             * @throws IOException If some I/O error occurs.
4718             * @throws LscpException If LSCP protocol corruption occurs.
4719             * @throws LSException If the specified path name is invalid.
4720             */
4721            public synchronized String[]
4722            getDbInstrumentNames(String dir) throws IOException, LscpException, LSException {
4723                    verifyConnection();
4724                    out.writeLine("LIST DB_INSTRUMENTS '" + conv(dir) + "'");
4725                    if(getPrintOnlyMode()) return null;
4726                    
4727                    String[] names = parseEscapedStringList(getSingleLineResultSet().getResult());
4728                    for(int i = 0; i < names.length; i++) {
4729                            names[i] = toNonEscapedString(names[i]);
4730                    }
4731                    return names;
4732            }
4733            
4734            /**
4735             * Gets information about the specified instrument.
4736             * @param instr The absolute path name of the instrument.
4737             * @return A <code>DbInstrumentInfo</code> instance providing information
4738             * about the specified instrument.
4739             * @throws IOException If some I/O error occurs.
4740             * @throws LscpException If LSCP protocol corruption occurs.
4741             * @throws LSException If the specified instrument is not found.
4742             */
4743            public synchronized DbInstrumentInfo
4744            getDbInstrumentInfo(String instr) throws IOException, LscpException, LSException {
4745                    verifyConnection();
4746                    out.writeLine("GET DB_INSTRUMENT INFO '" + conv(instr) + "'");
4747                    if(getPrintOnlyMode()) return null;
4748                    
4749                    ResultSet rs = getMultiLineResultSet();
4750                    DbInstrumentInfo info = new DbInstrumentInfo(rs.getMultiLineResult());
4751                    String s = getParentDirectory(instr);
4752                    if(s != null) info.setDirectoryPath(s);
4753                    s = getFileName(instr);
4754                    if(s != null) info.setName(toNonEscapedFileName(s));
4755                    
4756                    return info;
4757            }
4758            
4759            /**
4760             * Gets the list of instruments in the specified directory.
4761             * @param dir The absolute path name of the directory.
4762             * @return A <code>DbInstrumentInfo</code> array providing
4763             * information about all instruments in the specified directory.
4764             * @throws IOException If some I/O error occurs.
4765             * @throws LscpException If LSCP protocol corruption occurs.
4766             * @throws LSException If the specified path name is invalid.
4767             */
4768            public synchronized DbInstrumentInfo[]
4769            getDbInstruments(String dir) throws IOException, LscpException, LSException {
4770                    String[] instrS = getDbInstrumentNames(dir);
4771                    if(!hasEndingFileSeparator(dir)) dir += "/";
4772                    
4773                    DbInstrumentInfo[] infoS = new DbInstrumentInfo[instrS.length];
4774                    for(int i = 0; i < instrS.length; i++) {
4775                            infoS[i] = getDbInstrumentInfo(conv(dir) + toEscapedFsEntry(instrS[i]));
4776                    }
4777                    return infoS;
4778            }
4779            
4780            /**
4781             * Gets the list of instruments in the specified directory.
4782             * @param dir The absolute path name of the directory.
4783             * @return A <code>DbInstrumentInfo</code> array providing
4784             * information about all instruments in the specified directory.
4785             * @throws IOException If some I/O error occurs.
4786             * @throws LscpException If LSCP protocol corruption occurs.
4787             * @throws LSException If the specified path name is invalid.
4788             *
4789            public synchronized DbInstrumentInfo[]
4790            getDbInstruments(String dir) throws IOException, LscpException, LSException {
4791                    String[] instrS = getDbInstrumentNames(dir);
4792                    if(instrS.length == 0) return new DbInstrumentInfo[0];
4793                    
4794                    if(dir.charAt(dir.length() - 1) != '/') dir += "/"; FIXME:
4795                    
4796                    for(int i = 0; i < instrS.length; i++) {
4797                            out.writeLine("GET DB_INSTRUMENT INFO '" + conv(dir) + instrS[i] + "'");
4798                    }
4799                    
4800                    if(getPrintOnlyMode()) return null;
4801                    
4802                    if(dir.length() > 1) dir = dir.substring(0, dir.length() - 1);
4803                    StringBuffer sb = new StringBuffer();
4804                    DbInstrumentInfo[] infoS = new DbInstrumentInfo[instrS.length];
4805                    for(int i = 0; i < instrS.length; i++) {
4806                            try {
4807                                    ResultSet rs = getMultiLineResultSet();
4808                                    infoS[i] = new DbInstrumentInfo(rs.getMultiLineResult());
4809                                    infoS[i].setName(instrS[i]);
4810                                    infoS[i].setDirectoryPath(dir);
4811                            } catch (SocketTimeoutException e) {
4812                                    getLogger().log(Level.FINE, e.getMessage(), e);
4813                                    sb.append(e.getMessage()).append("\n");
4814                                    break;
4815                            } catch (Exception e) {
4816                                    getLogger().log(Level.FINE, e.getMessage(), e);
4817                                    sb.append(e.getMessage()).append("\n");
4818                            }
4819                    }
4820                    
4821                    String details = sb.toString();
4822                    if(details.length() > 0) {
4823                            String err = LscpI18n.getLogMsg("Client.getInstrsInfoFailed!");
4824                            throw new LSException(0, err, details);
4825                    }
4826                    
4827                    return infoS;
4828            }*/
4829            
4830            /**
4831             * Renames the specified instrument.
4832             * @param instr The absolute path name of the instrument to rename.
4833             * @param name The new name for the instrument.
4834             * @throws IOException If some I/O error occurs.
4835             * @throws LSException If the renaming of the instrument failed.
4836             * @throws LscpException If LSCP protocol corruption occurs.
4837             */
4838            public synchronized void
4839            renameDbInstrument(String instr, String name)
4840                                    throws IOException, LSException, LscpException {
4841                    
4842                    verifyConnection();
4843                    name = toEscapedText(name);
4844                    out.writeLine("SET DB_INSTRUMENT NAME '" + conv(instr) + "' '" + conv(name) + "'");
4845                    if(getPrintOnlyMode()) return;
4846                    
4847                    ResultSet rs = getEmptyResultSet();
4848            }
4849            
4850            /**
4851             * Moves the specified instrument into the specified location.
4852             * @param instr The absolute path name of the instrument to move.
4853             * @param dst The directory where the specified instrument will be moved to.
4854             * @throws IOException If some I/O error occurs.
4855             * @throws LSException If the operation failed.
4856             * @throws LscpException If LSCP protocol corruption occurs.
4857             */
4858            public synchronized void
4859            moveDbInstrument(String instr, String dst) throws IOException, LSException, LscpException {
4860                    verifyConnection();
4861                    out.writeLine("MOVE DB_INSTRUMENT '" + conv(instr) + "' '" + conv(dst) + "'");
4862                    if(getPrintOnlyMode()) return;
4863                    
4864                    ResultSet rs = getEmptyResultSet();
4865            }
4866            
4867            /**
4868             * Moves the specified instruments into the specified location.
4869             * @param instrs The absolute path names of the instruments to move.
4870             * @param dst The directory where the specified instruments will be moved 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            moveDbInstruments(String[] instrs, String dst) throws IOException, LSException, LscpException {
4877                    verifyConnection();
4878                    for(String s : instrs) {
4879                            out.writeLine("MOVE DB_INSTRUMENT '" + conv(s) + "' '" + conv(dst) + "'");
4880                    }
4881                    if(getPrintOnlyMode()) return;
4882                    
4883                    getEmptyResultSets(instrs.length, "Client.instrMovingFailed!");
4884            }
4885            
4886            /**
4887             * Copies the specified instrument into the specified location.
4888             * @param instr The absolute path name of the instrument to copy.
4889             * @param dst The directory where the specified instrument will be copied to.
4890             * @throws IOException If some I/O error occurs.
4891             * @throws LSException If the operation failed.
4892             * @throws LscpException If LSCP protocol corruption occurs.
4893             */
4894            public synchronized void
4895            copyDbInstrument(String instr, String dst) throws IOException, LSException, LscpException {
4896                    verifyConnection();
4897                    out.writeLine("COPY DB_INSTRUMENT '" + conv(instr) + "' '" + conv(dst) + "'");
4898                    if(getPrintOnlyMode()) return;
4899                    
4900                    ResultSet rs = getEmptyResultSet();
4901            }
4902            
4903            /**
4904             * Copies the specified instruments into the specified location.
4905             * @param instrs The absolute path name of the instruments to copy.
4906             * @param dst The directory where the specified instruments will be copied to.
4907             * @throws IOException If some I/O error occurs.
4908             * @throws LSException If the operation failed.
4909             * @throws LscpException If LSCP protocol corruption occurs.
4910             */
4911            public synchronized void
4912            copyDbInstruments(String[] instrs, String dst) throws IOException, LSException, LscpException {
4913                    verifyConnection();
4914                    for(String s : instrs) {
4915                            out.writeLine("COPY DB_INSTRUMENT '" + conv(s) + "' '" + conv(dst) + "'");
4916                    }
4917                    if(getPrintOnlyMode()) return;
4918                    
4919                    getEmptyResultSets(instrs.length, "Client.instrCopyingFailed!");
4920            }
4921            
4922            /**
4923             * Changes the description of the specified instrument.
4924             * @param instr The absolute path name of the instrument.
4925             * @param desc The new description for the instrument.
4926             * @throws IOException If some I/O error occurs.
4927             * @throws LSException If failed to change the description.
4928             * @throws LscpException If LSCP protocol corruption occurs.
4929             */
4930            public synchronized void
4931            setDbInstrumentDescription(String instr, String desc)
4932                                    throws IOException, LSException, LscpException {
4933                    
4934                    verifyConnection();
4935                    desc = toEscapedText(desc);
4936                    out.writeLine("SET DB_INSTRUMENT DESCRIPTION '" + conv(instr) + "' '" + desc + "'");
4937                    if(getPrintOnlyMode()) return;
4938                    
4939                    ResultSet rs = getEmptyResultSet();
4940            }
4941            
4942            /**
4943             * Substitutes all occurrences of the instrument file
4944             * <code>oldPath</code> in the database, with <code>newPath</code>.
4945             * @param oldPath The absolute path name of the instrument file to substitute.
4946             * @param newPath The new absolute path name.
4947             * @throws IOException If some I/O error occurs.
4948             * @throws LSException If the operation failed.
4949             * @throws LscpException If LSCP protocol corruption occurs.
4950             */
4951            public synchronized void
4952            setDbInstrumentFilePath(String oldPath, String newPath)
4953                                    throws IOException, LSException, LscpException {
4954                    
4955                    verifyConnection();
4956                    out.writeLine("SET DB_INSTRUMENT FILE_PATH '" + conv(oldPath) + "' '" + conv(newPath) + "'");
4957                    if(getPrintOnlyMode()) return;
4958                    
4959                    ResultSet rs = getEmptyResultSet();
4960            }
4961            
4962            /**
4963             * Finds all directories in the specified directory
4964             * that corresponds to the specified search criterias.
4965             * @param dir The absolute path name of the directory to search.
4966             * @param query Provides the search criterias.
4967             * @return A <code>DbDirectoryInfo</code> array providing
4968             * information about all directories that are found in the specified directory.
4969             * @throws IOException If some I/O error occurs.
4970             * @throws LscpException If LSCP protocol corruption occurs.
4971             * @throws LSException If the specified path name is invalid.
4972             */
4973            public synchronized DbDirectoryInfo[]
4974            findDbDirectories(String dir, DbSearchQuery query)
4975                                    throws IOException, LscpException, LSException {
4976                    
4977                    return findDbDirectories(dir, query, false);
4978            }
4979            
4980            /**
4981             * Finds all directories in the specified directory
4982             * that corresponds to the specified search criterias.
4983             * @param dir The absolute path name of the directory to search.
4984             * @param query Provides the search criterias.
4985             * @param nonRecursive If <code>true</code>, the search will be non-recursive.
4986             * @return A <code>DbDirectoryInfo</code> array providing
4987             * information about all directories that are found in the specified directory.
4988             * @throws IOException If some I/O error occurs.
4989             * @throws LscpException If LSCP protocol corruption occurs.
4990             * @throws LSException If the specified path name is invalid.
4991             */
4992            public synchronized DbDirectoryInfo[]
4993            findDbDirectories(String dir, DbSearchQuery query, boolean nonRecursive)
4994                                    throws IOException, LscpException, LSException {
4995                    
4996                    verifyConnection();
4997                    StringBuffer sb = new StringBuffer();
4998                    sb.append("FIND DB_INSTRUMENT_DIRECTORIES");
4999                    if(nonRecursive) sb.append(" NON_RECURSIVE");
5000                    sb.append(" '").append(conv(dir)).append("'");
5001                    
5002                    if(query.name != null && query.name.length() > 0) {
5003                            sb.append(" NAME='").append(toEscapedText(query.name)).append("'");
5004                    }
5005                    
5006                    String s = query.getCreatedAfter();
5007                    String s2 = query.getCreatedBefore();
5008                    if(s != null || s2 != null) {
5009                            sb.append(" CREATED='");
5010                            if(s != null) sb.append(s);
5011                            sb.append("..");
5012                            if(s2 != null) sb.append(s2);
5013                            sb.append("'");
5014                    }
5015                    
5016                    s = query.getModifiedAfter();
5017                    s2 = query.getModifiedBefore();
5018                    if(s != null || s2 != null) {
5019                            sb.append(" MODIFIED='");
5020                            if(s != null) sb.append(s);
5021                            sb.append("..");
5022                            if(s2 != null) sb.append(s2);
5023                            sb.append("'");
5024                    }
5025                    
5026                    if(query.description != null && query.description.length() > 0) {
5027                            sb.append(" DESCRIPTION='");
5028                            sb.append(toEscapedText(query.description)).append("'");
5029                    }
5030                    
5031                    out.writeLine(sb.toString());
5032                    if(getPrintOnlyMode()) return null;
5033                    
5034                    String[] dirS = parseEscapedStringList(getSingleLineResultSet().getResult());
5035                    
5036                    DbDirectoryInfo[] infoS = new DbDirectoryInfo[dirS.length];
5037                    for(int i = 0; i < dirS.length; i++) {
5038                            infoS[i] = getDbDirectoryInfo(dirS[i]);
5039                    }
5040                    return infoS;
5041            }
5042            
5043            /**
5044             * Finds all instruments in the specified directory
5045             * that corresponds to the specified search criterias.
5046             * @param dir The absolute path name of the directory to search.
5047             * @param query Provides the search criterias.
5048             * @return A <code>DbInstrumentInfo</code> array providing
5049             * information about all instruments that are found in the specified directory.
5050             * @throws IOException If some I/O error occurs.
5051             * @throws LscpException If LSCP protocol corruption occurs.
5052             * @throws LSException If the specified path name is invalid.
5053             */
5054            public synchronized DbInstrumentInfo[]
5055            findDbInstruments(String dir, DbSearchQuery query)
5056                                    throws IOException, LscpException, LSException {
5057                    
5058                    return findDbInstruments(dir, query, false);
5059            }
5060            
5061            /**
5062             * Finds all instruments in the specified directory
5063             * that corresponds to the specified search criterias.
5064             * @param dir The absolute path name of the directory to search.
5065             * @param query Provides the search criterias.
5066             * @param nonRecursive If <code>true</code>, the search will be non-recursive.
5067             * @return A <code>DbInstrumentInfo</code> array providing
5068             * information about all instruments that are found in the specified directory.
5069             * @throws IOException If some I/O error occurs.
5070             * @throws LscpException If LSCP protocol corruption occurs.
5071             * @throws LSException If the specified path name is invalid.
5072             */
5073            public synchronized DbInstrumentInfo[]
5074            findDbInstruments(String dir, DbSearchQuery query, boolean nonRecursive)
5075                                    throws IOException, LscpException, LSException {
5076                    
5077                    verifyConnection();
5078                    StringBuffer sb = new StringBuffer();
5079                    sb.append("FIND DB_INSTRUMENTS");
5080                    if(nonRecursive) sb.append(" NON_RECURSIVE");
5081                    sb.append(" '").append(conv(dir)).append("'");
5082                    
5083                    if(query.name != null && query.name.length() > 0) {
5084                            sb.append(" NAME='").append(toEscapedText(query.name)).append("'");
5085                    }
5086                    
5087                    if(query.formatFamilies.size() > 0) {
5088                            sb.append(" FORMAT_FAMILIES='").append(query.formatFamilies.get(0));
5089                            for(int i = 1; i < query.formatFamilies.size(); i++) {
5090                                    sb.append(',').append(query.formatFamilies.get(i));
5091                            }
5092                            sb.append("'");
5093                    }
5094                    
5095                    if(query.minSize != -1 || query.maxSize != -1) {
5096                            sb.append(" SIZE='");
5097                            if(query.minSize != -1) sb.append(query.minSize);
5098                            sb.append("..");
5099                            if(query.maxSize != -1) sb.append(query.maxSize);
5100                            sb.append("'");
5101                    }
5102                    
5103                    String s = query.getCreatedAfter();
5104                    String s2 = query.getCreatedBefore();
5105                    if(s != null || s2 != null) {
5106                            sb.append(" CREATED='");
5107                            if(s != null) sb.append(s);
5108                            sb.append("..");
5109                            if(s2 != null) sb.append(s2);
5110                            sb.append("'");
5111                    }
5112                    
5113                    s = query.getModifiedAfter();
5114                    s2 = query.getModifiedBefore();
5115                    if(s != null || s2 != null) {
5116                            sb.append(" MODIFIED='");
5117                            if(s != null) sb.append(s);
5118                            sb.append("..");
5119                            if(s2 != null) sb.append(s2);
5120                            sb.append("'");
5121                    }
5122                    
5123                    if(query.description != null && query.description.length() > 0) {
5124                            sb.append(" DESCRIPTION='");
5125                            sb.append(toEscapedText(query.description)).append("'");
5126                    }
5127                    
5128                    if(query.instrumentType != DbSearchQuery.InstrumentType.BOTH) {
5129                            sb.append(" IS_DRUM=");
5130                            if(query.instrumentType == DbSearchQuery.InstrumentType.DRUM) {
5131                                    sb.append("'true'");
5132                            } else {
5133                                    sb.append("'false'");
5134                            }
5135                    }
5136                    
5137                    if(query.product != null && query.product.length() > 0) {
5138                            sb.append(" PRODUCT='").append(toEscapedText(query.product)).append("'");
5139                    }
5140                    
5141                    if(query.artists != null && query.artists.length() > 0) {
5142                            sb.append(" ARTISTS='").append(toEscapedText(query.artists)).append("'");
5143                    }
5144                    
5145                    if(query.keywords != null && query.keywords.length() > 0) {
5146                            sb.append(" KEYWORDS='");
5147                            sb.append(toEscapedText(query.keywords)).append("'");
5148                    }
5149                    
5150                    out.writeLine(sb.toString());
5151                    if(getPrintOnlyMode()) return null;
5152                    
5153                    String[] instrS = parseEscapedStringList(getSingleLineResultSet().getResult());
5154                    
5155                    DbInstrumentInfo[] infoS = new DbInstrumentInfo[instrS.length];
5156                    for(int i = 0; i < instrS.length; i++) {
5157                            infoS[i] = getDbInstrumentInfo(instrS[i]);
5158                    }
5159                    return infoS;
5160            }
5161            
5162            /**
5163             * Returns a list of all instrument files in the database
5164             * that that don't exist in the filesystem.
5165             * @throws IOException If some I/O error occurs.
5166             * @throws LscpException If LSCP protocol corruption occurs.
5167             * @throws LSException If other error occurs.
5168             */
5169            public synchronized String[]
5170            findLostDbInstrumentFiles() throws IOException, LscpException, LSException {
5171                    
5172                    verifyConnection();
5173                    out.writeLine("FIND LOST DB_INSTRUMENT_FILES");
5174                    if(getPrintOnlyMode()) return null;
5175                    
5176                    return parseEscapedStringList(getSingleLineResultSet().getResult());
5177            }
5178            
5179            /**
5180             * Gets status information about the specified job.
5181             * @param jobId The ID of the job.
5182             * @return A <code>ScanJobInfo</code> instance providing information
5183             * about the specified job.
5184             * @throws IOException If some I/O error occurs.
5185             * @throws LscpException If LSCP protocol corruption occurs.
5186             * @throws LSException If the specified job is not found.
5187             */
5188            public synchronized ScanJobInfo
5189            getDbInstrumentsJobInfo(int jobId) throws IOException, LscpException, LSException {
5190                    verifyConnection();
5191                    out.writeLine("GET DB_INSTRUMENTS_JOB INFO " + String.valueOf(jobId));
5192                    if(getPrintOnlyMode()) return null;
5193                    
5194                    ResultSet rs = getMultiLineResultSet();
5195                    ScanJobInfo info = new ScanJobInfo(rs.getMultiLineResult());
5196                    
5197                    return info;
5198            }
5199            
5200            /**
5201             * Removes all instruments and directories and re-creates
5202             * the instruments database structure.
5203             * @throws IOException If some I/O error occurs.
5204             * @throws LscpException If LSCP protocol corruption occurs.
5205             * @throws LSException If the formatting of the instruments database failed.
5206             */
5207            public synchronized void
5208            formatInstrumentsDb() throws IOException, LscpException, LSException {
5209                    verifyConnection();
5210                    out.writeLine("FORMAT INSTRUMENTS_DB");
5211                    if(getPrintOnlyMode()) return;
5212                                    
5213                  ResultSet rs = getEmptyResultSet();                  ResultSet rs = getEmptyResultSet();
5214          }          }
# Line 2372  public class Client { Line 5223  public class Client {
5223          resetSampler() throws IOException, LscpException {          resetSampler() throws IOException, LscpException {
5224                  verifyConnection();                  verifyConnection();
5225                  out.writeLine("RESET");                  out.writeLine("RESET");
5226                    if(getPrintOnlyMode()) return;
5227                    
5228                  try { ResultSet rs = getEmptyResultSet(); }                  try { ResultSet rs = getEmptyResultSet(); }
5229                  catch(LSException x) { getLogger().warning(x.getMessage()); }                  catch(LSException x) { getLogger().warning(x.getMessage()); }
5230          }          }
5231                    
5232          /**          /**
5233             * Gets the current number of all active streams.
5234             * @return The current number of all active streams.
5235             * @throws IOException If some I/O error occurs.
5236             * @throws LscpException If LSCP protocol corruption occurs.
5237             * @throws LSException If some other error occurs.
5238             */
5239            public synchronized int
5240            getTotalStreamCount() throws IOException, LscpException, LSException {
5241                    verifyConnection();
5242                    out.writeLine("GET TOTAL_STREAM_COUNT");
5243                    if(getPrintOnlyMode()) return -1;
5244                    
5245                    String s = getSingleLineResultSet().getResult();
5246                    return parseInt(s);
5247            }
5248            
5249            /**
5250           * Gets the current number of all active voices.           * Gets the current number of all active voices.
5251           * @return The current number of all active voices.           * @return The current number of all active voices.
5252           * @throws IOException If some I/O error occurs.           * @throws IOException If some I/O error occurs.
# Line 2387  public class Client { Line 5257  public class Client {
5257          getTotalVoiceCount() throws IOException, LscpException, LSException {          getTotalVoiceCount() throws IOException, LscpException, LSException {
5258                  verifyConnection();                  verifyConnection();
5259                  out.writeLine("GET TOTAL_VOICE_COUNT");                  out.writeLine("GET TOTAL_VOICE_COUNT");
5260                    if(getPrintOnlyMode()) return -1;
5261                    
5262                  String s = getSingleLineResultSet().getResult();                  String s = getSingleLineResultSet().getResult();
5263                  return parseInt(s);                  return parseInt(s);
5264          }          }
# Line 2402  public class Client { Line 5274  public class Client {
5274          getTotalVoiceCountMax() throws IOException, LscpException, LSException {          getTotalVoiceCountMax() throws IOException, LscpException, LSException {
5275                  verifyConnection();                  verifyConnection();
5276                  out.writeLine("GET TOTAL_VOICE_COUNT_MAX");                  out.writeLine("GET TOTAL_VOICE_COUNT_MAX");
5277                    if(getPrintOnlyMode()) return -1;
5278                    
5279                  String s = getSingleLineResultSet().getResult();                  String s = getSingleLineResultSet().getResult();
5280                  return parseInt(s);                  return parseInt(s);
5281          }          }
# Line 2420  public class Client { Line 5294  public class Client {
5294          getServerInfo() throws IOException, LscpException, LSException {          getServerInfo() throws IOException, LscpException, LSException {
5295                  verifyConnection();                  verifyConnection();
5296                  out.writeLine("GET SERVER INFO");                  out.writeLine("GET SERVER INFO");
5297                    if(getPrintOnlyMode()) return null;
5298                    
5299                  ResultSet rs = getMultiLineResultSet();                  ResultSet rs = getMultiLineResultSet();
5300                  return new ServerInfo(rs.getMultiLineResult());                  return new ServerInfo(rs.getMultiLineResult());
5301          }          }
5302                    
5303          /**          /**
5304             * Gets the global volume of the sampler.
5305             * @return The global volume of the sampler.
5306             * @throws IOException If some I/O error occurs.
5307             * @throws LscpException If LSCP protocol corruption occurs.
5308             * @throws LSException If some other error occurs.
5309             */
5310            public synchronized float
5311            getVolume() throws IOException, LscpException, LSException {
5312                    verifyConnection();
5313                    out.writeLine("GET VOLUME");
5314                    if(getPrintOnlyMode()) return -1;
5315                    
5316                    String s = getSingleLineResultSet().getResult();
5317                    return parseFloat(s);
5318            }
5319            
5320            /**
5321             * Sets the global volume of the sampler.
5322             * @param volume The new volume value.
5323             * @throws IOException If some I/O error occurs.
5324             * @throws LscpException If LSCP protocol corruption occurs.
5325             * @throws LSException If some other error occurs.
5326             * @see #getVolume
5327             */
5328            public synchronized void
5329            setVolume(float volume) throws IOException, LscpException, LSException {
5330            
5331                    verifyConnection();
5332                    out.writeLine("SET VOLUME " + volume);
5333                    if(getPrintOnlyMode()) return;
5334                    
5335                    ResultSet rs = getEmptyResultSet();
5336            }
5337            
5338            /**
5339             * Gets the global sampler-wide limit of maximum voices.
5340             * @return The global sampler-wide limit of maximum voices.
5341             * @throws IOException If some I/O error occurs.
5342             * @throws LscpException If LSCP protocol corruption occurs.
5343             * @throws LSException If some other error occurs.
5344             */
5345            public synchronized int
5346            getGlobalVoiceLimit() throws IOException, LscpException, LSException {
5347                    verifyConnection();
5348                    out.writeLine("GET VOICES");
5349                    if(getPrintOnlyMode()) return -1;
5350                    
5351                    String s = getSingleLineResultSet().getResult();
5352                    return parseInt(s);
5353            }
5354            
5355            /**
5356             * Sets the global sampler-wide limit of maximum voices.
5357             * @param maxVoices The new global limit of maximum voices.
5358             * @throws IOException If some I/O error occurs.
5359             * @throws LscpException If LSCP protocol corruption occurs.
5360             * @throws LSException If some other error occurs.
5361             * @see #getVolume
5362             */
5363            public synchronized void
5364            setGlobalVoiceLimit(int maxVoices) throws IOException, LscpException, LSException {
5365                    verifyConnection();
5366                    out.writeLine("SET VOICES " + maxVoices);
5367                    if(getPrintOnlyMode()) return;
5368                    
5369                    ResultSet rs = getEmptyResultSet();
5370            }
5371            
5372            /**
5373             * Gets the global sampler-wide limit of maximum disk streams.
5374             * @return The global sampler-wide limit of maximum disk streams.
5375             * @throws IOException If some I/O error occurs.
5376             * @throws LscpException If LSCP protocol corruption occurs.
5377             * @throws LSException If some other error occurs.
5378             */
5379            public synchronized int
5380            getGlobalStreamLimit() throws IOException, LscpException, LSException {
5381                    verifyConnection();
5382                    out.writeLine("GET STREAMS");
5383                    if(getPrintOnlyMode()) return -1;
5384                    
5385                    String s = getSingleLineResultSet().getResult();
5386                    return parseInt(s);
5387            }
5388            
5389            /**
5390             * Sets the global sampler-wide limit for maximum disk streams.
5391             * @param maxVoices The new global limit of maximum disk streams.
5392             * @throws IOException If some I/O error occurs.
5393             * @throws LscpException If LSCP protocol corruption occurs.
5394             * @throws LSException If some other error occurs.
5395             * @see #getVolume
5396             */
5397            public synchronized void
5398            setGlobalStreamLimit(int maxStreams) throws IOException, LscpException, LSException {
5399                    verifyConnection();
5400                    out.writeLine("SET STREAMS " + maxStreams);
5401                    if(getPrintOnlyMode()) return;
5402                    
5403                    ResultSet rs = getEmptyResultSet();
5404            }
5405            
5406            /**
5407             * Gets the number of instruments in the specified instrument file.
5408             * @param filename The absolute path name of the instrument file.
5409             * @return The number of instruments in the specified instrument file.
5410             * @throws IOException If some I/O error occurs.
5411             * @throws LscpException If LSCP protocol corruption occurs.
5412             * @throws LSException If the file is not found, or other error occur.
5413             */
5414            public synchronized int
5415            getFileInstrumentCount(String filename) throws IOException, LscpException, LSException {
5416                    verifyConnection();
5417                    out.writeLine("GET FILE INSTRUMENTS '" + conv(filename) +"'");
5418                    if(getPrintOnlyMode()) return -1;
5419                    
5420                    String s = getSingleLineResultSet().getResult();
5421                    return parseInt(s);
5422            }
5423            
5424            /**
5425             * Gets information about the instrument with index
5426             * <code>instrIdx</code> in the specified instrument file.
5427             * @param filename The absolute path name of the instrument file.
5428             * @param instrIdx The index of the instrument in the specified instrument file.
5429             * @throws IOException If some I/O error occurs.
5430             * @throws LscpException If LSCP protocol corruption occurs.
5431             * @throws LSException If failed to retrieve information.
5432             */
5433            public synchronized Instrument
5434            getFileInstrumentInfo(String filename, int instrIdx)
5435                                    throws IOException, LscpException, LSException {
5436                    
5437                    verifyConnection();
5438                    out.writeLine("GET FILE INSTRUMENT INFO '" + conv(filename) + "' " + String.valueOf(instrIdx));
5439                    if(getPrintOnlyMode()) return null;
5440                    
5441                    ResultSet rs = getMultiLineResultSet();
5442                    Instrument instr = new FileInstrument(rs.getMultiLineResult()) { };
5443                    
5444                    return instr;
5445            }
5446            
5447            /**
5448             * Gets the list of instruments in the specified instrument file.
5449             * @param filename The absolute path name of the instrument file.
5450             * @return An <code>Instrument</code> array providing
5451             * information about all instruments in the specified instrument file.
5452             * @throws IOException If some I/O error occurs.
5453             * @throws LscpException If LSCP protocol corruption occurs.
5454             * @throws LSException If the specified file name is invalid.
5455             */
5456            public synchronized Instrument[]
5457            getFileInstruments(String filename) throws IOException, LscpException, LSException {
5458                    int l = getFileInstrumentCount(filename);
5459                    if(l < 0) return null;
5460                    Instrument[] instrS = new FileInstrument[l];
5461                    
5462                    for(int i = 0; i < instrS.length; i++) {
5463                            instrS[i] = getFileInstrumentInfo(filename, i);
5464                    }
5465                    return instrS;
5466            }
5467            
5468            private static class FileInstrument extends AbstractInstrument {
5469                    FileInstrument(String[] resultSet) throws LscpException {
5470                            super(resultSet);
5471                    }
5472                    
5473                    @Override
5474                    public String
5475                    getEngine() {
5476                            // TODO: engine lookup?
5477                            return getFormatFamily();
5478                    }
5479                    
5480                    @Override
5481                    public boolean
5482                    parse(String s) throws LscpException {
5483                            if(s.startsWith("PRODUCT: ") || s.startsWith("ARTISTS: ")) return true;
5484                            return super.parse(s);
5485                    }
5486            }
5487            
5488            private void
5489            getEmptyResultSets(int count, String err) throws LSException {
5490                    StringBuffer sb = new StringBuffer();
5491                    for(int i = 0; i < count; i++) {
5492                            try { getEmptyResultSet(); }
5493                            catch (SocketTimeoutException e) {
5494                                    getLogger().log(Level.FINE, e.getMessage(), e);
5495                                    sb.append(e.getMessage()).append("\n");
5496                                    break;
5497                            } catch (Exception e) {
5498                                    getLogger().log(Level.FINE, e.getMessage(), e);
5499                                    sb.append(e.getMessage()).append("\n");
5500                            }
5501                    }
5502                    
5503                    String details = sb.toString();
5504                    if(details.length() > 0) {
5505                            String s = LscpI18n.getLogMsg(err);
5506                            throw new LSException(0, s, details);
5507                    }
5508            }
5509            
5510            /**
5511           * Returns the logger for this library.           * Returns the logger for this library.
5512           * @return The logger for this library.           * @return The logger for this library.
5513           */           */

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

  ViewVC Help
Powered by ViewVC