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

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

  ViewVC Help
Powered by ViewVC