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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1326 - (hide annotations) (download)
Fri Sep 7 11:03:52 2007 UTC (16 years, 7 months ago) by iliev
File size: 169918 byte(s)
* Client: getAudioOutputDriverInfo is now public and accepts a dependences
  list of parameters
* Client: getMidiInputDriverInfo is now public and accepts a dependences
  list of parameters
* bugfix: parameters with unset values are now not sent to LinuxSampler

1 iliev 596 /*
2     * jlscp - a java LinuxSampler control protocol API
3     *
4 iliev 1139 * Copyright (C) 2005-2007 Grigor Iliev <grigor@grigoriliev.com>
5 iliev 596 *
6     * This file is part of jlscp.
7     *
8     * jlscp is free software; you can redistribute it and/or modify
9     * it under the terms of the GNU General Public License version 2
10     * as published by the Free Software Foundation.
11     *
12     * jlscp is distributed in the hope that it will be useful,
13     * but WITHOUT ANY WARRANTY; without even the implied warranty of
14     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15     * GNU General Public License for more details.
16     *
17     * You should have received a copy of the GNU General Public License
18     * along with jlscp; if not, write to the Free Software
19     * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
20     * MA 02111-1307 USA
21     */
22    
23     package org.linuxsampler.lscp;
24    
25     import java.io.IOException;
26 iliev 1139 import java.io.OutputStream;
27 iliev 596
28     import java.net.InetSocketAddress;
29     import java.net.Socket;
30     import java.net.SocketTimeoutException;
31     import java.net.UnknownHostException;
32    
33     import java.util.Vector;
34     import java.util.logging.Level;
35     import java.util.logging.Logger;
36    
37     import static org.linuxsampler.lscp.Parser.*;
38     import org.linuxsampler.lscp.event.*;
39    
40    
41     /**
42     * This class is the abstraction representing a client endpoint for communication with LinuxSampler
43 iliev 1139 * instance. Since it implements all commands specified in the LSCP protocol v1.1, for more
44 iliev 671 * information look at the
45 iliev 1139 * <a href=http://www.linuxsampler.org/api/lscp-1.1.html>LSCP</a> specification.
46 iliev 596 *
47     * <p> The following code establishes connection to LinuxSampler instance and gets the
48     * LinuxSampler version:
49     * <pre>
50     * try {
51     * Client client = new Client();
52     * client.connect();
53     *
54     * String version = client.getServerInfo().getVersion();
55     * System.out.println(version);
56     *
57     * client.disconnect();
58     * } catch(Exception x) { x.printStackTrace(); }
59     * </pre>
60     * </p>
61     *
62     * <p>For more examples look at the <code>examples</code> directory
63     * located in the <b>jlscp</b> distribution.</p>
64     *
65     * All methods are thread safe.
66     * @author Grigor Iliev
67     */
68     public class Client {
69     private String address;
70     private int port;
71     private Socket sock = null;
72 iliev 1202 private int soTimeout = 20000;
73 iliev 596
74     private LscpInputStream in = null;
75     private LscpOutputStream out = null;
76    
77     private EventThread eventThread;
78    
79 iliev 1139 private boolean printOnlyMode = false;
80    
81 iliev 596 class EventThread extends Thread {
82 iliev 1202 private Vector<String> queue = new Vector<String>();
83 iliev 596 private boolean terminate = false;
84    
85     EventThread() { super("LSCP-Event-Thread"); }
86    
87     public void
88     run() {
89     while(!mustTerminate()) {
90 iliev 1202 try {
91     processQueue();
92     processNotifications();
93     } catch(Exception x) {
94 iliev 596 getLogger().log(Level.FINE, x.getMessage(), x);
95     }
96     try { synchronized(this) { wait(100); } }
97     catch(Exception x) {
98     getLogger().log(Level.FINE, x.getMessage(), x);
99     }
100     }
101     }
102    
103     private synchronized boolean
104     mustTerminate() { return terminate; }
105    
106     public synchronized void
107     terminate() {
108     terminate = true;
109     this.notifyAll();
110     }
111 iliev 1202
112     public synchronized void
113     scheduleNotification(String s) { queue.add(s); }
114    
115     private void
116     processQueue() {
117     String[] notifications = popAllNotifications();
118     for(String n : notifications) fireEvent(n);
119     }
120    
121     private synchronized String[]
122     popAllNotifications() {
123     String[] notifications = queue.toArray(new String[queue.size()]);
124     queue.removeAllElements();
125     return notifications;
126     }
127 iliev 596 }
128    
129     /**
130     * Creates a new instance of Client with default server address and port.
131     * The default server address and port are 127.0.0.1:8888.
132     */
133     public
134     Client() { this("127.0.0.1"); }
135    
136     /**
137     * Creates a new instance of Client with the specified address and default port.
138     * The default port is 8888.
139     * @param address The address of linux sampler server.
140     */
141     public
142     Client(String address) { this(address, 8888); }
143    
144     /**
145     * Creates a new instance of Client with the specified address and port.
146     * @param address The address of the Linux Sampler.
147     * @param port The Linux Sampler port number.
148     */
149     public
150     Client(String address, int port) {
151     setServerAddress(address);
152     setServerPort(port);
153    
154     eventThread = new EventThread();
155     }
156    
157     /**
158 iliev 1139 * Creates a new instance of Client.
159     * @param printOnlyMode Determines whether the client will be in print-only mode.
160     */
161     public
162     Client(boolean printOnlyMode) {
163     if(printOnlyMode) setPrintOnlyMode(true);
164     }
165    
166     /**
167     * Determines whether the client is in print-only mode.
168     * Print-only mode means that the client will just print all
169     * LSCP commands to the specified output stream or to the standard output stream
170     * (<code>java.lang.System.out</code>) if no output stream is specified,
171     * without taking any further actions. Thus, in print-only mode all returned
172     * values by <code>Client</code>'s methods are meaningless and should be discarded.
173     * @return <code>true</code> if the client is in
174     * print-only mode, <code>false</code> otherwise.
175     * @see #setPrintOnlyModeOutputStream
176     */
177     public synchronized boolean
178     getPrintOnlyMode() { return printOnlyMode; }
179    
180     /**
181     * Sets the print-only mode. Note that in print-only mode all returned
182     * values by <code>Client</code>'s methods are meaningless and should be discarded.
183     * The default output stream in print-only mode is <code>java.lang.System.out</code>.
184     * @param b If <code>true</code> all LSCP commands will be sent
185     * to the specified output stream or to the standard output stream
186     * (<code>java.lang.System.out</code>) if no output stream is specified,
187     * and no further actions will be taken.
188     * @throws IllegalStateException If the client is connected.
189     * @see #setPrintOnlyModeOutputStream
190     */
191     public synchronized void
192     setPrintOnlyMode(boolean b) {
193     if(printOnlyMode == b) return;
194     if(isConnected()) throw new IllegalStateException();
195    
196     printOnlyMode = b;
197     if(b) out = new LscpOutputStream(System.out);
198     }
199    
200     /**
201     * Sets the output stream to be used in print-only mode.
202     * @param out The output stream to be used in print-only mode.
203     * @throws IllegalStateException If the client is not in print-only mode.
204     * @throws IllegalArgumentException if <code>out</code> is <code>null</code>.
205     * @see #setPrintOnlyMode
206     */
207     public synchronized void
208     setPrintOnlyModeOutputStream(OutputStream out) {
209     if(!getPrintOnlyMode()) throw new IllegalStateException("Not in print-only mode");
210     if(out == null) throw new IllegalArgumentException("out must be non-null");
211     this.out = new LscpOutputStream(out);
212     }
213    
214     /**
215 iliev 596 * Specifies the jlscp version.
216     * @return The jlscp version.
217     */
218     public static String
219 iliev 671 getClientVersion() {
220     return Package.getPackage("org.linuxsampler.lscp").getImplementationVersion();
221     }
222 iliev 596
223     /**
224     * Gets the Linux Sampler address.
225     * @return The Linux Sampler address.
226     */
227     public synchronized String
228     getServerAddress() { return address; }
229    
230     /**
231     * Sets the Linux Sampler address.
232     * @param address The Linux Sampler address.
233     * If <code>address</code> is <code>null</code> sets to default address - 127.0.0.1.
234     */
235     public synchronized void
236     setServerAddress(String address) {
237     this.address = (address == null ? "127.0.0.1" : address);
238     }
239    
240     /**
241     * Gets the Linux Sampler port number.
242     * @return The Linux Sampler port number.
243     */
244     public synchronized int
245     getServerPort() { return port; }
246    
247     /**
248     * Sets the Linux Sampler port number.
249     * @param port The Linux Sampler port number.
250     */
251     public synchronized void
252     setServerPort(int port) { this.port = port; }
253    
254     /**
255     * Connects to the LinuxSampler. If there is already established connection then
256     * the currently available connection is closed berfore connecting.
257     * @throws LscpException If timeout occurs or any other I/O exception.
258     */
259     public synchronized void
260     connect() throws LscpException {
261     if(sock != null) disconnect();
262 iliev 1139 if(getPrintOnlyMode()) return;
263 iliev 596
264     // Initializing LSCP event thread
265     if(eventThread.isAlive()) {
266     getLogger().warning("LSCP event thread already running!");
267     eventThread.terminate();
268     }
269    
270     if(eventThread.getState() != Thread.State.NEW) eventThread = new EventThread();
271     ///////
272    
273     InetSocketAddress sockAddr = null;
274    
275     try { sockAddr = new InetSocketAddress(address, port); }
276     catch(IllegalArgumentException x) {
277     String s = String.valueOf(port);
278     throw new LscpException(LscpI18n.getLogMsg("Client.invalidPort!", s), x);
279     }
280    
281     if(sockAddr.isUnresolved()) throw new LscpException (
282     LscpI18n.getLogMsg("Client.unknownHost!", address)
283     );
284    
285     try {
286     sock = new Socket();
287     sock.bind(null);
288     sock.connect(sockAddr, soTimeout);
289     sock.setSoTimeout(soTimeout);
290 iliev 784 sock.setTcpNoDelay(true);
291 iliev 596
292     in = new LscpInputStream(sock.getInputStream());
293     out = new LscpOutputStream(sock.getOutputStream());
294     } catch(SocketTimeoutException x) {
295     throw new LscpException(LscpI18n.getLogMsg("Client.conTimeout!"), x);
296     } catch(Exception x) {
297     throw new LscpException (
298     LscpI18n.getLogMsg("Client.connectionFailed!"), x
299     );
300     }
301    
302 iliev 671 String s = Package.getPackage("org.linuxsampler.lscp").getSpecificationVersion();
303     String s2, sv, sv2;
304    
305     try {
306     s2 = s.substring(0, s.indexOf('.'));
307     sv = getServerInfo().getProtocolVersion();
308     sv2 = sv.substring(0, sv.indexOf('.'));
309     } catch(Exception x) {
310     disconnect();
311    
312     throw new LscpException (
313     LscpI18n.getLogMsg("Client.connectionFailed!"), x
314     );
315     }
316    
317     if(!sv2.equals(s2)) {
318     disconnect();
319    
320     throw new LscpException (
321     LscpI18n.getLogMsg("Client.incompatibleLscpVersion!", sv)
322     );
323     }
324    
325     s2 = s.substring(s.indexOf('.'));
326     sv2 = sv.substring(sv.indexOf('.'));
327    
328     if(sv2.compareToIgnoreCase(s2) < 0) getLogger().info (
329     LscpI18n.getLogMsg("Client.incompatibleLscpMinVersion!", sv)
330     );
331    
332 iliev 596 if(hasSubscriptions()) eventThread.start();
333    
334     if(!llM.isEmpty()) subscribe("MISCELLANEOUS");
335 iliev 1139 if(!llAODC.isEmpty()) subscribe("AUDIO_OUTPUT_DEVICE_COUNT");
336     if(!llAODI.isEmpty()) subscribe("AUDIO_OUTPUT_DEVICE_INFO");
337     if(!llMIDC.isEmpty()) subscribe("MIDI_INPUT_DEVICE_COUNT");
338     if(!llMIDI.isEmpty()) subscribe("MIDI_INPUT_DEVICE_INFO");
339 iliev 596 if(!llBF.isEmpty()) subscribe("BUFFER_FILL");
340     if(!llCC.isEmpty()) subscribe("CHANNEL_COUNT");
341     if(!llCI.isEmpty()) subscribe("CHANNEL_INFO");
342 iliev 1139 if(!llFSC.isEmpty()) subscribe("FX_SEND_COUNT");
343     if(!llFSI.isEmpty()) subscribe("FX_SEND_INFO");
344 iliev 596 if(!llSC.isEmpty()) subscribe("STREAM_COUNT");
345     if(!llVC.isEmpty()) subscribe("VOICE_COUNT");
346 iliev 784 if(!llTVC.isEmpty()) subscribe("TOTAL_VOICE_COUNT");
347 iliev 1139 if(!llMIMC.isEmpty()) subscribe("MIDI_INSTRUMENT_MAP_COUNT");
348     if(!llMIMI.isEmpty()) subscribe("MIDI_INSTRUMENT_MAP_INFO");
349     if(!llMIC.isEmpty()) subscribe("MIDI_INSTRUMENT_COUNT");
350     if(!llMII.isEmpty()) subscribe("MIDI_INSTRUMENT_INFO");
351 iliev 1202 if(!llID.isEmpty()) {
352     subscribe("DB_INSTRUMENT_DIRECTORY_COUNT");
353     subscribe("DB_INSTRUMENT_DIRECTORY_INFO");
354     subscribe("DB_INSTRUMENT_COUNT");
355     subscribe("DB_INSTRUMENT_INFO");
356     }
357 iliev 1139 if(!llGI.isEmpty()) subscribe("GLOBAL_INFO");
358 iliev 596 }
359    
360     /**
361     * Closes the connection to LinuxSampler.
362     */
363     public synchronized void
364     disconnect() {
365 iliev 1139 if(getPrintOnlyMode()) return;
366 iliev 596 try { if(sock != null) sock.close(); }
367     catch(Exception x) { getLogger().log(Level.FINE, x.getMessage(), x); }
368     sock = null;
369    
370     if(eventThread.getState() != Thread.State.NEW) {
371     eventThread.terminate();
372     eventThread = new EventThread();
373     }
374     }
375    
376     /**
377     * Determines whether the client is connected.
378     * @return <code>true</code> if there is established connection,
379     * <code>false</code> otherwise.
380     */
381     public synchronized boolean
382     isConnected() {
383     if(sock == null) return false;
384     else return sock.isConnected();
385     }
386    
387     /**
388     * Verifies that there is established connection.
389     * @throws IOException If the connection is not established.
390     */
391     private void
392     verifyConnection() throws IOException {
393 iliev 1139 if(getPrintOnlyMode()) return;
394    
395 iliev 596 if(!isConnected())
396     throw new IOException(LscpI18n.getLogMsg("Client.notConnected!"));
397     }
398    
399     private String
400     getLine() throws IOException, LscpException {
401     String s;
402     for(;;) {
403     s = in.readLine();
404 iliev 1202 if(s.startsWith("NOTIFY:")) {
405     eventThread.scheduleNotification(s.substring("NOTIFY:".length()));
406     }
407 iliev 596 else break;
408     }
409     return s;
410     }
411    
412 iliev 1139 /** Processes the notifications sent by LinuxSampler */
413 iliev 596 private synchronized void
414     processNotifications() throws IOException, LscpException {
415     while(in.available() > 0) {
416     String s = in.readLine();
417     if(s.startsWith("NOTIFY:")) fireEvent(s.substring("NOTIFY:".length()));
418     else getLogger().severe("Unknown notification format: " + s);
419     }
420     }
421    
422     /**
423     * Gets empty result set.
424     * @return <code>ResultSet</code> instance.
425     */
426     private ResultSet
427     getEmptyResultSet() throws IOException, LscpException, LSException {
428     return parseEmptyResultSet(getLine());
429     }
430    
431     private ResultSet
432     getSingleLineResultSet() throws IOException, LscpException, LSException {
433     ResultSet rs = new ResultSet();
434     String ln = getLine();
435    
436     if(ln.startsWith("WRN")) {
437     parseWarning(ln, rs);
438     getLogger().warning(rs.getMessage());
439     return rs;
440     } else if(ln.startsWith("ERR")) {
441     parseError(ln, rs);
442     throw new LSException(rs.getCode(), rs.getMessage());
443     } else {
444     rs.setResult(ln);
445     return rs;
446     }
447     }
448    
449     private ResultSet
450     getMultiLineResultSet() throws IOException, LscpException, LSException {
451     ResultSet rs = new ResultSet();
452     String ln = getLine();
453    
454     if(ln.startsWith("WRN")) {
455     parseWarning(ln, rs);
456     getLogger().warning(rs.getMessage());
457     return rs;
458     } else if(ln.startsWith("ERR")) {
459     parseError(ln, rs);
460     throw new LSException(rs.getCode(), rs.getMessage());
461     }
462    
463     while(!ln.equals(".")) {
464     rs.addLine(ln);
465     ln = getLine();
466     }
467    
468     return rs;
469     }
470    
471 iliev 1139 /** Audio output device count listeners */
472     private final Vector<ItemCountListener> llAODC = new Vector<ItemCountListener>();
473     /** Audio output device info listeners */
474     private final Vector<ItemInfoListener> llAODI = new Vector<ItemInfoListener>();
475 iliev 596 private final Vector<BufferFillListener> llBF = new Vector<BufferFillListener>();
476     private final Vector<ChannelCountListener> llCC = new Vector<ChannelCountListener>();
477     private final Vector<ChannelInfoListener> llCI = new Vector<ChannelInfoListener>();
478 iliev 1139 private final Vector<FxSendCountListener> llFSC = new Vector<FxSendCountListener>();
479     private final Vector<FxSendInfoListener> llFSI = new Vector<FxSendInfoListener>();
480 iliev 596 private final Vector<MiscellaneousListener> llM = new Vector<MiscellaneousListener>();
481 iliev 1139 /** MIDI input device count listeners */
482     private final Vector<ItemCountListener> llMIDC = new Vector<ItemCountListener>();
483     /** MIDI input device info listeners */
484     private final Vector<ItemInfoListener> llMIDI = new Vector<ItemInfoListener>();
485 iliev 596 private final Vector<StreamCountListener> llSC = new Vector<StreamCountListener>();
486     private final Vector<VoiceCountListener> llVC = new Vector<VoiceCountListener>();
487 iliev 784 private final Vector<TotalVoiceCountListener> llTVC = new Vector<TotalVoiceCountListener>();
488 iliev 596
489 iliev 1139 /** MIDI instrument map count listeners */
490     private final Vector<ItemCountListener> llMIMC = new Vector<ItemCountListener>();
491     /** MIDI instrument map info listeners */
492     private final Vector<ItemInfoListener> llMIMI = new Vector<ItemInfoListener>();
493     /** MIDI instrument count listeners */
494     private final Vector<MidiInstrumentCountListener> llMIC =
495     new Vector<MidiInstrumentCountListener>();
496     /** MIDI instrument info listeners */
497     private final Vector<MidiInstrumentInfoListener> llMII =
498     new Vector<MidiInstrumentInfoListener>();
499 iliev 1202 private final Vector<InstrumentsDbListener> llID = new Vector<InstrumentsDbListener>();
500 iliev 1139 private final Vector<GlobalInfoListener> llGI = new Vector<GlobalInfoListener>();
501    
502    
503 iliev 596 /**
504     * Determines whether there is at least one subscription for notification events.
505     * Do not forget to check for additional listeners if the LSCP specification
506 iliev 784 * is extended in the future.
507 iliev 596 * @return <code>true</code> if there is at least one subscription for notification events,
508     * <code>false</code> otherwise.
509     */
510     private boolean
511     hasSubscriptions() {
512 iliev 1139 return !llAODC.isEmpty() ||
513     !llAODI.isEmpty() ||
514     !llBF.isEmpty() ||
515     !llCC.isEmpty() ||
516     !llCI.isEmpty() ||
517     !llFSC.isEmpty() ||
518     !llFSI.isEmpty() ||
519     !llM.isEmpty() ||
520     !llMIDC.isEmpty() ||
521     !llMIDI.isEmpty() ||
522     !llSC.isEmpty() ||
523     !llVC.isEmpty() ||
524     !llTVC.isEmpty() ||
525     !llMIMC.isEmpty() ||
526     !llMIMI.isEmpty() ||
527     !llMIC.isEmpty() ||
528     !llMII.isEmpty() ||
529 iliev 1202 !llID.isEmpty() ||
530 iliev 1139 !llGI.isEmpty();
531 iliev 596 }
532    
533 iliev 1202 private synchronized void
534 iliev 596 fireEvent(String s) {
535 iliev 1202 if(s.startsWith("DB_INSTRUMENT_DIRECTORY_COUNT:")) {
536     s = s.substring("DB_INSTRUMENT_DIRECTORY_COUNT:".length());
537     InstrumentsDbEvent e = new InstrumentsDbEvent(this, s);
538     for(InstrumentsDbListener l : llID) l.directoryCountChanged(e);
539     } else if(s.startsWith("DB_INSTRUMENT_DIRECTORY_INFO:")) {
540     InstrumentsDbEvent e;
541     s = s.substring("DB_INSTRUMENT_DIRECTORY_INFO:".length());
542     if(s.startsWith("NAME ")) {
543     String[] list;
544     try {
545 iliev 1326 list = parseQuotedStringList(s.substring("NAME ".length()), ' ');
546 iliev 1202 if(list.length != 2) throw new LscpException();
547     e = new InstrumentsDbEvent(this, list[0], list[1]);
548     for(InstrumentsDbListener l : llID) {
549     l.directoryNameChanged(e);
550     }
551     } catch(LscpException x) {
552     getLogger().log (
553     Level.WARNING,
554     LscpI18n.getLogMsg("CommandFailed!"),
555     x
556     );
557     }
558     } else {
559     e = new InstrumentsDbEvent(this, s);
560     for(InstrumentsDbListener l : llID) l.directoryInfoChanged(e);
561     }
562     } else if(s.startsWith("DB_INSTRUMENT_COUNT:")) {
563     s = s.substring("DB_INSTRUMENT_COUNT:".length());
564     InstrumentsDbEvent e = new InstrumentsDbEvent(this, s);
565     for(InstrumentsDbListener l : llID) l.instrumentCountChanged(e);
566     } else if(s.startsWith("DB_INSTRUMENT_INFO:")) {
567     InstrumentsDbEvent e;
568     s = s.substring("DB_INSTRUMENT_INFO:".length());
569     if(s.startsWith("NAME ")) {
570     String[] list;
571     try {
572 iliev 1326 list = parseQuotedStringList(s.substring("NAME ".length()), ' ');
573 iliev 1202 if(list.length != 2) throw new LscpException();
574     e = new InstrumentsDbEvent(this, list[0], list[1]);
575     for(InstrumentsDbListener l : llID) {
576     l.instrumentNameChanged(e);
577     }
578     } catch(LscpException x) {
579     getLogger().log (
580     Level.WARNING,
581     LscpI18n.getLogMsg("CommandFailed!"),
582     x
583     );
584     }
585     } else {
586     e = new InstrumentsDbEvent(this, s);
587     for(InstrumentsDbListener l : llID) l.instrumentInfoChanged(e);
588     }
589     } else if(s.startsWith("DB_INSTRUMENTS_JOB_INFO:")) {
590     s = s.substring("DB_INSTRUMENTS_JOB_INFO:".length());
591 iliev 596 try {
592 iliev 1202 int i = Integer.parseInt(s);
593     InstrumentsDbEvent e = new InstrumentsDbEvent(this, i);
594     for(InstrumentsDbListener l : llID) l.jobStatusChanged(e);
595     } catch(NumberFormatException x) {
596     s = "Unknown DB_INSTRUMENTS_JOB_INFO format";
597     getLogger().log(Level.WARNING, s, x);
598     }
599    
600     } else if(s.startsWith("CHANNEL_COUNT:")) {
601     try {
602 iliev 596 int i = Integer.parseInt(s.substring("CHANNEL_COUNT:".length()));
603     ChannelCountEvent e = new ChannelCountEvent(this, i);
604     for(ChannelCountListener l : llCC) l.channelCountChanged(e);
605     } catch(NumberFormatException x) {
606     getLogger().log (
607     Level.WARNING, LscpI18n.getLogMsg("CommandFailed!"), x
608     );
609     }
610     } else if(s.startsWith("VOICE_COUNT:")) {
611     try {
612     s = s.substring("VOICE_COUNT:".length());
613 iliev 1139 Integer[] i = parseIntList(s, ' ');
614     if(i.length != 2) {
615 iliev 596 getLogger().warning("Unknown VOICE_COUNT format");
616     return;
617     }
618 iliev 1139 VoiceCountEvent e = new VoiceCountEvent(this, i[0], i[1]);
619 iliev 596 for(VoiceCountListener l : llVC) l.voiceCountChanged(e);
620 iliev 1139 } catch(Exception x) {
621 iliev 596 getLogger().log(Level.WARNING, "Unknown VOICE_COUNT format", x);
622     }
623     } else if(s.startsWith("STREAM_COUNT:")) {
624     try {
625     s = s.substring("STREAM_COUNT:".length());
626 iliev 1139 Integer[] i = parseIntList(s, ' ');
627     if(i.length != 2) {
628 iliev 596 getLogger().warning("Unknown STREAM_COUNT format");
629     return;
630     }
631 iliev 1139 StreamCountEvent e = new StreamCountEvent(this, i[0], i[1]);
632 iliev 596 for(StreamCountListener l : llSC) l.streamCountChanged(e);
633 iliev 1139 } catch(Exception x) {
634 iliev 596 getLogger().log(Level.WARNING, "Unknown STREAM_COUNT format", x);
635     }
636     } else if(s.startsWith("BUFFER_FILL:")) {
637     try {
638     s = s.substring("BUFFER_FILL:".length());
639     int i = s.indexOf(' ');
640     if(i == -1) {
641 iliev 1139 getLogger().warning("Unknown BUFFER_FILL format");
642 iliev 596 return;
643     }
644     int j = Integer.parseInt(s.substring(0, i));
645     Vector<BufferFill> v =
646     getChannelBufferFillPercentage(s.substring(i + 1));
647     BufferFillEvent e = new BufferFillEvent(this, j, v);
648     for(BufferFillListener l : llBF) l.bufferFillChanged(e);
649     } catch(Exception x) {
650 iliev 1139 getLogger().log(Level.WARNING, "Unknown BUFFER_FILL format", x);
651 iliev 596 }
652     } else if(s.startsWith("CHANNEL_INFO:")) {
653     try {
654     int i = Integer.parseInt(s.substring("CHANNEL_INFO:".length()));
655     ChannelInfoEvent e = new ChannelInfoEvent(this, i);
656     for(ChannelInfoListener l : llCI) l.channelInfoChanged(e);
657     } catch(NumberFormatException x) {
658 iliev 1139 getLogger().log(Level.WARNING, "Unknown CHANNEL_INFO format", x);
659 iliev 596 }
660 iliev 784 } else if(s.startsWith("TOTAL_VOICE_COUNT:")) {
661     try {
662     s = s.substring("TOTAL_VOICE_COUNT:".length());
663     int i = Integer.parseInt(s);
664     TotalVoiceCountEvent e = new TotalVoiceCountEvent(this, i);
665     for(TotalVoiceCountListener l : llTVC) l.totalVoiceCountChanged(e);
666     } catch(NumberFormatException x) {
667     getLogger().log (
668     Level.WARNING, "Unknown TOTAL_VOICE_COUNT format", x
669     );
670     }
671 iliev 1139 } else if(s.startsWith("AUDIO_OUTPUT_DEVICE_COUNT:")) {
672     try {
673     s = s.substring("AUDIO_OUTPUT_DEVICE_COUNT:".length());
674     int i = Integer.parseInt(s);
675     ItemCountEvent e = new ItemCountEvent(this, i);
676     for(ItemCountListener l : llAODC) l.itemCountChanged(e);
677     } catch(NumberFormatException x) {
678     getLogger().log (
679     Level.WARNING, "Unknown AUDIO_OUTPUT_DEVICE_COUNT format", x
680     );
681     }
682     } else if(s.startsWith("AUDIO_OUTPUT_DEVICE_INFO:")) {
683     try {
684     s = s.substring("AUDIO_OUTPUT_DEVICE_INFO:".length());
685     int i = Integer.parseInt(s);
686     ItemInfoEvent e = new ItemInfoEvent(this, i);
687     for(ItemInfoListener l : llAODI) l.itemInfoChanged(e);
688     } catch(NumberFormatException x) {
689     getLogger().log (
690     Level.WARNING, "Unknown AUDIO_OUTPUT_DEVICE_INFO format", x
691     );
692     }
693     } else if(s.startsWith("MIDI_INPUT_DEVICE_COUNT:")) {
694     try {
695     s = s.substring("MIDI_INPUT_DEVICE_COUNT:".length());
696     int i = Integer.parseInt(s);
697     ItemCountEvent e = new ItemCountEvent(this, i);
698     for(ItemCountListener l : llMIDC) l.itemCountChanged(e);
699     } catch(NumberFormatException x) {
700     getLogger().log (
701     Level.WARNING, "Unknown MIDI_INPUT_DEVICE_COUNT format", x
702     );
703     }
704     } else if(s.startsWith("MIDI_INPUT_DEVICE_INFO:")) {
705     try {
706     s = s.substring("MIDI_INPUT_DEVICE_INFO:".length());
707     int i = Integer.parseInt(s);
708     ItemInfoEvent e = new ItemInfoEvent(this, i);
709     for(ItemInfoListener l : llMIDI) l.itemInfoChanged(e);
710     } catch(NumberFormatException x) {
711     getLogger().log (
712     Level.WARNING, "Unknown MIDI_INPUT_DEVICE_INFO format", x
713     );
714     }
715     } else if(s.startsWith("MIDI_INSTRUMENT_MAP_COUNT:")) {
716     try {
717     s = s.substring("MIDI_INSTRUMENT_MAP_COUNT:".length());
718     int i = Integer.parseInt(s);
719     ItemCountEvent e = new ItemCountEvent(this, i);
720     for(ItemCountListener l : llMIMC) l.itemCountChanged(e);
721     } catch(NumberFormatException x) {
722     getLogger().log (
723     Level.WARNING, "Unknown MIDI_INSTRUMENT_MAP_COUNT format", x
724     );
725     }
726     } else if(s.startsWith("MIDI_INSTRUMENT_MAP_INFO:")) {
727     try {
728     s = s.substring("MIDI_INSTRUMENT_MAP_INFO:".length());
729     int i = Integer.parseInt(s);
730     ItemInfoEvent e = new ItemInfoEvent(this, i);
731     for(ItemInfoListener l : llMIMI) l.itemInfoChanged(e);
732     } catch(NumberFormatException x) {
733     getLogger().log (
734     Level.WARNING, "Unknown MIDI_INSTRUMENT_MAP_INFO format", x
735     );
736     }
737     } else if(s.startsWith("MIDI_INSTRUMENT_COUNT:")) {
738     try {
739     s = s.substring("MIDI_INSTRUMENT_COUNT:".length());
740     Integer[] i = parseIntList(s, ' ');
741     if(i.length != 2) {
742     getLogger().warning("Unknown MIDI_INSTRUMENT_COUNT format");
743     return;
744     }
745    
746     MidiInstrumentCountEvent e =
747     new MidiInstrumentCountEvent(this, i[0], i[1]);
748    
749     for(MidiInstrumentCountListener l : llMIC) {
750     l.instrumentCountChanged(e);
751     }
752     } catch(Exception x) {
753     getLogger().log (
754     Level.WARNING, "Unknown MIDI_INSTRUMENT_COUNT format", x
755     );
756     }
757     } else if(s.startsWith("MIDI_INSTRUMENT_INFO:")) {
758     try {
759     s = s.substring("MIDI_INSTRUMENT_INFO:".length());
760     Integer[] i = parseIntList(s, ' ');
761     if(i.length != 3) {
762     getLogger().warning("Unknown MIDI_INSTRUMENT_INFO format");
763     return;
764     }
765    
766     MidiInstrumentInfoEvent e =
767     new MidiInstrumentInfoEvent(this, i[0], i[1], i[2]);
768     for(MidiInstrumentInfoListener l : llMII) {
769     l.instrumentInfoChanged(e);
770     }
771     } catch(Exception x) {
772     getLogger().log (
773     Level.WARNING, "Unknown MIDI_INSTRUMENT_INFO format", x
774     );
775     }
776     } else if(s.startsWith("FX_SEND_COUNT:")) {
777     try {
778     s = s.substring("FX_SEND_COUNT:".length());
779     Integer[] i = parseIntList(s, ' ');
780     if(i.length != 2) {
781     getLogger().warning("Unknown FX_SEND_COUNT format");
782     return;
783     }
784    
785     FxSendCountEvent e = new FxSendCountEvent(this, i[0], i[1]);
786    
787     for(FxSendCountListener l : llFSC) l.fxSendCountChanged(e);
788     } catch(Exception x) {
789     getLogger().log(Level.WARNING, "Unknown FX_SEND_COUNT format", x);
790     }
791     } else if(s.startsWith("FX_SEND_INFO:")) {
792     try {
793     s = s.substring("FX_SEND_INFO:".length());
794     Integer[] i = parseIntList(s, ' ');
795     if(i.length != 2) {
796     getLogger().warning("Unknown FX_SEND_INFO format");
797     return;
798     }
799    
800     FxSendInfoEvent e = new FxSendInfoEvent(this, i[0], i[1]);
801     for(FxSendInfoListener l : llFSI) {
802     l.fxSendInfoChanged(e);
803     }
804     } catch(Exception x) {
805     getLogger().log(Level.WARNING, "Unknown FX_SEND_INFO format", x);
806     }
807     } else if(s.startsWith("GLOBAL_INFO:")) {
808     handleGlobalInfoEvent(s.substring("GLOBAL_INFO:".length()));
809 iliev 596 } else if(s.startsWith("MISCELLANEOUS:")) {
810     s = s.substring("MISCELLANEOUS:".length());
811     MiscellaneousEvent e = new MiscellaneousEvent(this, s);
812     for(MiscellaneousListener l : llM) l.miscEventOccured(e);
813     }
814     }
815    
816     private void
817 iliev 1139 handleGlobalInfoEvent(String s) {
818     try {
819     if(s.startsWith("VOLUME ")) {
820     float f = Float.parseFloat(s.substring("VOLUME ".length()));
821     GlobalInfoEvent e = new GlobalInfoEvent(this, f);
822     for(GlobalInfoListener l : llGI) l.volumeChanged(e);
823     }
824     } catch(NumberFormatException x) {
825     getLogger().log(Level.WARNING, "Unknown GLOBAL_INFO format", x);
826     }
827     }
828    
829     private void
830 iliev 596 subscribe(String event) {
831 iliev 1139 if(!getPrintOnlyMode()) {
832     if(!isConnected()) return;
833 iliev 596
834 iliev 1139 if(!eventThread.isAlive()) eventThread.start();
835     }
836 iliev 596
837     try {
838     out.writeLine("SUBSCRIBE " + event);
839 iliev 1139 if(!getPrintOnlyMode()) getEmptyResultSet();
840 iliev 596 } catch(Exception x) {
841     getLogger().log (
842     Level.WARNING,
843     LscpI18n.getLogMsg("Client.subscriptionFailed!", event),
844     x
845     );
846     }
847     }
848    
849     private void
850     unsubscribe(String event) {
851 iliev 1139 if(!getPrintOnlyMode() && !isConnected()) return;
852 iliev 596
853     try {
854     out.writeLine("UNSUBSCRIBE " + event);
855 iliev 1139 if(!getPrintOnlyMode()) getEmptyResultSet();
856 iliev 596 } catch(Exception x) {
857     getLogger().log (
858     Level.WARNING,
859     LscpI18n.getLogMsg("Client.unsubscriptionFailed!", event),
860     x
861     );
862     }
863     }
864    
865     /**
866     * Registers the specified listener for receiving event messages.
867 iliev 1139 * Listeners can be registered regardless of the connection state.
868     * @param l The <code>ItemCountListener</code> to register.
869     */
870     public synchronized void
871     addAudioDeviceCountListener(ItemCountListener l) {
872     if(llAODC.isEmpty()) subscribe("AUDIO_OUTPUT_DEVICE_COUNT");
873     llAODC.add(l);
874     }
875    
876     /**
877     * Removes the specified listener.
878 iliev 596 * Listeners can be removed regardless of the connection state.
879 iliev 1139 * @param l The <code>ItemCountListener</code> to remove.
880     */
881     public synchronized void
882     removeAudioDeviceCountListener(ItemCountListener l) {
883     boolean b = llAODC.remove(l);
884     if(b && llAODC.isEmpty()) unsubscribe("AUDIO_OUTPUT_DEVICE_COUNT");
885     }
886    
887     /**
888     * Registers the specified listener for receiving event messages.
889     * Listeners can be registered regardless of the connection state.
890     * @param l The <code>ItemInfoListener</code> to register.
891     */
892     public synchronized void
893     addAudioDeviceInfoListener(ItemInfoListener l) {
894     if(llAODI.isEmpty()) subscribe("AUDIO_OUTPUT_DEVICE_INFO");
895     llAODI.add(l);
896     }
897    
898     /**
899     * Removes the specified listener.
900     * Listeners can be removed regardless of the connection state.
901     * @param l The <code>ItemInfoListener</code> to remove.
902     */
903     public synchronized void
904     removeAudioDeviceInfoListener(ItemInfoListener l) {
905     boolean b = llAODI.remove(l);
906     if(b && llAODI.isEmpty()) unsubscribe("AUDIO_OUTPUT_DEVICE_INFO");
907     }
908    
909     /**
910     * Registers the specified listener for receiving event messages.
911     * Listeners can be removed regardless of the connection state.
912 iliev 596 * @param l The <code>BufferFillListener</code> to register.
913     */
914     public synchronized void
915     addBufferFillListener(BufferFillListener l) {
916     if(llBF.isEmpty()) subscribe("BUFFER_FILL");
917     llBF.add(l);
918     }
919    
920     /**
921     * Removes the specified listener.
922     * Listeners can be removed regardless of the connection state.
923     * @param l The <code>BufferFillListener</code> to remove.
924     */
925     public synchronized void
926     removeBufferFillListener(BufferFillListener l) {
927     boolean b = llBF.remove(l);
928     if(b && llBF.isEmpty()) unsubscribe("BUFFER_FILL");
929     }
930    
931     /**
932     * Registers the specified listener for receiving event messages.
933     * Listeners can be registered regardless of the connection state.
934     * @param l The <code>ChannelCountListener</code> to register.
935     */
936     public synchronized void
937     addChannelCountListener(ChannelCountListener l) {
938     if(llCC.isEmpty()) subscribe("CHANNEL_COUNT");
939     llCC.add(l);
940     }
941    
942     /**
943     * Removes the specified listener.
944     * Listeners can be removed regardless of the connection state.
945     * @param l The <code>ChannelCountListener</code> to remove.
946     */
947     public synchronized void
948     removeChannelCountListener(ChannelCountListener l) {
949     boolean b = llCC.remove(l);
950     if(b && llCC.isEmpty()) unsubscribe("CHANNEL_COUNT");
951     }
952    
953     /**
954     * Registers the specified listener for receiving event messages.
955     * Listeners can be registered regardless of the connection state.
956     * @param l The <code>ChannelInfoListener</code> to register.
957     */
958     public synchronized void
959     addChannelInfoListener(ChannelInfoListener l) {
960     if(llCI.isEmpty()) subscribe("CHANNEL_INFO");
961     llCI.add(l);
962     }
963    
964     /**
965     * Removes the specified listener.
966     * Listeners can be removed regardless of the connection state.
967     * @param l The <code>ChannelInfoListener</code> to remove.
968     */
969     public synchronized void
970     removeChannelInfoListener(ChannelInfoListener l) {
971     boolean b = llCI.remove(l);
972     if(b && llCI.isEmpty()) unsubscribe("CHANNEL_INFO");
973     }
974    
975     /**
976     * Registers the specified listener for receiving event messages.
977     * Listeners can be registered regardless of the connection state.
978 iliev 1139 * @param l The <code>FxSendCountListener</code> to register.
979     */
980     public synchronized void
981     addFxSendCountListener(FxSendCountListener l) {
982     if(llFSC.isEmpty()) subscribe("FX_SEND_COUNT");
983     llFSC.add(l);
984     }
985    
986     /**
987     * Removes the specified listener.
988     * Listeners can be removed regardless of the connection state.
989     * @param l The <code>FxSendCountListener</code> to remove.
990     */
991     public synchronized void
992     removeFxSendCountListener(FxSendCountListener l) {
993     boolean b = llFSC.remove(l);
994     if(b && llFSC.isEmpty()) unsubscribe("FX_SEND_COUNT");
995     }
996    
997     /**
998     * Registers the specified listener for receiving event messages.
999     * Listeners can be registered regardless of the connection state.
1000     * @param l The <code>FxSendInfoListener</code> to register.
1001     */
1002     public synchronized void
1003     addFxSendInfoListener(FxSendInfoListener l) {
1004     if(llFSI.isEmpty()) subscribe("FX_SEND_INFO");
1005     llFSI.add(l);
1006     }
1007    
1008     /**
1009     * Removes the specified listener.
1010     * Listeners can be removed regardless of the connection state.
1011     * @param l The <code>FxSendInfoListener</code> to remove.
1012     */
1013     public synchronized void
1014     removeFxSendInfoListener(FxSendInfoListener l) {
1015     boolean b = llFSI.remove(l);
1016     if(b && llFSI.isEmpty()) unsubscribe("FX_SEND_INFO");
1017     }
1018    
1019     /**
1020     * Registers the specified listener for receiving event messages.
1021     * Listeners can be registered regardless of the connection state.
1022     * @param l The <code>ItemCountListener</code> to register.
1023     */
1024     public synchronized void
1025     addMidiDeviceCountListener(ItemCountListener l) {
1026     if(llMIDC.isEmpty()) subscribe("MIDI_INPUT_DEVICE_COUNT");
1027     llMIDC.add(l);
1028     }
1029    
1030     /**
1031     * Removes the specified listener.
1032     * Listeners can be removed regardless of the connection state.
1033     * @param l The <code>ItemCountListener</code> to remove.
1034     */
1035     public synchronized void
1036     removeMidiDeviceCountListener(ItemCountListener l) {
1037     boolean b = llMIDC.remove(l);
1038     if(b && llMIDC.isEmpty()) unsubscribe("MIDI_INPUT_DEVICE_COUNT");
1039     }
1040    
1041     /**
1042     * Registers the specified listener for receiving event messages.
1043     * Listeners can be registered regardless of the connection state.
1044     * @param l The <code>ItemInfoListener</code> to register.
1045     */
1046     public synchronized void
1047     addMidiDeviceInfoListener(ItemInfoListener l) {
1048     if(llMIDI.isEmpty()) subscribe("MIDI_INPUT_DEVICE_INFO");
1049     llMIDI.add(l);
1050     }
1051    
1052     /**
1053     * Removes the specified listener.
1054     * Listeners can be removed regardless of the connection state.
1055     * @param l The <code>ItemInfoListener</code> to remove.
1056     */
1057     public synchronized void
1058     removeMidiDeviceInfoListener(ItemInfoListener l) {
1059     boolean b = llMIDI.remove(l);
1060     if(b && llMIDI.isEmpty()) unsubscribe("MIDI_INPUT_DEVICE_INFO");
1061     }
1062    
1063     /**
1064     * Registers the specified listener for receiving event messages.
1065     * Listeners can be registered regardless of the connection state.
1066 iliev 596 * @param l The <code>MiscellaneousListener</code> to register.
1067     */
1068     public synchronized void
1069     addMiscellaneousListener(MiscellaneousListener l) {
1070     if(llM.isEmpty()) subscribe("MISCELLANEOUS");
1071     llM.add(l);
1072     }
1073    
1074     /**
1075     * Removes the specified listener.
1076     * Listeners can be removed regardless of the connection state.
1077     * @param l The <code>MiscellaneousListener</code> to remove.
1078     */
1079     public synchronized void
1080     removeMiscellaneousListener(MiscellaneousListener l) {
1081     boolean b = llM.remove(l);
1082     if(b && llM.isEmpty()) unsubscribe("MISCELLANEOUS");
1083     }
1084    
1085     /**
1086     * Registers the specified listener for receiving event messages.
1087     * Listeners can be registered regardless of the connection state.
1088     * @param l The <code>StreamCountListener</code> to register.
1089     */
1090     public synchronized void
1091     addStreamCountListener(StreamCountListener l) {
1092     if(llSC.isEmpty()) subscribe("STREAM_COUNT");
1093     llSC.add(l);
1094     }
1095    
1096     /**
1097     * Removes the specified listener.
1098     * Listeners can be removed regardless of the connection state.
1099     * @param l The <code>StreamCountListener</code> to remove.
1100     */
1101     public synchronized void
1102     removeStreamCountListener(StreamCountListener l) {
1103     boolean b = llSC.remove(l);
1104     if(b && llSC.isEmpty()) unsubscribe("STREAM_COUNT");
1105     }
1106    
1107     /**
1108     * Registers the specified listener for receiving event messages.
1109     * Listeners can be registered regardless of the connection state.
1110     * @param l The <code>VoiceCountListener</code> to register.
1111     */
1112     public synchronized void
1113     addVoiceCountListener(VoiceCountListener l) {
1114     if(llVC.isEmpty()) subscribe("VOICE_COUNT");
1115     llVC.add(l);
1116     }
1117    
1118     /**
1119     * Removes the specified listener.
1120     * Listeners can be removed regardless of the connection state.
1121     * @param l The <code>VoiceCountListener</code> to remove.
1122     */
1123     public synchronized void
1124     removeVoiceCountListener(VoiceCountListener l) {
1125     boolean b = llVC.remove(l);
1126     if(b && llVC.isEmpty()) unsubscribe("VOICE_COUNT");
1127     }
1128    
1129     /**
1130 iliev 784 * Registers the specified listener for receiving event messages.
1131     * Listeners can be registered regardless of the connection state.
1132     * @param l The <code>TotalVoiceCountListener</code> to register.
1133     */
1134     public synchronized void
1135     addTotalVoiceCountListener(TotalVoiceCountListener l) {
1136     if(llTVC.isEmpty()) subscribe("TOTAL_VOICE_COUNT");
1137     llTVC.add(l);
1138     }
1139    
1140     /**
1141     * Removes the specified listener.
1142     * Listeners can be removed regardless of the connection state.
1143     * @param l The <code>TotalVoiceCountListener</code> to remove.
1144     */
1145     public synchronized void
1146     removeTotalVoiceCountListener(TotalVoiceCountListener l) {
1147     boolean b = llTVC.remove(l);
1148     if(b && llTVC.isEmpty()) unsubscribe("TOTAL_VOICE_COUNT");
1149     }
1150    
1151     /**
1152 iliev 1139 * Registers the specified listener for receiving event messages.
1153     * Listeners can be registered regardless of the connection state.
1154     * @param l The <code>ItemCountListener</code> to register.
1155     */
1156     public synchronized void
1157     addMidiInstrumentMapCountListener(ItemCountListener l) {
1158     if(llMIMC.isEmpty()) subscribe("MIDI_INSTRUMENT_MAP_COUNT");
1159     llMIMC.add(l);
1160     }
1161    
1162     /**
1163     * Removes the specified listener.
1164     * Listeners can be removed regardless of the connection state.
1165     * @param l The <code>ItemCountListener</code> to remove.
1166     */
1167     public synchronized void
1168     removeMidiInstrumentMapCountListener(ItemCountListener l) {
1169     boolean b = llMIMC.remove(l);
1170     if(b && llMIMC.isEmpty()) unsubscribe("MIDI_INSTRUMENT_MAP_COUNT");
1171     }
1172    
1173     /**
1174     * Registers the specified listener for receiving event messages.
1175     * Listeners can be registered regardless of the connection state.
1176     * @param l The <code>ItemInfoListener</code> to register.
1177     */
1178     public synchronized void
1179     addMidiInstrumentMapInfoListener(ItemInfoListener l) {
1180     if(llMIMI.isEmpty()) subscribe("MIDI_INSTRUMENT_MAP_INFO");
1181     llMIMI.add(l);
1182     }
1183    
1184     /**
1185     * Removes the specified listener.
1186     * Listeners can be removed regardless of the connection state.
1187     * @param l The <code>ItemInfoListener</code> to remove.
1188     */
1189     public synchronized void
1190     removeMidiInstrumentMapInfoListener(ItemInfoListener l) {
1191     boolean b = llMIMI.remove(l);
1192     if(b && llMIMI.isEmpty()) unsubscribe("MIDI_INSTRUMENT_MAP_INFO");
1193     }
1194    
1195     /**
1196     * Registers the specified listener for receiving event messages.
1197     * Listeners can be registered regardless of the connection state.
1198     * @param l The <code>MidiInstrumentCountListener</code> to register.
1199     */
1200     public synchronized void
1201     addMidiInstrumentCountListener(MidiInstrumentCountListener l) {
1202     if(llMIC.isEmpty()) subscribe("MIDI_INSTRUMENT_COUNT");
1203     llMIC.add(l);
1204     }
1205    
1206     /**
1207     * Removes the specified listener.
1208     * Listeners can be removed regardless of the connection state.
1209     * @param l The <code>MidiInstrumentCountListener</code> to remove.
1210     */
1211     public synchronized void
1212     removeMidiInstrumentCountListener(MidiInstrumentCountListener l) {
1213     boolean b = llMIC.remove(l);
1214     if(b && llMIC.isEmpty()) unsubscribe("MIDI_INSTRUMENT_COUNT");
1215     }
1216    
1217     /**
1218     * Registers the specified listener for receiving event messages.
1219     * Listeners can be registered regardless of the connection state.
1220     * @param l The <code>MidiInstrumentInfoListener</code> to register.
1221     */
1222     public synchronized void
1223     addMidiInstrumentInfoListener(MidiInstrumentInfoListener l) {
1224     if(llMII.isEmpty()) subscribe("MIDI_INSTRUMENT_INFO");
1225     llMII.add(l);
1226     }
1227    
1228     /**
1229     * Removes the specified listener.
1230     * Listeners can be removed regardless of the connection state.
1231     * @param l The <code>MidiInstrumentInfoListener</code> to remove.
1232     */
1233     public synchronized void
1234     removeMidiInstrumentInfoListener(MidiInstrumentInfoListener l) {
1235     boolean b = llMII.remove(l);
1236     if(b && llMII.isEmpty()) unsubscribe("MIDI_INSTRUMENT_INFO");
1237     }
1238    
1239     /**
1240     * Registers the specified listener for receiving event messages.
1241     * Listeners can be registered regardless of the connection state.
1242 iliev 1202 * @param l The <code>InstrumentsDbListener</code> to register.
1243     */
1244     public synchronized void
1245     addInstrumentsDbListener(InstrumentsDbListener l) {
1246     if(llID.isEmpty()) {
1247     subscribe("DB_INSTRUMENT_DIRECTORY_COUNT");
1248     subscribe("DB_INSTRUMENT_DIRECTORY_INFO");
1249     subscribe("DB_INSTRUMENT_COUNT");
1250     subscribe("DB_INSTRUMENT_INFO");
1251     subscribe("DB_INSTRUMENTS_JOB_INFO");
1252     }
1253     llID.add(l);
1254     }
1255    
1256     /**
1257     * Removes the specified listener.
1258     * Listeners can be removed regardless of the connection state.
1259     * @param l The <code>InstrumentsDbListener</code> to remove.
1260     */
1261     public synchronized void
1262     removeInstrumentsDbListener(InstrumentsDbListener l) {
1263     boolean b = llID.remove(l);
1264     if(b && llID.isEmpty()) {
1265     unsubscribe("DB_INSTRUMENT_DIRECTORY_COUNT");
1266     unsubscribe("DB_INSTRUMENT_DIRECTORY_INFO");
1267     unsubscribe("DB_INSTRUMENT_COUNT");
1268     unsubscribe("DB_INSTRUMENT_INFO");
1269     unsubscribe("DB_INSTRUMENTS_JOB_INFO");
1270     }
1271     }
1272    
1273     /**
1274     * Registers the specified listener for receiving event messages.
1275     * Listeners can be registered regardless of the connection state.
1276 iliev 1139 * @param l The <code>GlobalInfoListener</code> to register.
1277     */
1278     public synchronized void
1279     addGlobalInfoListener(GlobalInfoListener l) {
1280     if(llGI.isEmpty()) subscribe("GLOBAL_INFO");
1281     llGI.add(l);
1282     }
1283    
1284     /**
1285     * Removes the specified listener.
1286     * Listeners can be removed regardless of the connection state.
1287     * @param l The <code>GlobalInfoListener</code> to remove.
1288     */
1289     public synchronized void
1290     removeGlobalInfoListener(GlobalInfoListener l) {
1291     boolean b = llGI.remove(l);
1292     if(b && llGI.isEmpty()) unsubscribe("GLOBAL_INFO");
1293     }
1294    
1295     /**
1296 iliev 596 * Gets the number of all audio output drivers currently
1297     * available for the LinuxSampler instance.
1298     * @return The number of all audio output drivers currently
1299     * available for the LinuxSampler instance.
1300     * @throws IOException If some I/O error occurs.
1301     * @throws LscpException If LSCP protocol corruption occurs.
1302     * @throws LSException If some other error occurs.
1303     */
1304     public synchronized int
1305     getAudioOutputDriverCount() throws IOException, LscpException, LSException {
1306     verifyConnection();
1307     out.writeLine("GET AVAILABLE_AUDIO_OUTPUT_DRIVERS");
1308 iliev 1139
1309     if(getPrintOnlyMode()) return -1;
1310    
1311 iliev 596 String s = getSingleLineResultSet().getResult();
1312     return parseInt(s);
1313     }
1314 iliev 671
1315 iliev 596 /**
1316     * Gets all audio output drivers currently available for the LinuxSampler instance.
1317     *
1318 iliev 671 * @return <code>AudioOutputDriver</code> array containing all audio output drivers
1319     * currently available for the LinuxSampler instance.
1320 iliev 596 *
1321     * @throws IOException If an I/O error occurs.
1322     * @throws LscpException If LSCP protocol corruption occurs.
1323     * @throws LSException If some other error occurs.
1324     */
1325 iliev 671 public synchronized AudioOutputDriver[]
1326 iliev 596 getAudioOutputDrivers() throws IOException, LscpException, LSException {
1327 iliev 671 String[] drivers = getAudioOutputDriverNames();
1328 iliev 1139 if(getPrintOnlyMode()) return null;
1329    
1330 iliev 671 AudioOutputDriver[] aod = new AudioOutputDriver[drivers.length];
1331    
1332     for(int i = 0; i < aod.length; i++) aod[i] = getAudioOutputDriverInfo(drivers[i]);
1333    
1334     return aod;
1335     }
1336    
1337     /**
1338     * Gets all audio output drivers currently available for the LinuxSampler instance.
1339     *
1340     * @return <code>String</code> array containing all audio output drivers currently
1341     * available for the LinuxSampler instance.
1342     *
1343     * @throws IOException If an I/O error occurs.
1344     * @throws LscpException If LSCP protocol corruption occurs.
1345     * @throws LSException If some other error occurs.
1346     */
1347     private synchronized String[]
1348     getAudioOutputDriverNames() throws IOException, LscpException, LSException {
1349 iliev 596 verifyConnection();
1350     out.writeLine("LIST AVAILABLE_AUDIO_OUTPUT_DRIVERS");
1351 iliev 1139 if(getPrintOnlyMode()) return null;
1352 iliev 596 return parseList(getSingleLineResultSet().getResult());
1353     }
1354    
1355     /**
1356     * Gets detailed information about a specific audio output driver.
1357     * @param driverName The name of the audio output driver.
1358 iliev 1326 * @param depList An optional list of dependences parameters.
1359 iliev 596 * @return An <code>AudioOutputDriver</code> object containing
1360     * information about the specified audio output driver.
1361     *
1362     * @throws IOException If an I/O error occurs.
1363     * @throws LscpException If LSCP protocol corruption occurs.
1364     * @throws LSException If there is no driver with name <code>driverName</code>.
1365     *
1366 iliev 671 * @see #getAudioOutputDriverNames
1367 iliev 596 */
1368 iliev 1326 public synchronized AudioOutputDriver
1369     getAudioOutputDriverInfo(String driverName, Parameter... depList)
1370     throws IOException, LscpException, LSException {
1371    
1372 iliev 596 verifyConnection();
1373     out.writeLine("GET AUDIO_OUTPUT_DRIVER INFO " + driverName);
1374 iliev 1139 if(getPrintOnlyMode()) return null;
1375    
1376 iliev 596 ResultSet rs = getMultiLineResultSet();
1377     AudioOutputDriver aod = new AudioOutputDriver(rs.getMultiLineResult());
1378     aod.setName(driverName);
1379    
1380     for(String s : aod.getParameterNames())
1381 iliev 1326 aod.addParameter(getAudioOutputDriverParameterInfo(driverName, s, depList));
1382 iliev 596
1383     return aod;
1384     }
1385    
1386     /**
1387     * Gets detailed information about a specific audio output driver parameter.
1388     *
1389     * @param driver The name of the audio output driver.
1390     * @param param A specific parameter name for which information should be obtained.
1391     * @param deplist An optional list of parameters on which the sought parameter
1392     * <code>param</code> depends on. <code>Parameter</code> instances can be
1393     * easily created using {@link ParameterFactory} factory.
1394     *
1395     * @return <code>Parameter</code> object containing
1396     * information about the specified audio output driver parameter.
1397     *
1398     * @throws IOException If an I/O error occurs.
1399     * @throws LscpException If LSCP protocol corruption occurs.
1400     * @throws LSException If <code>driver</code> is not a valid driver name
1401     * or <code>param</code> is not a valid parameter for the specified driver.
1402     *
1403     * @see #getAudioOutputDrivers
1404     * @see #getAudioOutputDriverInfo
1405     * @see ParameterFactory
1406     */
1407     public synchronized Parameter
1408     getAudioOutputDriverParameterInfo(String driver, String param, Parameter... deplist)
1409     throws IOException, LscpException, LSException {
1410    
1411     verifyConnection();
1412     StringBuffer args = new StringBuffer(driver);
1413     args.append(' ').append(param);
1414    
1415 iliev 1326 for(Parameter p : deplist) {
1416     if(p.getValue() == null) continue;
1417 iliev 596 args.append(' ').append(p.getName()).append('=').append(p.getStringValue());
1418 iliev 1326 }
1419 iliev 596
1420     out.writeLine("GET AUDIO_OUTPUT_DRIVER_PARAMETER INFO " + args.toString());
1421 iliev 1139 if(getPrintOnlyMode()) return null;
1422 iliev 596
1423     ResultSet rs = getMultiLineResultSet();
1424    
1425     String[] lnS = rs.getMultiLineResult();
1426     ParameterType type = parseType(lnS);
1427     boolean multi = parseMultiplicity(lnS);
1428     Parameter prm;
1429    
1430     switch(type) {
1431     case BOOL:
1432     if(!multi) prm = new BoolParameter(lnS);
1433     else prm = new BoolListParameter(lnS);
1434     prm.setName(param);
1435 iliev 784 prm.setValue(prm.getDefault());
1436 iliev 596 return prm;
1437     case INT:
1438     if(!multi) prm = new IntParameter(lnS);
1439     else prm = new IntListParameter(lnS);
1440     prm.setName(param);
1441 iliev 784 prm.setValue(prm.getDefault());
1442 iliev 596 return prm;
1443     case FLOAT:
1444     if(!multi) prm = new FloatParameter(lnS);
1445     else prm = new FloatListParameter(lnS);
1446     prm.setName(param);
1447 iliev 784 prm.setValue(prm.getDefault());
1448 iliev 596 return prm;
1449     case STRING:
1450     if(!multi) prm = new StringParameter(lnS);
1451     else prm = new StringListParameter(lnS);
1452     prm.setName(param);
1453 iliev 784 prm.setValue(prm.getDefault());
1454 iliev 596 return prm;
1455     default: throw new LscpException(LscpI18n.getLogMsg("Client.unknownPrmType!"));
1456     }
1457     }
1458    
1459     /**
1460     * Creates a new audio output device for the desired audio output system.
1461     * @param aoDriver The desired audio output system.
1462     * @param paramList An optional list of driver specific parameters. <code>Parameter</code>
1463     * instances can be easily created using {@link ParameterFactory} factory.
1464     * @return The numerical ID of the newly created device.
1465     * @throws IOException If some I/O error occurs.
1466     * @throws LSException If the creation of the new audio output device failed.
1467     * @throws LscpException If LSCP protocol corruption occurs.
1468     * @see #getAudioOutputDrivers
1469     * @see #getAudioOutputDriverInfo
1470     * @see ParameterFactory
1471     */
1472     public synchronized int
1473     createAudioOutputDevice(String aoDriver, Parameter... paramList)
1474     throws IOException, LSException, LscpException {
1475    
1476     verifyConnection();
1477     StringBuffer args = new StringBuffer(aoDriver);
1478    
1479 iliev 1326 for(Parameter p : paramList) {
1480     if(p.getValue() == null) continue;
1481 iliev 596 args.append(' ').append(p.getName()).append('=').append(p.getStringValue());
1482 iliev 1326 }
1483 iliev 596
1484     out.writeLine("CREATE AUDIO_OUTPUT_DEVICE " + args.toString());
1485 iliev 1139 if(getPrintOnlyMode()) return -1;
1486    
1487 iliev 596 ResultSet rs = getEmptyResultSet();
1488    
1489     return rs.getIndex();
1490     }
1491    
1492     /**
1493     * Destroys already created audio output device.
1494 iliev 1139 * @param deviceId The ID of the audio output device to be destroyed.
1495 iliev 596 * @throws IOException If some I/O error occurs.
1496     * @throws LSException If the destroying of the audio output device failed.
1497     * @throws LscpException If LSCP protocol corruption occurs.
1498     * @see #getAudioOutputDevices
1499     */
1500     public synchronized void
1501 iliev 1139 destroyAudioOutputDevice(int deviceId) throws IOException, LSException, LscpException {
1502 iliev 596 verifyConnection();
1503 iliev 1139 out.writeLine("DESTROY AUDIO_OUTPUT_DEVICE " + deviceId);
1504     if(getPrintOnlyMode()) return;
1505    
1506 iliev 596 ResultSet rs = getEmptyResultSet();
1507     }
1508    
1509 iliev 784 /**
1510     * Enables/disables the specified audio output device.
1511 iliev 1139 * @param deviceId The ID of the audio output device to be enabled/disabled.
1512 iliev 784 * @param enable If <code>true</code> the audio output device is enabled,
1513     * else the device is disabled.
1514     * @throws IOException If some I/O error occurs.
1515     * @throws LSException If there is no audio output
1516 iliev 1139 * device with numerical ID <code>deviceId</code>.
1517 iliev 784 * @throws LscpException If LSCP protocol corruption occurs.
1518     */
1519     public void
1520 iliev 1139 enableAudioOutputDevice(int deviceId, boolean enable)
1521 iliev 784 throws IOException, LSException, LscpException {
1522    
1523 iliev 1139 setAudioOutputDeviceParameter(deviceId, new BoolParameter("ACTIVE", enable));
1524 iliev 784 }
1525    
1526 iliev 596 /**
1527     * Gets the current number of all created audio output devices.
1528     * @return The current number of all created audio output devices.
1529     * @throws IOException If some I/O error occurs.
1530     * @throws LscpException If LSCP protocol corruption occurs.
1531     * @throws LSException If some other error occurs.
1532     */
1533     public synchronized int
1534     getAudioOutputDeviceCount() throws IOException, LscpException, LSException {
1535     verifyConnection();
1536     out.writeLine("GET AUDIO_OUTPUT_DEVICES");
1537 iliev 1139 if(getPrintOnlyMode()) return -1;
1538    
1539 iliev 596 String s = getSingleLineResultSet().getResult();
1540     return parseInt(s);
1541     }
1542    
1543     /**
1544 iliev 784 * Gets a list of all created audio output devices.
1545     * @return An <code>AudioOutputDevice</code> array
1546     * providing all created audio output devices.
1547     * @throws IOException If some I/O error occurs.
1548     * @throws LscpException If LSCP protocol corruption occurs.
1549     * @throws LSException If some other error occurs.
1550     */
1551     public synchronized AudioOutputDevice[]
1552     getAudioOutputDevices() throws IOException, LscpException, LSException {
1553     Integer[] idS = getAudioOutputDeviceIDs();
1554 iliev 1139 if(getPrintOnlyMode()) return null;
1555    
1556 iliev 784 AudioOutputDevice[] devices = new AudioOutputDevice[idS.length];
1557    
1558     for(int i = 0; i < devices.length; i++)
1559     devices[i] = getAudioOutputDeviceInfo(idS[i]);
1560    
1561     return devices;
1562     }
1563    
1564     /**
1565 iliev 596 * Gets a list of numerical IDs of all created audio output devices.
1566 iliev 784 * @return An <code>Integer</code> array providing the numerical IDs of
1567 iliev 596 * all created audio output devices.
1568     * @throws IOException If some I/O error occurs.
1569     * @throws LscpException If LSCP protocol corruption occurs.
1570     * @throws LSException If some other error occurs.
1571     */
1572     public synchronized Integer[]
1573 iliev 784 getAudioOutputDeviceIDs() throws IOException, LscpException, LSException {
1574 iliev 596 verifyConnection();
1575     out.writeLine("LIST AUDIO_OUTPUT_DEVICES");
1576 iliev 1139 if(getPrintOnlyMode()) return null;
1577    
1578 iliev 596 return parseIntList(getSingleLineResultSet().getResult());
1579     }
1580    
1581     /**
1582     * Gets the current settings of a specific, already created audio output device.
1583     *
1584 iliev 1139 * @param deviceId Specifies the numerical ID of the audio output device.
1585 iliev 596 *
1586     * @return An <code>AudioOutputDevice</code> instance containing information
1587     * about the specified device.
1588     *
1589     * @throws IOException If some I/O error occurs.
1590     * @throws LscpException If LSCP protocol corruption occurs.
1591     * @throws LSException If there is no audio output device
1592 iliev 1139 * with device id <code>deviceId</code>.
1593 iliev 596 *
1594     * @see #getAudioOutputDevices
1595     */
1596     public synchronized AudioOutputDevice
1597 iliev 1139 getAudioOutputDeviceInfo(int deviceId) throws IOException, LscpException, LSException {
1598 iliev 596 verifyConnection();
1599 iliev 1139 out.writeLine("GET AUDIO_OUTPUT_DEVICE INFO " + deviceId);
1600     if(getPrintOnlyMode()) return null;
1601 iliev 596
1602     ResultSet rs = getMultiLineResultSet();
1603    
1604     String[] lnS = rs.getMultiLineResult();
1605    
1606     AudioOutputDevice aod = new AudioOutputDevice();
1607 iliev 1139 aod.setDeviceId(deviceId);
1608 iliev 596 Parameter<Integer> channels;
1609     Parameter<Integer> samplerate;
1610    
1611     String drv = getCategoryInfo(lnS, "DRIVER");
1612     aod.setDriverName(drv);
1613    
1614     for(String s : lnS) {
1615     if(s.startsWith("CHANNELS: ")) {
1616     channels = (Parameter<Integer>)
1617     getAudioOutputDriverParameterInfo(drv, "CHANNELS");
1618    
1619     s = s.substring("CHANNELS: ".length(), s.length());
1620     channels.parseValue(s);
1621     aod.setChannelsParameter(channels);
1622 iliev 784 int count = channels.getValue() > 0 ? channels.getValue() : 0;
1623     AudioOutputChannel[] aoc = new AudioOutputChannel[count];
1624     for(int i = 0; i < count; i++) {
1625 iliev 1139 aoc[i] = getAudioOutputChannelInfo(deviceId, i);
1626 iliev 784 }
1627     aod.setAudioChannels(aoc);
1628 iliev 596 } else if(s.startsWith("SAMPLERATE: ")) {
1629     samplerate = (Parameter<Integer>)
1630     getAudioOutputDriverParameterInfo(drv, "SAMPLERATE");
1631    
1632     s = s.substring("SAMPLERATE: ".length(), s.length());
1633     samplerate.parseValue(s);
1634     aod.setSampleRateParameter(samplerate);
1635     } else if(s.startsWith("ACTIVE: ")) {
1636     s = s.substring("ACTIVE: ".length(), s.length());
1637     aod.setActive(Boolean.parseBoolean(s));
1638     } else if(s.startsWith("DRIVER: ")) {
1639    
1640     } else {
1641     int i = s.indexOf(": ");
1642     if(i == -1) throw new LscpException (
1643     LscpI18n.getLogMsg("CommandFailed!")
1644     );
1645    
1646     Parameter prm =
1647     getAudioOutputDriverParameterInfo(drv, s.substring(0, i));
1648    
1649     s = s.substring(i + 2);
1650     prm.parseValue(s);
1651    
1652     aod.addParameter(prm);
1653     }
1654     }
1655    
1656     return aod;
1657     }
1658    
1659     /**
1660     * Alters a specific setting of a created audio output device.
1661     *
1662 iliev 1139 * @param deviceId The numerical ID of the audio output device.
1663 iliev 596 * @param prm A <code>Parameter</code> instance containing the name of the parameter
1664     * and the new value for this parameter.
1665     *
1666     * @throws IOException If some I/O error occurs.
1667     * @throws LscpException If LSCP protocol corruption occurs.
1668     * @throws LSException If
1669     * <ul>
1670 iliev 1139 * <li>There is no audio output device with numerical ID <code>deviceId</code>;
1671 iliev 596 * <li>There is no device parameter with the specified name;
1672     * <li>The device parameter is readonly;
1673     * <li>The device parameter is from different type.
1674     * </ul>
1675     *
1676     * @see #getAudioOutputDevices
1677     * @see #getAudioOutputDeviceInfo
1678     */
1679     public synchronized void
1680 iliev 1139 setAudioOutputDeviceParameter(int deviceId, Parameter prm)
1681 iliev 596 throws IOException, LscpException, LSException {
1682    
1683     verifyConnection();
1684     String kv = prm.getName() + '=' + prm.getStringValue();
1685 iliev 1139 out.writeLine("SET AUDIO_OUTPUT_DEVICE_PARAMETER " + deviceId + ' ' + kv);
1686     if(getPrintOnlyMode()) return;
1687 iliev 596
1688     ResultSet rs = getEmptyResultSet();
1689     }
1690    
1691     /**
1692 iliev 1139 * Changes the channel number of the speicifed audio output device.
1693     * @param deviceId The numerical ID of the audio output device.
1694 iliev 784 * @param channels The new number of audio output channels.
1695     *
1696     * @throws IOException If an I/O error occurs.
1697     * @throws LscpException If LSCP protocol corruption occurs.
1698 iliev 1139 * @throws LSException If there is no device with ID <code>deviceId</code> or
1699 iliev 784 * if <code>channels</code> number is out of range.
1700     *
1701     * @see #getAudioOutputChannelInfo
1702     */
1703     public synchronized void
1704 iliev 1139 setAudioOutputChannelCount(int deviceId, int channels)
1705 iliev 784 throws IOException, LscpException, LSException {
1706    
1707 iliev 1139 setAudioOutputDeviceParameter(deviceId, new IntParameter("CHANNELS", channels));
1708 iliev 784 }
1709    
1710     /**
1711 iliev 596 * Gets information about an audio channel.
1712     *
1713 iliev 1139 * @param deviceId The numerical ID of the audio output device.
1714 iliev 596 * @param audioChn The audio channel number.
1715     *
1716     * @return An <code>AudioOutputChannel</code> instance containing the
1717     * information about the specified audio output channel.
1718     *
1719     * @throws IOException If some I/O error occurs.
1720     * @throws LscpException If LSCP protocol corruption occurs.
1721     * @throws LSException If
1722     * <ul>
1723 iliev 1139 * <li>There is no audio output device with numerical ID <code>deviceId</code>;
1724 iliev 596 * <li><code>audioChn</code> is not a valid channel number;
1725     * </ul>
1726     *
1727     * @see #getAudioOutputDevices
1728     * @see #getAudioOutputDeviceInfo
1729     */
1730     public synchronized AudioOutputChannel
1731 iliev 1139 getAudioOutputChannelInfo(int deviceId, int audioChn)
1732 iliev 596 throws IOException, LscpException, LSException {
1733    
1734     verifyConnection();
1735 iliev 1139 out.writeLine("GET AUDIO_OUTPUT_CHANNEL INFO " + deviceId + ' ' + audioChn);
1736     if(getPrintOnlyMode()) return null;
1737 iliev 596
1738     ResultSet rs = getMultiLineResultSet();
1739    
1740     AudioOutputChannel aoc = new AudioOutputChannel();
1741    
1742     String[] lnS = rs.getMultiLineResult();
1743     for(String s : lnS) {
1744     if(s.startsWith("NAME: ")) {
1745 iliev 784 s = s.substring("NAME: ".length());
1746     Parameter<String> prm = getAudioOutputChannelParameterInfo (
1747 iliev 1139 deviceId, audioChn, "NAME"
1748 iliev 784 );
1749     prm.setValue(removeQuotation(s));
1750     aoc.setNameParameter(prm);
1751 iliev 596 } else if(s.startsWith("IS_MIX_CHANNEL: ")) {
1752     s = s.substring("IS_MIX_CHANNEL: ".length());
1753 iliev 784 Parameter<Boolean> prm = getAudioOutputChannelParameterInfo (
1754 iliev 1139 deviceId, audioChn, "IS_MIX_CHANNEL"
1755 iliev 784 );
1756     prm.setValue(Boolean.parseBoolean(s));
1757     aoc.setMixChannelParameter(prm);
1758 iliev 596 } else if(s.startsWith("MIX_CHANNEL_DESTINATION: ")) {
1759     s = s.substring("MIX_CHANNEL_DESTINATION: ".length());
1760 iliev 784 Parameter<Integer> prm = getAudioOutputChannelParameterInfo (
1761 iliev 1139 deviceId, audioChn, "MIX_CHANNEL_DESTINATION"
1762 iliev 784 );
1763     prm.setValue(parseInt(s));
1764     aoc.setMixChannelDestParameter(prm);
1765 iliev 596 } else {
1766     int i = s.indexOf(": ");
1767     if(i == -1) throw new LscpException (
1768     LscpI18n.getLogMsg("CommandFailed!")
1769     );
1770    
1771     Parameter prm = getAudioOutputChannelParameterInfo (
1772 iliev 1139 deviceId, audioChn, s.substring(0, i)
1773 iliev 596 );
1774    
1775     s = s.substring(i + 2);
1776     prm.parseValue(s);
1777    
1778     aoc.addParameter(prm);
1779     }
1780     }
1781    
1782     return aoc;
1783     }
1784    
1785     /**
1786     * Gets detailed information about a specific audio output channel parameter.
1787     *
1788 iliev 1139 * @param devId The numerical ID of the audio output device.
1789 iliev 596 * @param chan The audio channel number.
1790     * @param param a specific channel parameter name for which information should be obtained.
1791     *
1792     * @return An <code>Parameter</code> instance containing
1793     * information about the specified audio output channel parameter.
1794     *
1795     * @throws IOException If an I/O error occurs.
1796     * @throws LscpException If LSCP protocol corruption occurs.
1797     * @throws LSException If
1798     * <ul>
1799 iliev 1139 * <li><code>devId</code> is not a valid device ID;
1800 iliev 596 * <li><code>chan</code> is not a valid channel number;
1801     * <li>There is no channel parameter with the specified name.
1802     * </ul>
1803     *
1804     * @see #getAudioOutputDevices
1805     * @see #getAudioOutputChannelInfo
1806     */
1807     public synchronized Parameter
1808 iliev 1139 getAudioOutputChannelParameterInfo(int devId, int chan, String param)
1809 iliev 596 throws IOException, LscpException, LSException {
1810    
1811     verifyConnection();
1812 iliev 1139 String args = devId + " " + chan + " " + param;
1813 iliev 596 out.writeLine("GET AUDIO_OUTPUT_CHANNEL_PARAMETER INFO " + args);
1814 iliev 1139 if(getPrintOnlyMode()) return null;
1815 iliev 596
1816     ResultSet rs = getMultiLineResultSet();
1817    
1818     String[] lnS = rs.getMultiLineResult();
1819     ParameterType type = parseType(lnS);
1820     boolean multi = parseMultiplicity(lnS);
1821     Parameter prm;
1822    
1823     switch(type) {
1824     case BOOL:
1825     if(!multi) prm = new BoolParameter(lnS);
1826     else prm = new BoolListParameter(lnS);
1827     prm.setName(param);
1828     return prm;
1829     case INT:
1830     if(!multi) prm = new IntParameter(lnS);
1831     else prm = new IntListParameter(lnS);
1832     prm.setName(param);
1833     return prm;
1834     case FLOAT:
1835     if(!multi) prm = new FloatParameter(lnS);
1836     else prm = new FloatListParameter(lnS);
1837     prm.setName(param);
1838     return prm;
1839     case STRING:
1840     if(!multi) prm = new StringParameter(lnS);
1841     else prm = new StringListParameter(lnS);
1842     prm.setName(param);
1843     return prm;
1844     default: throw new LscpException(LscpI18n.getLogMsg("Client.unknownPrmType!"));
1845     }
1846     }
1847    
1848     /**
1849     * Alters a specific setting of an audio output channel.
1850     *
1851 iliev 1139 * @param devId The numerical ID of the audio device.
1852 iliev 596 * @param chn The audio channel number.
1853     * @param prm A <code>Parameter</code> instance containing the name of the parameter
1854     * and the new value for this parameter.
1855     *
1856     * @throws IOException If some I/O error occurs.
1857     * @throws LscpException If LSCP protocol corruption occurs.
1858     * @throws LSException If
1859     * <ul>
1860 iliev 1139 * <li>There is no audio output device with numerical ID <code>devId</code>;
1861 iliev 596 * <li><code>chn</code> is not a valid channel number;
1862     * <li>There is no channel parameter with the specified name;
1863     * <li>The channel parameter is readonly;
1864     * <li>The channel parameter is from different type.
1865     * </ul>
1866     *
1867     * @see #getAudioOutputDevices
1868     * @see #getAudioOutputChannelInfo
1869     */
1870     public synchronized void
1871 iliev 1139 setAudioOutputChannelParameter(int devId, int chn, Parameter prm)
1872 iliev 596 throws IOException, LscpException, LSException {
1873    
1874     verifyConnection();
1875 iliev 1139 String args = devId + " " + chn + " " + prm.getName() + '=' + prm.getStringValue();
1876 iliev 596 out.writeLine("SET AUDIO_OUTPUT_CHANNEL_PARAMETER " + args);
1877 iliev 1139 if(getPrintOnlyMode()) return;
1878 iliev 596
1879     ResultSet rs = getEmptyResultSet();
1880     }
1881    
1882     /**
1883     * Gets the current number of all MIDI input drivers.
1884     * @return The current number of all MIDI input drivers.
1885     * @throws IOException If some I/O error occurs.
1886     * @throws LscpException If LSCP protocol corruption occurs.
1887     * @throws LSException If some other error occurs.
1888     */
1889     public synchronized int
1890     getMidiInputDriverCount() throws IOException, LscpException, LSException {
1891     verifyConnection();
1892     out.writeLine("GET AVAILABLE_MIDI_INPUT_DRIVERS");
1893 iliev 1139 if(getPrintOnlyMode()) return -1;
1894    
1895 iliev 596 String s = getSingleLineResultSet().getResult();
1896     return parseInt(s);
1897     }
1898    
1899     /**
1900     * Gets all MIDI input drivers currently available for the LinuxSampler instance.
1901     *
1902 iliev 671 * @return <code>MidiInputDriver</code> array containing all MIDI input drivers currently
1903     * available for the LinuxSampler instance.
1904 iliev 596 *
1905     * @throws IOException If an I/O error occurs.
1906     * @throws LscpException If LSCP protocol corruption occurs.
1907     * @throws LSException If some other error occurs.
1908     */
1909 iliev 671 public synchronized MidiInputDriver[]
1910 iliev 596 getMidiInputDrivers() throws IOException, LscpException, LSException {
1911 iliev 671 String[] drivers = getMidiInputDriverNames();
1912 iliev 1139 if(getPrintOnlyMode()) return null;
1913    
1914 iliev 671 MidiInputDriver[] mid = new MidiInputDriver[drivers.length];
1915    
1916     for(int i = 0; i < mid.length; i++) mid[i] = getMidiInputDriverInfo(drivers[i]);
1917    
1918     return mid;
1919     }
1920    
1921     /**
1922     * Gets all MIDI input drivers currently available for the LinuxSampler instance.
1923     *
1924     * @return <code>String</code> array containing all MIDI input drivers currently available
1925     * for the LinuxSampler instance.
1926     *
1927     * @throws IOException If an I/O error occurs.
1928     * @throws LscpException If LSCP protocol corruption occurs.
1929     * @throws LSException If some other error occurs.
1930     */
1931     private synchronized String[]
1932     getMidiInputDriverNames() throws IOException, LscpException, LSException {
1933 iliev 596 verifyConnection();
1934     out.writeLine("LIST AVAILABLE_MIDI_INPUT_DRIVERS");
1935 iliev 1139 if(getPrintOnlyMode()) return null;
1936    
1937 iliev 596 return parseList(getSingleLineResultSet().getResult());
1938     }
1939    
1940     /**
1941     * Gets detailed information about a specific MIDI input driver.
1942     * @param driverName The name of the MIDI input driver.
1943 iliev 1326 * @param depList An optional list of dependences parameters.
1944 iliev 671 * @return A <code>MidiInputDriver</code> object containing
1945 iliev 596 * information about the specified MIDI input driver.
1946     *
1947     * @throws IOException If an I/O error occurs.
1948     * @throws LscpException If LSCP protocol corruption occurs.
1949     * @throws LSException If there is no driver with name <code>driverName</code>.
1950     *
1951 iliev 671 * @see #getMidiInputDriverNames
1952 iliev 596 */
1953 iliev 1326 public synchronized MidiInputDriver
1954     getMidiInputDriverInfo(String driverName, Parameter... depList)
1955     throws IOException, LscpException, LSException {
1956    
1957 iliev 596 verifyConnection();
1958     out.writeLine("GET MIDI_INPUT_DRIVER INFO " + driverName);
1959 iliev 1139 if(getPrintOnlyMode()) return null;
1960    
1961 iliev 596 ResultSet rs = getMultiLineResultSet();
1962    
1963     MidiInputDriver mid = new MidiInputDriver(rs.getMultiLineResult());
1964     mid.setName(driverName);
1965    
1966     for(String s : mid.getParameterNames())
1967 iliev 1326 mid.addParameter(getMidiInputDriverParameterInfo(driverName, s, depList));
1968 iliev 596
1969     return mid;
1970     }
1971    
1972     /**
1973     * Gets detailed information about a specific MIDI input driver parameter.
1974     *
1975     * @param driver The name of the MIDI input driver.
1976     * @param param a specific parameter name for which information should be obtained.
1977     * @param deplist An optional list of parameters on which the sought parameter
1978     * <code>param</code> depends on. <code>Parameter</code> instances can be
1979     * easily created using {@link ParameterFactory} factory.
1980     *
1981 iliev 671 * @return A <code>Parameter</code> object containing
1982 iliev 596 * information about the specified MIDI input driver parameter.
1983     *
1984     * @throws IOException If an I/O error occurs.
1985     * @throws LscpException If LSCP protocol corruption occurs.
1986     * @throws LSException If <code>driver</code> is not a valid driver name
1987     * or <code>param</code> is not a valid parameter for the specified driver.
1988     *
1989     * @see #getMidiInputDrivers
1990     * @see #getMidiInputDriverInfo
1991     * @see ParameterFactory
1992     */
1993     public synchronized Parameter
1994     getMidiInputDriverParameterInfo(String driver, String param, Parameter... deplist)
1995     throws IOException, LscpException, LSException {
1996    
1997     verifyConnection();
1998     StringBuffer args = new StringBuffer(driver);
1999     args.append(' ').append(param);
2000    
2001 iliev 1326 for(Parameter p : deplist) {
2002     if(p.getValue() == null) continue;
2003 iliev 596 args.append(' ').append(p.getName()).append('=').append(p.getStringValue());
2004 iliev 1326 }
2005 iliev 596
2006     out.writeLine("GET MIDI_INPUT_DRIVER_PARAMETER INFO " + args.toString());
2007 iliev 1139 if(getPrintOnlyMode()) return null;
2008 iliev 596
2009     ResultSet rs = getMultiLineResultSet();
2010    
2011     String[] lnS = rs.getMultiLineResult();
2012     ParameterType type = parseType(lnS);
2013     boolean multi = parseMultiplicity(lnS);
2014     Parameter prm;
2015    
2016     switch(type) {
2017     case BOOL:
2018     if(!multi) prm = new BoolParameter(lnS);
2019     else prm = new BoolListParameter(lnS);
2020     prm.setName(param);
2021 iliev 784 prm.setValue(prm.getDefault());
2022 iliev 596 return prm;
2023     case INT:
2024     if(!multi) prm = new IntParameter(lnS);
2025     else prm = new IntListParameter(lnS);
2026     prm.setName(param);
2027 iliev 784 prm.setValue(prm.getDefault());
2028 iliev 596 return prm;
2029     case FLOAT:
2030     if(!multi) prm = new FloatParameter(lnS);
2031     else prm = new FloatListParameter(lnS);
2032     prm.setName(param);
2033 iliev 784 prm.setValue(prm.getDefault());
2034 iliev 596 return prm;
2035     case STRING:
2036     if(!multi) prm = new StringParameter(lnS);
2037     else prm = new StringListParameter(lnS);
2038     prm.setName(param);
2039 iliev 784 prm.setValue(prm.getDefault());
2040 iliev 596 return prm;
2041     default: throw new LscpException(LscpI18n.getLogMsg("Client.unknownPrmType!"));
2042     }
2043     }
2044    
2045     /**
2046     * Creates a new MIDI input device.
2047     * @param miDriver The desired MIDI input system.
2048     * @param paramList An optional list of driver specific parameters. <code>Parameter</code>
2049     * instances can be easily created using {@link ParameterFactory} factory.
2050     * @return The numerical ID of the newly created device.
2051     * @throws IOException If some I/O error occurs.
2052     * @throws LSException If the creation of the new MIDI input device failed.
2053     * @throws LscpException If LSCP protocol corruption occurs.
2054     *
2055     * @see #getMidiInputDrivers
2056     * @see #getMidiInputDriverInfo
2057     * @see ParameterFactory
2058     */
2059     public synchronized int
2060     createMidiInputDevice(String miDriver, Parameter... paramList)
2061     throws IOException, LSException, LscpException {
2062    
2063     verifyConnection();
2064     StringBuffer args = new StringBuffer(miDriver);
2065    
2066 iliev 1326 for(Parameter p : paramList) {
2067     if(p.getValue() == null) continue;
2068 iliev 596 args.append(' ').append(p.getName()).append('=').append(p.getStringValue());
2069 iliev 1326 }
2070 iliev 596
2071     out.writeLine("CREATE MIDI_INPUT_DEVICE " + args.toString());
2072 iliev 1139 if(getPrintOnlyMode()) return -1;
2073    
2074 iliev 596 ResultSet rs = getEmptyResultSet();
2075    
2076     return rs.getIndex();
2077     }
2078    
2079     /**
2080     * Destroys already created MIDI input device.
2081 iliev 1139 * @param deviceId The numerical ID of the MIDI input device to be destroyed.
2082 iliev 596 * @throws IOException If some I/O error occurs.
2083     * @throws LSException If the destroying of the MIDI input device failed.
2084     * @throws LscpException If LSCP protocol corruption occurs.
2085     * @see #createMidiInputDevice
2086     * @see #getMidiInputDevices
2087     */
2088     public synchronized void
2089 iliev 1139 destroyMidiInputDevice(int deviceId) throws IOException, LSException, LscpException {
2090 iliev 596 verifyConnection();
2091 iliev 1139 out.writeLine("DESTROY MIDI_INPUT_DEVICE " + deviceId);
2092     if(getPrintOnlyMode()) return;
2093    
2094 iliev 596 ResultSet rs = getEmptyResultSet();
2095     }
2096    
2097 iliev 784 /**
2098     * Enables/disables the specified MIDI input device.
2099 iliev 1139 * @param deviceId The ID of the MIDI input device to be enabled/disabled.
2100 iliev 784 * @param enable If <code>true</code> the MIDI input device is enabled,
2101     * else the device is disabled.
2102     * @throws IOException If some I/O error occurs.
2103     * @throws LSException If there is no MIDI input
2104 iliev 1139 * device with numerical ID <code>deviceId</code>.
2105 iliev 784 * @throws LscpException If LSCP protocol corruption occurs.
2106     */
2107     public void
2108 iliev 1139 enableMidiInputDevice(int deviceId, boolean enable)
2109 iliev 784 throws IOException, LSException, LscpException {
2110    
2111 iliev 1139 setMidiInputDeviceParameter(deviceId, new BoolParameter("ACTIVE", enable));
2112 iliev 784 }
2113    
2114 iliev 596 /**
2115     * Gets the current number of all created MIDI input devices.
2116     * @return The current number of all created MIDI input devices.
2117     * @throws IOException If some I/O error occurs.
2118     * @throws LscpException If LSCP protocol corruption occurs.
2119     * @throws LSException If some other error occurs.
2120     */
2121     public synchronized int
2122     getMidiInputDeviceCount() throws IOException, LscpException, LSException {
2123     verifyConnection();
2124     out.writeLine("GET MIDI_INPUT_DEVICES");
2125 iliev 1139 if(getPrintOnlyMode()) return -1;
2126    
2127 iliev 596 String s = getSingleLineResultSet().getResult();
2128     return parseInt(s);
2129     }
2130    
2131     /**
2132 iliev 784 * Gets a list of all created MIDI input devices.
2133     * @return A <code>MidiInputDevice</code> array
2134     * providing all created MIDI input devices.
2135     * @throws IOException If some I/O error occurs.
2136     * @throws LscpException If LSCP protocol corruption occurs.
2137     * @throws LSException If some other error occurs.
2138     *
2139     * @see #createMidiInputDevice
2140     * @see #destroyMidiInputDevice
2141     */
2142     public synchronized MidiInputDevice[]
2143     getMidiInputDevices() throws IOException, LscpException, LSException {
2144     Integer[] idS = getMidiInputDeviceIDs();
2145 iliev 1139 if(getPrintOnlyMode()) return null;
2146    
2147 iliev 784 MidiInputDevice[] devices = new MidiInputDevice[idS.length];
2148    
2149     for(int i = 0; i < devices.length; i++)
2150     devices[i] = getMidiInputDeviceInfo(idS[i]);
2151    
2152     return devices;
2153     }
2154    
2155     /**
2156 iliev 596 * Gets a list of numerical IDs of all created MIDI input devices.
2157 iliev 784 * @return An <code>Integer</code> array providing the numerical IDs of
2158 iliev 596 * all created MIDI input devices.
2159     * @throws IOException If some I/O error occurs.
2160     * @throws LscpException If LSCP protocol corruption occurs.
2161     * @throws LSException If some other error occurs.
2162     *
2163     * @see #createMidiInputDevice
2164     * @see #destroyMidiInputDevice
2165     */
2166     public synchronized Integer[]
2167 iliev 784 getMidiInputDeviceIDs() throws IOException, LscpException, LSException {
2168 iliev 596 verifyConnection();
2169     out.writeLine("LIST MIDI_INPUT_DEVICES");
2170 iliev 1139 if(getPrintOnlyMode()) return null;
2171    
2172 iliev 596 return parseIntList(getSingleLineResultSet().getResult());
2173     }
2174    
2175     /**
2176     * Gets the current settings of a specific, already created MIDI input device.
2177     *
2178 iliev 1139 * @param deviceId Specifies the numerical ID of the MIDI input device.
2179 iliev 596 *
2180 iliev 1139 * @return A <code>MidiInputDevice</code> instance containing information
2181 iliev 596 * about the specified device.
2182     *
2183     * @throws IOException If some I/O error occurs.
2184     * @throws LscpException If LSCP protocol corruption occurs.
2185     * @throws LSException If there is no MIDI input device
2186 iliev 1139 * with device id <code>deviceId</code>.
2187 iliev 596 *
2188     * @see #getMidiInputDevices
2189     */
2190     public synchronized MidiInputDevice
2191 iliev 1139 getMidiInputDeviceInfo(int deviceId) throws IOException, LscpException, LSException {
2192 iliev 596 verifyConnection();
2193 iliev 1139 out.writeLine("GET MIDI_INPUT_DEVICE INFO " + deviceId);
2194     if(getPrintOnlyMode()) return null;
2195 iliev 596
2196     ResultSet rs = getMultiLineResultSet();
2197    
2198     String[] lnS = rs.getMultiLineResult();
2199    
2200     MidiInputDevice mid = new MidiInputDevice();
2201 iliev 1139 mid.setDeviceId(deviceId);
2202 iliev 596
2203     String drv = getCategoryInfo(lnS, "DRIVER");
2204     mid.setDriverName(drv);
2205    
2206     for(String s : lnS) {
2207     if(s.startsWith("DRIVER: ")) {
2208    
2209     } else if(s.startsWith("ACTIVE: ")) {
2210     s = s.substring("ACTIVE: ".length());
2211     mid.setActive(Boolean.parseBoolean(s));
2212 iliev 784 } else if(s.startsWith("PORTS: ")) {
2213     s = s.substring("PORTS: ".length());
2214     int ports = Parser.parseInt(s);
2215     MidiPort[] midiPorts = new MidiPort[ports > 0 ? ports : 0];
2216    
2217     for(int i = 0; i < midiPorts.length; i++)
2218 iliev 1139 midiPorts[i] = getMidiInputPortInfo(deviceId, i);
2219 iliev 784
2220     mid.setMidiPorts(midiPorts);
2221 iliev 596 } else {
2222     int i = s.indexOf(": ");
2223     if(i == -1) throw new LscpException (
2224     LscpI18n.getLogMsg("CommandFailed!")
2225     );
2226    
2227     Parameter prm =
2228     getMidiInputDriverParameterInfo(drv, s.substring(0, i));
2229    
2230     s = s.substring(i + 2);
2231     prm.parseValue(s);
2232    
2233     mid.addParameter(prm);
2234     }
2235     }
2236    
2237     return mid;
2238     }
2239    
2240     /**
2241     * Alters a specific setting of a created MIDI input device.
2242     *
2243 iliev 1139 * @param deviceId The numerical ID of the MIDI input device.
2244 iliev 596 * @param prm A <code>Parameter</code> instance containing the name of the parameter
2245     * and the new value for this parameter.
2246     *
2247     * @throws IOException If some I/O error occurs.
2248     * @throws LscpException If LSCP protocol corruption occurs.
2249     * @throws LSException If
2250     * <ul>
2251 iliev 1139 * <li>There is no MIDI input device with numerical ID <code>deviceId</code>;
2252 iliev 596 * <li>There is no device parameter with the specified name;
2253     * <li>The device parameter is readonly;
2254     * <li>The device parameter is from different type.
2255     * </ul>
2256     *
2257     * @see #getMidiInputDevices
2258     * @see #getMidiInputDeviceInfo
2259     */
2260     public synchronized void
2261 iliev 1139 setMidiInputDeviceParameter(int deviceId, Parameter prm)
2262 iliev 596 throws IOException, LscpException, LSException {
2263    
2264     verifyConnection();
2265     String kv = prm.getName() + '=' + prm.getStringValue();
2266 iliev 1139 out.writeLine("SET MIDI_INPUT_DEVICE_PARAMETER " + deviceId + ' ' + kv);
2267     if(getPrintOnlyMode()) return;
2268 iliev 596
2269     ResultSet rs = getEmptyResultSet();
2270     }
2271    
2272 iliev 784
2273 iliev 596 /**
2274 iliev 1139 * Changes the port number of the speicified MIDI input device.
2275     * @param deviceId The numerical ID of the MIDI input device.
2276 iliev 784 * @param ports The new number of MIDI input ports.
2277     *
2278     * @throws IOException If an I/O error occurs.
2279     * @throws LscpException If LSCP protocol corruption occurs.
2280 iliev 1139 * @throws LSException If there is no device with ID <code>deviceId</code> or
2281 iliev 784 * if <code>ports</code> number is out of range.
2282     *
2283     * @see #getMidiInputPortInfo
2284     */
2285     public synchronized void
2286 iliev 1139 setMidiInputPortCount(int deviceId, int ports)
2287 iliev 784 throws IOException, LscpException, LSException {
2288    
2289 iliev 1139 setMidiInputDeviceParameter(deviceId, new IntParameter("PORTS", ports));
2290 iliev 784 }
2291    
2292     /**
2293 iliev 596 * Gets detailed information about a specific MIDI input port.
2294 iliev 1139 * @param deviceId The numerical ID of the MIDI input device.
2295 iliev 596 * @param midiPort The MIDI input port number.
2296     *
2297     * @return A <code>MidiPort</code> instance containing
2298     * information about the specified MIDI input port.
2299     *
2300     * @throws IOException If an I/O error occurs.
2301     * @throws LscpException If LSCP protocol corruption occurs.
2302 iliev 1139 * @throws LSException If there is no device with ID <code>deviceId</code> or
2303 iliev 596 * if <code>midiPort</code> is not a valid MIDI port number.
2304     *
2305     * @see #getMidiInputDevices
2306     */
2307     public synchronized MidiPort
2308 iliev 1139 getMidiInputPortInfo(int deviceId, int midiPort)
2309 iliev 596 throws IOException, LscpException, LSException {
2310    
2311     verifyConnection();
2312 iliev 1139 out.writeLine("GET MIDI_INPUT_PORT INFO " + deviceId + " " + midiPort);
2313     if(getPrintOnlyMode()) return null;
2314    
2315 iliev 596 ResultSet rs = getMultiLineResultSet();
2316    
2317     MidiPort mp = new MidiPort();
2318     String[] lnS = rs.getMultiLineResult();
2319    
2320     for(String s : lnS) {
2321     if(s.startsWith("NAME: ")) {
2322 iliev 784 s = s.substring("NAME: ".length());
2323     Parameter prm = getMidiInputPortParameterInfo (
2324 iliev 1139 deviceId, midiPort, "NAME"
2325 iliev 784 );
2326     prm.setValue(removeQuotation(s));
2327     mp.setNameParameter(prm);
2328 iliev 596 } else {
2329     int i = s.indexOf(": ");
2330     if(i == -1) throw new LscpException (
2331     LscpI18n.getLogMsg("CommandFailed!")
2332     );
2333    
2334     Parameter prm = getMidiInputPortParameterInfo (
2335 iliev 1139 deviceId, midiPort, s.substring(0, i)
2336 iliev 596 );
2337    
2338     s = s.substring(i + 2);
2339     prm.parseValue(s);
2340    
2341     mp.addParameter(prm);
2342     }
2343     }
2344    
2345     return mp;
2346     }
2347    
2348     /**
2349     * Gets detailed information about a specific MIDI input port parameter.
2350     *
2351 iliev 1139 * @param deviceId The numerical ID of the MIDI input device.
2352 iliev 596 * @param port The MIDI port number.
2353     * @param param A specific parameter name for which information should be obtained.
2354     *
2355     * @return A <code>Parameter</code> instance containing
2356     * information about the specified MIDI input port parameter.
2357     *
2358     * @throws IOException If an I/O error occurs.
2359     * @throws LscpException If LSCP protocol corruption occurs.
2360     * @throws LSException If
2361     * <ul>
2362 iliev 1139 * <li>There is no MIDI input device with numerical ID <code>deviceId</code>;
2363 iliev 596 * <li> <code>port</code> is not a valid MIDI port number;
2364     * <li><code>param</code> is not a valid parameter for the specified MIDI port.
2365     * </ul>
2366     *
2367     * @see #getMidiInputDevices
2368     * @see #getMidiInputPortInfo
2369     */
2370     public synchronized Parameter
2371 iliev 1139 getMidiInputPortParameterInfo(int deviceId, int port, String param)
2372 iliev 596 throws IOException, LscpException, LSException {
2373    
2374     verifyConnection();
2375 iliev 1139 String args = deviceId + " " + port + " " + param;
2376 iliev 596 out.writeLine("GET MIDI_INPUT_PORT_PARAMETER INFO " + args);
2377 iliev 1139 if(getPrintOnlyMode()) return null;
2378 iliev 596
2379     ResultSet rs = getMultiLineResultSet();
2380    
2381     String[] lnS = rs.getMultiLineResult();
2382     ParameterType type = parseType(lnS);
2383     boolean multi = parseMultiplicity(lnS);
2384     Parameter prm;
2385    
2386     switch(type) {
2387     case BOOL:
2388     if(!multi) prm = new BoolParameter(lnS);
2389     else prm = new BoolListParameter(lnS);
2390     prm.setName(param);
2391     return prm;
2392     case INT:
2393     if(!multi) prm = new IntParameter(lnS);
2394     else prm = new IntListParameter(lnS);
2395     prm.setName(param);
2396     return prm;
2397     case FLOAT:
2398     if(!multi) prm = new FloatParameter(lnS);
2399     else prm = new FloatListParameter(lnS);
2400     prm.setName(param);
2401     return prm;
2402     case STRING:
2403     if(!multi) prm = new StringParameter(lnS);
2404     else prm = new StringListParameter(lnS);
2405     prm.setName(param);
2406     return prm;
2407     default: throw new LscpException(LscpI18n.getLogMsg("Client.unknownPrmType!"));
2408     }
2409     }
2410    
2411     /**
2412     * Alters a specific setting of a MIDI input port.
2413     *
2414 iliev 1139 * @param deviceId The numerical ID of the MIDI device.
2415 iliev 596 * @param port The MIDI port number.
2416     * @param prm A <code>Parameter</code> instance containing the name of the parameter
2417     * and the new value for this parameter.
2418     *
2419     * @throws IOException If some I/O error occurs.
2420     * @throws LscpException If LSCP protocol corruption occurs.
2421     * @throws LSException If
2422     * <ul>
2423 iliev 1139 * <li>There is no MIDI device with numerical ID <code>deviceId</code>;
2424 iliev 596 * <li><code>port</code> is not a valid MIDI port number;
2425     * <li><code>prm</code> is not a valid parameter;
2426     * <li>The parameter is readonly;
2427     * <li>The parameter is from different type.
2428     * </ul>
2429     *
2430     * @see #getMidiInputDevices
2431     * @see #getMidiInputPortInfo
2432     */
2433     public synchronized void
2434 iliev 1139 setMidiInputPortParameter(int deviceId, int port, Parameter prm)
2435 iliev 596 throws IOException, LscpException, LSException {
2436    
2437     verifyConnection();
2438 iliev 1139 String args = deviceId + " " + port + " " +
2439 iliev 596 prm.getName() + '=' + prm.getStringValue();
2440     out.writeLine("SET MIDI_INPUT_PORT_PARAMETER " + args);
2441 iliev 1139 if(getPrintOnlyMode()) return;
2442 iliev 596
2443     ResultSet rs = getEmptyResultSet();
2444     }
2445    
2446     /**
2447 iliev 1139 * Adds a new MIDI instrument map.
2448     * @param name The name of this MIDI instrument map.
2449     * @return The number of the newly MIDI instrument map.
2450     * @throws IOException If some I/O error occurs.
2451     * @throws LSException If the creation of the new MIDI instrument map failed.
2452     * @throws LscpException If LSCP protocol corruption occurs.
2453     * @see #removeMidiInstrumentMap
2454     */
2455     public synchronized int
2456     addMidiInstrumentMap(String name) throws IOException, LSException, LscpException {
2457     verifyConnection();
2458     out.writeLine("ADD MIDI_INSTRUMENT_MAP '" + name + "'");
2459     if(getPrintOnlyMode()) return -1;
2460    
2461     ResultSet rs = getEmptyResultSet();
2462    
2463     return rs.getIndex();
2464     }
2465    
2466     /**
2467     * Removes the specified MIDI instrument map.
2468     * @param mapId The numerical ID of the MIDI instrument map to be removed.
2469     * @throws IOException If some I/O error occurs.
2470     * @throws LscpException If LSCP protocol corruption occurs.
2471     * @throws LSException If the removing of the MIDI instrument map failed.
2472     * @see #addMidiInstrumentMap
2473     * @see #getMidiInstrumentMapIDs
2474     */
2475     public synchronized void
2476     removeMidiInstrumentMap(int mapId) throws IOException, LscpException, LSException {
2477     verifyConnection();
2478     out.writeLine("REMOVE MIDI_INSTRUMENT_MAP " + mapId);
2479     if(getPrintOnlyMode()) return;
2480    
2481     ResultSet rs = getEmptyResultSet();
2482     }
2483    
2484     /**
2485     * Removes the all MIDI instrument maps.
2486     * @throws IOException If some I/O error occurs.
2487     * @throws LscpException If LSCP protocol corruption occurs.
2488     * @throws LSException If the removing of the MIDI instrument maps failed.
2489     */
2490     public synchronized void
2491     removeAllMidiInstrumentMaps() throws IOException, LscpException, LSException {
2492     verifyConnection();
2493     out.writeLine("REMOVE MIDI_INSTRUMENT_MAP ALL");
2494     if(getPrintOnlyMode()) return;
2495    
2496     ResultSet rs = getEmptyResultSet();
2497     }
2498    
2499     /**
2500     * Gets the current number of all MIDI instrument maps.
2501     * @return The current number of all MIDI instrument maps.
2502     * @throws IOException If some I/O error occurs.
2503     * @throws LscpException If LSCP protocol corruption occurs.
2504     * @throws LSException If some other error occurs.
2505     */
2506     public synchronized int
2507     getMidiInstrumentMapCount() throws IOException, LscpException, LSException {
2508     verifyConnection();
2509     out.writeLine("GET MIDI_INSTRUMENT_MAPS");
2510     if(getPrintOnlyMode()) return -1;
2511    
2512     String s = getSingleLineResultSet().getResult();
2513     return parseInt(s);
2514     }
2515    
2516     /**
2517     * Gets a list of numerical IDs of all created MIDI instrument maps.
2518     * @return An <code>Integer</code> array providing the numerical IDs of
2519     * all created MIDI instrument maps.
2520     * @throws IOException If some I/O error occurs.
2521     * @throws LscpException If LSCP protocol corruption occurs.
2522     * @throws LSException If some other error occurs.
2523     * @see #addMidiInstrumentMap
2524     * @see #removeMidiInstrumentMap
2525     */
2526     public synchronized Integer[]
2527     getMidiInstrumentMapIDs() throws IOException, LscpException, LSException {
2528     verifyConnection();
2529     out.writeLine("LIST MIDI_INSTRUMENT_MAPS");
2530     if(getPrintOnlyMode()) return null;
2531    
2532     return parseIntList(getSingleLineResultSet().getResult());
2533     }
2534    
2535     /**
2536     * Gets the current settings of a specific, already created MIDI instrument map.
2537     * @param mapId Specifies the numerical ID of the MIDI instrument map.
2538     * @return A <code>MidiInstrumentMapInfo</code> instance containing information
2539     * about the specified device.
2540     * @throws IOException If some I/O error occurs.
2541     * @throws LscpException If LSCP protocol corruption occurs.
2542     * @throws LSException If there is no MIDI instrument map
2543     * with map id <code>mapId</code>.
2544     * @see #getMidiInstrumentMaps
2545     */
2546     public synchronized MidiInstrumentMapInfo
2547     getMidiInstrumentMapInfo(int mapId) throws IOException, LscpException, LSException {
2548     verifyConnection();
2549     out.writeLine("GET MIDI_INSTRUMENT_MAP INFO " + mapId);
2550     if(getPrintOnlyMode()) return null;
2551    
2552     ResultSet rs = getMultiLineResultSet();
2553    
2554     String[] lnS = rs.getMultiLineResult();
2555    
2556     String name = "";
2557     boolean b = false;
2558    
2559     for(String s : lnS) {
2560     if(s.startsWith("NAME: ")) {
2561     name = s.substring("NAME: ".length());
2562     } else if(s.startsWith("DEFAULT: ")) {
2563     b = Boolean.parseBoolean(s.substring("DEFAULT: ".length()));
2564     } else {
2565     getLogger().info(LscpI18n.getLogMsg("unknownLine", s));
2566     }
2567     }
2568    
2569     return new MidiInstrumentMapInfo(mapId, name, b);
2570     }
2571    
2572     /**
2573     * Gets an information of all created MIDI instrument maps.
2574     * @return A <code>MidiInstrumentMap</code> array
2575     * providing information for all created MIDI instrument maps.
2576     * @throws IOException If some I/O error occurs.
2577     * @throws LscpException If LSCP protocol corruption occurs.
2578     * @throws LSException If some other error occurs.
2579     * @see #addMidiInstrumentMap
2580     * @see #removeMidiInstrumentMap
2581     */
2582     public synchronized MidiInstrumentMapInfo[]
2583     getMidiInstrumentMaps() throws IOException, LscpException, LSException {
2584     Integer[] idS = getMidiInstrumentMapIDs();
2585     if(getPrintOnlyMode()) return null;
2586    
2587     MidiInstrumentMapInfo[] maps = new MidiInstrumentMapInfo[idS.length];
2588    
2589     for(int i = 0; i < maps.length; i++)
2590     maps[i] = getMidiInstrumentMapInfo(idS[i]);
2591    
2592     return maps;
2593     }
2594    
2595     /**
2596     * Sets the name of the specified MIDI instrument map.
2597     * @param mapId The numerical ID of the MIDI instrument map.
2598     * @param name The new name for the specified MIDI instrument map.
2599     * @throws IOException If some I/O error occurs.
2600     * @throws LscpException If LSCP protocol corruption occurs.
2601     * @throws LSException If <code>mapId</code> is not a valid MIDI
2602     * instrument map number or <code>name</code> is not a valid name;
2603     */
2604     public synchronized void
2605     setMidiInstrumentMapName(int mapId, String name)
2606     throws IOException, LscpException, LSException {
2607    
2608     verifyConnection();
2609     out.writeLine("SET MIDI_INSTRUMENT_MAP NAME " + + mapId + " '" + name + "'");
2610     if(getPrintOnlyMode()) return;
2611    
2612     ResultSet rs = getEmptyResultSet();
2613     }
2614    
2615 iliev 1202
2616    
2617 iliev 1139 /**
2618     * Creates or replaces a MIDI instrument map entry.
2619     * @param mapId The ID of the map, where this instrument should be mapped.
2620     * @param entry Specifies the position of the MIDI instrument in the MIDI instrument map.
2621     * @param info Provides the needed information of the
2622     * MIDI instrument, which will be mapped to the specified MIDI instrument map.
2623     * @throws IOException If some I/O error occurs.
2624     * @throws LSException If the mapping failed.
2625     * @throws LscpException If LSCP protocol corruption occurs.
2626     * @see #unmapMidiInstrument
2627     */
2628     public synchronized void
2629     mapMidiInstrument(int mapId, MidiInstrumentEntry entry, MidiInstrumentInfo info)
2630     throws IOException, LSException, LscpException {
2631 iliev 1202 mapMidiInstrument(mapId, entry, info, false);
2632     }
2633    
2634     /**
2635     * Creates or replaces a MIDI instrument map entry.
2636     * @param mapId The ID of the map, where this instrument should be mapped.
2637     * @param entry Specifies the position of the MIDI instrument in the MIDI instrument map.
2638     * @param info Provides the needed information of the
2639     * MIDI instrument, which will be mapped to the specified MIDI instrument map.
2640     * @param nonModal If <code>true</code> the function returns immediately
2641     * and the mapping is established in the background.
2642     * @throws IOException If some I/O error occurs.
2643     * @throws LSException If the mapping failed.
2644     * @throws LscpException If LSCP protocol corruption occurs.
2645     * @see #unmapMidiInstrument
2646     */
2647     public synchronized void
2648     mapMidiInstrument(int mapId, MidiInstrumentEntry entry, MidiInstrumentInfo info, boolean nonModal)
2649     throws IOException, LSException, LscpException {
2650 iliev 1139
2651     verifyConnection();
2652     StringBuffer cmd = new StringBuffer("MAP MIDI_INSTRUMENT ");
2653 iliev 1202 if(nonModal) cmd.append("NON_MODAL ");
2654 iliev 1139 cmd.append(mapId).append(' ');
2655     cmd.append(entry.getMidiBank()).append(' ');
2656     cmd.append(entry.getMidiProgram()).append(' ');
2657     cmd.append(info.getEngine()).append(" '");
2658 iliev 1202 cmd.append(info.getFilePath()).append("' ");
2659 iliev 1139 cmd.append(info.getInstrumentIndex()).append(' ');
2660     cmd.append(info.getVolume());
2661     if(!info.getLoadMode().name().equals("DEFAULT")) {
2662     cmd.append(' ').append(info.getLoadMode().name());
2663     }
2664     if(info.getName() != null) cmd.append(" '").append(info.getName()).append("'");
2665    
2666     out.writeLine(cmd.toString());
2667     if(getPrintOnlyMode()) return;
2668    
2669     ResultSet rs = getEmptyResultSet();
2670     }
2671    
2672     /**
2673     * Removes an entry MIDI instrument map.
2674     * @param mapId The ID of the map, from which
2675     * the specified MIDI instrument should be removed.
2676     * @param entry The entry to remove from the specified MIDI instrument map.
2677     * @throws IOException If some I/O error occurs.
2678     * @throws LSException If the unmapping failed.
2679     * @throws LscpException If LSCP protocol corruption occurs.
2680     * @see #mapMidiInstrument
2681     */
2682     public synchronized void
2683     unmapMidiInstrument(int mapId, MidiInstrumentEntry entry)
2684     throws IOException, LSException, LscpException {
2685    
2686     verifyConnection();
2687     StringBuffer cmd = new StringBuffer("UNMAP MIDI_INSTRUMENT ");
2688     cmd.append(mapId).append(' ');
2689     cmd.append(entry.getMidiBank()).append(' ');
2690     cmd.append(entry.getMidiProgram());
2691    
2692     out.writeLine(cmd.toString());
2693     if(getPrintOnlyMode()) return;
2694    
2695     ResultSet rs = getEmptyResultSet();
2696     }
2697    
2698     /**
2699     * Gets the current number of all MIDI instrument in all maps.
2700     * @return The current number of all MIDI instrument in all maps.
2701     * @throws IOException If some I/O error occurs.
2702     * @throws LscpException If LSCP protocol corruption occurs.
2703     * @throws LSException If some other error occurs.
2704     */
2705     public synchronized int
2706     getMidiInstrumentCount() throws IOException, LscpException, LSException {
2707     verifyConnection();
2708     out.writeLine("GET MIDI_INSTRUMENTS ALL");
2709     if(getPrintOnlyMode()) return -1;
2710    
2711     String s = getSingleLineResultSet().getResult();
2712     return parseInt(s);
2713     }
2714    
2715     /**
2716     * Gets the current number of MIDI instrument in the specified map.
2717     * @param mapId The ID of the map.
2718     * @return The current number of MIDI instrument in the specified map.
2719     * @throws IOException If some I/O error occurs.
2720     * @throws LscpException If LSCP protocol corruption occurs.
2721     * @throws LSException If some other error occurs.
2722     */
2723     public synchronized int
2724     getMidiInstrumentCount(int mapId) throws IOException, LscpException, LSException {
2725     verifyConnection();
2726     out.writeLine("GET MIDI_INSTRUMENTS " + String.valueOf(mapId));
2727     if(getPrintOnlyMode()) return -1;
2728    
2729     String s = getSingleLineResultSet().getResult();
2730     return parseInt(s);
2731     }
2732    
2733     /**
2734     * Gets all MIDI instrument from all maps.
2735     * @return A <code>MidiInstrumentInfo</code> array providing
2736     * all MIDI instruments from all MIDI instrument maps.
2737     * @throws IOException If some I/O error occurs.
2738     * @throws LscpException If LSCP protocol corruption occurs.
2739     * @throws LSException If some other error occurs.
2740     */
2741     public synchronized MidiInstrumentInfo[]
2742     getMidiInstruments() throws IOException, LscpException, LSException {
2743     verifyConnection();
2744     out.writeLine("LIST MIDI_INSTRUMENTS ALL");
2745     if(getPrintOnlyMode()) return null;
2746    
2747     String[] entries = parseArray(getSingleLineResultSet().getResult());
2748    
2749     return getMidiInstruments(entries);
2750     }
2751    
2752     /**
2753     * Gets all MIDI instrument contained int the specified MIDI instrument map.
2754     * @param mapId The ID of the map, which instruments should be obtained.
2755     * @return A <code>MidiInstrumentInfo</code> array providing
2756     * all MIDI instruments from all MIDI instrument maps.
2757     * @throws IOException If some I/O error occurs.
2758     * @throws LscpException If LSCP protocol corruption occurs.
2759     * @throws LSException If some other error occurs.
2760     */
2761     public synchronized MidiInstrumentInfo[]
2762     getMidiInstruments(int mapId) throws IOException, LscpException, LSException {
2763     verifyConnection();
2764     out.writeLine("LIST MIDI_INSTRUMENTS " + String.valueOf(mapId));
2765     if(getPrintOnlyMode()) return null;
2766    
2767     String[] entries = parseArray(getSingleLineResultSet().getResult());
2768    
2769     return getMidiInstruments(entries);
2770     }
2771    
2772     private MidiInstrumentInfo[]
2773     getMidiInstruments(String[] entries) throws IOException, LscpException, LSException {
2774     Vector<MidiInstrumentInfo> v = new Vector<MidiInstrumentInfo>();
2775    
2776     for(String s : entries) {
2777     Integer[] vals = parseIntList(s);
2778     if(vals.length != 3) {
2779     throw new LscpException(LscpI18n.getLogMsg("CommandFailed!"));
2780     }
2781    
2782     v.add(getMidiInstrumentInfo(vals[0], vals[1], vals[2]));
2783     }
2784    
2785     return v.toArray(new MidiInstrumentInfo[v.size()]);
2786     }
2787    
2788     /**
2789     * Gets the current settings of the specified MIDI instrument.
2790     * @param mapId The ID of the map.
2791     * @param bank The index of the MIDI bank.
2792     * @param program The MIDI program number of the instrument.
2793     * @return <code>MidiInstrumentInfo</code> instance containing
2794     * the current settings of the specified MIDI instrument.
2795     * @throws IOException If an I/O error occurs.
2796     * @throws LscpException If LSCP protocol corruption occurs.
2797     * @throws LSException If the specified MIDI instrument is missing.
2798     */
2799     public synchronized MidiInstrumentInfo
2800     getMidiInstrumentInfo(int mapId, int bank, int program)
2801     throws IOException, LscpException, LSException {
2802    
2803     verifyConnection();
2804     StringBuffer cmd = new StringBuffer("GET MIDI_INSTRUMENT INFO ");
2805     cmd.append(mapId).append(' ');
2806     cmd.append(bank).append(' ');
2807     cmd.append(program);
2808    
2809     out.writeLine(cmd.toString());
2810     if(getPrintOnlyMode()) return null;
2811    
2812     ResultSet rs = getMultiLineResultSet();
2813     MidiInstrumentEntry entry = new MidiInstrumentEntry(bank, program);
2814     return new MidiInstrumentInfo(mapId, entry, rs.getMultiLineResult());
2815     }
2816    
2817     /**
2818 iliev 596 * Loads and assigns an instrument to a sampler channel. Notice that this function will
2819     * return after the instrument is fully loaded and the channel is ready to be used.
2820     * @param filename The name of the instrument file
2821     * on the LinuxSampler instance's host system.
2822     * @param instrIdx The index of the instrument in the instrument file.
2823     * @param samplerChn The number of the sampler channel the instrument should be assigned to.
2824     * @throws IOException If some I/O error occurs.
2825     * @throws LscpException If LSCP protocol corruption occurs.
2826     * @throws LSException If the loading of the instrument failed.
2827     * @see #loadInstrument(String, int, int, boolean)
2828     * @see #getSamplerChannels
2829     */
2830     public synchronized void
2831     loadInstrument(String filename, int instrIdx, int samplerChn)
2832     throws IOException, LscpException, LSException {
2833    
2834     verifyConnection();
2835     loadInstrument(filename, instrIdx, samplerChn, false);
2836     }
2837    
2838     /**
2839     * Loads and assigns an instrument to a sampler channel.
2840     *
2841     * @param filename The name of the instrument file
2842     * on the LinuxSampler instance's host system.
2843     * @param instrIdx The index of the instrument in the instrument file.
2844     * @param samplerChn The number of the sampler channel the instrument should be assigned to.
2845     * @param nonModal If <code>false</code> the function will return after the instrument
2846     * has been fully loaded and the channel is ready to be used. If <code>true</code>
2847     * the function returns immediately.
2848     *
2849     * @throws IOException If some I/O error occurs.
2850     * @throws LscpException If LSCP protocol corruption occurs.
2851     * @throws LSException If the loading of the instrument failed.
2852     *
2853     * @see #loadInstrument(String, int, int)
2854     * @see #getSamplerChannels
2855     */
2856     public synchronized void
2857     loadInstrument(String filename, int instrIdx, int samplerChn, boolean nonModal)
2858     throws IOException, LscpException, LSException {
2859    
2860 iliev 1307 filename = getEscapedString(filename);
2861 iliev 596 String cmd = nonModal ? "LOAD INSTRUMENT NON_MODAL " : "LOAD INSTRUMENT ";
2862     String args = '\'' + filename + "' " + instrIdx + ' ' + samplerChn;
2863    
2864     out.writeLine(cmd + args);
2865 iliev 1139 if(getPrintOnlyMode()) return;
2866 iliev 596
2867     ResultSet rs = getEmptyResultSet();
2868     }
2869    
2870     /**
2871     * Loads a sampler engine to a specific sampler channel.
2872     * @param engineName The name of the engine.
2873     * @param samplerChn The number of the sampler channel
2874     * the deployed engine should be assigned to.
2875     *
2876     * @throws IOException If some I/O error occurs.
2877     * @throws LscpException If LSCP protocol corruption occurs.
2878     * @throws LSException If the loading of the sampler engine failed.
2879     * @see #getEngines
2880     * @see #getSamplerChannels
2881     */
2882     public synchronized void
2883     loadSamplerEngine(String engineName, int samplerChn)
2884     throws IOException, LscpException, LSException {
2885    
2886     verifyConnection();
2887     out.writeLine("LOAD ENGINE " + engineName + ' ' + samplerChn);
2888 iliev 1139 if(getPrintOnlyMode()) return;
2889 iliev 596
2890     ResultSet rs = getEmptyResultSet();
2891     }
2892    
2893     /**
2894     * Gets the current number of all created sampler channels.
2895     * @return The current number of all created sampler channels.
2896     * @throws IOException If some I/O error occurs.
2897     * @throws LscpException If LSCP protocol corruption occurs.
2898     * @throws LSException If some other error occurs.
2899     */
2900     public synchronized int
2901     getSamplerChannelCount() throws IOException, LscpException, LSException {
2902     verifyConnection();
2903     out.writeLine("GET CHANNELS");
2904 iliev 1139 if(getPrintOnlyMode()) return -1;
2905    
2906 iliev 596 String s = getSingleLineResultSet().getResult();
2907     return parseInt(s);
2908     }
2909    
2910     /**
2911 iliev 784 * Gets a list of all created sampler channels.
2912     * @return A <code>SamplerChannel</code> array providing all created sampler channels.
2913     * @throws IOException If some I/O error occurs.
2914     * @throws LscpException If LSCP protocol corruption occurs.
2915     * @throws LSException If some other error occurs.
2916     * @see #addSamplerChannel
2917     * @see #removeSamplerChannel
2918     */
2919     public synchronized SamplerChannel[]
2920     getSamplerChannels() throws IOException, LscpException, LSException {
2921     Integer[] idS = getSamplerChannelIDs();
2922 iliev 1139 if(getPrintOnlyMode()) return null;
2923    
2924 iliev 784 SamplerChannel[] channels = new SamplerChannel[idS.length];
2925    
2926     for(int i = 0; i < channels.length; i++)
2927     channels[i] = getSamplerChannelInfo(idS[i]);
2928    
2929     return channels;
2930     }
2931    
2932     /**
2933 iliev 596 * Gets a list with numerical IDs of all created sampler channels.
2934 iliev 784 * @return An <code>Integer</code> array providing
2935     * the numerical IDs of all created sampler channels.
2936 iliev 596 * @throws IOException If some I/O error occurs.
2937     * @throws LscpException If LSCP protocol corruption occurs.
2938     * @throws LSException If some other error occurs.
2939     * @see #addSamplerChannel
2940     * @see #removeSamplerChannel
2941     */
2942     public synchronized Integer[]
2943 iliev 784 getSamplerChannelIDs() throws IOException, LscpException, LSException {
2944 iliev 596 verifyConnection();
2945     out.writeLine("LIST CHANNELS");
2946 iliev 1139 if(getPrintOnlyMode()) return null;
2947    
2948 iliev 596 return parseIntList(getSingleLineResultSet().getResult());
2949     }
2950    
2951     /**
2952     * Adds a new sampler channel. This method will increment the sampler channel count by one
2953     * and the new sampler channel will be appended to the end of the sampler channel list.
2954     *
2955     * @return The number of the newly created sampler channel.
2956     * @throws IOException If some I/O error occurs.
2957     * @throws LSException If the creation of the new sampler channel failed.
2958     * @throws LscpException If LSCP protocol corruption occurs.
2959     * @see #removeSamplerChannel
2960     */
2961     public synchronized int
2962     addSamplerChannel() throws IOException, LSException, LscpException {
2963     verifyConnection();
2964     out.writeLine("ADD CHANNEL");
2965 iliev 1139 if(getPrintOnlyMode()) return -1;
2966    
2967 iliev 596 ResultSet rs = getEmptyResultSet();
2968    
2969     return rs.getIndex();
2970     }
2971    
2972     /**
2973     * Removes the specified sampler channel.
2974     *
2975     * @param samplerChn The numerical ID of the sampler channel to be removed.
2976     *
2977     * @throws IOException If some I/O error occurs.
2978     * @throws LscpException If LSCP protocol corruption occurs.
2979     * @throws LSException If the removing of the sampler channel failed.
2980     * @see #addSamplerChannel
2981     * @see #getSamplerChannels
2982     */
2983     public synchronized void
2984     removeSamplerChannel(int samplerChn) throws IOException, LscpException, LSException {
2985     verifyConnection();
2986     out.writeLine("REMOVE CHANNEL " + samplerChn);
2987 iliev 1139 if(getPrintOnlyMode()) return;
2988 iliev 596
2989     ResultSet rs = getEmptyResultSet();
2990     }
2991    
2992     /**
2993     * Gets the number of all available engines.
2994     * @return The number of all available engines.
2995     * @throws IOException If some I/O error occurs.
2996     * @throws LscpException If LSCP protocol corruption occurs.
2997     * @throws LSException If some other error occurs.
2998     */
2999     public synchronized int
3000     getEngineCount() throws IOException, LscpException, LSException {
3001     verifyConnection();
3002     out.writeLine("GET AVAILABLE_ENGINES");
3003 iliev 1139 if(getPrintOnlyMode()) return -1;
3004    
3005 iliev 596 String s = getSingleLineResultSet().getResult();
3006     return parseInt(s);
3007     }
3008    
3009     /**
3010 iliev 671 * Gets a list of all available engines.
3011     *
3012     * @return <code>SamplerEngine</code> array containing all available engines.
3013     * @throws IOException If some I/O error occurs.
3014     * @throws LscpException If LSCP protocol corruption occurs.
3015     * @throws LSException If some other error occurs.
3016     */
3017     public synchronized SamplerEngine[]
3018     getEngines() throws IOException, LscpException, LSException {
3019     String[] engines = getEngineNames();
3020 iliev 1139 if(getPrintOnlyMode()) return null;
3021    
3022 iliev 671 SamplerEngine[] se = new SamplerEngine[engines.length];
3023    
3024     for(int i = 0; i < engines.length; i++) se[i] = getEngineInfo(engines[i]);
3025    
3026     return se;
3027     }
3028    
3029     /**
3030 iliev 596 * Gets a list of all available engines' names.
3031     *
3032     * @return <code>String</code> array with all available engines' names.
3033     * @throws IOException If some I/O error occurs.
3034     * @throws LscpException If LSCP protocol corruption occurs.
3035     * @throws LSException If some other error occurs.
3036     */
3037 iliev 671 private synchronized String[]
3038     getEngineNames() throws IOException, LscpException, LSException {
3039 iliev 596 verifyConnection();
3040     out.writeLine("LIST AVAILABLE_ENGINES");
3041 iliev 1139 if(getPrintOnlyMode()) return null;
3042    
3043 iliev 1326 return parseQuotedStringList(getSingleLineResultSet().getResult());
3044 iliev 596 }
3045    
3046     /**
3047     * Gets information about a specific sampler engine.
3048     * @param engineName The name of the sampler engine.
3049     *
3050     * @return <code>SamplerEngine</code> instance containing
3051     * information about the specified sampler engine.
3052     *
3053     * @throws IOException If an I/O error occurs.
3054     * @throws LscpException If LSCP protocol corruption occurs.
3055     * @throws LSException If there is no sampler engine with name <code>engineName</code>.
3056 iliev 671 * @see #getEngineNames
3057 iliev 596 */
3058 iliev 671 private synchronized SamplerEngine
3059 iliev 596 getEngineInfo(String engineName) throws IOException, LscpException, LSException {
3060     verifyConnection();
3061     out.writeLine("GET ENGINE INFO " + engineName);
3062 iliev 1139 if(getPrintOnlyMode()) return null;
3063    
3064 iliev 596 ResultSet rs = getMultiLineResultSet();
3065     SamplerEngine se = new SamplerEngine(rs.getMultiLineResult());
3066     se.setName(engineName);
3067     return se;
3068     }
3069    
3070     /**
3071     * Gets the current settings of the specified sampler channel.
3072     * @param samplerChn The sampler channel number.
3073     *
3074     * @return <code>SamplerChannel</code> instance containing
3075     * the current settings of the specified sampler channel.
3076     *
3077     * @throws IOException If an I/O error occurs.
3078     * @throws LscpException If LSCP protocol corruption occurs.
3079     * @throws LSException If there is no sampler channel with <code>samplerChn</code> number.
3080     * @see #getSamplerChannels
3081     */
3082     public synchronized SamplerChannel
3083     getSamplerChannelInfo(int samplerChn) throws IOException, LscpException, LSException {
3084     verifyConnection();
3085     out.writeLine("GET CHANNEL INFO " + samplerChn);
3086 iliev 1139 if(getPrintOnlyMode()) return null;
3087    
3088 iliev 596 ResultSet rs = getMultiLineResultSet();
3089     SamplerChannel sc = new SamplerChannel(rs.getMultiLineResult());
3090 iliev 1139 sc.setChannelId(samplerChn);
3091 iliev 784 if(sc.getEngine() != null) sc.setEngine(getEngineInfo(sc.getEngine().getName()));
3092 iliev 596
3093     return sc;
3094     }
3095    
3096     /**
3097     * Gets the current number of active voices on the specified sampler channel.
3098     *
3099     * @param samplerChn The sampler channel number.
3100     * @return The current number of active voices on the specified sampler channel.
3101     * @throws IOException If some I/O error occurs.
3102     * @throws LscpException If LSCP protocol corruption occurs.
3103     * @throws LSException If there is no sampler channel with number <code>samplerChn</code>.
3104     * @see #getSamplerChannels
3105     */
3106     public synchronized int
3107     getChannelVoiceCount(int samplerChn) throws IOException, LscpException, LSException {
3108     verifyConnection();
3109     out.writeLine("GET CHANNEL VOICE_COUNT " + samplerChn);
3110 iliev 1139 if(getPrintOnlyMode()) return -1;
3111    
3112 iliev 596 ResultSet rs = getSingleLineResultSet();
3113    
3114     return parseInt(rs.getResult());
3115     }
3116    
3117     /**
3118     * Gets the current number of active disk streams on the specified sampler channel.
3119     *
3120     * @param samplerChn The sampler channel number.
3121     * @return The current number of active disk streams on the specified sampler channel
3122     * or -1 if the engine doesn't support disk streaming.
3123     * @throws IOException If some I/O error occurs.
3124     * @throws LscpException If LSCP protocol corruption occurs.
3125     * @throws LSException If there is no sampler channel with number <code>samplerChn</code>.
3126     * @see #getSamplerChannels
3127     */
3128     public synchronized int
3129     getChannelStreamCount(int samplerChn) throws IOException, LscpException, LSException {
3130     verifyConnection();
3131     out.writeLine("GET CHANNEL STREAM_COUNT " + samplerChn);
3132 iliev 1139 if(getPrintOnlyMode()) return -1;
3133    
3134 iliev 596 ResultSet rs = getSingleLineResultSet();
3135    
3136     if(rs.getResult().equals("NA")) return -1;
3137    
3138     return parseInt(rs.getResult());
3139     }
3140    
3141     /**
3142     * Gets the current fill state of all disk streams on the specified sampler channel
3143     * in bytes.
3144     *
3145     * @param samplerChn The sampler channel number.
3146     * @return The current fill state of all disk streams on the specified sampler channel
3147     * or <code>null</code> if the engine which is deployed doesn't support disk streaming.
3148     * @throws IOException If some I/O error occurs.
3149     * @throws LscpException If LSCP protocol corruption occurs.
3150     * @throws LSException If there is no sampler channel with number <code>samplerChn</code>.
3151     * @see #getChannelBufferFillPercentage
3152     * @see #getSamplerChannels
3153     */
3154     public synchronized Vector<BufferFill>
3155     getChannelBufferFillBytes(int samplerChn) throws IOException, LscpException, LSException {
3156     verifyConnection();
3157     out.writeLine("GET CHANNEL BUFFER_FILL BYTES " + samplerChn);
3158 iliev 1139 if(getPrintOnlyMode()) return null;
3159    
3160 iliev 596 ResultSet rs = getSingleLineResultSet();
3161    
3162     if(rs.getResult().equals("NA")) return null;
3163    
3164     Vector<BufferFill> v = new Vector<BufferFill>();
3165     String[] args = parseList(rs.getResult());
3166    
3167     for(String s : args) {
3168     if(s.charAt(0) != '[')
3169     throw new LscpException(LscpI18n.getLogMsg("CommandFailed!"));
3170    
3171     int i = s.indexOf(']');
3172     if(i == -1) throw new LscpException(LscpI18n.getLogMsg("CommandFailed!"));
3173    
3174     BufferFill bf = new BufferFill();
3175 iliev 1139 bf.setStreamId(parseInt(s.substring(1, i)));
3176 iliev 596 bf.setValue(parseInt(s.substring(i + 1)));
3177     v.add(bf);
3178     }
3179    
3180     return v;
3181     }
3182    
3183     /**
3184     * Gets the current fill state of all disk streams on the specified sampler channel
3185     * in percent.
3186     *
3187     * @param samplerChn The sampler channel number.
3188     * @return The current fill state of all disk streams on the specified sampler channel
3189     * or <code>null</code> if the engine which is deployed doesn't support disk streaming.
3190     * @throws IOException If some I/O error occurs.
3191     * @throws LscpException If LSCP protocol corruption occurs.
3192     * @throws LSException If there is no sampler channel with number <code>samplerChn</code>.
3193     * @see #getChannelBufferFillBytes
3194     * @see #getSamplerChannels
3195     */
3196     public synchronized Vector<BufferFill>
3197     getChannelBufferFillPercentage(int samplerChn)
3198     throws IOException, LscpException, LSException {
3199    
3200     verifyConnection();
3201     out.writeLine("GET CHANNEL BUFFER_FILL PERCENTAGE " + samplerChn);
3202 iliev 1139 if(getPrintOnlyMode()) return null;
3203    
3204 iliev 596 ResultSet rs = getSingleLineResultSet();
3205    
3206     return getChannelBufferFillPercentage(rs.getResult());
3207     }
3208    
3209     private Vector<BufferFill>
3210     getChannelBufferFillPercentage(String ln) throws LscpException {
3211     if(ln.equals("NA")) return null;
3212    
3213     Vector<BufferFill> v = new Vector<BufferFill>();
3214     String[] args = parseList(ln);
3215    
3216     for(String s : args) {
3217     if(s.charAt(0) != '[')
3218     throw new LscpException(LscpI18n.getLogMsg("CommandFailed!"));
3219    
3220     int i = s.indexOf(']');
3221     if(i == -1) throw new LscpException(LscpI18n.getLogMsg("CommandFailed!"));
3222    
3223     if(s.charAt(s.length() - 1) != '%')
3224     throw new LscpException(LscpI18n.getLogMsg("CommandFailed!"));
3225    
3226     BufferFill bf = new BufferFill();
3227 iliev 1139 bf.setStreamId(parseInt(s.substring(1, i)));
3228 iliev 596 bf.setValue(parseInt(s.substring(i + 1, s.length() - 1)));
3229     v.add(bf);
3230     }
3231    
3232     return v;
3233     }
3234    
3235     /**
3236     * Sets the audio output device on the specified sampler channel.
3237     *
3238     * @param samplerChn The sampler channel number.
3239 iliev 1139 * @param devId The numerical ID of the audio output device.
3240 iliev 596 *
3241     * @throws IOException If some I/O error occurs.
3242     * @throws LscpException If LSCP protocol corruption occurs.
3243     * @throws LSException If
3244     * <ul>
3245     * <li><code>samplerChn</code> is not a valid channel number;
3246 iliev 1139 * <li><code>devId</code> is not a valid audio output device ID;
3247 iliev 596 * </ul>
3248     *
3249     * @see #getSamplerChannels
3250     * @see #getAudioOutputDevices
3251     */
3252     public synchronized void
3253 iliev 1139 setChannelAudioOutputDevice(int samplerChn, int devId)
3254 iliev 596 throws IOException, LscpException, LSException {
3255    
3256     verifyConnection();
3257 iliev 1139 out.writeLine("SET CHANNEL AUDIO_OUTPUT_DEVICE " + samplerChn + ' ' + devId);
3258     if(getPrintOnlyMode()) return;
3259 iliev 596
3260     ResultSet rs = getEmptyResultSet();
3261     }
3262    
3263     /**
3264     * Sets the audio output channel on the specified sampler channel.
3265     *
3266     * @param samplerChn The sampler channel number.
3267     * @param audioOut The sampler channel's audio output channel which should be rerouted.
3268     * @param audioIn The audio channel of the selected audio output device
3269     * where <code>audioOut</code> should be routed to.
3270     *
3271     * @throws IOException If some I/O error occurs.
3272     * @throws LscpException If LSCP protocol corruption occurs.
3273     * @throws LSException If
3274     * <ul>
3275     * <li><code>samplerChn</code> is not a valid channel number;
3276     * <li>There is no engine assigned yet to the specified sampler channel.
3277     * <li> There is no audio output device connected to the specified sampler channel.
3278     * </ul>
3279     *
3280     * @see #getSamplerChannels
3281     */
3282     public synchronized void
3283     setChannelAudioOutputChannel(int samplerChn, int audioOut, int audioIn)
3284     throws IOException, LscpException, LSException {
3285    
3286     verifyConnection();
3287     String args = " " + samplerChn + ' ' + audioOut + ' ' + audioIn;
3288     out.writeLine("SET CHANNEL AUDIO_OUTPUT_CHANNEL" + args);
3289 iliev 1139 if(getPrintOnlyMode()) return;
3290 iliev 596
3291     ResultSet rs = getEmptyResultSet();
3292     }
3293    
3294     /**
3295     * Sets the MIDI input device on the specified sampler channel.
3296     *
3297     * @param samplerChn The sampler channel number.
3298 iliev 1139 * @param devId The numerical ID of the MIDI input device.
3299 iliev 596 *
3300     * @throws IOException If some I/O error occurs.
3301     * @throws LscpException If LSCP protocol corruption occurs.
3302     * @throws LSException If
3303     * <ul>
3304     * <li><code>samplerChn</code> is not a valid channel number;
3305 iliev 1139 * <li><code>devId</code> is not a valid MIDI input device ID;
3306 iliev 596 * </ul>
3307     *
3308     * @see #getSamplerChannels
3309     * @see #getMidiInputDevices
3310     */
3311     public synchronized void
3312 iliev 1139 setChannelMidiInputDevice(int samplerChn, int devId)
3313 iliev 596 throws IOException, LscpException, LSException {
3314    
3315     verifyConnection();
3316 iliev 1139 out.writeLine("SET CHANNEL MIDI_INPUT_DEVICE " + samplerChn + ' ' + devId);
3317     if(getPrintOnlyMode()) return;
3318 iliev 596
3319     ResultSet rs = getEmptyResultSet();
3320     }
3321    
3322     /**
3323     * Sets the MIDI input port on the specified sampler channel.
3324     *
3325     * @param samplerChn The sampler channel number.
3326     * @param port The MIDI input port number of
3327     * the MIDI input device connected to the specified sampler channel.
3328     *
3329     * @throws IOException If some I/O error occurs.
3330     * @throws LscpException If LSCP protocol corruption occurs.
3331     * @throws LSException If <code>samplerChn</code> is not a valid channel number.
3332     * @see #getSamplerChannels
3333     */
3334     public synchronized void
3335     setChannelMidiInputPort(int samplerChn, int port)
3336     throws IOException, LscpException, LSException {
3337    
3338     verifyConnection();
3339     out.writeLine("SET CHANNEL MIDI_INPUT_PORT " + samplerChn + ' ' + port);
3340 iliev 1139 if(getPrintOnlyMode()) return;
3341 iliev 596
3342     ResultSet rs = getEmptyResultSet();
3343     }
3344    
3345     /**
3346     * Sets the MIDI input channel the specified sampler channel should listen to.
3347     *
3348     * @param samplerChn The sampler channel number.
3349     * @param midiChn The number of the new MIDI input channel where
3350     * <code>samplerChn</code> should listen to or -1 to listen on all 16 MIDI channels.
3351     *
3352     * @throws IOException If some I/O error occurs.
3353     * @throws LscpException If LSCP protocol corruption occurs.
3354     * @throws LSException If <code>samplerChn</code> is not a valid channel number.
3355     * @see #getSamplerChannels
3356     */
3357     public synchronized void
3358     setChannelMidiInputChannel(int samplerChn, int midiChn)
3359     throws IOException, LscpException, LSException {
3360    
3361     verifyConnection();
3362     String args = String.valueOf(samplerChn) + ' ';
3363     args += (midiChn == -1 ? "ALL" : String.valueOf(midiChn));
3364     out.writeLine("SET CHANNEL MIDI_INPUT_CHANNEL " + args);
3365 iliev 1139 if(getPrintOnlyMode()) return;
3366 iliev 596
3367     ResultSet rs = getEmptyResultSet();
3368     }
3369    
3370     /**
3371 iliev 1139 * Sets the MIDI instrument map to be used on the specified sampler channel.
3372     *
3373     * @param samplerChn The sampler channel number.
3374     * @param mapId Specifies the numerical ID of the MIDI instrument
3375     * map to assign. To remove the current map binding use <code>-1</code>.
3376     * To set the current map to be the default map use <code>-2</code>.
3377     *
3378     * @throws IOException If some I/O error occurs.
3379     * @throws LscpException If LSCP protocol corruption occurs.
3380     * @throws LSException If
3381     * <ul>
3382     * <li><code>samplerChn</code> is not a valid channel number;
3383     * <li><code>mapId</code> is not a valid MIDI instrument map ID;
3384     * </ul>
3385     *
3386     * @see #getSamplerChannels
3387     * @see #getMidiInstrumentMaps
3388     */
3389     public synchronized void
3390     setChannelMidiInstrumentMap(int samplerChn, int mapId)
3391     throws IOException, LscpException, LSException {
3392    
3393     verifyConnection();
3394     String s;
3395     if(mapId == -1) {
3396     s = " NONE";
3397     } else if(mapId == -2) {
3398     s = " DEFAULT";
3399     } else {
3400     s = " " + String.valueOf(mapId);
3401     }
3402     out.writeLine("SET CHANNEL MIDI_INSTRUMENT_MAP " + samplerChn + s);
3403     if(getPrintOnlyMode()) return;
3404    
3405     ResultSet rs = getEmptyResultSet();
3406     }
3407    
3408     /**
3409 iliev 596 * Sets the volume of the specified sampler channel.
3410     *
3411     * @param samplerChn The sampler channel number.
3412     * @param volume The new volume value.
3413     *
3414     * @throws IOException If some I/O error occurs.
3415     * @throws LscpException If LSCP protocol corruption occurs.
3416     * @throws LSException If <code>samplerChn</code> is not a valid channel number or if
3417     * there is no engine assigned yet to the specified sampler channel.
3418     * @see #getSamplerChannels
3419     */
3420     public synchronized void
3421     setChannelVolume(int samplerChn, float volume)
3422     throws IOException, LscpException, LSException {
3423    
3424     verifyConnection();
3425     out.writeLine("SET CHANNEL VOLUME " + samplerChn + ' ' + volume);
3426 iliev 1139 if(getPrintOnlyMode()) return;
3427 iliev 596
3428     ResultSet rs = getEmptyResultSet();
3429     }
3430    
3431     /**
3432 iliev 784 * Mute/unmute the specified sampler channel.
3433     *
3434     * @param samplerChn The sampler channel number.
3435     * @param mute If <code>true</code> the specified channel is muted, else the channel
3436     * is unmuted.
3437     *
3438     * @throws IOException If some I/O error occurs.
3439     * @throws LscpException If LSCP protocol corruption occurs.
3440     * @throws LSException If <code>samplerChn</code> is not a valid channel number or if
3441     * there is no engine assigned yet to the specified sampler channel.
3442     * @see #getSamplerChannels
3443     */
3444     public synchronized void
3445     setChannelMute(int samplerChn, boolean mute)
3446     throws IOException, LscpException, LSException {
3447    
3448     verifyConnection();
3449     out.writeLine("SET CHANNEL MUTE " + samplerChn + ' ' + (mute ? 1 : 0));
3450 iliev 1139 if(getPrintOnlyMode()) return;
3451 iliev 784
3452     ResultSet rs = getEmptyResultSet();
3453     }
3454    
3455     /**
3456     * Solo/unsolo the specified sampler channel.
3457     *
3458     * @param samplerChn The sampler channel number.
3459     * @param solo <code>true</code> to solo the specified channel, <code>false</code>
3460     * otherwise.
3461     *
3462     * @throws IOException If some I/O error occurs.
3463     * @throws LscpException If LSCP protocol corruption occurs.
3464     * @throws LSException If <code>samplerChn</code> is not a valid channel number or if
3465     * there is no engine assigned yet to the specified sampler channel.
3466     * @see #getSamplerChannels
3467     */
3468     public synchronized void
3469     setChannelSolo(int samplerChn, boolean solo)
3470     throws IOException, LscpException, LSException {
3471    
3472     verifyConnection();
3473     out.writeLine("SET CHANNEL SOLO " + samplerChn + ' ' + (solo ? 1 : 0));
3474 iliev 1139 if(getPrintOnlyMode()) return;
3475 iliev 784
3476     ResultSet rs = getEmptyResultSet();
3477     }
3478    
3479     /**
3480 iliev 1139 * Creates an additional effect send on the specified sampler channel.
3481     * @param channel The sampler channel, on which a new effect send should be added.
3482     * @param midiCtrl Defines the MIDI controller, which
3483     * will be able alter the effect send level.
3484     * @return The unique ID of the newly created effect send entity.
3485     * @throws IOException If some I/O error occurs.
3486     * @throws LSException If the creation of the effect send failed.
3487     * @throws LscpException If LSCP protocol corruption occurs.
3488     * @see #destroyFxSend
3489     */
3490     public synchronized int
3491     createFxSend(int channel, int midiCtrl)
3492     throws IOException, LSException, LscpException {
3493    
3494     return createFxSend(channel, midiCtrl, null);
3495     }
3496    
3497     /**
3498     * Creates an additional effect send on the specified sampler channel.
3499     * @param channel The sampler channel, on which the effect send should be created on.
3500     * @param midiCtrl Defines the MIDI controller, which can alter the effect send level.
3501     * @param name The name of the effect send entity. The name does not have to be unique.
3502     * @return The unique ID of the newly created effect send entity.
3503     * @throws IOException If some I/O error occurs.
3504     * @throws LSException If the creation of the effect send failed.
3505     * @throws LscpException If LSCP protocol corruption occurs.
3506     * @see #destroyFxSend
3507     */
3508     public synchronized int
3509     createFxSend(int channel, int midiCtrl, String name)
3510     throws IOException, LSException, LscpException {
3511    
3512     verifyConnection();
3513     String s = String.valueOf(channel) + " " + String.valueOf(midiCtrl);
3514     if(name != null) s += " '" + name + "'";
3515     out.writeLine("CREATE FX_SEND " + s);
3516     if(getPrintOnlyMode()) return -1;
3517    
3518     ResultSet rs = getEmptyResultSet();
3519    
3520     return rs.getIndex();
3521     }
3522    
3523     /**
3524     * Destroys the specified effect send on the specified sampler channel.
3525     * @param channel The sampler channel, from which
3526     * the specified effect send should be removed.
3527     * @param fxSend The ID of the effect send that should be removed.
3528     * @throws LSException If some other error occurs.
3529     * @throws LscpException If LSCP protocol corruption occurs.
3530     * @see #createFxSend
3531     */
3532     public synchronized void
3533     destroyFxSend(int channel, int fxSend)
3534     throws IOException, LSException, LscpException {
3535    
3536     verifyConnection();
3537     String s = String.valueOf(channel) + " " + String.valueOf(fxSend);
3538     out.writeLine("DESTROY FX_SEND " + s);
3539     if(getPrintOnlyMode()) return;
3540    
3541     ResultSet rs = getEmptyResultSet();
3542     }
3543    
3544     /**
3545     * Gets the current number of effect sends on the specified sampler channel.
3546     * @param channel The ID of the sampler channel.
3547     * @return The current number of effect sends on the specified sampler channels.
3548     * @throws IOException If some I/O error occurs.
3549     * @throws LscpException If LSCP protocol corruption occurs.
3550     * @throws LSException If some other error occurs.
3551     */
3552     public synchronized int
3553     getFxSoundCount(int channel) throws IOException, LscpException, LSException {
3554     verifyConnection();
3555     out.writeLine("GET FX_SENDS " + String.valueOf(channel));
3556     if(getPrintOnlyMode()) return -1;
3557    
3558     String s = getSingleLineResultSet().getResult();
3559     return parseInt(s);
3560     }
3561    
3562     /**
3563     * Gets a list of all created effect sends on the specified sampler channel.
3564     * @param channel The sampler channel number.
3565     * @return A <code>FxSend</code> array providing all created
3566     * effect sends on the specified sampler channel.
3567     * @throws IOException If some I/O error occurs.
3568     * @throws LscpException If LSCP protocol corruption occurs.
3569     * @throws LSException If <code>channel</code> is not a valid sampler channel ID.
3570     * @see #createFxSend
3571     * @see #destroyFxSend
3572     */
3573     public synchronized FxSend[]
3574     getFxSends(int channel) throws IOException, LscpException, LSException {
3575     Integer[] idS = getFxSendIDs(channel);
3576     if(getPrintOnlyMode()) return null;
3577    
3578     FxSend[] fxSends = new FxSend[idS.length];
3579    
3580     for(int i = 0; i < fxSends.length; i++)
3581     fxSends[i] = getFxSendInfo(channel, idS[i]);
3582    
3583     return fxSends;
3584     }
3585    
3586     /**
3587     * Gets a list of effect sends on the specified sampler channel.
3588     * @param channel The sampler channel number.
3589     * @return An <code>Integer</code> array providing
3590     * the numerical IDs of all effect sends on the specified sampler channel.
3591     * @throws IOException If some I/O error occurs.
3592     * @throws LscpException If LSCP protocol corruption occurs.
3593     * @throws LSException If <code>channel</code> is not a valid sampler channel ID.
3594     * @see #createFxSend
3595     * @see #destroyFxSend
3596     */
3597     public synchronized Integer[]
3598     getFxSendIDs(int channel) throws IOException, LscpException, LSException {
3599     verifyConnection();
3600     out.writeLine("LIST FX_SENDS " + channel);
3601     if(getPrintOnlyMode()) return null;
3602    
3603     return parseIntList(getSingleLineResultSet().getResult());
3604     }
3605    
3606     /**
3607     * Gets the current settings of the specified effect send entity.
3608     * @param channel The sampler channel number.
3609     * @param fxSend The numerical ID of the effect send entity.
3610     * @return <code>FxSend</code> instance containing
3611     * the current settings of the specified effect send entity.
3612     * @throws IOException If an I/O error occurs.
3613     * @throws LscpException If LSCP protocol corruption occurs.
3614     * @throws LSException If the sampler channel and/or the effect send number are invalid.
3615     */
3616     public synchronized FxSend
3617     getFxSendInfo(int channel, int fxSend) throws IOException, LscpException, LSException {
3618     verifyConnection();
3619     String s = String.valueOf(channel) + " " + String.valueOf(fxSend);
3620     out.writeLine("GET FX_SEND INFO " + s);
3621     if(getPrintOnlyMode()) return null;
3622    
3623     ResultSet rs = getMultiLineResultSet();
3624     FxSend fxs = new FxSend(rs.getMultiLineResult());
3625     fxs.setFxSendId(fxSend);
3626    
3627     return fxs;
3628     }
3629    
3630     /**
3631     * Sets the name of the specified effect send.
3632     * @param channel The sampler channel number.
3633     * @param fxSend The numerical ID of the effect send entity.
3634     * @param name The new name for the specified effect send.
3635     * @throws IOException If some I/O error occurs.
3636     * @throws LscpException If LSCP protocol corruption occurs.
3637     * @throws LSException If <code>channel</code> is not a valid channel
3638     * number or <code>fxSend</code> is not a valid effect send ID;
3639     */
3640     public synchronized void
3641     setFxSendName(int channel, int fxSend, String name)
3642     throws IOException, LscpException, LSException {
3643    
3644     verifyConnection();
3645     String args = " " + channel + " " + fxSend + " '" + name + "'";
3646     out.writeLine("SET FX_SEND NAME" + args);
3647     if(getPrintOnlyMode()) return;
3648    
3649     ResultSet rs = getEmptyResultSet();
3650     }
3651    
3652     /**
3653     * Sets the destination of an effect send's audio channel in the specified sampler channel.
3654     * @param channel The sampler channel number.
3655     * @param fxSend The numerical ID of the effect send entity to be rerouted.
3656     * @param audioSrc The numerical ID of the effect send's audio output channel,
3657     * which should be rerouted.
3658     * @param audioDst The audio channel of the selected audio output device
3659     * where <code>audioSrc</code> should be routed to.
3660     * @throws IOException If some I/O error occurs.
3661     * @throws LscpException If LSCP protocol corruption occurs.
3662     * @throws LSException If
3663     * <ul>
3664     * <li><code>channel</code> is not a valid channel number;
3665     * <li><code>fxSend</code> is not a valid effect send ID;
3666     * <li>There is no engine assigned yet to the specified sampler channel;
3667     * <li>There is no audio output device connected to the specified sampler channel.
3668     * </ul>
3669     */
3670     public synchronized void
3671     setFxSendAudioOutputChannel(int channel, int fxSend, int audioSrc, int audioDst)
3672     throws IOException, LscpException, LSException {
3673    
3674     verifyConnection();
3675     String args = " " + channel + " " + fxSend + " " + audioSrc + " " + audioDst;
3676     out.writeLine("SET FX_SEND AUDIO_OUTPUT_CHANNEL" + args);
3677     if(getPrintOnlyMode()) return;
3678    
3679     ResultSet rs = getEmptyResultSet();
3680     }
3681    
3682     /**
3683     * Sets the MIDI controller, which will be able to modify
3684     * the send level of the specified effect send in the specified sampler channel.
3685     * @param channel The sampler channel number.
3686     * @param fxSend The numerical ID of the effect send entity.
3687     * @param midiCtrl The MIDI controller which shall be
3688     * able to modify the effect send's send level.
3689     * @throws IOException If some I/O error occurs.
3690     * @throws LscpException If LSCP protocol corruption occurs.
3691     * @throws LSException If
3692     * <ul>
3693     * <li><code>channel</code> is not a valid channel number;
3694     * <li><code>fxSend</code> is not a valid effect send ID;
3695     * <li><code>midiCtrl</code> is not a valid controller;
3696     * </ul>
3697     */
3698     public synchronized void
3699     setFxSendMidiController(int channel, int fxSend, int midiCtrl)
3700     throws IOException, LscpException, LSException {
3701    
3702     verifyConnection();
3703     String args = " " + channel + " " + fxSend + " " + midiCtrl;
3704     out.writeLine("SET FX_SEND MIDI_CONTROLLER" + args);
3705     if(getPrintOnlyMode()) return;
3706    
3707     ResultSet rs = getEmptyResultSet();
3708     }
3709    
3710     /**
3711     * Sets the current send level of the specified
3712     * effect send entity in the specified sampler channel.
3713     * @param channel The sampler channel number.
3714     * @param fxSend The numerical ID of the effect send entity.
3715     * @param volume The new volume value (a value smaller than 1.0 means
3716     * attenuation, whereas a value greater than 1.0 means amplification).
3717     * @throws IOException If some I/O error occurs.
3718     * @throws LscpException If LSCP protocol corruption occurs.
3719     * @throws LSException If some other error occurs.
3720     */
3721     public synchronized void
3722     setFxSendLevel(int channel, int fxSend, float volume)
3723     throws IOException, LscpException, LSException {
3724    
3725     verifyConnection();
3726     String args = " " + channel + " " + fxSend + " " + String.valueOf(volume);
3727     out.writeLine("SET FX_SEND LEVEL" + args);
3728     if(getPrintOnlyMode()) return;
3729    
3730     ResultSet rs = getEmptyResultSet();
3731     }
3732    
3733 iliev 1202
3734    
3735 iliev 1139 /**
3736 iliev 1202 * Adds the specified directory to the instruments database.
3737     * @param dir The absolute path name of the directory to add.
3738     * @throws IOException If some I/O error occurs.
3739     * @throws LSException If the creation of the directory failed.
3740     * @throws LscpException If LSCP protocol corruption occurs.
3741     */
3742     public synchronized void
3743     addDbDirectory(String dir) throws IOException, LSException, LscpException {
3744     verifyConnection();
3745     out.writeLine("ADD DB_INSTRUMENT_DIRECTORY '" + dir + "'");
3746     if(getPrintOnlyMode()) return;
3747    
3748     ResultSet rs = getEmptyResultSet();
3749     }
3750    
3751     /**
3752     * Removes the specified directory from the instruments database.
3753     * @param dir The absolute path name of the directory to remove.
3754     * @throws IOException If some I/O error occurs.
3755     * @throws LscpException If LSCP protocol corruption occurs.
3756     * @throws LSException If the specified directory is not
3757     * empty or if the removal of the directory failed.
3758     */
3759     public synchronized void
3760     removeDbDirectory(String dir) throws IOException, LscpException, LSException {
3761     removeDbDirectory(dir, false);
3762     }
3763    
3764     /**
3765     * Removes the specified directory from the instruments database.
3766     * @param dir The absolute path name of the directory to remove.
3767     * @param force If <code>true</code> forces the removal of non-empty
3768     * directory and all its content.
3769     * @throws IOException If some I/O error occurs.
3770     * @throws LscpException If LSCP protocol corruption occurs.
3771     * @throws LSException If the removing of the directory failed.
3772     */
3773     public synchronized void
3774     removeDbDirectory(String dir, boolean force)
3775     throws IOException, LscpException, LSException {
3776    
3777     verifyConnection();
3778     String s = "REMOVE DB_INSTRUMENT_DIRECTORY ";
3779     if(force) s += "FORCE ";
3780     out.writeLine(s + "'" + dir + "'");
3781     if(getPrintOnlyMode()) return;
3782    
3783     ResultSet rs = getEmptyResultSet();
3784     }
3785    
3786     /**
3787     * Removes the specified directories from the instruments database.
3788     * @param dirs The absolute path names of the directories to remove.
3789     * @param force If <code>true</code> forces the removal of non-empty
3790     * directories.
3791     * @throws IOException If some I/O error occurs.
3792     * @throws LscpException If LSCP protocol corruption occurs.
3793     * @throws LSException If the removing of the directores failed.
3794     */
3795     public synchronized void
3796     removeDbDirectories(String[] dirs, boolean force)
3797     throws IOException, LscpException, LSException {
3798    
3799     verifyConnection();
3800     String cmd = "REMOVE DB_INSTRUMENT_DIRECTORY ";
3801     if(force) cmd += "FORCE ";
3802    
3803     for(String s : dirs) out.writeLine(cmd + "'" + s + "'");
3804    
3805     if(getPrintOnlyMode()) return;
3806    
3807     getEmptyResultSets(dirs.length, "Client.dirDeletionFailed!");
3808     }
3809    
3810     /**
3811     * Gets the number of directories in the specified directory.
3812     * @return The current number of directories in the specified directory.
3813     * @param dir The absolute path name of the directory.
3814     * @throws IOException If some I/O error occurs.
3815     * @throws LscpException If LSCP protocol corruption occurs.
3816     * @throws LSException If some other error occurs.
3817     */
3818     public synchronized int
3819     getDbDirectoryCount(String dir) throws IOException, LscpException, LSException {
3820     return getDbDirectoryCount(dir, false);
3821     }
3822    
3823     /**
3824     * Gets the number of directories in the specified directory.
3825     * @return The current number of directories in the specified directory.
3826     * @param dir The absolute path name of the directory.
3827     * @param recursive If <code>true</code>, the number of all directories
3828     * in the specified subtree will be returned.
3829     * @throws IOException If some I/O error occurs.
3830     * @throws LscpException If LSCP protocol corruption occurs.
3831     * @throws LSException If some other error occurs.
3832     */
3833     public synchronized int
3834     getDbDirectoryCount(String dir, boolean recursive)
3835     throws IOException, LscpException, LSException {
3836    
3837     verifyConnection();
3838     String s;
3839     if(recursive) s = "GET DB_INSTRUMENT_DIRECTORIES RECURSIVE '";
3840     else s = "GET DB_INSTRUMENT_DIRECTORIES '";
3841     out.writeLine(s + dir + "'");
3842     if(getPrintOnlyMode()) return -1;
3843    
3844     s = getSingleLineResultSet().getResult();
3845     return parseInt(s);
3846     }
3847    
3848     /**
3849     * Gets the list of directories in the specified directory.
3850     * @param dir The absolute path name of the directory.
3851     * @return A <code>String</code> array providing the names of
3852     * all directories in the specified directory.
3853     * @throws IOException If some I/O error occurs.
3854     * @throws LscpException If LSCP protocol corruption occurs.
3855     * @throws LSException If the specified path name is invalid.
3856     */
3857     public synchronized String[]
3858     getDbDirectoryNames(String dir) throws IOException, LscpException, LSException {
3859     verifyConnection();
3860     out.writeLine("LIST DB_INSTRUMENT_DIRECTORIES '" + dir + "'");
3861     if(getPrintOnlyMode()) return null;
3862    
3863 iliev 1326 return parseQuotedStringList(getSingleLineResultSet().getResult());
3864 iliev 1202 }
3865    
3866     /**
3867     * Gets information about the specified directory.
3868     * @param dir The absolute path name of the directory.
3869     * @return A <code>DbDirectoryInfo</code> instance providing information
3870     * about the specified directory.
3871     * @throws IOException If some I/O error occurs.
3872     * @throws LscpException If LSCP protocol corruption occurs.
3873     * @throws LSException If the specified directory is not found.
3874     */
3875     public synchronized DbDirectoryInfo
3876     getDbDirectoryInfo(String dir) throws IOException, LscpException, LSException {
3877     verifyConnection();
3878     out.writeLine("GET DB_INSTRUMENT_DIRECTORY INFO '" + dir + "'");
3879     if(getPrintOnlyMode()) return null;
3880    
3881     ResultSet rs = getMultiLineResultSet();
3882     DbDirectoryInfo info = new DbDirectoryInfo(rs.getMultiLineResult());
3883     if(dir.equals("/")) {
3884     info.setName("/");
3885     } else if(dir.length() > 1 && dir.charAt(dir.length() - 1) == '/') {
3886     dir = dir.substring(0, dir.length() - 1);
3887     }
3888     int i = dir.lastIndexOf('/');
3889     if(i != -1 && i < dir.length() - 1) {
3890     info.setName(dir.substring(i + 1));
3891     if(i == 0) info.setParentDirectoryPath("/");
3892     else info.setParentDirectoryPath(dir.substring(0, i));
3893     }
3894    
3895     return info;
3896     }
3897    
3898     /**
3899     * Gets the list of directories in the specified directory.
3900     * @param dir The absolute path name of the directory.
3901     * @return A <code>DbDirectoryInfo</code> array providing
3902     * information about all directories in the specified directory.
3903     * @throws IOException If some I/O error occurs.
3904     * @throws LscpException If LSCP protocol corruption occurs.
3905     * @throws LSException If the specified path name is invalid.
3906     */
3907     public synchronized DbDirectoryInfo[]
3908     getDbDirectories(String dir) throws IOException, LscpException, LSException {
3909     String[] dirS = getDbDirectoryNames(dir);
3910     if(dir.charAt(dir.length() - 1) != '/') dir += "/";
3911     DbDirectoryInfo[] infoS = new DbDirectoryInfo[dirS.length];
3912     for(int i = 0; i < dirS.length; i++) infoS[i] = getDbDirectoryInfo(dir + dirS[i]);
3913     return infoS;
3914     }
3915    
3916     /**
3917     * Gets the list of directories in the specified directory.
3918     * @param dir The absolute path name of the directory.
3919     * @return A <code>DbDirectoryInfo</code> array providing
3920     * information about all directories in the specified directory.
3921     * @throws IOException If some I/O error occurs.
3922     * @throws LscpException If LSCP protocol corruption occurs.
3923     * @throws LSException If the specified path name is invalid.
3924     *
3925     public synchronized DbDirectoryInfo[]
3926     getDbDirectories(String dir) throws IOException, LscpException, LSException {
3927     String[] dirS = getDbDirectoryNames(dir);
3928     if(dirS.length == 0) return new DbDirectoryInfo[0];
3929    
3930     if(dir.charAt(dir.length() - 1) != '/') dir += "/";
3931    
3932     for(int i = 0; i < dirS.length; i++) {
3933     out.writeLine("GET DB_INSTRUMENT_DIRECTORY INFO '" + dir + dirS[i] + "'");
3934     }
3935    
3936     if(getPrintOnlyMode()) return null;
3937    
3938     if(dir.length() > 1) dir = dir.substring(0, dir.length() - 1);
3939     StringBuffer sb = new StringBuffer();
3940     DbDirectoryInfo[] infoS = new DbDirectoryInfo[dirS.length];
3941     for(int i = 0; i < dirS.length; i++) {
3942     try {
3943     ResultSet rs = getMultiLineResultSet();
3944     infoS[i] = new DbDirectoryInfo(rs.getMultiLineResult());
3945     infoS[i].setName(dirS[i]);
3946     infoS[i].setParentDirectoryPath(dir);
3947     } catch (SocketTimeoutException e) {
3948     getLogger().log(Level.FINE, e.getMessage(), e);
3949     sb.append(e.getMessage()).append("\n");
3950     break;
3951     } catch (Exception e) {
3952     getLogger().log(Level.FINE, e.getMessage(), e);
3953     sb.append(e.getMessage()).append("\n");
3954     }
3955     }
3956    
3957     String details = sb.toString();
3958     if(details.length() > 0) {
3959     String err = LscpI18n.getLogMsg("Client.getInstrsInfoFailed!");
3960     throw new LSException(0, err, details);
3961     }
3962    
3963     return infoS;
3964     }*/
3965    
3966     /**
3967     * Renames the specified directory.
3968     * @param dir The absolute path name of the directory to rename.
3969     * @param name The new name for the directory.
3970     * @throws IOException If some I/O error occurs.
3971     * @throws LSException If the renaming of the directory failed.
3972     * @throws LscpException If LSCP protocol corruption occurs.
3973     */
3974     public synchronized void
3975     renameDbDirectory(String dir, String name) throws IOException, LSException, LscpException {
3976     verifyConnection();
3977     out.writeLine("SET DB_INSTRUMENT_DIRECTORY NAME '" + dir + "' '" + name + "'");
3978     if(getPrintOnlyMode()) return;
3979    
3980     ResultSet rs = getEmptyResultSet();
3981     }
3982    
3983     /**
3984     * Moves the specified directory into the specified location.
3985     * @param dir The absolute path name of the directory to move.
3986     * @param dst The location where the directory will be moved to.
3987     * @throws IOException If some I/O error occurs.
3988     * @throws LSException If the operation failed.
3989     * @throws LscpException If LSCP protocol corruption occurs.
3990     */
3991     public synchronized void
3992     moveDbDirectory(String dir, String dst) throws IOException, LSException, LscpException {
3993     verifyConnection();
3994     out.writeLine("MOVE DB_INSTRUMENT_DIRECTORY '" + dir + "' '" + dst + "'");
3995     if(getPrintOnlyMode()) return;
3996    
3997     ResultSet rs = getEmptyResultSet();
3998     }
3999    
4000     /**
4001     * Moves the specified directories into the specified location.
4002     * @param dirs The absolute path names of the directories to move.
4003     * @param dst The location where the directories will be moved to.
4004     * @throws IOException If some I/O error occurs.
4005     * @throws LSException If the operation failed.
4006     * @throws LscpException If LSCP protocol corruption occurs.
4007     */
4008     public synchronized void
4009     moveDbDirectories(String dirs[], String dst) throws IOException, LSException, LscpException {
4010     verifyConnection();
4011     for(String s : dirs) {
4012     out.writeLine("MOVE DB_INSTRUMENT_DIRECTORY '" + s + "' '" + dst + "'");
4013     }
4014     if(getPrintOnlyMode()) return;
4015    
4016     getEmptyResultSets(dirs.length, "Client.dirMovingFailed!");
4017     }
4018    
4019     /**
4020     * Copies the specified directory into the specified location.
4021     * @param dir The absolute path name of the directory to copy.
4022     * @param dst The location where the directory will be copied to.
4023     * @throws IOException If some I/O error occurs.
4024     * @throws LSException If the operation failed.
4025     * @throws LscpException If LSCP protocol corruption occurs.
4026     */
4027     public synchronized void
4028     copyDbDirectory(String dir, String dst) throws IOException, LSException, LscpException {
4029     verifyConnection();
4030     out.writeLine("COPY DB_INSTRUMENT_DIRECTORY '" + dir + "' '" + dst + "'");
4031     if(getPrintOnlyMode()) return;
4032    
4033     ResultSet rs = getEmptyResultSet();
4034     }
4035    
4036     /**
4037     * Copies the specified directories into the specified location.
4038     * @param dirs The absolute path names of the directories to copy.
4039     * @param dst The location where the directories will be copied to.
4040     * @throws IOException If some I/O error occurs.
4041     * @throws LSException If the operation failed.
4042     * @throws LscpException If LSCP protocol corruption occurs.
4043     */
4044     public synchronized void
4045     copyDbDirectories(String[] dirs, String dst) throws IOException, LSException, LscpException {
4046     verifyConnection();
4047     for(String s : dirs) {
4048     out.writeLine("COPY DB_INSTRUMENT_DIRECTORY '" + s + "' '" + dst + "'");
4049     }
4050     if(getPrintOnlyMode()) return;
4051    
4052     getEmptyResultSets(dirs.length, "Client.dirCopyingFailed!");
4053     }
4054    
4055     /**
4056     * Changes the description of the specified directory.
4057     * @param dir The absolute path name of the directory.
4058     * @param desc The new description for the directory.
4059     * @throws IOException If some I/O error occurs.
4060     * @throws LSException If failed to change the description.
4061     * @throws LscpException If LSCP protocol corruption occurs.
4062     */
4063     public synchronized void
4064     setDbDirectoryDescription(String dir, String desc)
4065     throws IOException, LSException, LscpException {
4066    
4067     verifyConnection();
4068     String s = "SET DB_INSTRUMENT_DIRECTORY DESCRIPTION '";
4069     out.writeLine(s + dir + "' '" + desc + "'");
4070     if(getPrintOnlyMode()) return;
4071    
4072     ResultSet rs = getEmptyResultSet();
4073     }
4074    
4075     public static enum ScanMode {
4076     RECURSIVE, NON_RECURSIVE, FLAT
4077     }
4078    
4079     /**
4080     * Adds the specified instrument to the specified instruments database directory.
4081     * @param dbDir The absolute path name of the database directory in which the
4082     * specified instrument will be added.
4083     * @param filePath The absolute path name of the instrument file.
4084     * @param instrIndex The index of the instrument (in the given instrument file) to add.
4085     * @throws IOException If some I/O error occurs.
4086     * @throws LSException If the operation failed.
4087     * @throws LscpException If LSCP protocol corruption occurs.
4088     */
4089     public synchronized void
4090     addDbInstrument(String dbDir, String filePath, int instrIndex)
4091     throws IOException, LSException, LscpException {
4092    
4093     addDbInstrument(dbDir, filePath, instrIndex, false);
4094     }
4095    
4096     /**
4097     * Adds the specified instrument to the specified instruments database directory.
4098     * @param dbDir The absolute path name of the database directory in which the
4099     * specified instrument will be added.
4100     * @param filePath The absolute path name of the instrument file.
4101     * @param instrIndex The index of the instrument (in the given instrument file) to add.
4102     * @param background If <code>true</code>, the scan will be done
4103     * in background and this method may return before the job is finished.
4104     * @return If <code>background</code> is <code>true</code>, the ID
4105     * of the scan job.
4106     * @throws IOException If some I/O error occurs.
4107     * @throws LSException If the operation failed.
4108     * @throws LscpException If LSCP protocol corruption occurs.
4109     * @see #addInstrumentsDbListener
4110     */
4111     public synchronized int
4112     addDbInstrument(String dbDir, String filePath, int instrIndex, boolean background)
4113     throws IOException, LSException, LscpException {
4114    
4115     verifyConnection();
4116     String s = "ADD DB_INSTRUMENTS";
4117     if(background) s += " NON_MODAL";
4118     s += " '" + dbDir + "' '" + filePath + "' ";
4119     out.writeLine(s + String.valueOf(instrIndex));
4120     if(getPrintOnlyMode()) return -1;
4121    
4122     ResultSet rs = getEmptyResultSet();
4123     return rs.getIndex();
4124     }
4125    
4126     /**
4127     * Adds the instruments in the specified file to the specified
4128     * instruments database directory.
4129     * @param dbDir The absolute path name of the database directory
4130     * in which the the supported instruments will be added.
4131     * @param filePath The absolute path name of the file to scan for instruments.
4132     * @throws IOException If some I/O error occurs.
4133     * @throws LSException If the operation failed.
4134     * @throws LscpException If LSCP protocol corruption occurs.
4135     */
4136     public synchronized void
4137     addDbInstruments(String dbDir, String filePath)
4138     throws IOException, LSException, LscpException {
4139    
4140     addDbInstruments(dbDir, filePath, false);
4141     }
4142    
4143     /**
4144     * Adds the instruments in the specified file to the specified
4145     * instruments database directory.
4146     * @param dbDir The absolute path name of the database directory
4147     * in which the the supported instruments will be added.
4148     * @param filePath The absolute path name of the file to scan for instruments.
4149     * @param background If <code>true</code>, the scan will be done
4150     * in background and this method may return before the job is finished.
4151     * @return If <code>background</code> is <code>true</code>, the ID
4152     * of the scan job.
4153     * @throws IOException If some I/O error occurs.
4154     * @throws LSException If the operation failed.
4155     * @throws LscpException If LSCP protocol corruption occurs.
4156     * @see #addInstrumentsDbListener
4157     */
4158     public synchronized int
4159     addDbInstruments(String dbDir, String filePath, boolean background)
4160     throws IOException, LSException, LscpException {
4161    
4162     verifyConnection();
4163     String s = "ADD DB_INSTRUMENTS";
4164     if(background) s += " NON_MODAL";
4165     out.writeLine(s + " '" + dbDir + "' '" + filePath + "'");
4166     if(getPrintOnlyMode()) return -1;
4167    
4168     ResultSet rs = getEmptyResultSet();
4169     return rs.getIndex();
4170     }
4171    
4172     /**
4173     * Adds the instruments in the specified file system directory
4174     * to the specified instruments database directory.
4175     * @param mode Determines the scanning mode. If RECURSIVE is
4176     * specified, all supported instruments in the specified file system
4177     * direcotry will be added to the specified instruments database
4178     * directory, including the instruments in subdirectories
4179     * of the supplied directory. If NON_RECURSIVE is specified,
4180     * the instruments in the subdirectories will not be processed.
4181     * If FLAT is specified, all supported instruments in the specified
4182     * file system direcotry will be added, including the instruments in
4183     * subdirectories of the supplied directory, but the respective
4184     * subdirectory structure will not be recreated in the instruments
4185     * database and all instruments will be added directly in the
4186     * specified database directory.
4187     * @param dbDir The absolute path name of the database directory
4188     * in which the supported instruments will be added.
4189     * @param fsDir The absolute path name of the file system directory.
4190     * @throws IOException If some I/O error occurs.
4191     * @throws LSException If the operation failed.
4192     * @throws LscpException If LSCP protocol corruption occurs.
4193     */
4194     public synchronized void
4195     addDbInstruments(ScanMode mode, String dbDir, String fsDir)
4196     throws IOException, LSException, LscpException {
4197    
4198     addDbInstruments(mode, dbDir, fsDir, false);
4199     }
4200    
4201     /**
4202     * Adds the instruments in the specified file system directory
4203     * to the specified instruments database directory.
4204     * @param mode Determines the scanning mode. If RECURSIVE is
4205     * specified, all supported instruments in the specified file system
4206     * direcotry will be added to the specified instruments database
4207     * directory, including the instruments in subdirectories
4208     * of the supplied directory. If NON_RECURSIVE is specified,
4209     * the instruments in the subdirectories will not be processed.
4210     * If FLAT is specified, all supported instruments in the specified
4211     * file system direcotry will be added, including the instruments in
4212     * subdirectories of the supplied directory, but the respective
4213     * subdirectory structure will not be recreated in the instruments
4214     * database and all instruments will be added directly in the
4215     * specified database directory.
4216     * @param dbDir The absolute path name of the database directory
4217     * in which the supported instruments will be added.
4218     * @param fsDir The absolute path name of the file system directory.
4219     * @param background If <code>true</code>, the scan will be done
4220     * in background and this method may return before the job is finished.
4221     * @return If <code>background</code> is <code>true</code>, the ID
4222     * of the scan job.
4223     * @throws IOException If some I/O error occurs.
4224     * @throws LSException If the operation failed.
4225     * @throws LscpException If LSCP protocol corruption occurs.
4226     * @see #addInstrumentsDbListener
4227     */
4228     public synchronized int
4229     addDbInstruments(ScanMode mode, String dbDir, String fsDir, boolean background)
4230     throws IOException, LSException, LscpException {
4231    
4232     verifyConnection();
4233     StringBuffer sb = new StringBuffer("ADD DB_INSTRUMENTS");
4234     if(background) sb.append(" NON_MODAL");
4235    
4236     switch(mode) {
4237     case RECURSIVE:
4238     sb.append(" RECURSIVE");
4239     break;
4240     case NON_RECURSIVE:
4241     sb.append(" NON_RECURSIVE");
4242     break;
4243     case FLAT:
4244     sb.append(" FLAT");
4245     break;
4246     }
4247    
4248     sb.append(" '").append(dbDir).append("' '").append(fsDir).append("'");
4249     out.writeLine(sb.toString());
4250     if(getPrintOnlyMode()) return -1;
4251    
4252     ResultSet rs = getEmptyResultSet();
4253     return rs.getIndex();
4254     }
4255    
4256     /**
4257     * Removes the specified instrument from the instruments database.
4258     * @param instr The absolute path name of the instrument to remove.
4259     * @throws IOException If some I/O error occurs.
4260     * @throws LscpException If LSCP protocol corruption occurs.
4261     * @throws LSException If the removing of the instrument failed.
4262     */
4263     public synchronized void
4264     removeDbInstrument(String instr) throws IOException, LscpException, LSException {
4265    
4266     verifyConnection();
4267     out.writeLine("REMOVE DB_INSTRUMENT '" + instr + "'");
4268     if(getPrintOnlyMode()) return;
4269    
4270     ResultSet rs = getEmptyResultSet();
4271     }
4272    
4273     /**
4274     * Removes the specified instruments from the instruments database.
4275     * @param instrs The absolute path names of the instruments to remove.
4276     * @throws IOException If some I/O error occurs.
4277     * @throws LscpException If LSCP protocol corruption occurs.
4278     * @throws LSException If the removing of the instruments failed.
4279     */
4280     public synchronized void
4281     removeDbInstruments(String[] instrs) throws IOException, LscpException, LSException {
4282     verifyConnection();
4283     for(String s : instrs) {
4284     out.writeLine("REMOVE DB_INSTRUMENT '" + s + "'");
4285     }
4286     if(getPrintOnlyMode()) return;
4287    
4288     getEmptyResultSets(instrs.length, "Client.instrDeletionFailed!");
4289     }
4290    
4291     /**
4292     * Gets the number of instruments in the specified directory.
4293     * @return The current number of instruments in the specified directory.
4294     * @param dir The absolute path name of the directory.
4295     * @throws IOException If some I/O error occurs.
4296     * @throws LscpException If LSCP protocol corruption occurs.
4297     * @throws LSException If some other error occurs.
4298     */
4299     public synchronized int
4300     getDbInstrumentCount(String dir) throws IOException, LscpException, LSException {
4301     return getDbInstrumentCount(dir, false);
4302     }
4303    
4304     /**
4305     * Gets the number of instruments in the specified directory.
4306     * @return The current number of instruments in the specified directory.
4307     * @param dir The absolute path name of the directory.
4308     * @param recursive If <code>true</code>, the number of all instruments
4309     * in the specified subtree will be returned.
4310     * @throws IOException If some I/O error occurs.
4311     * @throws LscpException If LSCP protocol corruption occurs.
4312     * @throws LSException If some other error occurs.
4313     */
4314     public synchronized int
4315     getDbInstrumentCount(String dir, boolean recursive)
4316     throws IOException, LscpException, LSException {
4317    
4318     verifyConnection();
4319     String s;
4320     if(recursive) s = "GET DB_INSTRUMENTS RECURSIVE '";
4321     else s = "GET DB_INSTRUMENTS '";
4322     out.writeLine(s + dir + "'");
4323     if(getPrintOnlyMode()) return -1;
4324    
4325     s = getSingleLineResultSet().getResult();
4326     return parseInt(s);
4327     }
4328    
4329     /**
4330     * Gets the list of instruments in the specified directory.
4331     * @param dir The absolute path name of the directory.
4332     * @return A <code>String</code> array providing the names of
4333     * all instruments in the specified directory.
4334     * @throws IOException If some I/O error occurs.
4335     * @throws LscpException If LSCP protocol corruption occurs.
4336     * @throws LSException If the specified path name is invalid.
4337     */
4338     public synchronized String[]
4339     getDbInstrumentNames(String dir) throws IOException, LscpException, LSException {
4340     verifyConnection();
4341     out.writeLine("LIST DB_INSTRUMENTS '" + dir + "'");
4342     if(getPrintOnlyMode()) return null;
4343    
4344 iliev 1326 return parseQuotedStringList(getSingleLineResultSet().getResult());
4345 iliev 1202 }
4346    
4347     /**
4348     * Gets information about the specified instrument.
4349     * @param instr The absolute path name of the instrument.
4350     * @return A <code>DbInstrumentInfo</code> instance providing information
4351     * about the specified instrument.
4352     * @throws IOException If some I/O error occurs.
4353     * @throws LscpException If LSCP protocol corruption occurs.
4354     * @throws LSException If the specified instrument is not found.
4355     */
4356     public synchronized DbInstrumentInfo
4357     getDbInstrumentInfo(String instr) throws IOException, LscpException, LSException {
4358     verifyConnection();
4359     out.writeLine("GET DB_INSTRUMENT INFO '" + instr + "'");
4360     if(getPrintOnlyMode()) return null;
4361    
4362     ResultSet rs = getMultiLineResultSet();
4363     DbInstrumentInfo info = new DbInstrumentInfo(rs.getMultiLineResult());
4364     int i = instr.lastIndexOf('/');
4365     if(i != -1 && i < instr.length() - 1) {
4366     info.setName(instr.substring(i + 1));
4367     if(i == 0) info.setDirectoryPath("/");
4368     else info.setDirectoryPath(instr.substring(0, i));
4369     }
4370    
4371     return info;
4372     }
4373    
4374     /**
4375     * Gets the list of instruments in the specified directory.
4376     * @param dir The absolute path name of the directory.
4377     * @return A <code>DbInstrumentInfo</code> array providing
4378     * information about all instruments in the specified directory.
4379     * @throws IOException If some I/O error occurs.
4380     * @throws LscpException If LSCP protocol corruption occurs.
4381     * @throws LSException If the specified path name is invalid.
4382     */
4383     public synchronized DbInstrumentInfo[]
4384     getDbInstruments(String dir) throws IOException, LscpException, LSException {
4385     String[] instrS = getDbInstrumentNames(dir);
4386     if(dir.charAt(dir.length() - 1) != '/') dir += "/";
4387    
4388     DbInstrumentInfo[] infoS = new DbInstrumentInfo[instrS.length];
4389     for(int i = 0; i < instrS.length; i++) {
4390     infoS[i] = getDbInstrumentInfo(dir + instrS[i]);
4391     }
4392     return infoS;
4393     }
4394    
4395     /**
4396     * Gets the list of instruments in the specified directory.
4397     * @param dir The absolute path name of the directory.
4398     * @return A <code>DbInstrumentInfo</code> array providing
4399     * information about all instruments in the specified directory.
4400     * @throws IOException If some I/O error occurs.
4401     * @throws LscpException If LSCP protocol corruption occurs.
4402     * @throws LSException If the specified path name is invalid.
4403     *
4404     public synchronized DbInstrumentInfo[]
4405     getDbInstruments(String dir) throws IOException, LscpException, LSException {
4406     String[] instrS = getDbInstrumentNames(dir);
4407     if(instrS.length == 0) return new DbInstrumentInfo[0];
4408    
4409     if(dir.charAt(dir.length() - 1) != '/') dir += "/";
4410    
4411     for(int i = 0; i < instrS.length; i++) {
4412     out.writeLine("GET DB_INSTRUMENT INFO '" + dir + instrS[i] + "'");
4413     }
4414    
4415     if(getPrintOnlyMode()) return null;
4416    
4417     if(dir.length() > 1) dir = dir.substring(0, dir.length() - 1);
4418     StringBuffer sb = new StringBuffer();
4419     DbInstrumentInfo[] infoS = new DbInstrumentInfo[instrS.length];
4420     for(int i = 0; i < instrS.length; i++) {
4421     try {
4422     ResultSet rs = getMultiLineResultSet();
4423     infoS[i] = new DbInstrumentInfo(rs.getMultiLineResult());
4424     infoS[i].setName(instrS[i]);
4425     infoS[i].setDirectoryPath(dir);
4426     } catch (SocketTimeoutException e) {
4427     getLogger().log(Level.FINE, e.getMessage(), e);
4428     sb.append(e.getMessage()).append("\n");
4429     break;
4430     } catch (Exception e) {
4431     getLogger().log(Level.FINE, e.getMessage(), e);
4432     sb.append(e.getMessage()).append("\n");
4433     }
4434     }
4435    
4436     String details = sb.toString();
4437     if(details.length() > 0) {
4438     String err = LscpI18n.getLogMsg("Client.getInstrsInfoFailed!");
4439     throw new LSException(0, err, details);
4440     }
4441    
4442     return infoS;
4443     }*/
4444    
4445     /**
4446     * Renames the specified instrument.
4447     * @param instr The absolute path name of the instrument to rename.
4448     * @param name The new name for the instrument.
4449     * @throws IOException If some I/O error occurs.
4450     * @throws LSException If the renaming of the instrument failed.
4451     * @throws LscpException If LSCP protocol corruption occurs.
4452     */
4453     public synchronized void
4454     renameDbInstrument(String instr, String name)
4455     throws IOException, LSException, LscpException {
4456    
4457     verifyConnection();
4458     out.writeLine("SET DB_INSTRUMENT NAME '" + instr + "' '" + name + "'");
4459     if(getPrintOnlyMode()) return;
4460    
4461     ResultSet rs = getEmptyResultSet();
4462     }
4463    
4464     /**
4465     * Moves the specified instrument into the specified location.
4466     * @param instr The absolute path name of the instrument to move.
4467     * @param dst The directory where the specified instrument will be moved to.
4468     * @throws IOException If some I/O error occurs.
4469     * @throws LSException If the operation failed.
4470     * @throws LscpException If LSCP protocol corruption occurs.
4471     */
4472     public synchronized void
4473     moveDbInstrument(String instr, String dst) throws IOException, LSException, LscpException {
4474     verifyConnection();
4475     out.writeLine("MOVE DB_INSTRUMENT '" + instr + "' '" + dst + "'");
4476     if(getPrintOnlyMode()) return;
4477    
4478     ResultSet rs = getEmptyResultSet();
4479     }
4480    
4481     /**
4482     * Moves the specified instruments into the specified location.
4483     * @param instrs The absolute path names of the instruments to move.
4484     * @param dst The directory where the specified instruments will be moved to.
4485     * @throws IOException If some I/O error occurs.
4486     * @throws LSException If the operation failed.
4487     * @throws LscpException If LSCP protocol corruption occurs.
4488     */
4489     public synchronized void
4490     moveDbInstruments(String[] instrs, String dst) throws IOException, LSException, LscpException {
4491     verifyConnection();
4492     for(String s : instrs) {
4493     out.writeLine("MOVE DB_INSTRUMENT '" + s + "' '" + dst + "'");
4494     }
4495     if(getPrintOnlyMode()) return;
4496    
4497     getEmptyResultSets(instrs.length, "Client.instrMovingFailed!");
4498     }
4499    
4500     /**
4501     * Copies the specified instrument into the specified location.
4502     * @param instr The absolute path name of the instrument to copy.
4503     * @param dst The directory where the specified instrument will be copied to.
4504     * @throws IOException If some I/O error occurs.
4505     * @throws LSException If the operation failed.
4506     * @throws LscpException If LSCP protocol corruption occurs.
4507     */
4508     public synchronized void
4509     copyDbInstrument(String instr, String dst) throws IOException, LSException, LscpException {
4510     verifyConnection();
4511     out.writeLine("COPY DB_INSTRUMENT '" + instr + "' '" + dst + "'");
4512     if(getPrintOnlyMode()) return;
4513    
4514     ResultSet rs = getEmptyResultSet();
4515     }
4516    
4517     /**
4518     * Copies the specified instruments into the specified location.
4519     * @param instrs The absolute path name of the instruments to copy.
4520     * @param dst The directory where the specified instruments will be copied to.
4521     * @throws IOException If some I/O error occurs.
4522     * @throws LSException If the operation failed.
4523     * @throws LscpException If LSCP protocol corruption occurs.
4524     */
4525     public synchronized void
4526     copyDbInstruments(String[] instrs, String dst) throws IOException, LSException, LscpException {
4527     verifyConnection();
4528     for(String s : instrs) {
4529     out.writeLine("COPY DB_INSTRUMENT '" + s + "' '" + dst + "'");
4530     }
4531     if(getPrintOnlyMode()) return;
4532    
4533     getEmptyResultSets(instrs.length, "Client.instrCopyingFailed!");
4534     }
4535    
4536     /**
4537     * Changes the description of the specified instrument.
4538     * @param instr The absolute path name of the instrument.
4539     * @param desc The new description for the instrument.
4540     * @throws IOException If some I/O error occurs.
4541     * @throws LSException If failed to change the description.
4542     * @throws LscpException If LSCP protocol corruption occurs.
4543     */
4544     public synchronized void
4545     setDbInstrumentDescription(String instr, String desc)
4546     throws IOException, LSException, LscpException {
4547    
4548     verifyConnection();
4549     out.writeLine("SET DB_INSTRUMENT DESCRIPTION '" + instr + "' '" + desc + "'");
4550     if(getPrintOnlyMode()) return;
4551    
4552     ResultSet rs = getEmptyResultSet();
4553     }
4554    
4555     /**
4556     * Finds all directories in the specified directory
4557     * that corresponds to the specified search criterias.
4558     * @param dir The absolute path name of the directory to search.
4559     * @param query Provides the search criterias.
4560     * @return A <code>DbDirectoryInfo</code> array providing
4561     * information about all directories that are found in the specified directory.
4562     * @throws IOException If some I/O error occurs.
4563     * @throws LscpException If LSCP protocol corruption occurs.
4564     * @throws LSException If the specified path name is invalid.
4565     */
4566     public synchronized DbDirectoryInfo[]
4567     findDbDirectories(String dir, DbSearchQuery query)
4568     throws IOException, LscpException, LSException {
4569    
4570     return findDbDirectories(dir, query, false);
4571     }
4572    
4573     /**
4574     * Finds all directories in the specified directory
4575     * that corresponds to the specified search criterias.
4576     * @param dir The absolute path name of the directory to search.
4577     * @param query Provides the search criterias.
4578     * @param nonRecursive If <code>true</code>, the search will be non-recursive.
4579     * @return A <code>DbDirectoryInfo</code> array providing
4580     * information about all directories that are found in the specified directory.
4581     * @throws IOException If some I/O error occurs.
4582     * @throws LscpException If LSCP protocol corruption occurs.
4583     * @throws LSException If the specified path name is invalid.
4584     */
4585     public synchronized DbDirectoryInfo[]
4586     findDbDirectories(String dir, DbSearchQuery query, boolean nonRecursive)
4587     throws IOException, LscpException, LSException {
4588    
4589     verifyConnection();
4590     StringBuffer sb = new StringBuffer();
4591     sb.append("FIND DB_INSTRUMENT_DIRECTORIES");
4592     if(nonRecursive) sb.append(" NON_RECURSIVE");
4593     sb.append(" '").append(dir).append("'");
4594    
4595     if(query.name != null && query.name.length() > 0) {
4596     sb.append(" NAME='").append(query.name).append("'");
4597     }
4598    
4599     String s = query.getCreatedAfter();
4600     String s2 = query.getCreatedBefore();
4601     if(s != null || s2 != null) {
4602     sb.append(" CREATED='");
4603     if(s != null) sb.append(s);
4604     sb.append("..");
4605     if(s2 != null) sb.append(s2);
4606     sb.append("'");
4607     }
4608    
4609     s = query.getModifiedAfter();
4610     s2 = query.getModifiedBefore();
4611     if(s != null || s2 != null) {
4612     sb.append(" MODIFIED='");
4613     if(s != null) sb.append(s);
4614     sb.append("..");
4615     if(s2 != null) sb.append(s2);
4616     sb.append("'");
4617     }
4618    
4619     if(query.description != null && query.description.length() > 0) {
4620     sb.append(" DESCRIPTION='").append(query.description).append("'");
4621     }
4622    
4623     out.writeLine(sb.toString());
4624     if(getPrintOnlyMode()) return null;
4625    
4626 iliev 1326 String[] dirS = parseQuotedStringList(getSingleLineResultSet().getResult());
4627 iliev 1202
4628     DbDirectoryInfo[] infoS = new DbDirectoryInfo[dirS.length];
4629     for(int i = 0; i < dirS.length; i++) {
4630     infoS[i] = getDbDirectoryInfo(dirS[i]);
4631     }
4632     return infoS;
4633     }
4634    
4635     /**
4636     * Finds all instruments in the specified directory
4637     * that corresponds to the specified search criterias.
4638     * @param dir The absolute path name of the directory to search.
4639     * @param query Provides the search criterias.
4640     * @return A <code>DbInstrumentInfo</code> array providing
4641     * information about all instruments that are found in the specified directory.
4642     * @throws IOException If some I/O error occurs.
4643     * @throws LscpException If LSCP protocol corruption occurs.
4644     * @throws LSException If the specified path name is invalid.
4645     */
4646     public synchronized DbInstrumentInfo[]
4647     findDbInstruments(String dir, DbSearchQuery query)
4648     throws IOException, LscpException, LSException {
4649    
4650     return findDbInstruments(dir, query, false);
4651     }
4652    
4653     /**
4654     * Finds all instruments in the specified directory
4655     * that corresponds to the specified search criterias.
4656     * @param dir The absolute path name of the directory to search.
4657     * @param query Provides the search criterias.
4658     * @param nonRecursive If <code>true</code>, the search will be non-recursive.
4659     * @return A <code>DbInstrumentInfo</code> array providing
4660     * information about all instruments that are found in the specified directory.
4661     * @throws IOException If some I/O error occurs.
4662     * @throws LscpException If LSCP protocol corruption occurs.
4663     * @throws LSException If the specified path name is invalid.
4664     */
4665     public synchronized DbInstrumentInfo[]
4666     findDbInstruments(String dir, DbSearchQuery query, boolean nonRecursive)
4667     throws IOException, LscpException, LSException {
4668    
4669     verifyConnection();
4670     StringBuffer sb = new StringBuffer();
4671     sb.append("FIND DB_INSTRUMENTS");
4672     if(nonRecursive) sb.append(" NON_RECURSIVE");
4673     sb.append(" '").append(dir).append("'");
4674    
4675     if(query.name != null && query.name.length() > 0) {
4676     sb.append(" NAME='").append(query.name).append("'");
4677     }
4678    
4679     if(query.formatFamilies.size() > 0) {
4680     sb.append(" FORMAT_FAMILIES='").append(query.formatFamilies.get(0));
4681     for(int i = 1; i < query.formatFamilies.size(); i++) {
4682     sb.append(',').append(query.formatFamilies.get(i));
4683     }
4684     sb.append("'");
4685     }
4686    
4687     if(query.minSize != -1 || query.maxSize != -1) {
4688     sb.append(" SIZE='");
4689     if(query.minSize != -1) sb.append(query.minSize);
4690     sb.append("..");
4691     if(query.maxSize != -1) sb.append(query.maxSize);
4692     sb.append("'");
4693     }
4694    
4695     String s = query.getCreatedAfter();
4696     String s2 = query.getCreatedBefore();
4697     if(s != null || s2 != null) {
4698     sb.append(" CREATED='");
4699     if(s != null) sb.append(s);
4700     sb.append("..");
4701     if(s2 != null) sb.append(s2);
4702     sb.append("'");
4703     }
4704    
4705     s = query.getModifiedAfter();
4706     s2 = query.getModifiedBefore();
4707     if(s != null || s2 != null) {
4708     sb.append(" MODIFIED='");
4709     if(s != null) sb.append(s);
4710     sb.append("..");
4711     if(s2 != null) sb.append(s2);
4712     sb.append("'");
4713     }
4714    
4715     if(query.description != null && query.description.length() > 0) {
4716     sb.append(" DESCRIPTION='").append(query.description).append("'");
4717     }
4718    
4719     if(query.instrumentType != DbSearchQuery.InstrumentType.BOTH) {
4720     sb.append(" IS_DRUM=");
4721     if(query.instrumentType == DbSearchQuery.InstrumentType.DRUM) {
4722     sb.append("'true'");
4723     } else {
4724     sb.append("'false'");
4725     }
4726     }
4727    
4728     if(query.product != null && query.product.length() > 0) {
4729     sb.append(" PRODUCT='").append(query.product).append("'");
4730     }
4731    
4732     if(query.artists != null && query.artists.length() > 0) {
4733     sb.append(" ARTISTS='").append(query.artists).append("'");
4734     }
4735    
4736     if(query.keywords != null && query.keywords.length() > 0) {
4737     sb.append(" KEYWORDS='").append(query.keywords).append("'");
4738     }
4739    
4740     out.writeLine(sb.toString());
4741     if(getPrintOnlyMode()) return null;
4742    
4743 iliev 1326 String[] instrS = parseQuotedStringList(getSingleLineResultSet().getResult());
4744 iliev 1202
4745     DbInstrumentInfo[] infoS = new DbInstrumentInfo[instrS.length];
4746     for(int i = 0; i < instrS.length; i++) {
4747     infoS[i] = getDbInstrumentInfo(instrS[i]);
4748     }
4749     return infoS;
4750     }
4751    
4752     /**
4753     * Gets status information about the specified job.
4754     * @param jobId The ID of the job.
4755     * @return A <code>ScanJobInfo</code> instance providing information
4756     * about the specified job.
4757     * @throws IOException If some I/O error occurs.
4758     * @throws LscpException If LSCP protocol corruption occurs.
4759     * @throws LSException If the specified job is not found.
4760     */
4761     public synchronized ScanJobInfo
4762     getDbInstrumentsJobInfo(int jobId) throws IOException, LscpException, LSException {
4763     verifyConnection();
4764     out.writeLine("GET DB_INSTRUMENTS_JOB INFO " + String.valueOf(jobId));
4765     if(getPrintOnlyMode()) return null;
4766    
4767     ResultSet rs = getMultiLineResultSet();
4768     ScanJobInfo info = new ScanJobInfo(rs.getMultiLineResult());
4769    
4770     return info;
4771     }
4772    
4773     /**
4774 iliev 596 * Resets the specified sampler channel.
4775     *
4776     * @param samplerChn The sampler channel number.
4777     *
4778     * @throws IOException If some I/O error occurs.
4779     * @throws LscpException If LSCP protocol corruption occurs.
4780     * @throws LSException If <code>samplerChn</code> is not a valid channel number or if
4781     * there is no engine assigned yet to the specified sampler channel.
4782     * @see #getSamplerChannels
4783     */
4784     public synchronized void
4785     resetChannel(int samplerChn) throws IOException, LscpException, LSException {
4786     verifyConnection();
4787     out.writeLine("RESET CHANNEL " + samplerChn);
4788 iliev 1139 if(getPrintOnlyMode()) return;
4789 iliev 596
4790     ResultSet rs = getEmptyResultSet();
4791     }
4792    
4793     /**
4794     * Resets the whole sampler.
4795     *
4796     * @throws IOException If some I/O error occurs.
4797     * @throws LscpException If LSCP protocol corruption occurs.
4798     */
4799     public synchronized void
4800     resetSampler() throws IOException, LscpException {
4801     verifyConnection();
4802     out.writeLine("RESET");
4803 iliev 1139 if(getPrintOnlyMode()) return;
4804    
4805 iliev 596 try { ResultSet rs = getEmptyResultSet(); }
4806     catch(LSException x) { getLogger().warning(x.getMessage()); }
4807     }
4808    
4809     /**
4810 iliev 784 * Gets the current number of all active voices.
4811     * @return The current number of all active voices.
4812     * @throws IOException If some I/O error occurs.
4813     * @throws LscpException If LSCP protocol corruption occurs.
4814     * @throws LSException If some other error occurs.
4815     */
4816     public synchronized int
4817     getTotalVoiceCount() throws IOException, LscpException, LSException {
4818     verifyConnection();
4819     out.writeLine("GET TOTAL_VOICE_COUNT");
4820 iliev 1139 if(getPrintOnlyMode()) return -1;
4821    
4822 iliev 784 String s = getSingleLineResultSet().getResult();
4823     return parseInt(s);
4824     }
4825    
4826     /**
4827     * Gets the maximum number of active voices.
4828     * @return The maximum number of active voices.
4829     * @throws IOException If some I/O error occurs.
4830     * @throws LscpException If LSCP protocol corruption occurs.
4831     * @throws LSException If some other error occurs.
4832     */
4833     public synchronized int
4834     getTotalVoiceCountMax() throws IOException, LscpException, LSException {
4835     verifyConnection();
4836     out.writeLine("GET TOTAL_VOICE_COUNT_MAX");
4837 iliev 1139 if(getPrintOnlyMode()) return -1;
4838    
4839 iliev 784 String s = getSingleLineResultSet().getResult();
4840     return parseInt(s);
4841     }
4842    
4843     /**
4844 iliev 596 * Gets information about the LinuxSampler instance.
4845     *
4846     * @return <code>ServerInfo</code> instance containing
4847     * information about the LinuxSampler instance.
4848     *
4849     * @throws IOException If an I/O error occurs.
4850     * @throws LscpException If LSCP protocol corruption occurs.
4851     * @throws LSException If some other error occurs.
4852     */
4853     public synchronized ServerInfo
4854     getServerInfo() throws IOException, LscpException, LSException {
4855     verifyConnection();
4856     out.writeLine("GET SERVER INFO");
4857 iliev 1139 if(getPrintOnlyMode()) return null;
4858    
4859 iliev 596 ResultSet rs = getMultiLineResultSet();
4860     return new ServerInfo(rs.getMultiLineResult());
4861     }
4862    
4863     /**
4864 iliev 1139 * Gets the golobal volume of the sampler.
4865     * @return The golobal volume of the sampler.
4866     * @throws IOException If some I/O error occurs.
4867     * @throws LscpException If LSCP protocol corruption occurs.
4868     * @throws LSException If some other error occurs.
4869     */
4870     public synchronized float
4871     getVolume() throws IOException, LscpException, LSException {
4872     verifyConnection();
4873     out.writeLine("GET VOLUME");
4874     if(getPrintOnlyMode()) return -1;
4875    
4876     String s = getSingleLineResultSet().getResult();
4877     return parseFloat(s);
4878     }
4879    
4880     /**
4881     * Sets the global volume of the sampler.
4882     * @param volume The new volume value.
4883     * @throws IOException If some I/O error occurs.
4884     * @throws LscpException If LSCP protocol corruption occurs.
4885     * @throws LSException If some other error occurs.
4886     * @see #getVolume
4887     */
4888     public synchronized void
4889     setVolume(float volume) throws IOException, LscpException, LSException {
4890    
4891     verifyConnection();
4892     out.writeLine("SET VOLUME " + volume);
4893     if(getPrintOnlyMode()) return;
4894    
4895     ResultSet rs = getEmptyResultSet();
4896     }
4897    
4898 iliev 1202 private void
4899     getEmptyResultSets(int count, String err) throws LSException {
4900     StringBuffer sb = new StringBuffer();
4901     for(int i = 0; i < count; i++) {
4902     try { getEmptyResultSet(); }
4903     catch (SocketTimeoutException e) {
4904     getLogger().log(Level.FINE, e.getMessage(), e);
4905     sb.append(e.getMessage()).append("\n");
4906     break;
4907     } catch (Exception e) {
4908     getLogger().log(Level.FINE, e.getMessage(), e);
4909     sb.append(e.getMessage()).append("\n");
4910     }
4911     }
4912    
4913     String details = sb.toString();
4914     if(details.length() > 0) {
4915     String s = LscpI18n.getLogMsg(err);
4916     throw new LSException(0, s, details);
4917     }
4918     }
4919    
4920 iliev 1139 /**
4921 iliev 596 * Returns the logger for this library.
4922     * @return The logger for this library.
4923     */
4924     protected static Logger
4925     getLogger() { return Logger.getLogger("org.linuxsampler.lscp"); }
4926     }

  ViewVC Help
Powered by ViewVC