/[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 1139 by iliev, Mon Apr 2 20:43:58 2007 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-2007 Grigor Iliev <grigor@grigoriliev.com>   *   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 28  import java.io.OutputStream; Line 28  import java.io.OutputStream;
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.1, 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.1.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 69  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;
# Line 77  public class Client { Line 78  public class Client {
78          private EventThread eventThread;          private EventThread eventThread;
79                    
80          private boolean printOnlyMode = false;          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 105  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 144  public class Client { Line 180  public class Client {
180                  if(printOnlyMode) setPrintOnlyMode(true);                  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.           * Determines whether the client is in print-only mode.
230           * Print-only mode means that the client will just print all           * Print-only mode means that the client will just print all
# Line 324  public class Client { Line 405  public class Client {
405                  if(!llFSI.isEmpty()) subscribe("FX_SEND_INFO");                  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");                  if(!llMIMC.isEmpty()) subscribe("MIDI_INSTRUMENT_MAP_COUNT");
411                  if(!llMIMI.isEmpty()) subscribe("MIDI_INSTRUMENT_MAP_INFO");                  if(!llMIMI.isEmpty()) subscribe("MIDI_INSTRUMENT_MAP_INFO");
412                  if(!llMIC.isEmpty()) subscribe("MIDI_INSTRUMENT_COUNT");                  if(!llMIC.isEmpty()) subscribe("MIDI_INSTRUMENT_COUNT");
413                  if(!llMII.isEmpty()) subscribe("MIDI_INSTRUMENT_INFO");                  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");                  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 376  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;
# Line 391  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 421  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 457  public class Client { Line 582  public class Client {
582          private final Vector<ItemInfoListener> llMIDI = new Vector<ItemInfoListener>();          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 */          /** MIDI instrument map count listeners */
# Line 469  public class Client { Line 595  public class Client {
595          /** MIDI instrument info listeners */          /** MIDI instrument info listeners */
596          private final Vector<MidiInstrumentInfoListener> llMII =          private final Vector<MidiInstrumentInfoListener> llMII =
597                  new Vector<MidiInstrumentInfoListener>();                  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>();          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          /**          /**
# Line 493  public class Client { Line 626  public class Client {
626                          !llMIDI.isEmpty() ||                          !llMIDI.isEmpty() ||
627                          !llSC.isEmpty()   ||                          !llSC.isEmpty()   ||
628                          !llVC.isEmpty()   ||                          !llVC.isEmpty()   ||
629                            !llTSC.isEmpty()  ||
630                          !llTVC.isEmpty()  ||                          !llTVC.isEmpty()  ||
631                          !llMIMC.isEmpty() ||                          !llMIMC.isEmpty() ||
632                          !llMIMI.isEmpty() ||                          !llMIMI.isEmpty() ||
633                          !llMIC.isEmpty()  ||                          !llMIC.isEmpty()  ||
634                          !llMII.isEmpty()  ||                          !llMII.isEmpty()  ||
635                          !llGI.isEmpty();                          !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 563  public class Client { Line 847  public class Client {
847                          } catch(NumberFormatException x) {                          } catch(NumberFormatException x) {
848                                  getLogger().log(Level.WARNING, "Unknown CHANNEL_INFO 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 {
863                                  s = s.substring("TOTAL_VOICE_COUNT:".length());                                  s = s.substring("TOTAL_VOICE_COUNT:".length());
# Line 710  public class Client { Line 1005  public class Client {
1005                          } catch(Exception x) {                          } catch(Exception x) {
1006                                  getLogger().log(Level.WARNING, "Unknown FX_SEND_INFO format", x);                                  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:")) {                  } else if(s.startsWith("GLOBAL_INFO:")) {
1069                          handleGlobalInfoEvent(s.substring("GLOBAL_INFO:".length()));                          handleGlobalInfoEvent(s.substring("GLOBAL_INFO:".length()));
1070                  } else if(s.startsWith("MISCELLANEOUS:")) {                  } else if(s.startsWith("MISCELLANEOUS:")) {
# Line 726  public class Client { Line 1081  public class Client {
1081                                  float f = Float.parseFloat(s.substring("VOLUME ".length()));                                  float f = Float.parseFloat(s.substring("VOLUME ".length()));
1082                                  GlobalInfoEvent e = new GlobalInfoEvent(this, f);                                  GlobalInfoEvent e = new GlobalInfoEvent(this, f);
1083                                  for(GlobalInfoListener l : llGI) l.volumeChanged(e);                                  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) {                  } catch(NumberFormatException x) {
1096                          getLogger().log(Level.WARNING, "Unknown GLOBAL_INFO format", x);                          getLogger().log(Level.WARNING, "Unknown GLOBAL_INFO format", x);
# Line 1035  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 1145  public class Client { Line 1532  public class Client {
1532          /**          /**
1533           * Registers the specified listener for receiving event messages.           * Registers the specified listener for receiving event messages.
1534           * Listeners can be registered regardless of the connection state.           * 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.           * @param l The <code>GlobalInfoListener</code> to register.
1614           */           */
1615          public synchronized void          public synchronized void
# Line 1165  public class Client { Line 1630  public class Client {
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");  
                   
                 if(getPrintOnlyMode()) return -1;  
                   
                 String s = getSingleLineResultSet().getResult();  
                 return parseInt(s);  
1732          }          }
1733                    
1734          /**          /**
# Line 1227  public class Client { Line 1774  public class Client {
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 1237  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                  if(getPrintOnlyMode()) return null;                  AudioOutputDriver aod = new AudioOutputDriver();
1792                                    if(!retrieveInfo("GET AUDIO_OUTPUT_DRIVER INFO " + driverName, aod)) return null;
                 ResultSet rs = getMultiLineResultSet();  
                 AudioOutputDriver aod = new AudioOutputDriver(rs.getMultiLineResult());  
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 1282  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;                  if(getPrintOnlyMode()) return null;
# Line 1341  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                  if(getPrintOnlyMode()) return -1;                  return retrieveIndex("CREATE AUDIO_OUTPUT_DEVICE " + args.toString());
                   
                 ResultSet rs = getEmptyResultSet();  
                   
                 return rs.getIndex();  
1899          }          }
1900                    
1901          /**          /**
# Line 1365  public class Client { Line 1908  public class Client {
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);  
                 if(getPrintOnlyMode()) return;  
                   
                 ResultSet rs = getEmptyResultSet();  
1912          }          }
1913                    
1914          /**          /**
# Line 1391  public class Client { Line 1930  public class Client {
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");  
                 if(getPrintOnlyMode()) return -1;  
                   
                 String s = getSingleLineResultSet().getResult();  
                 return parseInt(s);  
1942          }          }
1943                                    
1944          /**          /**
# Line 1437  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");  
                 if(getPrintOnlyMode()) return null;  
                   
                 return parseIntList(getSingleLineResultSet().getResult());  
1976          }          }
1977                    
1978          /**          /**
# Line 1544  public class Client { Line 2075  public class Client {
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);
                 if(getPrintOnlyMode()) return;  
                   
                 ResultSet rs = getEmptyResultSet();  
2082          }          }
2083                    
2084          /**          /**
# Line 1735  public class Client { Line 2262  public class Client {
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                            {
                 verifyConnection();  
2267                  String args = devId + " " + chn + " " + prm.getName() + '=' + prm.getStringValue();                  String args = devId + " " + chn + " " + prm.getName() + '=' + prm.getStringValue();
2268                  out.writeLine("SET AUDIO_OUTPUT_CHANNEL_PARAMETER " + args);                  retrieveIndex("SET AUDIO_OUTPUT_CHANNEL_PARAMETER " + args);
                 if(getPrintOnlyMode()) return;  
                   
                 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");  
                 if(getPrintOnlyMode()) return -1;  
                   
                 String s = getSingleLineResultSet().getResult();  
                 return parseInt(s);  
2281          }          }
2282                    
2283          /**          /**
# Line 1806  public class Client { Line 2324  public class Client {
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 1816  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                  if(getPrintOnlyMode()) return null;                  MidiInputDriver mid = new MidiInputDriver();
2342                                    if(!retrieveInfo("GET MIDI_INPUT_DRIVER INFO " + driverName, mid)) return null;
                 ResultSet rs = getMultiLineResultSet();  
                   
                 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 1862  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;                  if(getPrintOnlyMode()) return null;
# Line 1920  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                  if(getPrintOnlyMode()) return -1;                  return retrieveIndex("CREATE MIDI_INPUT_DEVICE " + args.toString());
                   
                 ResultSet rs = getEmptyResultSet();  
                   
                 return rs.getIndex();  
2450          }          }
2451                    
2452          /**          /**
# Line 1947  public class Client { Line 2460  public class Client {
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);  
                 if(getPrintOnlyMode()) return;  
                   
                 ResultSet rs = getEmptyResultSet();  
2464          }          }
2465                    
2466          /**          /**
# Line 1973  public class Client { Line 2482  public class Client {
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");  
                 if(getPrintOnlyMode()) return -1;  
                   
                 String s = getSingleLineResultSet().getResult();  
                 return parseInt(s);  
2494          }          }
2495                    
2496          /**          /**
# Line 2025  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");  
                 if(getPrintOnlyMode()) return null;  
                   
                 return parseIntList(getSingleLineResultSet().getResult());  
2534          }          }
2535                    
2536          /**          /**
# Line 2071  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);
# Line 2119  public class Client { Line 2627  public class Client {
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);
                 if(getPrintOnlyMode()) return;  
                   
                 ResultSet rs = getEmptyResultSet();  
2634          }          }
2635                    
2636                    
2637          /**          /**
2638           * Changes the port number of the speicified 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           *           *
# Line 2292  public class Client { Line 2796  public class Client {
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                            {
                 verifyConnection();  
2801                  String args = deviceId + " " + port + " " +                  String args = deviceId + " " + port + " " +
2802                          prm.getName() + '=' + prm.getStringValue();                          prm.getName() + '=' + prm.getStringValue();
2803                  out.writeLine("SET MIDI_INPUT_PORT_PARAMETER " + args);                  retrieveIndex("SET MIDI_INPUT_PORT_PARAMETER " + args);
                 if(getPrintOnlyMode()) return;  
                   
                 ResultSet rs = getEmptyResultSet();  
2804          }          }
2805                    
2806          /**          /**
# Line 2314  public class Client { Line 2814  public class Client {
2814           */           */
2815          public synchronized int          public synchronized int
2816          addMidiInstrumentMap(String name) throws IOException, LSException, LscpException {          addMidiInstrumentMap(String name) throws IOException, LSException, LscpException {
2817                  verifyConnection();                  return retrieveIndex("ADD MIDI_INSTRUMENT_MAP '" + toEscapedText(name) + "'");
                 out.writeLine("ADD MIDI_INSTRUMENT_MAP '" + name + "'");  
                 if(getPrintOnlyMode()) return -1;  
                   
                 ResultSet rs = getEmptyResultSet();  
                   
                 return rs.getIndex();  
2818          }          }
2819                    
2820          /**          /**
# Line 2334  public class Client { Line 2828  public class Client {
2828           */           */
2829          public synchronized void          public synchronized void
2830          removeMidiInstrumentMap(int mapId) throws IOException, LscpException, LSException {          removeMidiInstrumentMap(int mapId) throws IOException, LscpException, LSException {
2831                  verifyConnection();                  retrieveIndex("REMOVE MIDI_INSTRUMENT_MAP " + mapId);
                 out.writeLine("REMOVE MIDI_INSTRUMENT_MAP " + mapId);  
                 if(getPrintOnlyMode()) return;  
                   
                 ResultSet rs = getEmptyResultSet();  
2832          }          }
2833                    
2834          /**          /**
# Line 2349  public class Client { Line 2839  public class Client {
2839           */           */
2840          public synchronized void          public synchronized void
2841          removeAllMidiInstrumentMaps() throws IOException, LscpException, LSException {          removeAllMidiInstrumentMaps() throws IOException, LscpException, LSException {
2842                  verifyConnection();                  retrieveIndex("REMOVE MIDI_INSTRUMENT_MAP ALL");
                 out.writeLine("REMOVE MIDI_INSTRUMENT_MAP ALL");  
                 if(getPrintOnlyMode()) return;  
                   
                 ResultSet rs = getEmptyResultSet();  
2843          }          }
2844                    
2845          /**          /**
2846           * Gets the current number of all MIDI instrument maps.           * Gets the current number of all MIDI instrument maps.
2847           * @return The current number of all MIDI instrument maps.           * @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.           * @throws IOException If some I/O error occurs.
2850           * @throws LscpException If LSCP protocol corruption occurs.           * @throws LscpException If LSCP protocol corruption occurs.
2851           * @throws LSException If some other error occurs.           * @throws LSException If some other error occurs.
2852           */           */
2853          public synchronized int          public synchronized int
2854          getMidiInstrumentMapCount() throws IOException, LscpException, LSException {          getMidiInstrumentMapCount() throws IOException, LscpException, LSException {
2855                  verifyConnection();                  return retrieveInt("GET MIDI_INSTRUMENT_MAPS");
                 out.writeLine("GET MIDI_INSTRUMENT_MAPS");  
                 if(getPrintOnlyMode()) return -1;  
                   
                 String s = getSingleLineResultSet().getResult();  
                 return parseInt(s);  
2856          }          }
2857                    
2858          /**          /**
# Line 2385  public class Client { Line 2867  public class Client {
2867           */           */
2868          public synchronized Integer[]          public synchronized Integer[]
2869          getMidiInstrumentMapIDs() throws IOException, LscpException, LSException {          getMidiInstrumentMapIDs() throws IOException, LscpException, LSException {
2870                  verifyConnection();                  return getIntegerList("LIST MIDI_INSTRUMENT_MAPS");
                 out.writeLine("LIST MIDI_INSTRUMENT_MAPS");  
                 if(getPrintOnlyMode()) return null;  
                   
                 return parseIntList(getSingleLineResultSet().getResult());  
2871          }          }
2872                    
2873          /**          /**
# Line 2418  public class Client { Line 2896  public class Client {
2896                                    
2897                  for(String s : lnS) {                  for(String s : lnS) {
2898                          if(s.startsWith("NAME: ")) {                          if(s.startsWith("NAME: ")) {
2899                                  name = s.substring("NAME: ".length());                                  name = toNonEscapedString(s.substring("NAME: ".length()));
2900                          } else if(s.startsWith("DEFAULT: ")) {                          } else if(s.startsWith("DEFAULT: ")) {
2901                                  b = Boolean.parseBoolean(s.substring("DEFAULT: ".length()));                                  b = Boolean.parseBoolean(s.substring("DEFAULT: ".length()));
2902                          } else {                          } else {
# Line 2463  public class Client { Line 2941  public class Client {
2941           */           */
2942          public synchronized void          public synchronized void
2943          setMidiInstrumentMapName(int mapId, String name)          setMidiInstrumentMapName(int mapId, String name)
2944                                  throws IOException, LscpException, LSException {                                  throws IOException, LscpException, LSException
2945                            {
2946                  verifyConnection();                  name = toEscapedText(name);
2947                  out.writeLine("SET MIDI_INSTRUMENT_MAP NAME " +  + mapId + " '" + name + "'");                  retrieveIndex("SET MIDI_INSTRUMENT_MAP NAME " +  + mapId + " '" + name + "'");
                 if(getPrintOnlyMode()) return;  
                   
                 ResultSet rs = getEmptyResultSet();  
2948          }          }
2949                    
2950            
2951            
2952          /**          /**
2953           * Creates or replaces a MIDI instrument map entry.           * Creates or replaces a MIDI instrument map entry.
2954           * @param mapId The ID of the map, where this instrument should be mapped.           * @param mapId The ID of the map, where this instrument should be mapped.
# Line 2486  public class Client { Line 2963  public class Client {
2963          public synchronized void          public synchronized void
2964          mapMidiInstrument(int mapId, MidiInstrumentEntry entry, MidiInstrumentInfo info)          mapMidiInstrument(int mapId, MidiInstrumentEntry entry, MidiInstrumentInfo info)
2965                                          throws IOException, LSException, LscpException {                                          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                  StringBuffer cmd = new StringBuffer("MAP MIDI_INSTRUMENT ");                  StringBuffer cmd = new StringBuffer("MAP MIDI_INSTRUMENT ");
2988                    if(nonModal) cmd.append("NON_MODAL ");
2989                  cmd.append(mapId).append(' ');                  cmd.append(mapId).append(' ');
2990                  cmd.append(entry.getMidiBank()).append(' ');                  cmd.append(entry.getMidiBank()).append(' ');
2991                  cmd.append(entry.getMidiProgram()).append(' ');                  cmd.append(entry.getMidiProgram()).append(' ');
2992                  cmd.append(info.getEngine()).append(" '");                  cmd.append(info.getEngine()).append(" '");
2993                  cmd.append(info.getFileName()).append("' ");                  cmd.append(conv(info.getFilePath())).append("' ");
2994                  cmd.append(info.getInstrumentIndex()).append(' ');                  cmd.append(info.getInstrumentIndex()).append(' ');
2995                  cmd.append(info.getVolume());                  cmd.append(info.getVolume());
2996                  if(!info.getLoadMode().name().equals("DEFAULT")) {                  if(!info.getLoadMode().name().equals("DEFAULT")) {
2997                          cmd.append(' ').append(info.getLoadMode().name());                          cmd.append(' ').append(info.getLoadMode().name());
2998                  }                  }
2999                  if(info.getName() != null) cmd.append(" '").append(info.getName()).append("'");                  
3000                    if(info.getName() != null) {
3001                            String s = toEscapedText(info.getName());
3002                            cmd.append(" '").append(s).append("'");
3003                    }
3004                                    
3005                  out.writeLine(cmd.toString());                  out.writeLine(cmd.toString());
3006                  if(getPrintOnlyMode()) return;                  if(getPrintOnlyMode()) return;
# Line 2519  public class Client { Line 3020  public class Client {
3020           */           */
3021          public synchronized void          public synchronized void
3022          unmapMidiInstrument(int mapId, MidiInstrumentEntry entry)          unmapMidiInstrument(int mapId, MidiInstrumentEntry entry)
3023                                          throws IOException, LSException, LscpException {                                          throws IOException, LSException, LscpException
3024                            {
                 verifyConnection();  
3025                  StringBuffer cmd = new StringBuffer("UNMAP MIDI_INSTRUMENT ");                  StringBuffer cmd = new StringBuffer("UNMAP MIDI_INSTRUMENT ");
3026                  cmd.append(mapId).append(' ');                  cmd.append(mapId).append(' ');
3027                  cmd.append(entry.getMidiBank()).append(' ');                  cmd.append(entry.getMidiBank()).append(' ');
3028                  cmd.append(entry.getMidiProgram());                  cmd.append(entry.getMidiProgram());
3029                    
3030                  out.writeLine(cmd.toString());                  retrieveIndex(cmd.toString());
                 if(getPrintOnlyMode()) return;  
                   
                 ResultSet rs = getEmptyResultSet();  
3031          }          }
3032                    
3033          /**          /**
3034           * Gets the current number of all MIDI instrument in all maps.           * Gets the current number of all MIDI instrument in all maps.
3035           * @return The current number of all MIDI instrument in all maps.           * @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.           * @throws IOException If some I/O error occurs.
3038           * @throws LscpException If LSCP protocol corruption occurs.           * @throws LscpException If LSCP protocol corruption occurs.
3039           * @throws LSException If some other error occurs.           * @throws LSException If some other error occurs.
3040           */           */
3041          public synchronized int          public synchronized int
3042          getMidiInstrumentCount() throws IOException, LscpException, LSException {          getMidiInstrumentCount() throws IOException, LscpException, LSException {
3043                  verifyConnection();                  return retrieveInt("GET MIDI_INSTRUMENTS ALL");
                 out.writeLine("GET MIDI_INSTRUMENTS ALL");  
                 if(getPrintOnlyMode()) return -1;  
                   
                 String s = getSingleLineResultSet().getResult();  
                 return parseInt(s);  
3044          }          }
3045                    
3046          /**          /**
3047           * Gets the current number of MIDI instrument in the specified map.           * Gets the current number of MIDI instrument in the specified map.
3048           * @param mapId The ID of the map.           * @param mapId The ID of the map.
3049           * @return The current number of MIDI instrument in the specified map.           * @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.           * @throws IOException If some I/O error occurs.
3052           * @throws LscpException If LSCP protocol corruption occurs.           * @throws LscpException If LSCP protocol corruption occurs.
3053           * @throws LSException If some other error occurs.           * @throws LSException If some other error occurs.
3054           */           */
3055          public synchronized int          public synchronized int
3056          getMidiInstrumentCount(int mapId) throws IOException, LscpException, LSException {          getMidiInstrumentCount(int mapId) throws IOException, LscpException, LSException {
3057                  verifyConnection();                  return retrieveInt("GET MIDI_INSTRUMENTS " + String.valueOf(mapId));
                 out.writeLine("GET MIDI_INSTRUMENTS " + String.valueOf(mapId));  
                 if(getPrintOnlyMode()) return -1;  
                   
                 String s = getSingleLineResultSet().getResult();  
                 return parseInt(s);  
3058          }          }
3059                    
3060          /**          /**
# Line 2588  public class Client { Line 3077  public class Client {
3077          }          }
3078                    
3079          /**          /**
3080           * Gets all MIDI instrument contained int the specified MIDI instrument map.           * 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.           * @param mapId The ID of the map, which instruments should be obtained.
3114           * @return A <code>MidiInstrumentInfo</code> array providing           * @return A <code>MidiInstrumentInfo</code> array providing
3115           * all MIDI instruments from all MIDI instrument maps.           * all MIDI instruments in the specified MIDI instrument map.
3116           * @throws IOException If some I/O error occurs.           * @throws IOException If some I/O error occurs.
3117           * @throws LscpException If LSCP protocol corruption occurs.           * @throws LscpException If LSCP protocol corruption occurs.
3118           * @throws LSException If some other error occurs.           * @throws LSException If some other error occurs.
# Line 2639  public class Client { Line 3160  public class Client {
3160                                          throws IOException, LscpException, LSException {                                          throws IOException, LscpException, LSException {
3161                    
3162                  verifyConnection();                  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 ");                  StringBuffer cmd = new StringBuffer("GET MIDI_INSTRUMENT INFO ");
3170                  cmd.append(mapId).append(' ');                  cmd.append(mapId).append(' ');
3171                  cmd.append(bank).append(' ');                  cmd.append(bank).append(' ');
3172                  cmd.append(program);                  cmd.append(program);
3173                                    
3174                  out.writeLine(cmd.toString());                  out.writeLine(cmd.toString());
3175                  if(getPrintOnlyMode()) return null;          }
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();                  ResultSet rs = getMultiLineResultSet();
3183                  MidiInstrumentEntry entry = new MidiInstrumentEntry(bank, program);                  MidiInstrumentEntry entry = new MidiInstrumentEntry(bank, program);
3184                  return new MidiInstrumentInfo(mapId, entry, rs.getMultiLineResult());                  return new MidiInstrumentInfo(mapId, entry, rs.getMultiLineResult());
# Line 2693  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);
                 if(getPrintOnlyMode()) return;  
                   
                 ResultSet rs = getEmptyResultSet();  
3234          }          }
3235                    
3236          /**          /**
# Line 2718  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);  
                 if(getPrintOnlyMode()) return;  
                   
                 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");  
                 if(getPrintOnlyMode()) return -1;  
                   
                 String s = getSingleLineResultSet().getResult();  
                 return parseInt(s);  
3264          }          }
3265                    
3266          /**          /**
# Line 2765  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 2778  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");  
                 if(getPrintOnlyMode()) return null;  
                   
                 return parseIntList(getSingleLineResultSet().getResult());  
3410          }          }
3411                    
3412          /**          /**
# Line 2797  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");  
                 if(getPrintOnlyMode()) return -1;  
                   
                 ResultSet rs = getEmptyResultSet();  
                   
                 return rs.getIndex();  
3425          }          }
3426                    
3427          /**          /**
# Line 2819  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);  
                 if(getPrintOnlyMode()) return;  
                   
                 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");  
                 if(getPrintOnlyMode()) return -1;  
                   
                 String s = getSingleLineResultSet().getResult();  
                 return parseInt(s);  
3453          }          }
3454                    
3455          /**          /**
# Line 2894  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;
                 if(getPrintOnlyMode()) 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 2918  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;
                 if(getPrintOnlyMode()) return null;  
                   
                 ResultSet rs = getMultiLineResultSet();  
                 SamplerChannel sc = new SamplerChannel(rs.getMultiLineResult());  
3529                  sc.setChannelId(samplerChn);                  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                                    
# Line 2934  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 2942  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);  
                 if(getPrintOnlyMode()) return -1;  
                   
                 ResultSet rs = getSingleLineResultSet();  
                   
                 return parseInt(rs.getResult());  
3549          }          }
3550                    
3551          /**          /**
# Line 3088  public class Client { Line 3685  public class Client {
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);  
                 if(getPrintOnlyMode()) return;  
                   
                 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 3118  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);
                 if(getPrintOnlyMode()) return;  
                   
                 ResultSet rs = getEmptyResultSet();  
3716          }          }
3717                    
3718          /**          /**
# Line 3147  public class Client { Line 3734  public class Client {
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);  
                 if(getPrintOnlyMode()) return;  
                   
                 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 3170  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);  
                 if(getPrintOnlyMode()) return;  
                   
                 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 3193  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);
                 if(getPrintOnlyMode()) return;  
                   
                 ResultSet rs = getEmptyResultSet();  
3776          }          }
3777                    
3778          /**          /**
# Line 3225  public class Client { Line 3796  public class Client {
3796           */           */
3797          public synchronized void          public synchronized void
3798          setChannelMidiInstrumentMap(int samplerChn, int mapId)          setChannelMidiInstrumentMap(int samplerChn, int mapId)
3799                                  throws IOException, LscpException, LSException {                                  throws IOException, LscpException, LSException
3800                            {
                 verifyConnection();  
3801                  String s;                  String s;
3802                  if(mapId == -1) {                  if(mapId == -1) {
3803                          s = " NONE";                          s = " NONE";
# Line 3236  public class Client { Line 3806  public class Client {
3806                  } else {                  } else {
3807                          s = " " + String.valueOf(mapId);                          s = " " + String.valueOf(mapId);
3808                  }                  }
3809                  out.writeLine("SET CHANNEL MIDI_INSTRUMENT_MAP " + samplerChn + s);  
3810                  if(getPrintOnlyMode()) return;                  retrieveIndex("SET CHANNEL MIDI_INSTRUMENT_MAP " + samplerChn + s);
                   
                 ResultSet rs = getEmptyResultSet();  
3811          }          }
3812                    
3813          /**          /**
# Line 3256  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);  
                 if(getPrintOnlyMode()) return;  
                   
                 ResultSet rs = getEmptyResultSet();  
         }  
3829                    
3830          /**          /**
3831           * Mute/unmute the specified sampler channel.           * Mute/unmute the specified sampler channel.
# Line 3280  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));  
                 if(getPrintOnlyMode()) return;  
                   
                 ResultSet rs = getEmptyResultSet();  
         }  
3847                    
3848          /**          /**
3849           * Solo/unsolo the specified sampler channel.           * Solo/unsolo the specified sampler channel.
# Line 3304  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)); }
                 verifyConnection();  
                 out.writeLine("SET CHANNEL SOLO " + samplerChn + ' ' + (solo ? 1 : 0));  
                 if(getPrintOnlyMode()) return;  
                   
                 ResultSet rs = getEmptyResultSet();  
         }  
3865                    
3866          /**          /**
3867           * Creates an additional effect send on the specified sampler channel.           * Creates an additional effect send on the specified sampler channel.
# Line 3344  public class Client { Line 3894  public class Client {
3894           */           */
3895          public synchronized int          public synchronized int
3896          createFxSend(int channel, int midiCtrl, String name)          createFxSend(int channel, int midiCtrl, String name)
3897                          throws IOException, LSException, LscpException {                          throws IOException, LSException, LscpException
3898                            {
                 verifyConnection();  
3899                  String s = String.valueOf(channel) + " " + String.valueOf(midiCtrl);                  String s = String.valueOf(channel) + " " + String.valueOf(midiCtrl);
3900                  if(name != null) s += " '" + name + "'";                  if(name != null) s += " '" + toEscapedText(name) + "'";
3901                  out.writeLine("CREATE FX_SEND " + s);  
3902                  if(getPrintOnlyMode()) return -1;                  return retrieveIndex("CREATE FX_SEND " + s);
                   
                 ResultSet rs = getEmptyResultSet();  
                   
                 return rs.getIndex();  
3903          }          }
3904                    
3905          /**          /**
# Line 3368  public class Client { Line 3913  public class Client {
3913           */           */
3914          public synchronized void          public synchronized void
3915          destroyFxSend(int channel, int fxSend)          destroyFxSend(int channel, int fxSend)
3916                          throws IOException, LSException, LscpException {                          throws IOException, LSException, LscpException
3917                            {
                 verifyConnection();  
3918                  String s = String.valueOf(channel) + " " + String.valueOf(fxSend);                  String s = String.valueOf(channel) + " " + String.valueOf(fxSend);
3919                  out.writeLine("DESTROY FX_SEND " + s);                  retrieveIndex("DESTROY FX_SEND " + s);
                 if(getPrintOnlyMode()) return;  
                   
                 ResultSet rs = getEmptyResultSet();  
3920          }          }
3921                    
3922          /**          /**
# Line 3387  public class Client { Line 3928  public class Client {
3928           * @throws LSException If some other error occurs.           * @throws LSException If some other error occurs.
3929           */           */
3930          public synchronized int          public synchronized int
3931          getFxSoundCount(int channel) throws IOException, LscpException, LSException {          getFxSendCount(int channel) throws IOException, LscpException, LSException {
3932                  verifyConnection();                  return retrieveInt("GET FX_SENDS " + String.valueOf(channel));
                 out.writeLine("GET FX_SENDS " + String.valueOf(channel));  
                 if(getPrintOnlyMode()) return -1;  
                   
                 String s = getSingleLineResultSet().getResult();  
                 return parseInt(s);  
3933          }          }
3934                    
3935          /**          /**
# Line 3433  public class Client { Line 3969  public class Client {
3969           */           */
3970          public synchronized Integer[]          public synchronized Integer[]
3971          getFxSendIDs(int channel) throws IOException, LscpException, LSException {          getFxSendIDs(int channel) throws IOException, LscpException, LSException {
3972                  verifyConnection();                  return getIntegerList("LIST FX_SENDS " + channel);
                 out.writeLine("LIST FX_SENDS " + channel);  
                 if(getPrintOnlyMode()) return null;  
                   
                 return parseIntList(getSingleLineResultSet().getResult());  
3973          }          }
3974                    
3975          /**          /**
# Line 3452  public class Client { Line 3984  public class Client {
3984           */           */
3985          public synchronized FxSend          public synchronized FxSend
3986          getFxSendInfo(int channel, int fxSend) throws IOException, LscpException, LSException {          getFxSendInfo(int channel, int fxSend) throws IOException, LscpException, LSException {
3987                  verifyConnection();                  FxSend fxs = new FxSend();
3988                  String s = String.valueOf(channel) + " " + String.valueOf(fxSend);                  String s = String.valueOf(channel) + " " + String.valueOf(fxSend);
3989                  out.writeLine("GET FX_SEND INFO " + s);                  if(!retrieveInfo("GET FX_SEND INFO " + s, fxs)) return null;
                 if(getPrintOnlyMode()) return null;  
                   
                 ResultSet rs = getMultiLineResultSet();  
                 FxSend fxs = new FxSend(rs.getMultiLineResult());  
3990                  fxs.setFxSendId(fxSend);                  fxs.setFxSendId(fxSend);
3991                                    
3992                  return fxs;                  return fxs;
# Line 3476  public class Client { Line 4004  public class Client {
4004           */           */
4005          public synchronized void          public synchronized void
4006          setFxSendName(int channel, int fxSend, String name)          setFxSendName(int channel, int fxSend, String name)
4007                                  throws IOException, LscpException, LSException {                                  throws IOException, LscpException, LSException
4008                            {
4009                  verifyConnection();                  String args = " " + channel + " " + fxSend + " '" + toEscapedText(name) + "'";
4010                  String args = " " + channel + " " + fxSend + " '" + name + "'";                  retrieveIndex("SET FX_SEND NAME" + args);
                 out.writeLine("SET FX_SEND NAME" + args);  
                 if(getPrintOnlyMode()) return;  
                   
                 ResultSet rs = getEmptyResultSet();  
4011          }          }
4012                    
4013          /**          /**
# Line 3506  public class Client { Line 4030  public class Client {
4030           */           */
4031          public synchronized void          public synchronized void
4032          setFxSendAudioOutputChannel(int channel, int fxSend, int audioSrc, int audioDst)          setFxSendAudioOutputChannel(int channel, int fxSend, int audioSrc, int audioDst)
4033                                  throws IOException, LscpException, LSException {                                  throws IOException, LscpException, LSException
4034                            {
                 verifyConnection();  
4035                  String args = " " + channel + " " + fxSend + " " + audioSrc + " " + audioDst;                  String args = " " + channel + " " + fxSend + " " + audioSrc + " " + audioDst;
4036                  out.writeLine("SET FX_SEND AUDIO_OUTPUT_CHANNEL" + args);                  retrieveIndex("SET FX_SEND AUDIO_OUTPUT_CHANNEL" + args);
4037                  if(getPrintOnlyMode()) return;          }
4038                    
4039                  ResultSet rs = getEmptyResultSet();          /**
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          /**          /**
# Line 3534  public class Client { Line 4095  public class Client {
4095           */           */
4096          public synchronized void          public synchronized void
4097          setFxSendMidiController(int channel, int fxSend, int midiCtrl)          setFxSendMidiController(int channel, int fxSend, int midiCtrl)
4098                                  throws IOException, LscpException, LSException {                                  throws IOException, LscpException, LSException
4099                            {
                 verifyConnection();  
4100                  String args = " " + channel + " " + fxSend + " " + midiCtrl;                  String args = " " + channel + " " + fxSend + " " + midiCtrl;
4101                  out.writeLine("SET FX_SEND MIDI_CONTROLLER" + args);                  retrieveIndex("SET FX_SEND MIDI_CONTROLLER" + args);
                 if(getPrintOnlyMode()) return;  
                   
                 ResultSet rs = getEmptyResultSet();  
4102          }          }
4103                    
4104          /**          /**
# Line 3557  public class Client { Line 4114  public class Client {
4114           */           */
4115          public synchronized void          public synchronized void
4116          setFxSendLevel(int channel, int fxSend, float volume)          setFxSendLevel(int channel, int fxSend, float volume)
4117                                  throws IOException, LscpException, LSException {                                  throws IOException, LscpException, LSException
4118                            {
                 verifyConnection();  
4119                  String args = " " + channel + " " + fxSend + " " + String.valueOf(volume);                  String args = " " + channel + " " + fxSend + " " + String.valueOf(volume);
4120                  out.writeLine("SET FX_SEND LEVEL" + args);                  retrieveIndex("SET FX_SEND LEVEL" + args);
4121                  if(getPrintOnlyMode()) return;          }
4122                    
4123                  ResultSet rs = getEmptyResultSet();  
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 3579  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                    for(String s : dirs) out.writeLine(cmd + "'" + conv(s) + "'");
4635                    
4636                  if(getPrintOnlyMode()) return;                  if(getPrintOnlyMode()) return;
4637                                    
4638                  ResultSet rs = getEmptyResultSet();                  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 3604  public class Client { Line 5644  public class Client {
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");  
                 if(getPrintOnlyMode()) return -1;  
                   
                 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");  
                 if(getPrintOnlyMode()) return -1;  
                   
                 String s = getSingleLineResultSet().getResult();  
                 return parseInt(s);  
5680          }          }
5681                    
5682          /**          /**
# Line 3649  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                  verifyConnection();                  ServerInfo info = new ServerInfo();
5695                  out.writeLine("GET SERVER INFO");                  if(!retrieveInfo("GET SERVER INFO", info)) return null;
                 if(getPrintOnlyMode()) return null;  
5696                                    
5697                  ResultSet rs = getMultiLineResultSet();                  return info;
                 return new ServerInfo(rs.getMultiLineResult());  
5698          }          }
5699                    
5700          /**          /**
5701           * Gets the golobal volume of the sampler.           * Gets the global volume of the sampler.
5702           * @return The golobal volume of the sampler.           * @return The global volume of the sampler.
5703           * @throws IOException If some I/O error occurs.           * @throws IOException If some I/O error occurs.
5704           * @throws LscpException If LSCP protocol corruption occurs.           * @throws LscpException If LSCP protocol corruption occurs.
5705           * @throws LSException If some other error occurs.           * @throws LSException If some other error occurs.
# Line 3683  public class Client { Line 5723  public class Client {
5723           * @see #getVolume           * @see #getVolume
5724           */           */
5725          public synchronized void          public synchronized void
5726          setVolume(float volume) throws IOException, LscpException, LSException {          setVolume(float volume) throws IOException, LscpException, LSException
5727            { retrieveIndex("SET VOLUME " + volume); }
5728                    
5729                  verifyConnection();          /**
5730                  out.writeLine("SET VOLUME " + volume);           * Gets the global sampler-wide limit of maximum voices.
5731                  if(getPrintOnlyMode()) return;           * @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                  ResultSet rs = getEmptyResultSet();                  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();
5893    
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.1139  
changed lines
  Added in v.2190

  ViewVC Help
Powered by ViewVC