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

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

  ViewVC Help
Powered by ViewVC