/[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 1202 - (hide annotations) (download)
Thu May 24 20:17:25 2007 UTC (16 years, 10 months ago) by iliev
File size: 169464 byte(s)
* updated to version 0.5a

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     list = parseStringList(s.substring("NAME ".length()), ' ');
546     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     list = parseStringList(s.substring("NAME ".length()), ' ');
573     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     *
1359     * @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 671 private synchronized AudioOutputDriver
1369 iliev 596 getAudioOutputDriverInfo(String driverName) throws IOException, LscpException, LSException {
1370     verifyConnection();
1371     out.writeLine("GET AUDIO_OUTPUT_DRIVER INFO " + driverName);
1372 iliev 1139 if(getPrintOnlyMode()) return null;
1373    
1374 iliev 596 ResultSet rs = getMultiLineResultSet();
1375     AudioOutputDriver aod = new AudioOutputDriver(rs.getMultiLineResult());
1376     aod.setName(driverName);
1377    
1378     for(String s : aod.getParameterNames())
1379     aod.addParameter(getAudioOutputDriverParameterInfo(driverName, s));
1380    
1381     return aod;
1382     }
1383    
1384     /**
1385     * Gets detailed information about a specific audio output driver parameter.
1386     *
1387     * @param driver The name of the audio output driver.
1388     * @param param A specific parameter name for which information should be obtained.
1389     * @param deplist An optional list of parameters on which the sought parameter
1390     * <code>param</code> depends on. <code>Parameter</code> instances can be
1391     * easily created using {@link ParameterFactory} factory.
1392     *
1393     * @return <code>Parameter</code> object containing
1394     * information about the specified audio output driver parameter.
1395     *
1396     * @throws IOException If an I/O error occurs.
1397     * @throws LscpException If LSCP protocol corruption occurs.
1398     * @throws LSException If <code>driver</code> is not a valid driver name
1399     * or <code>param</code> is not a valid parameter for the specified driver.
1400     *
1401     * @see #getAudioOutputDrivers
1402     * @see #getAudioOutputDriverInfo
1403     * @see ParameterFactory
1404     */
1405     public synchronized Parameter
1406     getAudioOutputDriverParameterInfo(String driver, String param, Parameter... deplist)
1407     throws IOException, LscpException, LSException {
1408    
1409     verifyConnection();
1410     StringBuffer args = new StringBuffer(driver);
1411     args.append(' ').append(param);
1412    
1413     for(Parameter p : deplist)
1414     args.append(' ').append(p.getName()).append('=').append(p.getStringValue());
1415    
1416     out.writeLine("GET AUDIO_OUTPUT_DRIVER_PARAMETER INFO " + args.toString());
1417 iliev 1139 if(getPrintOnlyMode()) return null;
1418 iliev 596
1419     ResultSet rs = getMultiLineResultSet();
1420    
1421     String[] lnS = rs.getMultiLineResult();
1422     ParameterType type = parseType(lnS);
1423     boolean multi = parseMultiplicity(lnS);
1424     Parameter prm;
1425    
1426     switch(type) {
1427     case BOOL:
1428     if(!multi) prm = new BoolParameter(lnS);
1429     else prm = new BoolListParameter(lnS);
1430     prm.setName(param);
1431 iliev 784 prm.setValue(prm.getDefault());
1432 iliev 596 return prm;
1433     case INT:
1434     if(!multi) prm = new IntParameter(lnS);
1435     else prm = new IntListParameter(lnS);
1436     prm.setName(param);
1437 iliev 784 prm.setValue(prm.getDefault());
1438 iliev 596 return prm;
1439     case FLOAT:
1440     if(!multi) prm = new FloatParameter(lnS);
1441     else prm = new FloatListParameter(lnS);
1442     prm.setName(param);
1443 iliev 784 prm.setValue(prm.getDefault());
1444 iliev 596 return prm;
1445     case STRING:
1446     if(!multi) prm = new StringParameter(lnS);
1447     else prm = new StringListParameter(lnS);
1448     prm.setName(param);
1449 iliev 784 prm.setValue(prm.getDefault());
1450 iliev 596 return prm;
1451     default: throw new LscpException(LscpI18n.getLogMsg("Client.unknownPrmType!"));
1452     }
1453     }
1454    
1455     /**
1456     * Creates a new audio output device for the desired audio output system.
1457     * @param aoDriver The desired audio output system.
1458     * @param paramList An optional list of driver specific parameters. <code>Parameter</code>
1459     * instances can be easily created using {@link ParameterFactory} factory.
1460     * @return The numerical ID of the newly created device.
1461     * @throws IOException If some I/O error occurs.
1462     * @throws LSException If the creation of the new audio output device failed.
1463     * @throws LscpException If LSCP protocol corruption occurs.
1464     * @see #getAudioOutputDrivers
1465     * @see #getAudioOutputDriverInfo
1466     * @see ParameterFactory
1467     */
1468     public synchronized int
1469     createAudioOutputDevice(String aoDriver, Parameter... paramList)
1470     throws IOException, LSException, LscpException {
1471    
1472     verifyConnection();
1473     StringBuffer args = new StringBuffer(aoDriver);
1474    
1475     for(Parameter p : paramList)
1476     args.append(' ').append(p.getName()).append('=').append(p.getStringValue());
1477    
1478     out.writeLine("CREATE AUDIO_OUTPUT_DEVICE " + args.toString());
1479 iliev 1139 if(getPrintOnlyMode()) return -1;
1480    
1481 iliev 596 ResultSet rs = getEmptyResultSet();
1482    
1483     return rs.getIndex();
1484     }
1485    
1486     /**
1487     * Destroys already created audio output device.
1488 iliev 1139 * @param deviceId The ID of the audio output device to be destroyed.
1489 iliev 596 * @throws IOException If some I/O error occurs.
1490     * @throws LSException If the destroying of the audio output device failed.
1491     * @throws LscpException If LSCP protocol corruption occurs.
1492     * @see #getAudioOutputDevices
1493     */
1494     public synchronized void
1495 iliev 1139 destroyAudioOutputDevice(int deviceId) throws IOException, LSException, LscpException {
1496 iliev 596 verifyConnection();
1497 iliev 1139 out.writeLine("DESTROY AUDIO_OUTPUT_DEVICE " + deviceId);
1498     if(getPrintOnlyMode()) return;
1499    
1500 iliev 596 ResultSet rs = getEmptyResultSet();
1501     }
1502    
1503 iliev 784 /**
1504     * Enables/disables the specified audio output device.
1505 iliev 1139 * @param deviceId The ID of the audio output device to be enabled/disabled.
1506 iliev 784 * @param enable If <code>true</code> the audio output device is enabled,
1507     * else the device is disabled.
1508     * @throws IOException If some I/O error occurs.
1509     * @throws LSException If there is no audio output
1510 iliev 1139 * device with numerical ID <code>deviceId</code>.
1511 iliev 784 * @throws LscpException If LSCP protocol corruption occurs.
1512     */
1513     public void
1514 iliev 1139 enableAudioOutputDevice(int deviceId, boolean enable)
1515 iliev 784 throws IOException, LSException, LscpException {
1516    
1517 iliev 1139 setAudioOutputDeviceParameter(deviceId, new BoolParameter("ACTIVE", enable));
1518 iliev 784 }
1519    
1520 iliev 596 /**
1521     * Gets the current number of all created audio output devices.
1522     * @return The current number of all created audio output devices.
1523     * @throws IOException If some I/O error occurs.
1524     * @throws LscpException If LSCP protocol corruption occurs.
1525     * @throws LSException If some other error occurs.
1526     */
1527     public synchronized int
1528     getAudioOutputDeviceCount() throws IOException, LscpException, LSException {
1529     verifyConnection();
1530     out.writeLine("GET AUDIO_OUTPUT_DEVICES");
1531 iliev 1139 if(getPrintOnlyMode()) return -1;
1532    
1533 iliev 596 String s = getSingleLineResultSet().getResult();
1534     return parseInt(s);
1535     }
1536    
1537     /**
1538 iliev 784 * Gets a list of all created audio output devices.
1539     * @return An <code>AudioOutputDevice</code> array
1540     * providing all created audio output devices.
1541     * @throws IOException If some I/O error occurs.
1542     * @throws LscpException If LSCP protocol corruption occurs.
1543     * @throws LSException If some other error occurs.
1544     */
1545     public synchronized AudioOutputDevice[]
1546     getAudioOutputDevices() throws IOException, LscpException, LSException {
1547     Integer[] idS = getAudioOutputDeviceIDs();
1548 iliev 1139 if(getPrintOnlyMode()) return null;
1549    
1550 iliev 784 AudioOutputDevice[] devices = new AudioOutputDevice[idS.length];
1551    
1552     for(int i = 0; i < devices.length; i++)
1553     devices[i] = getAudioOutputDeviceInfo(idS[i]);
1554    
1555     return devices;
1556     }
1557    
1558     /**
1559 iliev 596 * Gets a list of numerical IDs of all created audio output devices.
1560 iliev 784 * @return An <code>Integer</code> array providing the numerical IDs of
1561 iliev 596 * all created audio output devices.
1562     * @throws IOException If some I/O error occurs.
1563     * @throws LscpException If LSCP protocol corruption occurs.
1564     * @throws LSException If some other error occurs.
1565     */
1566     public synchronized Integer[]
1567 iliev 784 getAudioOutputDeviceIDs() throws IOException, LscpException, LSException {
1568 iliev 596 verifyConnection();
1569     out.writeLine("LIST AUDIO_OUTPUT_DEVICES");
1570 iliev 1139 if(getPrintOnlyMode()) return null;
1571    
1572 iliev 596 return parseIntList(getSingleLineResultSet().getResult());
1573     }
1574    
1575     /**
1576     * Gets the current settings of a specific, already created audio output device.
1577     *
1578 iliev 1139 * @param deviceId Specifies the numerical ID of the audio output device.
1579 iliev 596 *
1580     * @return An <code>AudioOutputDevice</code> instance containing information
1581     * about the specified device.
1582     *
1583     * @throws IOException If some I/O error occurs.
1584     * @throws LscpException If LSCP protocol corruption occurs.
1585     * @throws LSException If there is no audio output device
1586 iliev 1139 * with device id <code>deviceId</code>.
1587 iliev 596 *
1588     * @see #getAudioOutputDevices
1589     */
1590     public synchronized AudioOutputDevice
1591 iliev 1139 getAudioOutputDeviceInfo(int deviceId) throws IOException, LscpException, LSException {
1592 iliev 596 verifyConnection();
1593 iliev 1139 out.writeLine("GET AUDIO_OUTPUT_DEVICE INFO " + deviceId);
1594     if(getPrintOnlyMode()) return null;
1595 iliev 596
1596     ResultSet rs = getMultiLineResultSet();
1597    
1598     String[] lnS = rs.getMultiLineResult();
1599    
1600     AudioOutputDevice aod = new AudioOutputDevice();
1601 iliev 1139 aod.setDeviceId(deviceId);
1602 iliev 596 Parameter<Integer> channels;
1603     Parameter<Integer> samplerate;
1604    
1605     String drv = getCategoryInfo(lnS, "DRIVER");
1606     aod.setDriverName(drv);
1607    
1608     for(String s : lnS) {
1609     if(s.startsWith("CHANNELS: ")) {
1610     channels = (Parameter<Integer>)
1611     getAudioOutputDriverParameterInfo(drv, "CHANNELS");
1612    
1613     s = s.substring("CHANNELS: ".length(), s.length());
1614     channels.parseValue(s);
1615     aod.setChannelsParameter(channels);
1616 iliev 784 int count = channels.getValue() > 0 ? channels.getValue() : 0;
1617     AudioOutputChannel[] aoc = new AudioOutputChannel[count];
1618     for(int i = 0; i < count; i++) {
1619 iliev 1139 aoc[i] = getAudioOutputChannelInfo(deviceId, i);
1620 iliev 784 }
1621     aod.setAudioChannels(aoc);
1622 iliev 596 } else if(s.startsWith("SAMPLERATE: ")) {
1623     samplerate = (Parameter<Integer>)
1624     getAudioOutputDriverParameterInfo(drv, "SAMPLERATE");
1625    
1626     s = s.substring("SAMPLERATE: ".length(), s.length());
1627     samplerate.parseValue(s);
1628     aod.setSampleRateParameter(samplerate);
1629     } else if(s.startsWith("ACTIVE: ")) {
1630     s = s.substring("ACTIVE: ".length(), s.length());
1631     aod.setActive(Boolean.parseBoolean(s));
1632     } else if(s.startsWith("DRIVER: ")) {
1633    
1634     } else {
1635     int i = s.indexOf(": ");
1636     if(i == -1) throw new LscpException (
1637     LscpI18n.getLogMsg("CommandFailed!")
1638     );
1639    
1640     Parameter prm =
1641     getAudioOutputDriverParameterInfo(drv, s.substring(0, i));
1642    
1643     s = s.substring(i + 2);
1644     prm.parseValue(s);
1645    
1646     aod.addParameter(prm);
1647     }
1648     }
1649    
1650     return aod;
1651     }
1652    
1653     /**
1654     * Alters a specific setting of a created audio output device.
1655     *
1656 iliev 1139 * @param deviceId The numerical ID of the audio output device.
1657 iliev 596 * @param prm A <code>Parameter</code> instance containing the name of the parameter
1658     * and the new value for this parameter.
1659     *
1660     * @throws IOException If some I/O error occurs.
1661     * @throws LscpException If LSCP protocol corruption occurs.
1662     * @throws LSException If
1663     * <ul>
1664 iliev 1139 * <li>There is no audio output device with numerical ID <code>deviceId</code>;
1665 iliev 596 * <li>There is no device parameter with the specified name;
1666     * <li>The device parameter is readonly;
1667     * <li>The device parameter is from different type.
1668     * </ul>
1669     *
1670     * @see #getAudioOutputDevices
1671     * @see #getAudioOutputDeviceInfo
1672     */
1673     public synchronized void
1674 iliev 1139 setAudioOutputDeviceParameter(int deviceId, Parameter prm)
1675 iliev 596 throws IOException, LscpException, LSException {
1676    
1677     verifyConnection();
1678     String kv = prm.getName() + '=' + prm.getStringValue();
1679 iliev 1139 out.writeLine("SET AUDIO_OUTPUT_DEVICE_PARAMETER " + deviceId + ' ' + kv);
1680     if(getPrintOnlyMode()) return;
1681 iliev 596
1682     ResultSet rs = getEmptyResultSet();
1683     }
1684    
1685     /**
1686 iliev 1139 * Changes the channel number of the speicifed audio output device.
1687     * @param deviceId The numerical ID of the audio output device.
1688 iliev 784 * @param channels The new number of audio output channels.
1689     *
1690     * @throws IOException If an I/O error occurs.
1691     * @throws LscpException If LSCP protocol corruption occurs.
1692 iliev 1139 * @throws LSException If there is no device with ID <code>deviceId</code> or
1693 iliev 784 * if <code>channels</code> number is out of range.
1694     *
1695     * @see #getAudioOutputChannelInfo
1696     */
1697     public synchronized void
1698 iliev 1139 setAudioOutputChannelCount(int deviceId, int channels)
1699 iliev 784 throws IOException, LscpException, LSException {
1700    
1701 iliev 1139 setAudioOutputDeviceParameter(deviceId, new IntParameter("CHANNELS", channels));
1702 iliev 784 }
1703    
1704     /**
1705 iliev 596 * Gets information about an audio channel.
1706     *
1707 iliev 1139 * @param deviceId The numerical ID of the audio output device.
1708 iliev 596 * @param audioChn The audio channel number.
1709     *
1710     * @return An <code>AudioOutputChannel</code> instance containing the
1711     * information about the specified audio output channel.
1712     *
1713     * @throws IOException If some I/O error occurs.
1714     * @throws LscpException If LSCP protocol corruption occurs.
1715     * @throws LSException If
1716     * <ul>
1717 iliev 1139 * <li>There is no audio output device with numerical ID <code>deviceId</code>;
1718 iliev 596 * <li><code>audioChn</code> is not a valid channel number;
1719     * </ul>
1720     *
1721     * @see #getAudioOutputDevices
1722     * @see #getAudioOutputDeviceInfo
1723     */
1724     public synchronized AudioOutputChannel
1725 iliev 1139 getAudioOutputChannelInfo(int deviceId, int audioChn)
1726 iliev 596 throws IOException, LscpException, LSException {
1727    
1728     verifyConnection();
1729 iliev 1139 out.writeLine("GET AUDIO_OUTPUT_CHANNEL INFO " + deviceId + ' ' + audioChn);
1730     if(getPrintOnlyMode()) return null;
1731 iliev 596
1732     ResultSet rs = getMultiLineResultSet();
1733    
1734     AudioOutputChannel aoc = new AudioOutputChannel();
1735    
1736     String[] lnS = rs.getMultiLineResult();
1737     for(String s : lnS) {
1738     if(s.startsWith("NAME: ")) {
1739 iliev 784 s = s.substring("NAME: ".length());
1740     Parameter<String> prm = getAudioOutputChannelParameterInfo (
1741 iliev 1139 deviceId, audioChn, "NAME"
1742 iliev 784 );
1743     prm.setValue(removeQuotation(s));
1744     aoc.setNameParameter(prm);
1745 iliev 596 } else if(s.startsWith("IS_MIX_CHANNEL: ")) {
1746     s = s.substring("IS_MIX_CHANNEL: ".length());
1747 iliev 784 Parameter<Boolean> prm = getAudioOutputChannelParameterInfo (
1748 iliev 1139 deviceId, audioChn, "IS_MIX_CHANNEL"
1749 iliev 784 );
1750     prm.setValue(Boolean.parseBoolean(s));
1751     aoc.setMixChannelParameter(prm);
1752 iliev 596 } else if(s.startsWith("MIX_CHANNEL_DESTINATION: ")) {
1753     s = s.substring("MIX_CHANNEL_DESTINATION: ".length());
1754 iliev 784 Parameter<Integer> prm = getAudioOutputChannelParameterInfo (
1755 iliev 1139 deviceId, audioChn, "MIX_CHANNEL_DESTINATION"
1756 iliev 784 );
1757     prm.setValue(parseInt(s));
1758     aoc.setMixChannelDestParameter(prm);
1759 iliev 596 } else {
1760     int i = s.indexOf(": ");
1761     if(i == -1) throw new LscpException (
1762     LscpI18n.getLogMsg("CommandFailed!")
1763     );
1764    
1765     Parameter prm = getAudioOutputChannelParameterInfo (
1766 iliev 1139 deviceId, audioChn, s.substring(0, i)
1767 iliev 596 );
1768    
1769     s = s.substring(i + 2);
1770     prm.parseValue(s);
1771    
1772     aoc.addParameter(prm);
1773     }
1774     }
1775    
1776     return aoc;
1777     }
1778    
1779     /**
1780     * Gets detailed information about a specific audio output channel parameter.
1781     *
1782 iliev 1139 * @param devId The numerical ID of the audio output device.
1783 iliev 596 * @param chan The audio channel number.
1784     * @param param a specific channel parameter name for which information should be obtained.
1785     *
1786     * @return An <code>Parameter</code> instance containing
1787     * information about the specified audio output channel parameter.
1788     *
1789     * @throws IOException If an I/O error occurs.
1790     * @throws LscpException If LSCP protocol corruption occurs.
1791     * @throws LSException If
1792     * <ul>
1793 iliev 1139 * <li><code>devId</code> is not a valid device ID;
1794 iliev 596 * <li><code>chan</code> is not a valid channel number;
1795     * <li>There is no channel parameter with the specified name.
1796     * </ul>
1797     *
1798     * @see #getAudioOutputDevices
1799     * @see #getAudioOutputChannelInfo
1800     */
1801     public synchronized Parameter
1802 iliev 1139 getAudioOutputChannelParameterInfo(int devId, int chan, String param)
1803 iliev 596 throws IOException, LscpException, LSException {
1804    
1805     verifyConnection();
1806 iliev 1139 String args = devId + " " + chan + " " + param;
1807 iliev 596 out.writeLine("GET AUDIO_OUTPUT_CHANNEL_PARAMETER INFO " + args);
1808 iliev 1139 if(getPrintOnlyMode()) return null;
1809 iliev 596
1810     ResultSet rs = getMultiLineResultSet();
1811    
1812     String[] lnS = rs.getMultiLineResult();
1813     ParameterType type = parseType(lnS);
1814     boolean multi = parseMultiplicity(lnS);
1815     Parameter prm;
1816    
1817     switch(type) {
1818     case BOOL:
1819     if(!multi) prm = new BoolParameter(lnS);
1820     else prm = new BoolListParameter(lnS);
1821     prm.setName(param);
1822     return prm;
1823     case INT:
1824     if(!multi) prm = new IntParameter(lnS);
1825     else prm = new IntListParameter(lnS);
1826     prm.setName(param);
1827     return prm;
1828     case FLOAT:
1829     if(!multi) prm = new FloatParameter(lnS);
1830     else prm = new FloatListParameter(lnS);
1831     prm.setName(param);
1832     return prm;
1833     case STRING:
1834     if(!multi) prm = new StringParameter(lnS);
1835     else prm = new StringListParameter(lnS);
1836     prm.setName(param);
1837     return prm;
1838     default: throw new LscpException(LscpI18n.getLogMsg("Client.unknownPrmType!"));
1839     }
1840     }
1841    
1842     /**
1843     * Alters a specific setting of an audio output channel.
1844     *
1845 iliev 1139 * @param devId The numerical ID of the audio device.
1846 iliev 596 * @param chn The audio channel number.
1847     * @param prm A <code>Parameter</code> instance containing the name of the parameter
1848     * and the new value for this parameter.
1849     *
1850     * @throws IOException If some I/O error occurs.
1851     * @throws LscpException If LSCP protocol corruption occurs.
1852     * @throws LSException If
1853     * <ul>
1854 iliev 1139 * <li>There is no audio output device with numerical ID <code>devId</code>;
1855 iliev 596 * <li><code>chn</code> is not a valid channel number;
1856     * <li>There is no channel parameter with the specified name;
1857     * <li>The channel parameter is readonly;
1858     * <li>The channel parameter is from different type.
1859     * </ul>
1860     *
1861     * @see #getAudioOutputDevices
1862     * @see #getAudioOutputChannelInfo
1863     */
1864     public synchronized void
1865 iliev 1139 setAudioOutputChannelParameter(int devId, int chn, Parameter prm)
1866 iliev 596 throws IOException, LscpException, LSException {
1867    
1868     verifyConnection();
1869 iliev 1139 String args = devId + " " + chn + " " + prm.getName() + '=' + prm.getStringValue();
1870 iliev 596 out.writeLine("SET AUDIO_OUTPUT_CHANNEL_PARAMETER " + args);
1871 iliev 1139 if(getPrintOnlyMode()) return;
1872 iliev 596
1873     ResultSet rs = getEmptyResultSet();
1874     }
1875    
1876     /**
1877     * Gets the current number of all MIDI input drivers.
1878     * @return The current number of all MIDI input drivers.
1879     * @throws IOException If some I/O error occurs.
1880     * @throws LscpException If LSCP protocol corruption occurs.
1881     * @throws LSException If some other error occurs.
1882     */
1883     public synchronized int
1884     getMidiInputDriverCount() throws IOException, LscpException, LSException {
1885     verifyConnection();
1886     out.writeLine("GET AVAILABLE_MIDI_INPUT_DRIVERS");
1887 iliev 1139 if(getPrintOnlyMode()) return -1;
1888    
1889 iliev 596 String s = getSingleLineResultSet().getResult();
1890     return parseInt(s);
1891     }
1892    
1893     /**
1894     * Gets all MIDI input drivers currently available for the LinuxSampler instance.
1895     *
1896 iliev 671 * @return <code>MidiInputDriver</code> array containing all MIDI input drivers currently
1897     * available for the LinuxSampler instance.
1898 iliev 596 *
1899     * @throws IOException If an I/O error occurs.
1900     * @throws LscpException If LSCP protocol corruption occurs.
1901     * @throws LSException If some other error occurs.
1902     */
1903 iliev 671 public synchronized MidiInputDriver[]
1904 iliev 596 getMidiInputDrivers() throws IOException, LscpException, LSException {
1905 iliev 671 String[] drivers = getMidiInputDriverNames();
1906 iliev 1139 if(getPrintOnlyMode()) return null;
1907    
1908 iliev 671 MidiInputDriver[] mid = new MidiInputDriver[drivers.length];
1909    
1910     for(int i = 0; i < mid.length; i++) mid[i] = getMidiInputDriverInfo(drivers[i]);
1911    
1912     return mid;
1913     }
1914    
1915     /**
1916     * Gets all MIDI input drivers currently available for the LinuxSampler instance.
1917     *
1918     * @return <code>String</code> array containing all MIDI input drivers currently available
1919     * for the LinuxSampler instance.
1920     *
1921     * @throws IOException If an I/O error occurs.
1922     * @throws LscpException If LSCP protocol corruption occurs.
1923     * @throws LSException If some other error occurs.
1924     */
1925     private synchronized String[]
1926     getMidiInputDriverNames() throws IOException, LscpException, LSException {
1927 iliev 596 verifyConnection();
1928     out.writeLine("LIST AVAILABLE_MIDI_INPUT_DRIVERS");
1929 iliev 1139 if(getPrintOnlyMode()) return null;
1930    
1931 iliev 596 return parseList(getSingleLineResultSet().getResult());
1932     }
1933    
1934     /**
1935     * Gets detailed information about a specific MIDI input driver.
1936     * @param driverName The name of the MIDI input driver.
1937     *
1938 iliev 671 * @return A <code>MidiInputDriver</code> object containing
1939 iliev 596 * information about the specified MIDI input driver.
1940     *
1941     * @throws IOException If an I/O error occurs.
1942     * @throws LscpException If LSCP protocol corruption occurs.
1943     * @throws LSException If there is no driver with name <code>driverName</code>.
1944     *
1945 iliev 671 * @see #getMidiInputDriverNames
1946 iliev 596 */
1947 iliev 671 private synchronized MidiInputDriver
1948 iliev 596 getMidiInputDriverInfo(String driverName) throws IOException, LscpException, LSException {
1949     verifyConnection();
1950     out.writeLine("GET MIDI_INPUT_DRIVER INFO " + driverName);
1951 iliev 1139 if(getPrintOnlyMode()) return null;
1952    
1953 iliev 596 ResultSet rs = getMultiLineResultSet();
1954    
1955     MidiInputDriver mid = new MidiInputDriver(rs.getMultiLineResult());
1956     mid.setName(driverName);
1957    
1958     for(String s : mid.getParameterNames())
1959     mid.addParameter(getMidiInputDriverParameterInfo(driverName, s));
1960    
1961     return mid;
1962     }
1963    
1964     /**
1965     * Gets detailed information about a specific MIDI input driver parameter.
1966     *
1967     * @param driver The name of the MIDI input driver.
1968     * @param param a specific parameter name for which information should be obtained.
1969     * @param deplist An optional list of parameters on which the sought parameter
1970     * <code>param</code> depends on. <code>Parameter</code> instances can be
1971     * easily created using {@link ParameterFactory} factory.
1972     *
1973 iliev 671 * @return A <code>Parameter</code> object containing
1974 iliev 596 * information about the specified MIDI input driver parameter.
1975     *
1976     * @throws IOException If an I/O error occurs.
1977     * @throws LscpException If LSCP protocol corruption occurs.
1978     * @throws LSException If <code>driver</code> is not a valid driver name
1979     * or <code>param</code> is not a valid parameter for the specified driver.
1980     *
1981     * @see #getMidiInputDrivers
1982     * @see #getMidiInputDriverInfo
1983     * @see ParameterFactory
1984     */
1985     public synchronized Parameter
1986     getMidiInputDriverParameterInfo(String driver, String param, Parameter... deplist)
1987     throws IOException, LscpException, LSException {
1988    
1989     verifyConnection();
1990     StringBuffer args = new StringBuffer(driver);
1991     args.append(' ').append(param);
1992    
1993     for(Parameter p : deplist)
1994     args.append(' ').append(p.getName()).append('=').append(p.getStringValue());
1995    
1996     out.writeLine("GET MIDI_INPUT_DRIVER_PARAMETER INFO " + args.toString());
1997 iliev 1139 if(getPrintOnlyMode()) return null;
1998 iliev 596
1999     ResultSet rs = getMultiLineResultSet();
2000    
2001     String[] lnS = rs.getMultiLineResult();
2002     ParameterType type = parseType(lnS);
2003     boolean multi = parseMultiplicity(lnS);
2004     Parameter prm;
2005    
2006     switch(type) {
2007     case BOOL:
2008     if(!multi) prm = new BoolParameter(lnS);
2009     else prm = new BoolListParameter(lnS);
2010     prm.setName(param);
2011 iliev 784 prm.setValue(prm.getDefault());
2012 iliev 596 return prm;
2013     case INT:
2014     if(!multi) prm = new IntParameter(lnS);
2015     else prm = new IntListParameter(lnS);
2016     prm.setName(param);
2017 iliev 784 prm.setValue(prm.getDefault());
2018 iliev 596 return prm;
2019     case FLOAT:
2020     if(!multi) prm = new FloatParameter(lnS);
2021     else prm = new FloatListParameter(lnS);
2022     prm.setName(param);
2023 iliev 784 prm.setValue(prm.getDefault());
2024 iliev 596 return prm;
2025     case STRING:
2026     if(!multi) prm = new StringParameter(lnS);
2027     else prm = new StringListParameter(lnS);
2028     prm.setName(param);
2029 iliev 784 prm.setValue(prm.getDefault());
2030 iliev 596 return prm;
2031     default: throw new LscpException(LscpI18n.getLogMsg("Client.unknownPrmType!"));
2032     }
2033     }
2034    
2035     /**
2036     * Creates a new MIDI input device.
2037     * @param miDriver The desired MIDI input system.
2038     * @param paramList An optional list of driver specific parameters. <code>Parameter</code>
2039     * instances can be easily created using {@link ParameterFactory} factory.
2040     * @return The numerical ID of the newly created device.
2041     * @throws IOException If some I/O error occurs.
2042     * @throws LSException If the creation of the new MIDI input device failed.
2043     * @throws LscpException If LSCP protocol corruption occurs.
2044     *
2045     * @see #getMidiInputDrivers
2046     * @see #getMidiInputDriverInfo
2047     * @see ParameterFactory
2048     */
2049     public synchronized int
2050     createMidiInputDevice(String miDriver, Parameter... paramList)
2051     throws IOException, LSException, LscpException {
2052    
2053     verifyConnection();
2054     StringBuffer args = new StringBuffer(miDriver);
2055    
2056     for(Parameter p : paramList)
2057     args.append(' ').append(p.getName()).append('=').append(p.getStringValue());
2058    
2059     out.writeLine("CREATE MIDI_INPUT_DEVICE " + args.toString());
2060 iliev 1139 if(getPrintOnlyMode()) return -1;
2061    
2062 iliev 596 ResultSet rs = getEmptyResultSet();
2063    
2064     return rs.getIndex();
2065     }
2066    
2067     /**
2068     * Destroys already created MIDI input device.
2069 iliev 1139 * @param deviceId The numerical ID of the MIDI input device to be destroyed.
2070 iliev 596 * @throws IOException If some I/O error occurs.
2071     * @throws LSException If the destroying of the MIDI input device failed.
2072     * @throws LscpException If LSCP protocol corruption occurs.
2073     * @see #createMidiInputDevice
2074     * @see #getMidiInputDevices
2075     */
2076     public synchronized void
2077 iliev 1139 destroyMidiInputDevice(int deviceId) throws IOException, LSException, LscpException {
2078 iliev 596 verifyConnection();
2079 iliev 1139 out.writeLine("DESTROY MIDI_INPUT_DEVICE " + deviceId);
2080     if(getPrintOnlyMode()) return;
2081    
2082 iliev 596 ResultSet rs = getEmptyResultSet();
2083     }
2084    
2085 iliev 784 /**
2086     * Enables/disables the specified MIDI input device.
2087 iliev 1139 * @param deviceId The ID of the MIDI input device to be enabled/disabled.
2088 iliev 784 * @param enable If <code>true</code> the MIDI input device is enabled,
2089     * else the device is disabled.
2090     * @throws IOException If some I/O error occurs.
2091     * @throws LSException If there is no MIDI input
2092 iliev 1139 * device with numerical ID <code>deviceId</code>.
2093 iliev 784 * @throws LscpException If LSCP protocol corruption occurs.
2094     */
2095     public void
2096 iliev 1139 enableMidiInputDevice(int deviceId, boolean enable)
2097 iliev 784 throws IOException, LSException, LscpException {
2098    
2099 iliev 1139 setMidiInputDeviceParameter(deviceId, new BoolParameter("ACTIVE", enable));
2100 iliev 784 }
2101    
2102 iliev 596 /**
2103     * Gets the current number of all created MIDI input devices.
2104     * @return The current number of all created MIDI input devices.
2105     * @throws IOException If some I/O error occurs.
2106     * @throws LscpException If LSCP protocol corruption occurs.
2107     * @throws LSException If some other error occurs.
2108     */
2109     public synchronized int
2110     getMidiInputDeviceCount() throws IOException, LscpException, LSException {
2111     verifyConnection();
2112     out.writeLine("GET MIDI_INPUT_DEVICES");
2113 iliev 1139 if(getPrintOnlyMode()) return -1;
2114    
2115 iliev 596 String s = getSingleLineResultSet().getResult();
2116     return parseInt(s);
2117     }
2118    
2119     /**
2120 iliev 784 * Gets a list of all created MIDI input devices.
2121     * @return A <code>MidiInputDevice</code> array
2122     * providing all created MIDI input devices.
2123     * @throws IOException If some I/O error occurs.
2124     * @throws LscpException If LSCP protocol corruption occurs.
2125     * @throws LSException If some other error occurs.
2126     *
2127     * @see #createMidiInputDevice
2128     * @see #destroyMidiInputDevice
2129     */
2130     public synchronized MidiInputDevice[]
2131     getMidiInputDevices() throws IOException, LscpException, LSException {
2132     Integer[] idS = getMidiInputDeviceIDs();
2133 iliev 1139 if(getPrintOnlyMode()) return null;
2134    
2135 iliev 784 MidiInputDevice[] devices = new MidiInputDevice[idS.length];
2136    
2137     for(int i = 0; i < devices.length; i++)
2138     devices[i] = getMidiInputDeviceInfo(idS[i]);
2139    
2140     return devices;
2141     }
2142    
2143     /**
2144 iliev 596 * Gets a list of numerical IDs of all created MIDI input devices.
2145 iliev 784 * @return An <code>Integer</code> array providing the numerical IDs of
2146 iliev 596 * all created MIDI input devices.
2147     * @throws IOException If some I/O error occurs.
2148     * @throws LscpException If LSCP protocol corruption occurs.
2149     * @throws LSException If some other error occurs.
2150     *
2151     * @see #createMidiInputDevice
2152     * @see #destroyMidiInputDevice
2153     */
2154     public synchronized Integer[]
2155 iliev 784 getMidiInputDeviceIDs() throws IOException, LscpException, LSException {
2156 iliev 596 verifyConnection();
2157     out.writeLine("LIST MIDI_INPUT_DEVICES");
2158 iliev 1139 if(getPrintOnlyMode()) return null;
2159    
2160 iliev 596 return parseIntList(getSingleLineResultSet().getResult());
2161     }
2162    
2163     /**
2164     * Gets the current settings of a specific, already created MIDI input device.
2165     *
2166 iliev 1139 * @param deviceId Specifies the numerical ID of the MIDI input device.
2167 iliev 596 *
2168 iliev 1139 * @return A <code>MidiInputDevice</code> instance containing information
2169 iliev 596 * about the specified device.
2170     *
2171     * @throws IOException If some I/O error occurs.
2172     * @throws LscpException If LSCP protocol corruption occurs.
2173     * @throws LSException If there is no MIDI input device
2174 iliev 1139 * with device id <code>deviceId</code>.
2175 iliev 596 *
2176     * @see #getMidiInputDevices
2177     */
2178     public synchronized MidiInputDevice
2179 iliev 1139 getMidiInputDeviceInfo(int deviceId) throws IOException, LscpException, LSException {
2180 iliev 596 verifyConnection();
2181 iliev 1139 out.writeLine("GET MIDI_INPUT_DEVICE INFO " + deviceId);
2182     if(getPrintOnlyMode()) return null;
2183 iliev 596
2184     ResultSet rs = getMultiLineResultSet();
2185    
2186     String[] lnS = rs.getMultiLineResult();
2187    
2188     MidiInputDevice mid = new MidiInputDevice();
2189 iliev 1139 mid.setDeviceId(deviceId);
2190 iliev 596
2191     String drv = getCategoryInfo(lnS, "DRIVER");
2192     mid.setDriverName(drv);
2193    
2194     for(String s : lnS) {
2195     if(s.startsWith("DRIVER: ")) {
2196    
2197     } else if(s.startsWith("ACTIVE: ")) {
2198     s = s.substring("ACTIVE: ".length());
2199     mid.setActive(Boolean.parseBoolean(s));
2200 iliev 784 } else if(s.startsWith("PORTS: ")) {
2201     s = s.substring("PORTS: ".length());
2202     int ports = Parser.parseInt(s);
2203     MidiPort[] midiPorts = new MidiPort[ports > 0 ? ports : 0];
2204    
2205     for(int i = 0; i < midiPorts.length; i++)
2206 iliev 1139 midiPorts[i] = getMidiInputPortInfo(deviceId, i);
2207 iliev 784
2208     mid.setMidiPorts(midiPorts);
2209 iliev 596 } else {
2210     int i = s.indexOf(": ");
2211     if(i == -1) throw new LscpException (
2212     LscpI18n.getLogMsg("CommandFailed!")
2213     );
2214    
2215     Parameter prm =
2216     getMidiInputDriverParameterInfo(drv, s.substring(0, i));
2217    
2218     s = s.substring(i + 2);
2219     prm.parseValue(s);
2220    
2221     mid.addParameter(prm);
2222     }
2223     }
2224    
2225     return mid;
2226     }
2227    
2228     /**
2229     * Alters a specific setting of a created MIDI input device.
2230     *
2231 iliev 1139 * @param deviceId The numerical ID of the MIDI input device.
2232 iliev 596 * @param prm A <code>Parameter</code> instance containing the name of the parameter
2233     * and the new value for this parameter.
2234     *
2235     * @throws IOException If some I/O error occurs.
2236     * @throws LscpException If LSCP protocol corruption occurs.
2237     * @throws LSException If
2238     * <ul>
2239 iliev 1139 * <li>There is no MIDI input device with numerical ID <code>deviceId</code>;
2240 iliev 596 * <li>There is no device parameter with the specified name;
2241     * <li>The device parameter is readonly;
2242     * <li>The device parameter is from different type.
2243     * </ul>
2244     *
2245     * @see #getMidiInputDevices
2246     * @see #getMidiInputDeviceInfo
2247     */
2248     public synchronized void
2249 iliev 1139 setMidiInputDeviceParameter(int deviceId, Parameter prm)
2250 iliev 596 throws IOException, LscpException, LSException {
2251    
2252     verifyConnection();
2253     String kv = prm.getName() + '=' + prm.getStringValue();
2254 iliev 1139 out.writeLine("SET MIDI_INPUT_DEVICE_PARAMETER " + deviceId + ' ' + kv);
2255     if(getPrintOnlyMode()) return;
2256 iliev 596
2257     ResultSet rs = getEmptyResultSet();
2258     }
2259    
2260 iliev 784
2261 iliev 596 /**
2262 iliev 1139 * Changes the port number of the speicified MIDI input device.
2263     * @param deviceId The numerical ID of the MIDI input device.
2264 iliev 784 * @param ports The new number of MIDI input ports.
2265     *
2266     * @throws IOException If an I/O error occurs.
2267     * @throws LscpException If LSCP protocol corruption occurs.
2268 iliev 1139 * @throws LSException If there is no device with ID <code>deviceId</code> or
2269 iliev 784 * if <code>ports</code> number is out of range.
2270     *
2271     * @see #getMidiInputPortInfo
2272     */
2273     public synchronized void
2274 iliev 1139 setMidiInputPortCount(int deviceId, int ports)
2275 iliev 784 throws IOException, LscpException, LSException {
2276    
2277 iliev 1139 setMidiInputDeviceParameter(deviceId, new IntParameter("PORTS", ports));
2278 iliev 784 }
2279    
2280     /**
2281 iliev 596 * Gets detailed information about a specific MIDI input port.
2282 iliev 1139 * @param deviceId The numerical ID of the MIDI input device.
2283 iliev 596 * @param midiPort The MIDI input port number.
2284     *
2285     * @return A <code>MidiPort</code> instance containing
2286     * information about the specified MIDI input port.
2287     *
2288     * @throws IOException If an I/O error occurs.
2289     * @throws LscpException If LSCP protocol corruption occurs.
2290 iliev 1139 * @throws LSException If there is no device with ID <code>deviceId</code> or
2291 iliev 596 * if <code>midiPort</code> is not a valid MIDI port number.
2292     *
2293     * @see #getMidiInputDevices
2294     */
2295     public synchronized MidiPort
2296 iliev 1139 getMidiInputPortInfo(int deviceId, int midiPort)
2297 iliev 596 throws IOException, LscpException, LSException {
2298    
2299     verifyConnection();
2300 iliev 1139 out.writeLine("GET MIDI_INPUT_PORT INFO " + deviceId + " " + midiPort);
2301     if(getPrintOnlyMode()) return null;
2302    
2303 iliev 596 ResultSet rs = getMultiLineResultSet();
2304    
2305     MidiPort mp = new MidiPort();
2306     String[] lnS = rs.getMultiLineResult();
2307    
2308     for(String s : lnS) {
2309     if(s.startsWith("NAME: ")) {
2310 iliev 784 s = s.substring("NAME: ".length());
2311     Parameter prm = getMidiInputPortParameterInfo (
2312 iliev 1139 deviceId, midiPort, "NAME"
2313 iliev 784 );
2314     prm.setValue(removeQuotation(s));
2315     mp.setNameParameter(prm);
2316 iliev 596 } else {
2317     int i = s.indexOf(": ");
2318     if(i == -1) throw new LscpException (
2319     LscpI18n.getLogMsg("CommandFailed!")
2320     );
2321    
2322     Parameter prm = getMidiInputPortParameterInfo (
2323 iliev 1139 deviceId, midiPort, s.substring(0, i)
2324 iliev 596 );
2325    
2326     s = s.substring(i + 2);
2327     prm.parseValue(s);
2328    
2329     mp.addParameter(prm);
2330     }
2331     }
2332    
2333     return mp;
2334     }
2335    
2336     /**
2337     * Gets detailed information about a specific MIDI input port parameter.
2338     *
2339 iliev 1139 * @param deviceId The numerical ID of the MIDI input device.
2340 iliev 596 * @param port The MIDI port number.
2341     * @param param A specific parameter name for which information should be obtained.
2342     *
2343     * @return A <code>Parameter</code> instance containing
2344     * information about the specified MIDI input port parameter.
2345     *
2346     * @throws IOException If an I/O error occurs.
2347     * @throws LscpException If LSCP protocol corruption occurs.
2348     * @throws LSException If
2349     * <ul>
2350 iliev 1139 * <li>There is no MIDI input device with numerical ID <code>deviceId</code>;
2351 iliev 596 * <li> <code>port</code> is not a valid MIDI port number;
2352     * <li><code>param</code> is not a valid parameter for the specified MIDI port.
2353     * </ul>
2354     *
2355     * @see #getMidiInputDevices
2356     * @see #getMidiInputPortInfo
2357     */
2358     public synchronized Parameter
2359 iliev 1139 getMidiInputPortParameterInfo(int deviceId, int port, String param)
2360 iliev 596 throws IOException, LscpException, LSException {
2361    
2362     verifyConnection();
2363 iliev 1139 String args = deviceId + " " + port + " " + param;
2364 iliev 596 out.writeLine("GET MIDI_INPUT_PORT_PARAMETER INFO " + args);
2365 iliev 1139 if(getPrintOnlyMode()) return null;
2366 iliev 596
2367     ResultSet rs = getMultiLineResultSet();
2368    
2369     String[] lnS = rs.getMultiLineResult();
2370     ParameterType type = parseType(lnS);
2371     boolean multi = parseMultiplicity(lnS);
2372     Parameter prm;
2373    
2374     switch(type) {
2375     case BOOL:
2376     if(!multi) prm = new BoolParameter(lnS);
2377     else prm = new BoolListParameter(lnS);
2378     prm.setName(param);
2379     return prm;
2380     case INT:
2381     if(!multi) prm = new IntParameter(lnS);
2382     else prm = new IntListParameter(lnS);
2383     prm.setName(param);
2384     return prm;
2385     case FLOAT:
2386     if(!multi) prm = new FloatParameter(lnS);
2387     else prm = new FloatListParameter(lnS);
2388     prm.setName(param);
2389     return prm;
2390     case STRING:
2391     if(!multi) prm = new StringParameter(lnS);
2392     else prm = new StringListParameter(lnS);
2393     prm.setName(param);
2394     return prm;
2395     default: throw new LscpException(LscpI18n.getLogMsg("Client.unknownPrmType!"));
2396     }
2397     }
2398    
2399     /**
2400     * Alters a specific setting of a MIDI input port.
2401     *
2402 iliev 1139 * @param deviceId The numerical ID of the MIDI device.
2403 iliev 596 * @param port The MIDI port number.
2404     * @param prm A <code>Parameter</code> instance containing the name of the parameter
2405     * and the new value for this parameter.
2406     *
2407     * @throws IOException If some I/O error occurs.
2408     * @throws LscpException If LSCP protocol corruption occurs.
2409     * @throws LSException If
2410     * <ul>
2411 iliev 1139 * <li>There is no MIDI device with numerical ID <code>deviceId</code>;
2412 iliev 596 * <li><code>port</code> is not a valid MIDI port number;
2413     * <li><code>prm</code> is not a valid parameter;
2414     * <li>The parameter is readonly;
2415     * <li>The parameter is from different type.
2416     * </ul>
2417     *
2418     * @see #getMidiInputDevices
2419     * @see #getMidiInputPortInfo
2420     */
2421     public synchronized void
2422 iliev 1139 setMidiInputPortParameter(int deviceId, int port, Parameter prm)
2423 iliev 596 throws IOException, LscpException, LSException {
2424    
2425     verifyConnection();
2426 iliev 1139 String args = deviceId + " " + port + " " +
2427 iliev 596 prm.getName() + '=' + prm.getStringValue();
2428     out.writeLine("SET MIDI_INPUT_PORT_PARAMETER " + args);
2429 iliev 1139 if(getPrintOnlyMode()) return;
2430 iliev 596
2431     ResultSet rs = getEmptyResultSet();
2432     }
2433    
2434     /**
2435 iliev 1139 * Adds a new MIDI instrument map.
2436     * @param name The name of this MIDI instrument map.
2437     * @return The number of the newly MIDI instrument map.
2438     * @throws IOException If some I/O error occurs.
2439     * @throws LSException If the creation of the new MIDI instrument map failed.
2440     * @throws LscpException If LSCP protocol corruption occurs.
2441     * @see #removeMidiInstrumentMap
2442     */
2443     public synchronized int
2444     addMidiInstrumentMap(String name) throws IOException, LSException, LscpException {
2445     verifyConnection();
2446     out.writeLine("ADD MIDI_INSTRUMENT_MAP '" + name + "'");
2447     if(getPrintOnlyMode()) return -1;
2448    
2449     ResultSet rs = getEmptyResultSet();
2450    
2451     return rs.getIndex();
2452     }
2453    
2454     /**
2455     * Removes the specified MIDI instrument map.
2456     * @param mapId The numerical ID of the MIDI instrument map to be removed.
2457     * @throws IOException If some I/O error occurs.
2458     * @throws LscpException If LSCP protocol corruption occurs.
2459     * @throws LSException If the removing of the MIDI instrument map failed.
2460     * @see #addMidiInstrumentMap
2461     * @see #getMidiInstrumentMapIDs
2462     */
2463     public synchronized void
2464     removeMidiInstrumentMap(int mapId) throws IOException, LscpException, LSException {
2465     verifyConnection();
2466     out.writeLine("REMOVE MIDI_INSTRUMENT_MAP " + mapId);
2467     if(getPrintOnlyMode()) return;
2468    
2469     ResultSet rs = getEmptyResultSet();
2470     }
2471    
2472     /**
2473     * Removes the all MIDI instrument maps.
2474     * @throws IOException If some I/O error occurs.
2475     * @throws LscpException If LSCP protocol corruption occurs.
2476     * @throws LSException If the removing of the MIDI instrument maps failed.
2477     */
2478     public synchronized void
2479     removeAllMidiInstrumentMaps() throws IOException, LscpException, LSException {
2480     verifyConnection();
2481     out.writeLine("REMOVE MIDI_INSTRUMENT_MAP ALL");
2482     if(getPrintOnlyMode()) return;
2483    
2484     ResultSet rs = getEmptyResultSet();
2485     }
2486    
2487     /**
2488     * Gets the current number of all MIDI instrument maps.
2489     * @return The current number of all MIDI instrument maps.
2490     * @throws IOException If some I/O error occurs.
2491     * @throws LscpException If LSCP protocol corruption occurs.
2492     * @throws LSException If some other error occurs.
2493     */
2494     public synchronized int
2495     getMidiInstrumentMapCount() throws IOException, LscpException, LSException {
2496     verifyConnection();
2497     out.writeLine("GET MIDI_INSTRUMENT_MAPS");
2498     if(getPrintOnlyMode()) return -1;
2499    
2500     String s = getSingleLineResultSet().getResult();
2501     return parseInt(s);
2502     }
2503    
2504     /**
2505     * Gets a list of numerical IDs of all created MIDI instrument maps.
2506     * @return An <code>Integer</code> array providing the numerical IDs of
2507     * all created MIDI instrument maps.
2508     * @throws IOException If some I/O error occurs.
2509     * @throws LscpException If LSCP protocol corruption occurs.
2510     * @throws LSException If some other error occurs.
2511     * @see #addMidiInstrumentMap
2512     * @see #removeMidiInstrumentMap
2513     */
2514     public synchronized Integer[]
2515     getMidiInstrumentMapIDs() throws IOException, LscpException, LSException {
2516     verifyConnection();
2517     out.writeLine("LIST MIDI_INSTRUMENT_MAPS");
2518     if(getPrintOnlyMode()) return null;
2519    
2520     return parseIntList(getSingleLineResultSet().getResult());
2521     }
2522    
2523     /**
2524     * Gets the current settings of a specific, already created MIDI instrument map.
2525     * @param mapId Specifies the numerical ID of the MIDI instrument map.
2526     * @return A <code>MidiInstrumentMapInfo</code> instance containing information
2527     * about the specified device.
2528     * @throws IOException If some I/O error occurs.
2529     * @throws LscpException If LSCP protocol corruption occurs.
2530     * @throws LSException If there is no MIDI instrument map
2531     * with map id <code>mapId</code>.
2532     * @see #getMidiInstrumentMaps
2533     */
2534     public synchronized MidiInstrumentMapInfo
2535     getMidiInstrumentMapInfo(int mapId) throws IOException, LscpException, LSException {
2536     verifyConnection();
2537     out.writeLine("GET MIDI_INSTRUMENT_MAP INFO " + mapId);
2538     if(getPrintOnlyMode()) return null;
2539    
2540     ResultSet rs = getMultiLineResultSet();
2541    
2542     String[] lnS = rs.getMultiLineResult();
2543    
2544     String name = "";
2545     boolean b = false;
2546    
2547     for(String s : lnS) {
2548     if(s.startsWith("NAME: ")) {
2549     name = s.substring("NAME: ".length());
2550     } else if(s.startsWith("DEFAULT: ")) {
2551     b = Boolean.parseBoolean(s.substring("DEFAULT: ".length()));
2552     } else {
2553     getLogger().info(LscpI18n.getLogMsg("unknownLine", s));
2554     }
2555     }
2556    
2557     return new MidiInstrumentMapInfo(mapId, name, b);
2558     }
2559    
2560     /**
2561     * Gets an information of all created MIDI instrument maps.
2562     * @return A <code>MidiInstrumentMap</code> array
2563     * providing information for all created MIDI instrument maps.
2564     * @throws IOException If some I/O error occurs.
2565     * @throws LscpException If LSCP protocol corruption occurs.
2566     * @throws LSException If some other error occurs.
2567     * @see #addMidiInstrumentMap
2568     * @see #removeMidiInstrumentMap
2569     */
2570     public synchronized MidiInstrumentMapInfo[]
2571     getMidiInstrumentMaps() throws IOException, LscpException, LSException {
2572     Integer[] idS = getMidiInstrumentMapIDs();
2573     if(getPrintOnlyMode()) return null;
2574    
2575     MidiInstrumentMapInfo[] maps = new MidiInstrumentMapInfo[idS.length];
2576    
2577     for(int i = 0; i < maps.length; i++)
2578     maps[i] = getMidiInstrumentMapInfo(idS[i]);
2579    
2580     return maps;
2581     }
2582    
2583     /**
2584     * Sets the name of the specified MIDI instrument map.
2585     * @param mapId The numerical ID of the MIDI instrument map.
2586     * @param name The new name for the specified MIDI instrument map.
2587     * @throws IOException If some I/O error occurs.
2588     * @throws LscpException If LSCP protocol corruption occurs.
2589     * @throws LSException If <code>mapId</code> is not a valid MIDI
2590     * instrument map number or <code>name</code> is not a valid name;
2591     */
2592     public synchronized void
2593     setMidiInstrumentMapName(int mapId, String name)
2594     throws IOException, LscpException, LSException {
2595    
2596     verifyConnection();
2597     out.writeLine("SET MIDI_INSTRUMENT_MAP NAME " + + mapId + " '" + name + "'");
2598     if(getPrintOnlyMode()) return;
2599    
2600     ResultSet rs = getEmptyResultSet();
2601     }
2602    
2603 iliev 1202
2604    
2605 iliev 1139 /**
2606     * Creates or replaces a MIDI instrument map entry.
2607     * @param mapId The ID of the map, where this instrument should be mapped.
2608     * @param entry Specifies the position of the MIDI instrument in the MIDI instrument map.
2609     * @param info Provides the needed information of the
2610     * MIDI instrument, which will be mapped to the specified MIDI instrument map.
2611     * @throws IOException If some I/O error occurs.
2612     * @throws LSException If the mapping failed.
2613     * @throws LscpException If LSCP protocol corruption occurs.
2614     * @see #unmapMidiInstrument
2615     */
2616     public synchronized void
2617     mapMidiInstrument(int mapId, MidiInstrumentEntry entry, MidiInstrumentInfo info)
2618     throws IOException, LSException, LscpException {
2619 iliev 1202 mapMidiInstrument(mapId, entry, info, false);
2620     }
2621    
2622     /**
2623     * Creates or replaces a MIDI instrument map entry.
2624     * @param mapId The ID of the map, where this instrument should be mapped.
2625     * @param entry Specifies the position of the MIDI instrument in the MIDI instrument map.
2626     * @param info Provides the needed information of the
2627     * MIDI instrument, which will be mapped to the specified MIDI instrument map.
2628     * @param nonModal If <code>true</code> the function returns immediately
2629     * and the mapping is established in the background.
2630     * @throws IOException If some I/O error occurs.
2631     * @throws LSException If the mapping failed.
2632     * @throws LscpException If LSCP protocol corruption occurs.
2633     * @see #unmapMidiInstrument
2634     */
2635     public synchronized void
2636     mapMidiInstrument(int mapId, MidiInstrumentEntry entry, MidiInstrumentInfo info, boolean nonModal)
2637     throws IOException, LSException, LscpException {
2638 iliev 1139
2639     verifyConnection();
2640     StringBuffer cmd = new StringBuffer("MAP MIDI_INSTRUMENT ");
2641 iliev 1202 if(nonModal) cmd.append("NON_MODAL ");
2642 iliev 1139 cmd.append(mapId).append(' ');
2643     cmd.append(entry.getMidiBank()).append(' ');
2644     cmd.append(entry.getMidiProgram()).append(' ');
2645     cmd.append(info.getEngine()).append(" '");
2646 iliev 1202 cmd.append(info.getFilePath()).append("' ");
2647 iliev 1139 cmd.append(info.getInstrumentIndex()).append(' ');
2648     cmd.append(info.getVolume());
2649     if(!info.getLoadMode().name().equals("DEFAULT")) {
2650     cmd.append(' ').append(info.getLoadMode().name());
2651     }
2652     if(info.getName() != null) cmd.append(" '").append(info.getName()).append("'");
2653    
2654     out.writeLine(cmd.toString());
2655     if(getPrintOnlyMode()) return;
2656    
2657     ResultSet rs = getEmptyResultSet();
2658     }
2659    
2660     /**
2661     * Removes an entry MIDI instrument map.
2662     * @param mapId The ID of the map, from which
2663     * the specified MIDI instrument should be removed.
2664     * @param entry The entry to remove from the specified MIDI instrument map.
2665     * @throws IOException If some I/O error occurs.
2666     * @throws LSException If the unmapping failed.
2667     * @throws LscpException If LSCP protocol corruption occurs.
2668     * @see #mapMidiInstrument
2669     */
2670     public synchronized void
2671     unmapMidiInstrument(int mapId, MidiInstrumentEntry entry)
2672     throws IOException, LSException, LscpException {
2673    
2674     verifyConnection();
2675     StringBuffer cmd = new StringBuffer("UNMAP MIDI_INSTRUMENT ");
2676     cmd.append(mapId).append(' ');
2677     cmd.append(entry.getMidiBank()).append(' ');
2678     cmd.append(entry.getMidiProgram());
2679    
2680     out.writeLine(cmd.toString());
2681     if(getPrintOnlyMode()) return;
2682    
2683     ResultSet rs = getEmptyResultSet();
2684     }
2685    
2686     /**
2687     * Gets the current number of all MIDI instrument in all maps.
2688     * @return The current number of all MIDI instrument in all maps.
2689     * @throws IOException If some I/O error occurs.
2690     * @throws LscpException If LSCP protocol corruption occurs.
2691     * @throws LSException If some other error occurs.
2692     */
2693     public synchronized int
2694     getMidiInstrumentCount() throws IOException, LscpException, LSException {
2695     verifyConnection();
2696     out.writeLine("GET MIDI_INSTRUMENTS ALL");
2697     if(getPrintOnlyMode()) return -1;
2698    
2699     String s = getSingleLineResultSet().getResult();
2700     return parseInt(s);
2701     }
2702    
2703     /**
2704     * Gets the current number of MIDI instrument in the specified map.
2705     * @param mapId The ID of the map.
2706     * @return The current number of MIDI instrument in the specified map.
2707     * @throws IOException If some I/O error occurs.
2708     * @throws LscpException If LSCP protocol corruption occurs.
2709     * @throws LSException If some other error occurs.
2710     */
2711     public synchronized int
2712     getMidiInstrumentCount(int mapId) throws IOException, LscpException, LSException {
2713     verifyConnection();
2714     out.writeLine("GET MIDI_INSTRUMENTS " + String.valueOf(mapId));
2715     if(getPrintOnlyMode()) return -1;
2716    
2717     String s = getSingleLineResultSet().getResult();
2718     return parseInt(s);
2719     }
2720    
2721     /**
2722     * Gets all MIDI instrument from all maps.
2723     * @return A <code>MidiInstrumentInfo</code> array providing
2724     * all MIDI instruments from all MIDI instrument maps.
2725     * @throws IOException If some I/O error occurs.
2726     * @throws LscpException If LSCP protocol corruption occurs.
2727     * @throws LSException If some other error occurs.
2728     */
2729     public synchronized MidiInstrumentInfo[]
2730     getMidiInstruments() throws IOException, LscpException, LSException {
2731     verifyConnection();
2732     out.writeLine("LIST MIDI_INSTRUMENTS ALL");
2733     if(getPrintOnlyMode()) return null;
2734    
2735     String[] entries = parseArray(getSingleLineResultSet().getResult());
2736    
2737     return getMidiInstruments(entries);
2738     }
2739    
2740     /**
2741     * Gets all MIDI instrument contained int the specified MIDI instrument map.
2742     * @param mapId The ID of the map, which instruments should be obtained.
2743     * @return A <code>MidiInstrumentInfo</code> array providing
2744     * all MIDI instruments from all MIDI instrument maps.
2745     * @throws IOException If some I/O error occurs.
2746     * @throws LscpException If LSCP protocol corruption occurs.
2747     * @throws LSException If some other error occurs.
2748     */
2749     public synchronized MidiInstrumentInfo[]
2750     getMidiInstruments(int mapId) throws IOException, LscpException, LSException {
2751     verifyConnection();
2752     out.writeLine("LIST MIDI_INSTRUMENTS " + String.valueOf(mapId));
2753     if(getPrintOnlyMode()) return null;
2754    
2755     String[] entries = parseArray(getSingleLineResultSet().getResult());
2756    
2757     return getMidiInstruments(entries);
2758     }
2759    
2760     private MidiInstrumentInfo[]
2761     getMidiInstruments(String[] entries) throws IOException, LscpException, LSException {
2762     Vector<MidiInstrumentInfo> v = new Vector<MidiInstrumentInfo>();
2763    
2764     for(String s : entries) {
2765     Integer[] vals = parseIntList(s);
2766     if(vals.length != 3) {
2767     throw new LscpException(LscpI18n.getLogMsg("CommandFailed!"));
2768     }
2769    
2770     v.add(getMidiInstrumentInfo(vals[0], vals[1], vals[2]));
2771     }
2772    
2773     return v.toArray(new MidiInstrumentInfo[v.size()]);
2774     }
2775    
2776     /**
2777     * Gets the current settings of the specified MIDI instrument.
2778     * @param mapId The ID of the map.
2779     * @param bank The index of the MIDI bank.
2780     * @param program The MIDI program number of the instrument.
2781     * @return <code>MidiInstrumentInfo</code> instance containing
2782     * the current settings of the specified MIDI instrument.
2783     * @throws IOException If an I/O error occurs.
2784     * @throws LscpException If LSCP protocol corruption occurs.
2785     * @throws LSException If the specified MIDI instrument is missing.
2786     */
2787     public synchronized MidiInstrumentInfo
2788     getMidiInstrumentInfo(int mapId, int bank, int program)
2789     throws IOException, LscpException, LSException {
2790    
2791     verifyConnection();
2792     StringBuffer cmd = new StringBuffer("GET MIDI_INSTRUMENT INFO ");
2793     cmd.append(mapId).append(' ');
2794     cmd.append(bank).append(' ');
2795     cmd.append(program);
2796    
2797     out.writeLine(cmd.toString());
2798     if(getPrintOnlyMode()) return null;
2799    
2800     ResultSet rs = getMultiLineResultSet();
2801     MidiInstrumentEntry entry = new MidiInstrumentEntry(bank, program);
2802     return new MidiInstrumentInfo(mapId, entry, rs.getMultiLineResult());
2803     }
2804    
2805     /**
2806 iliev 596 * Loads and assigns an instrument to a sampler channel. Notice that this function will
2807     * return after the instrument is fully loaded and the channel is ready to be used.
2808     * @param filename The name of the instrument file
2809     * on the LinuxSampler instance's host system.
2810     * @param instrIdx The index of the instrument in the instrument file.
2811     * @param samplerChn The number of the sampler channel the instrument should be assigned to.
2812     * @throws IOException If some I/O error occurs.
2813     * @throws LscpException If LSCP protocol corruption occurs.
2814     * @throws LSException If the loading of the instrument failed.
2815     * @see #loadInstrument(String, int, int, boolean)
2816     * @see #getSamplerChannels
2817     */
2818     public synchronized void
2819     loadInstrument(String filename, int instrIdx, int samplerChn)
2820     throws IOException, LscpException, LSException {
2821    
2822     verifyConnection();
2823     loadInstrument(filename, instrIdx, samplerChn, false);
2824     }
2825    
2826     /**
2827     * Loads and assigns an instrument to a sampler channel.
2828     *
2829     * @param filename The name of the instrument file
2830     * on the LinuxSampler instance's host system.
2831     * @param instrIdx The index of the instrument in the instrument file.
2832     * @param samplerChn The number of the sampler channel the instrument should be assigned to.
2833     * @param nonModal If <code>false</code> the function will return after the instrument
2834     * has been fully loaded and the channel is ready to be used. If <code>true</code>
2835     * the function returns immediately.
2836     *
2837     * @throws IOException If some I/O error occurs.
2838     * @throws LscpException If LSCP protocol corruption occurs.
2839     * @throws LSException If the loading of the instrument failed.
2840     *
2841     * @see #loadInstrument(String, int, int)
2842     * @see #getSamplerChannels
2843     */
2844     public synchronized void
2845     loadInstrument(String filename, int instrIdx, int samplerChn, boolean nonModal)
2846     throws IOException, LscpException, LSException {
2847    
2848     String cmd = nonModal ? "LOAD INSTRUMENT NON_MODAL " : "LOAD INSTRUMENT ";
2849     String args = '\'' + filename + "' " + instrIdx + ' ' + samplerChn;
2850    
2851     out.writeLine(cmd + args);
2852 iliev 1139 if(getPrintOnlyMode()) return;
2853 iliev 596
2854     ResultSet rs = getEmptyResultSet();
2855     }
2856    
2857     /**
2858     * Loads a sampler engine to a specific sampler channel.
2859     * @param engineName The name of the engine.
2860     * @param samplerChn The number of the sampler channel
2861     * the deployed engine should be assigned to.
2862     *
2863     * @throws IOException If some I/O error occurs.
2864     * @throws LscpException If LSCP protocol corruption occurs.
2865     * @throws LSException If the loading of the sampler engine failed.
2866     * @see #getEngines
2867     * @see #getSamplerChannels
2868     */
2869     public synchronized void
2870     loadSamplerEngine(String engineName, int samplerChn)
2871     throws IOException, LscpException, LSException {
2872    
2873     verifyConnection();
2874     out.writeLine("LOAD ENGINE " + engineName + ' ' + samplerChn);
2875 iliev 1139 if(getPrintOnlyMode()) return;
2876 iliev 596
2877     ResultSet rs = getEmptyResultSet();
2878     }
2879    
2880     /**
2881     * Gets the current number of all created sampler channels.
2882     * @return The current number of all created sampler channels.
2883     * @throws IOException If some I/O error occurs.
2884     * @throws LscpException If LSCP protocol corruption occurs.
2885     * @throws LSException If some other error occurs.
2886     */
2887     public synchronized int
2888     getSamplerChannelCount() throws IOException, LscpException, LSException {
2889     verifyConnection();
2890     out.writeLine("GET CHANNELS");
2891 iliev 1139 if(getPrintOnlyMode()) return -1;
2892    
2893 iliev 596 String s = getSingleLineResultSet().getResult();
2894     return parseInt(s);
2895     }
2896    
2897     /**
2898 iliev 784 * Gets a list of all created sampler channels.
2899     * @return A <code>SamplerChannel</code> array providing all created sampler channels.
2900     * @throws IOException If some I/O error occurs.
2901     * @throws LscpException If LSCP protocol corruption occurs.
2902     * @throws LSException If some other error occurs.
2903     * @see #addSamplerChannel
2904     * @see #removeSamplerChannel
2905     */
2906     public synchronized SamplerChannel[]
2907     getSamplerChannels() throws IOException, LscpException, LSException {
2908     Integer[] idS = getSamplerChannelIDs();
2909 iliev 1139 if(getPrintOnlyMode()) return null;
2910    
2911 iliev 784 SamplerChannel[] channels = new SamplerChannel[idS.length];
2912    
2913     for(int i = 0; i < channels.length; i++)
2914     channels[i] = getSamplerChannelInfo(idS[i]);
2915    
2916     return channels;
2917     }
2918    
2919     /**
2920 iliev 596 * Gets a list with numerical IDs of all created sampler channels.
2921 iliev 784 * @return An <code>Integer</code> array providing
2922     * the numerical IDs of all created sampler channels.
2923 iliev 596 * @throws IOException If some I/O error occurs.
2924     * @throws LscpException If LSCP protocol corruption occurs.
2925     * @throws LSException If some other error occurs.
2926     * @see #addSamplerChannel
2927     * @see #removeSamplerChannel
2928     */
2929     public synchronized Integer[]
2930 iliev 784 getSamplerChannelIDs() throws IOException, LscpException, LSException {
2931 iliev 596 verifyConnection();
2932     out.writeLine("LIST CHANNELS");
2933 iliev 1139 if(getPrintOnlyMode()) return null;
2934    
2935 iliev 596 return parseIntList(getSingleLineResultSet().getResult());
2936     }
2937    
2938     /**
2939     * Adds a new sampler channel. This method will increment the sampler channel count by one
2940     * and the new sampler channel will be appended to the end of the sampler channel list.
2941     *
2942     * @return The number of the newly created sampler channel.
2943     * @throws IOException If some I/O error occurs.
2944     * @throws LSException If the creation of the new sampler channel failed.
2945     * @throws LscpException If LSCP protocol corruption occurs.
2946     * @see #removeSamplerChannel
2947     */
2948     public synchronized int
2949     addSamplerChannel() throws IOException, LSException, LscpException {
2950     verifyConnection();
2951     out.writeLine("ADD CHANNEL");
2952 iliev 1139 if(getPrintOnlyMode()) return -1;
2953    
2954 iliev 596 ResultSet rs = getEmptyResultSet();
2955    
2956     return rs.getIndex();
2957     }
2958    
2959     /**
2960     * Removes the specified sampler channel.
2961     *
2962     * @param samplerChn The numerical ID of the sampler channel to be removed.
2963     *
2964     * @throws IOException If some I/O error occurs.
2965     * @throws LscpException If LSCP protocol corruption occurs.
2966     * @throws LSException If the removing of the sampler channel failed.
2967     * @see #addSamplerChannel
2968     * @see #getSamplerChannels
2969     */
2970     public synchronized void
2971     removeSamplerChannel(int samplerChn) throws IOException, LscpException, LSException {
2972     verifyConnection();
2973     out.writeLine("REMOVE CHANNEL " + samplerChn);
2974 iliev 1139 if(getPrintOnlyMode()) return;
2975 iliev 596
2976     ResultSet rs = getEmptyResultSet();
2977     }
2978    
2979     /**
2980     * Gets the number of all available engines.
2981     * @return The number of all available engines.
2982     * @throws IOException If some I/O error occurs.
2983     * @throws LscpException If LSCP protocol corruption occurs.
2984     * @throws LSException If some other error occurs.
2985     */
2986     public synchronized int
2987     getEngineCount() throws IOException, LscpException, LSException {
2988     verifyConnection();
2989     out.writeLine("GET AVAILABLE_ENGINES");
2990 iliev 1139 if(getPrintOnlyMode()) return -1;
2991    
2992 iliev 596 String s = getSingleLineResultSet().getResult();
2993     return parseInt(s);
2994     }
2995    
2996     /**
2997 iliev 671 * Gets a list of all available engines.
2998     *
2999     * @return <code>SamplerEngine</code> array containing all available engines.
3000     * @throws IOException If some I/O error occurs.
3001     * @throws LscpException If LSCP protocol corruption occurs.
3002     * @throws LSException If some other error occurs.
3003     */
3004     public synchronized SamplerEngine[]
3005     getEngines() throws IOException, LscpException, LSException {
3006     String[] engines = getEngineNames();
3007 iliev 1139 if(getPrintOnlyMode()) return null;
3008    
3009 iliev 671 SamplerEngine[] se = new SamplerEngine[engines.length];
3010    
3011     for(int i = 0; i < engines.length; i++) se[i] = getEngineInfo(engines[i]);
3012    
3013     return se;
3014     }
3015    
3016     /**
3017 iliev 596 * Gets a list of all available engines' names.
3018     *
3019     * @return <code>String</code> array with all available engines' names.
3020     * @throws IOException If some I/O error occurs.
3021     * @throws LscpException If LSCP protocol corruption occurs.
3022     * @throws LSException If some other error occurs.
3023     */
3024 iliev 671 private synchronized String[]
3025     getEngineNames() throws IOException, LscpException, LSException {
3026 iliev 596 verifyConnection();
3027     out.writeLine("LIST AVAILABLE_ENGINES");
3028 iliev 1139 if(getPrintOnlyMode()) return null;
3029    
3030 iliev 596 return parseStringList(getSingleLineResultSet().getResult());
3031     }
3032    
3033     /**
3034     * Gets information about a specific sampler engine.
3035     * @param engineName The name of the sampler engine.
3036     *
3037     * @return <code>SamplerEngine</code> instance containing
3038     * information about the specified sampler engine.
3039     *
3040     * @throws IOException If an I/O error occurs.
3041     * @throws LscpException If LSCP protocol corruption occurs.
3042     * @throws LSException If there is no sampler engine with name <code>engineName</code>.
3043 iliev 671 * @see #getEngineNames
3044 iliev 596 */
3045 iliev 671 private synchronized SamplerEngine
3046 iliev 596 getEngineInfo(String engineName) throws IOException, LscpException, LSException {
3047     verifyConnection();
3048     out.writeLine("GET ENGINE INFO " + engineName);
3049 iliev 1139 if(getPrintOnlyMode()) return null;
3050    
3051 iliev 596 ResultSet rs = getMultiLineResultSet();
3052     SamplerEngine se = new SamplerEngine(rs.getMultiLineResult());
3053     se.setName(engineName);
3054     return se;
3055     }
3056    
3057     /**
3058     * Gets the current settings of the specified sampler channel.
3059     * @param samplerChn The sampler channel number.
3060     *
3061     * @return <code>SamplerChannel</code> instance containing
3062     * the current settings of the specified sampler channel.
3063     *
3064     * @throws IOException If an I/O error occurs.
3065     * @throws LscpException If LSCP protocol corruption occurs.
3066     * @throws LSException If there is no sampler channel with <code>samplerChn</code> number.
3067     * @see #getSamplerChannels
3068     */
3069     public synchronized SamplerChannel
3070     getSamplerChannelInfo(int samplerChn) throws IOException, LscpException, LSException {
3071     verifyConnection();
3072     out.writeLine("GET CHANNEL INFO " + samplerChn);
3073 iliev 1139 if(getPrintOnlyMode()) return null;
3074    
3075 iliev 596 ResultSet rs = getMultiLineResultSet();
3076     SamplerChannel sc = new SamplerChannel(rs.getMultiLineResult());
3077 iliev 1139 sc.setChannelId(samplerChn);
3078 iliev 784 if(sc.getEngine() != null) sc.setEngine(getEngineInfo(sc.getEngine().getName()));
3079 iliev 596
3080     return sc;
3081     }
3082    
3083     /**
3084     * Gets the current number of active voices on the specified sampler channel.
3085     *
3086     * @param samplerChn The sampler channel number.
3087     * @return The current number of active voices on the specified sampler channel.
3088     * @throws IOException If some I/O error occurs.
3089     * @throws LscpException If LSCP protocol corruption occurs.
3090     * @throws LSException If there is no sampler channel with number <code>samplerChn</code>.
3091     * @see #getSamplerChannels
3092     */
3093     public synchronized int
3094     getChannelVoiceCount(int samplerChn) throws IOException, LscpException, LSException {
3095     verifyConnection();
3096     out.writeLine("GET CHANNEL VOICE_COUNT " + samplerChn);
3097 iliev 1139 if(getPrintOnlyMode()) return -1;
3098    
3099 iliev 596 ResultSet rs = getSingleLineResultSet();
3100    
3101     return parseInt(rs.getResult());
3102     }
3103    
3104     /**
3105     * Gets the current number of active disk streams on the specified sampler channel.
3106     *
3107     * @param samplerChn The sampler channel number.
3108     * @return The current number of active disk streams on the specified sampler channel
3109     * or -1 if the engine doesn't support disk streaming.
3110     * @throws IOException If some I/O error occurs.
3111     * @throws LscpException If LSCP protocol corruption occurs.
3112     * @throws LSException If there is no sampler channel with number <code>samplerChn</code>.
3113     * @see #getSamplerChannels
3114     */
3115     public synchronized int
3116     getChannelStreamCount(int samplerChn) throws IOException, LscpException, LSException {
3117     verifyConnection();
3118     out.writeLine("GET CHANNEL STREAM_COUNT " + samplerChn);
3119 iliev 1139 if(getPrintOnlyMode()) return -1;
3120    
3121 iliev 596 ResultSet rs = getSingleLineResultSet();
3122    
3123     if(rs.getResult().equals("NA")) return -1;
3124    
3125     return parseInt(rs.getResult());
3126     }
3127    
3128     /**
3129     * Gets the current fill state of all disk streams on the specified sampler channel
3130     * in bytes.
3131     *
3132     * @param samplerChn The sampler channel number.
3133     * @return The current fill state of all disk streams on the specified sampler channel
3134     * or <code>null</code> if the engine which is deployed doesn't support disk streaming.
3135     * @throws IOException If some I/O error occurs.
3136     * @throws LscpException If LSCP protocol corruption occurs.
3137     * @throws LSException If there is no sampler channel with number <code>samplerChn</code>.
3138     * @see #getChannelBufferFillPercentage
3139     * @see #getSamplerChannels
3140     */
3141     public synchronized Vector<BufferFill>
3142     getChannelBufferFillBytes(int samplerChn) throws IOException, LscpException, LSException {
3143     verifyConnection();
3144     out.writeLine("GET CHANNEL BUFFER_FILL BYTES " + samplerChn);
3145 iliev 1139 if(getPrintOnlyMode()) return null;
3146    
3147 iliev 596 ResultSet rs = getSingleLineResultSet();
3148    
3149     if(rs.getResult().equals("NA")) return null;
3150    
3151     Vector<BufferFill> v = new Vector<BufferFill>();
3152     String[] args = parseList(rs.getResult());
3153    
3154     for(String s : args) {
3155     if(s.charAt(0) != '[')
3156     throw new LscpException(LscpI18n.getLogMsg("CommandFailed!"));
3157    
3158     int i = s.indexOf(']');
3159     if(i == -1) throw new LscpException(LscpI18n.getLogMsg("CommandFailed!"));
3160    
3161     BufferFill bf = new BufferFill();
3162 iliev 1139 bf.setStreamId(parseInt(s.substring(1, i)));
3163 iliev 596 bf.setValue(parseInt(s.substring(i + 1)));
3164     v.add(bf);
3165     }
3166    
3167     return v;
3168     }
3169    
3170     /**
3171     * Gets the current fill state of all disk streams on the specified sampler channel
3172     * in percent.
3173     *
3174     * @param samplerChn The sampler channel number.
3175     * @return The current fill state of all disk streams on the specified sampler channel
3176     * or <code>null</code> if the engine which is deployed doesn't support disk streaming.
3177     * @throws IOException If some I/O error occurs.
3178     * @throws LscpException If LSCP protocol corruption occurs.
3179     * @throws LSException If there is no sampler channel with number <code>samplerChn</code>.
3180     * @see #getChannelBufferFillBytes
3181     * @see #getSamplerChannels
3182     */
3183     public synchronized Vector<BufferFill>
3184     getChannelBufferFillPercentage(int samplerChn)
3185     throws IOException, LscpException, LSException {
3186    
3187     verifyConnection();
3188     out.writeLine("GET CHANNEL BUFFER_FILL PERCENTAGE " + samplerChn);
3189 iliev 1139 if(getPrintOnlyMode()) return null;
3190    
3191 iliev 596 ResultSet rs = getSingleLineResultSet();
3192    
3193     return getChannelBufferFillPercentage(rs.getResult());
3194     }
3195    
3196     private Vector<BufferFill>
3197     getChannelBufferFillPercentage(String ln) throws LscpException {
3198     if(ln.equals("NA")) return null;
3199    
3200     Vector<BufferFill> v = new Vector<BufferFill>();
3201     String[] args = parseList(ln);
3202    
3203     for(String s : args) {
3204     if(s.charAt(0) != '[')
3205     throw new LscpException(LscpI18n.getLogMsg("CommandFailed!"));
3206    
3207     int i = s.indexOf(']');
3208     if(i == -1) throw new LscpException(LscpI18n.getLogMsg("CommandFailed!"));
3209    
3210     if(s.charAt(s.length() - 1) != '%')
3211     throw new LscpException(LscpI18n.getLogMsg("CommandFailed!"));
3212    
3213     BufferFill bf = new BufferFill();
3214 iliev 1139 bf.setStreamId(parseInt(s.substring(1, i)));
3215 iliev 596 bf.setValue(parseInt(s.substring(i + 1, s.length() - 1)));
3216     v.add(bf);
3217     }
3218    
3219     return v;
3220     }
3221    
3222     /**
3223     * Sets the audio output device on the specified sampler channel.
3224     *
3225     * @param samplerChn The sampler channel number.
3226 iliev 1139 * @param devId The numerical ID of the audio output device.
3227 iliev 596 *
3228     * @throws IOException If some I/O error occurs.
3229     * @throws LscpException If LSCP protocol corruption occurs.
3230     * @throws LSException If
3231     * <ul>
3232     * <li><code>samplerChn</code> is not a valid channel number;
3233 iliev 1139 * <li><code>devId</code> is not a valid audio output device ID;
3234 iliev 596 * </ul>
3235     *
3236     * @see #getSamplerChannels
3237     * @see #getAudioOutputDevices
3238     */
3239     public synchronized void
3240 iliev 1139 setChannelAudioOutputDevice(int samplerChn, int devId)
3241 iliev 596 throws IOException, LscpException, LSException {
3242    
3243     verifyConnection();
3244 iliev 1139 out.writeLine("SET CHANNEL AUDIO_OUTPUT_DEVICE " + samplerChn + ' ' + devId);
3245     if(getPrintOnlyMode()) return;
3246 iliev 596
3247     ResultSet rs = getEmptyResultSet();
3248     }
3249    
3250     /**
3251     * Sets the audio output channel on the specified sampler channel.
3252     *
3253     * @param samplerChn The sampler channel number.
3254     * @param audioOut The sampler channel's audio output channel which should be rerouted.
3255     * @param audioIn The audio channel of the selected audio output device
3256     * where <code>audioOut</code> should be routed to.
3257     *
3258     * @throws IOException If some I/O error occurs.
3259     * @throws LscpException If LSCP protocol corruption occurs.
3260     * @throws LSException If
3261     * <ul>
3262     * <li><code>samplerChn</code> is not a valid channel number;
3263     * <li>There is no engine assigned yet to the specified sampler channel.
3264     * <li> There is no audio output device connected to the specified sampler channel.
3265     * </ul>
3266     *
3267     * @see #getSamplerChannels
3268     */
3269     public synchronized void
3270     setChannelAudioOutputChannel(int samplerChn, int audioOut, int audioIn)
3271     throws IOException, LscpException, LSException {
3272    
3273     verifyConnection();
3274     String args = " " + samplerChn + ' ' + audioOut + ' ' + audioIn;
3275     out.writeLine("SET CHANNEL AUDIO_OUTPUT_CHANNEL" + args);
3276 iliev 1139 if(getPrintOnlyMode()) return;
3277 iliev 596
3278     ResultSet rs = getEmptyResultSet();
3279     }
3280    
3281     /**
3282     * Sets the MIDI input device on the specified sampler channel.
3283     *
3284     * @param samplerChn The sampler channel number.
3285 iliev 1139 * @param devId The numerical ID of the MIDI input device.
3286 iliev 596 *
3287     * @throws IOException If some I/O error occurs.
3288     * @throws LscpException If LSCP protocol corruption occurs.
3289     * @throws LSException If
3290     * <ul>
3291     * <li><code>samplerChn</code> is not a valid channel number;
3292 iliev 1139 * <li><code>devId</code> is not a valid MIDI input device ID;
3293 iliev 596 * </ul>
3294     *
3295     * @see #getSamplerChannels
3296     * @see #getMidiInputDevices
3297     */
3298     public synchronized void
3299 iliev 1139 setChannelMidiInputDevice(int samplerChn, int devId)
3300 iliev 596 throws IOException, LscpException, LSException {
3301    
3302     verifyConnection();
3303 iliev 1139 out.writeLine("SET CHANNEL MIDI_INPUT_DEVICE " + samplerChn + ' ' + devId);
3304     if(getPrintOnlyMode()) return;
3305 iliev 596
3306     ResultSet rs = getEmptyResultSet();
3307     }
3308    
3309     /**
3310     * Sets the MIDI input port on the specified sampler channel.
3311     *
3312     * @param samplerChn The sampler channel number.
3313     * @param port The MIDI input port number of
3314     * the MIDI input device connected to the specified sampler channel.
3315     *
3316     * @throws IOException If some I/O error occurs.
3317     * @throws LscpException If LSCP protocol corruption occurs.
3318     * @throws LSException If <code>samplerChn</code> is not a valid channel number.
3319     * @see #getSamplerChannels
3320     */
3321     public synchronized void
3322     setChannelMidiInputPort(int samplerChn, int port)
3323     throws IOException, LscpException, LSException {
3324    
3325     verifyConnection();
3326     out.writeLine("SET CHANNEL MIDI_INPUT_PORT " + samplerChn + ' ' + port);
3327 iliev 1139 if(getPrintOnlyMode()) return;
3328 iliev 596
3329     ResultSet rs = getEmptyResultSet();
3330     }
3331    
3332     /**
3333     * Sets the MIDI input channel the specified sampler channel should listen to.
3334     *
3335     * @param samplerChn The sampler channel number.
3336     * @param midiChn The number of the new MIDI input channel where
3337     * <code>samplerChn</code> should listen to or -1 to listen on all 16 MIDI channels.
3338     *
3339     * @throws IOException If some I/O error occurs.
3340     * @throws LscpException If LSCP protocol corruption occurs.
3341     * @throws LSException If <code>samplerChn</code> is not a valid channel number.
3342     * @see #getSamplerChannels
3343     */
3344     public synchronized void
3345     setChannelMidiInputChannel(int samplerChn, int midiChn)
3346     throws IOException, LscpException, LSException {
3347    
3348     verifyConnection();
3349     String args = String.valueOf(samplerChn) + ' ';
3350     args += (midiChn == -1 ? "ALL" : String.valueOf(midiChn));
3351     out.writeLine("SET CHANNEL MIDI_INPUT_CHANNEL " + args);
3352 iliev 1139 if(getPrintOnlyMode()) return;
3353 iliev 596
3354     ResultSet rs = getEmptyResultSet();
3355     }
3356    
3357     /**
3358 iliev 1139 * Sets the MIDI instrument map to be used on the specified sampler channel.
3359     *
3360     * @param samplerChn The sampler channel number.
3361     * @param mapId Specifies the numerical ID of the MIDI instrument
3362     * map to assign. To remove the current map binding use <code>-1</code>.
3363     * To set the current map to be the default map use <code>-2</code>.
3364     *
3365     * @throws IOException If some I/O error occurs.
3366     * @throws LscpException If LSCP protocol corruption occurs.
3367     * @throws LSException If
3368     * <ul>
3369     * <li><code>samplerChn</code> is not a valid channel number;
3370     * <li><code>mapId</code> is not a valid MIDI instrument map ID;
3371     * </ul>
3372     *
3373     * @see #getSamplerChannels
3374     * @see #getMidiInstrumentMaps
3375     */
3376     public synchronized void
3377     setChannelMidiInstrumentMap(int samplerChn, int mapId)
3378     throws IOException, LscpException, LSException {
3379    
3380     verifyConnection();
3381     String s;
3382     if(mapId == -1) {
3383     s = " NONE";
3384     } else if(mapId == -2) {
3385     s = " DEFAULT";
3386     } else {
3387     s = " " + String.valueOf(mapId);
3388     }
3389     out.writeLine("SET CHANNEL MIDI_INSTRUMENT_MAP " + samplerChn + s);
3390     if(getPrintOnlyMode()) return;
3391    
3392     ResultSet rs = getEmptyResultSet();
3393     }
3394    
3395     /**
3396 iliev 596 * Sets the volume of the specified sampler channel.
3397     *
3398     * @param samplerChn The sampler channel number.
3399     * @param volume The new volume value.
3400     *
3401     * @throws IOException If some I/O error occurs.
3402     * @throws LscpException If LSCP protocol corruption occurs.
3403     * @throws LSException If <code>samplerChn</code> is not a valid channel number or if
3404     * there is no engine assigned yet to the specified sampler channel.
3405     * @see #getSamplerChannels
3406     */
3407     public synchronized void
3408     setChannelVolume(int samplerChn, float volume)
3409     throws IOException, LscpException, LSException {
3410    
3411     verifyConnection();
3412     out.writeLine("SET CHANNEL VOLUME " + samplerChn + ' ' + volume);
3413 iliev 1139 if(getPrintOnlyMode()) return;
3414 iliev 596
3415     ResultSet rs = getEmptyResultSet();
3416     }
3417    
3418     /**
3419 iliev 784 * Mute/unmute the specified sampler channel.
3420     *
3421     * @param samplerChn The sampler channel number.
3422     * @param mute If <code>true</code> the specified channel is muted, else the channel
3423     * is unmuted.
3424     *
3425     * @throws IOException If some I/O error occurs.
3426     * @throws LscpException If LSCP protocol corruption occurs.
3427     * @throws LSException If <code>samplerChn</code> is not a valid channel number or if
3428     * there is no engine assigned yet to the specified sampler channel.
3429     * @see #getSamplerChannels
3430     */
3431     public synchronized void
3432     setChannelMute(int samplerChn, boolean mute)
3433     throws IOException, LscpException, LSException {
3434    
3435     verifyConnection();
3436     out.writeLine("SET CHANNEL MUTE " + samplerChn + ' ' + (mute ? 1 : 0));
3437 iliev 1139 if(getPrintOnlyMode()) return;
3438 iliev 784
3439     ResultSet rs = getEmptyResultSet();
3440     }
3441    
3442     /**
3443     * Solo/unsolo the specified sampler channel.
3444     *
3445     * @param samplerChn The sampler channel number.
3446     * @param solo <code>true</code> to solo the specified channel, <code>false</code>
3447     * otherwise.
3448     *
3449     * @throws IOException If some I/O error occurs.
3450     * @throws LscpException If LSCP protocol corruption occurs.
3451     * @throws LSException If <code>samplerChn</code> is not a valid channel number or if
3452     * there is no engine assigned yet to the specified sampler channel.
3453     * @see #getSamplerChannels
3454     */
3455     public synchronized void
3456     setChannelSolo(int samplerChn, boolean solo)
3457     throws IOException, LscpException, LSException {
3458    
3459     verifyConnection();
3460     out.writeLine("SET CHANNEL SOLO " + samplerChn + ' ' + (solo ? 1 : 0));
3461 iliev 1139 if(getPrintOnlyMode()) return;
3462 iliev 784
3463     ResultSet rs = getEmptyResultSet();
3464     }
3465    
3466     /**
3467 iliev 1139 * Creates an additional effect send on the specified sampler channel.
3468     * @param channel The sampler channel, on which a new effect send should be added.
3469     * @param midiCtrl Defines the MIDI controller, which
3470     * will be able alter the effect send level.
3471     * @return The unique ID of the newly created effect send entity.
3472     * @throws IOException If some I/O error occurs.
3473     * @throws LSException If the creation of the effect send failed.
3474     * @throws LscpException If LSCP protocol corruption occurs.
3475     * @see #destroyFxSend
3476     */
3477     public synchronized int
3478     createFxSend(int channel, int midiCtrl)
3479     throws IOException, LSException, LscpException {
3480    
3481     return createFxSend(channel, midiCtrl, null);
3482     }
3483    
3484     /**
3485     * Creates an additional effect send on the specified sampler channel.
3486     * @param channel The sampler channel, on which the effect send should be created on.
3487     * @param midiCtrl Defines the MIDI controller, which can alter the effect send level.
3488     * @param name The name of the effect send entity. The name does not have to be unique.
3489     * @return The unique ID of the newly created effect send entity.
3490     * @throws IOException If some I/O error occurs.
3491     * @throws LSException If the creation of the effect send failed.
3492     * @throws LscpException If LSCP protocol corruption occurs.
3493     * @see #destroyFxSend
3494     */
3495     public synchronized int
3496     createFxSend(int channel, int midiCtrl, String name)
3497     throws IOException, LSException, LscpException {
3498    
3499     verifyConnection();
3500     String s = String.valueOf(channel) + " " + String.valueOf(midiCtrl);
3501     if(name != null) s += " '" + name + "'";
3502     out.writeLine("CREATE FX_SEND " + s);
3503     if(getPrintOnlyMode()) return -1;
3504    
3505     ResultSet rs = getEmptyResultSet();
3506    
3507     return rs.getIndex();
3508     }
3509    
3510     /**
3511     * Destroys the specified effect send on the specified sampler channel.
3512     * @param channel The sampler channel, from which
3513     * the specified effect send should be removed.
3514     * @param fxSend The ID of the effect send that should be removed.
3515     * @throws LSException If some other error occurs.
3516     * @throws LscpException If LSCP protocol corruption occurs.
3517     * @see #createFxSend
3518     */
3519     public synchronized void
3520     destroyFxSend(int channel, int fxSend)
3521     throws IOException, LSException, LscpException {
3522    
3523     verifyConnection();
3524     String s = String.valueOf(channel) + " " + String.valueOf(fxSend);
3525     out.writeLine("DESTROY FX_SEND " + s);
3526     if(getPrintOnlyMode()) return;
3527    
3528     ResultSet rs = getEmptyResultSet();
3529     }
3530    
3531     /**
3532     * Gets the current number of effect sends on the specified sampler channel.
3533     * @param channel The ID of the sampler channel.
3534     * @return The current number of effect sends on the specified sampler channels.
3535     * @throws IOException If some I/O error occurs.
3536     * @throws LscpException If LSCP protocol corruption occurs.
3537     * @throws LSException If some other error occurs.
3538     */
3539     public synchronized int
3540     getFxSoundCount(int channel) throws IOException, LscpException, LSException {
3541     verifyConnection();
3542     out.writeLine("GET FX_SENDS " + String.valueOf(channel));
3543     if(getPrintOnlyMode()) return -1;
3544    
3545     String s = getSingleLineResultSet().getResult();
3546     return parseInt(s);
3547     }
3548    
3549     /**
3550     * Gets a list of all created effect sends on the specified sampler channel.
3551     * @param channel The sampler channel number.
3552     * @return A <code>FxSend</code> array providing all created
3553     * effect sends on the specified sampler channel.
3554     * @throws IOException If some I/O error occurs.
3555     * @throws LscpException If LSCP protocol corruption occurs.
3556     * @throws LSException If <code>channel</code> is not a valid sampler channel ID.
3557     * @see #createFxSend
3558     * @see #destroyFxSend
3559     */
3560     public synchronized FxSend[]
3561     getFxSends(int channel) throws IOException, LscpException, LSException {
3562     Integer[] idS = getFxSendIDs(channel);
3563     if(getPrintOnlyMode()) return null;
3564    
3565     FxSend[] fxSends = new FxSend[idS.length];
3566    
3567     for(int i = 0; i < fxSends.length; i++)
3568     fxSends[i] = getFxSendInfo(channel, idS[i]);
3569    
3570     return fxSends;
3571     }
3572    
3573     /**
3574     * Gets a list of effect sends on the specified sampler channel.
3575     * @param channel The sampler channel number.
3576     * @return An <code>Integer</code> array providing
3577     * the numerical IDs of all effect sends on the specified sampler channel.
3578     * @throws IOException If some I/O error occurs.
3579     * @throws LscpException If LSCP protocol corruption occurs.
3580     * @throws LSException If <code>channel</code> is not a valid sampler channel ID.
3581     * @see #createFxSend
3582     * @see #destroyFxSend
3583     */
3584     public synchronized Integer[]
3585     getFxSendIDs(int channel) throws IOException, LscpException, LSException {
3586     verifyConnection();
3587     out.writeLine("LIST FX_SENDS " + channel);
3588     if(getPrintOnlyMode()) return null;
3589    
3590     return parseIntList(getSingleLineResultSet().getResult());
3591     }
3592    
3593     /**
3594     * Gets the current settings of the specified effect send entity.
3595     * @param channel The sampler channel number.
3596     * @param fxSend The numerical ID of the effect send entity.
3597     * @return <code>FxSend</code> instance containing
3598     * the current settings of the specified effect send entity.
3599     * @throws IOException If an I/O error occurs.
3600     * @throws LscpException If LSCP protocol corruption occurs.
3601     * @throws LSException If the sampler channel and/or the effect send number are invalid.
3602     */
3603     public synchronized FxSend
3604     getFxSendInfo(int channel, int fxSend) throws IOException, LscpException, LSException {
3605     verifyConnection();
3606     String s = String.valueOf(channel) + " " + String.valueOf(fxSend);
3607     out.writeLine("GET FX_SEND INFO " + s);
3608     if(getPrintOnlyMode()) return null;
3609    
3610     ResultSet rs = getMultiLineResultSet();
3611     FxSend fxs = new FxSend(rs.getMultiLineResult());
3612     fxs.setFxSendId(fxSend);
3613    
3614     return fxs;
3615     }
3616    
3617     /**
3618     * Sets the name of the specified effect send.
3619     * @param channel The sampler channel number.
3620     * @param fxSend The numerical ID of the effect send entity.
3621     * @param name The new name for the specified effect send.
3622     * @throws IOException If some I/O error occurs.
3623     * @throws LscpException If LSCP protocol corruption occurs.
3624     * @throws LSException If <code>channel</code> is not a valid channel
3625     * number or <code>fxSend</code> is not a valid effect send ID;
3626     */
3627     public synchronized void
3628     setFxSendName(int channel, int fxSend, String name)
3629     throws IOException, LscpException, LSException {
3630    
3631     verifyConnection();
3632     String args = " " + channel + " " + fxSend + " '" + name + "'";
3633     out.writeLine("SET FX_SEND NAME" + args);
3634     if(getPrintOnlyMode()) return;
3635    
3636     ResultSet rs = getEmptyResultSet();
3637     }
3638    
3639     /**
3640     * Sets the destination of an effect send's audio channel in the specified sampler channel.
3641     * @param channel The sampler channel number.
3642     * @param fxSend The numerical ID of the effect send entity to be rerouted.
3643     * @param audioSrc The numerical ID of the effect send's audio output channel,
3644     * which should be rerouted.
3645     * @param audioDst The audio channel of the selected audio output device
3646     * where <code>audioSrc</code> should be routed to.
3647     * @throws IOException If some I/O error occurs.
3648     * @throws LscpException If LSCP protocol corruption occurs.
3649     * @throws LSException If
3650     * <ul>
3651     * <li><code>channel</code> is not a valid channel number;
3652     * <li><code>fxSend</code> is not a valid effect send ID;
3653     * <li>There is no engine assigned yet to the specified sampler channel;
3654     * <li>There is no audio output device connected to the specified sampler channel.
3655     * </ul>
3656     */
3657     public synchronized void
3658     setFxSendAudioOutputChannel(int channel, int fxSend, int audioSrc, int audioDst)
3659     throws IOException, LscpException, LSException {
3660    
3661     verifyConnection();
3662     String args = " " + channel + " " + fxSend + " " + audioSrc + " " + audioDst;
3663     out.writeLine("SET FX_SEND AUDIO_OUTPUT_CHANNEL" + args);
3664     if(getPrintOnlyMode()) return;
3665    
3666     ResultSet rs = getEmptyResultSet();
3667     }
3668    
3669     /**
3670     * Sets the MIDI controller, which will be able to modify
3671     * the send level of the specified effect send in the specified sampler channel.
3672     * @param channel The sampler channel number.
3673     * @param fxSend The numerical ID of the effect send entity.
3674     * @param midiCtrl The MIDI controller which shall be
3675     * able to modify the effect send's send level.
3676     * @throws IOException If some I/O error occurs.
3677     * @throws LscpException If LSCP protocol corruption occurs.
3678     * @throws LSException If
3679     * <ul>
3680     * <li><code>channel</code> is not a valid channel number;
3681     * <li><code>fxSend</code> is not a valid effect send ID;
3682     * <li><code>midiCtrl</code> is not a valid controller;
3683     * </ul>
3684     */
3685     public synchronized void
3686     setFxSendMidiController(int channel, int fxSend, int midiCtrl)
3687     throws IOException, LscpException, LSException {
3688    
3689     verifyConnection();
3690     String args = " " + channel + " " + fxSend + " " + midiCtrl;
3691     out.writeLine("SET FX_SEND MIDI_CONTROLLER" + args);
3692     if(getPrintOnlyMode()) return;
3693    
3694     ResultSet rs = getEmptyResultSet();
3695     }
3696    
3697     /**
3698     * Sets the current send level of the specified
3699     * effect send entity in the specified sampler channel.
3700     * @param channel The sampler channel number.
3701     * @param fxSend The numerical ID of the effect send entity.
3702     * @param volume The new volume value (a value smaller than 1.0 means
3703     * attenuation, whereas a value greater than 1.0 means amplification).
3704     * @throws IOException If some I/O error occurs.
3705     * @throws LscpException If LSCP protocol corruption occurs.
3706     * @throws LSException If some other error occurs.
3707     */
3708     public synchronized void
3709     setFxSendLevel(int channel, int fxSend, float volume)
3710     throws IOException, LscpException, LSException {
3711    
3712     verifyConnection();
3713     String args = " " + channel + " " + fxSend + " " + String.valueOf(volume);
3714     out.writeLine("SET FX_SEND LEVEL" + args);
3715     if(getPrintOnlyMode()) return;
3716    
3717     ResultSet rs = getEmptyResultSet();
3718     }
3719    
3720 iliev 1202
3721    
3722 iliev 1139 /**
3723 iliev 1202 * Adds the specified directory to the instruments database.
3724     * @param dir The absolute path name of the directory to add.
3725     * @throws IOException If some I/O error occurs.
3726     * @throws LSException If the creation of the directory failed.
3727     * @throws LscpException If LSCP protocol corruption occurs.
3728     */
3729     public synchronized void
3730     addDbDirectory(String dir) throws IOException, LSException, LscpException {
3731     verifyConnection();
3732     out.writeLine("ADD DB_INSTRUMENT_DIRECTORY '" + dir + "'");
3733     if(getPrintOnlyMode()) return;
3734    
3735     ResultSet rs = getEmptyResultSet();
3736     }
3737    
3738     /**
3739     * Removes the specified directory from the instruments database.
3740     * @param dir The absolute path name of the directory to remove.
3741     * @throws IOException If some I/O error occurs.
3742     * @throws LscpException If LSCP protocol corruption occurs.
3743     * @throws LSException If the specified directory is not
3744     * empty or if the removal of the directory failed.
3745     */
3746     public synchronized void
3747     removeDbDirectory(String dir) throws IOException, LscpException, LSException {
3748     removeDbDirectory(dir, false);
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     * @param force If <code>true</code> forces the removal of non-empty
3755     * directory and all its content.
3756     * @throws IOException If some I/O error occurs.
3757     * @throws LscpException If LSCP protocol corruption occurs.
3758     * @throws LSException If the removing of the directory failed.
3759     */
3760     public synchronized void
3761     removeDbDirectory(String dir, boolean force)
3762     throws IOException, LscpException, LSException {
3763    
3764     verifyConnection();
3765     String s = "REMOVE DB_INSTRUMENT_DIRECTORY ";
3766     if(force) s += "FORCE ";
3767     out.writeLine(s + "'" + dir + "'");
3768     if(getPrintOnlyMode()) return;
3769    
3770     ResultSet rs = getEmptyResultSet();
3771     }
3772    
3773     /**
3774     * Removes the specified directories from the instruments database.
3775     * @param dirs The absolute path names of the directories to remove.
3776     * @param force If <code>true</code> forces the removal of non-empty
3777     * directories.
3778     * @throws IOException If some I/O error occurs.
3779     * @throws LscpException If LSCP protocol corruption occurs.
3780     * @throws LSException If the removing of the directores failed.
3781     */
3782     public synchronized void
3783     removeDbDirectories(String[] dirs, boolean force)
3784     throws IOException, LscpException, LSException {
3785    
3786     verifyConnection();
3787     String cmd = "REMOVE DB_INSTRUMENT_DIRECTORY ";
3788     if(force) cmd += "FORCE ";
3789    
3790     for(String s : dirs) out.writeLine(cmd + "'" + s + "'");
3791    
3792     if(getPrintOnlyMode()) return;
3793    
3794     getEmptyResultSets(dirs.length, "Client.dirDeletionFailed!");
3795     }
3796    
3797     /**
3798     * Gets the number of directories in the specified directory.
3799     * @return The current number of directories in the specified directory.
3800     * @param dir The absolute path name of the directory.
3801     * @throws IOException If some I/O error occurs.
3802     * @throws LscpException If LSCP protocol corruption occurs.
3803     * @throws LSException If some other error occurs.
3804     */
3805     public synchronized int
3806     getDbDirectoryCount(String dir) throws IOException, LscpException, LSException {
3807     return getDbDirectoryCount(dir, false);
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     * @param recursive If <code>true</code>, the number of all directories
3815     * in the specified subtree will be returned.
3816     * @throws IOException If some I/O error occurs.
3817     * @throws LscpException If LSCP protocol corruption occurs.
3818     * @throws LSException If some other error occurs.
3819     */
3820     public synchronized int
3821     getDbDirectoryCount(String dir, boolean recursive)
3822     throws IOException, LscpException, LSException {
3823    
3824     verifyConnection();
3825     String s;
3826     if(recursive) s = "GET DB_INSTRUMENT_DIRECTORIES RECURSIVE '";
3827     else s = "GET DB_INSTRUMENT_DIRECTORIES '";
3828     out.writeLine(s + dir + "'");
3829     if(getPrintOnlyMode()) return -1;
3830    
3831     s = getSingleLineResultSet().getResult();
3832     return parseInt(s);
3833     }
3834    
3835     /**
3836     * Gets the list of directories in the specified directory.
3837     * @param dir The absolute path name of the directory.
3838     * @return A <code>String</code> array providing the names of
3839     * all directories in the specified directory.
3840     * @throws IOException If some I/O error occurs.
3841     * @throws LscpException If LSCP protocol corruption occurs.
3842     * @throws LSException If the specified path name is invalid.
3843     */
3844     public synchronized String[]
3845     getDbDirectoryNames(String dir) throws IOException, LscpException, LSException {
3846     verifyConnection();
3847     out.writeLine("LIST DB_INSTRUMENT_DIRECTORIES '" + dir + "'");
3848     if(getPrintOnlyMode()) return null;
3849    
3850     return parseStringList(getSingleLineResultSet().getResult());
3851     }
3852    
3853     /**
3854     * Gets information about the specified directory.
3855     * @param dir The absolute path name of the directory.
3856     * @return A <code>DbDirectoryInfo</code> instance providing information
3857     * about the specified directory.
3858     * @throws IOException If some I/O error occurs.
3859     * @throws LscpException If LSCP protocol corruption occurs.
3860     * @throws LSException If the specified directory is not found.
3861     */
3862     public synchronized DbDirectoryInfo
3863     getDbDirectoryInfo(String dir) throws IOException, LscpException, LSException {
3864     verifyConnection();
3865     out.writeLine("GET DB_INSTRUMENT_DIRECTORY INFO '" + dir + "'");
3866     if(getPrintOnlyMode()) return null;
3867    
3868     ResultSet rs = getMultiLineResultSet();
3869     DbDirectoryInfo info = new DbDirectoryInfo(rs.getMultiLineResult());
3870     if(dir.equals("/")) {
3871     info.setName("/");
3872     } else if(dir.length() > 1 && dir.charAt(dir.length() - 1) == '/') {
3873     dir = dir.substring(0, dir.length() - 1);
3874     }
3875     int i = dir.lastIndexOf('/');
3876     if(i != -1 && i < dir.length() - 1) {
3877     info.setName(dir.substring(i + 1));
3878     if(i == 0) info.setParentDirectoryPath("/");
3879     else info.setParentDirectoryPath(dir.substring(0, i));
3880     }
3881    
3882     return info;
3883     }
3884    
3885     /**
3886     * Gets the list of directories in the specified directory.
3887     * @param dir The absolute path name of the directory.
3888     * @return A <code>DbDirectoryInfo</code> array providing
3889     * information about all directories in the specified directory.
3890     * @throws IOException If some I/O error occurs.
3891     * @throws LscpException If LSCP protocol corruption occurs.
3892     * @throws LSException If the specified path name is invalid.
3893     */
3894     public synchronized DbDirectoryInfo[]
3895     getDbDirectories(String dir) throws IOException, LscpException, LSException {
3896     String[] dirS = getDbDirectoryNames(dir);
3897     if(dir.charAt(dir.length() - 1) != '/') dir += "/";
3898     DbDirectoryInfo[] infoS = new DbDirectoryInfo[dirS.length];
3899     for(int i = 0; i < dirS.length; i++) infoS[i] = getDbDirectoryInfo(dir + dirS[i]);
3900     return infoS;
3901     }
3902    
3903     /**
3904     * Gets the list of directories in the specified directory.
3905     * @param dir The absolute path name of the directory.
3906     * @return A <code>DbDirectoryInfo</code> array providing
3907     * information about all directories in the specified directory.
3908     * @throws IOException If some I/O error occurs.
3909     * @throws LscpException If LSCP protocol corruption occurs.
3910     * @throws LSException If the specified path name is invalid.
3911     *
3912     public synchronized DbDirectoryInfo[]
3913     getDbDirectories(String dir) throws IOException, LscpException, LSException {
3914     String[] dirS = getDbDirectoryNames(dir);
3915     if(dirS.length == 0) return new DbDirectoryInfo[0];
3916    
3917     if(dir.charAt(dir.length() - 1) != '/') dir += "/";
3918    
3919     for(int i = 0; i < dirS.length; i++) {
3920     out.writeLine("GET DB_INSTRUMENT_DIRECTORY INFO '" + dir + dirS[i] + "'");
3921     }
3922    
3923     if(getPrintOnlyMode()) return null;
3924    
3925     if(dir.length() > 1) dir = dir.substring(0, dir.length() - 1);
3926     StringBuffer sb = new StringBuffer();
3927     DbDirectoryInfo[] infoS = new DbDirectoryInfo[dirS.length];
3928     for(int i = 0; i < dirS.length; i++) {
3929     try {
3930     ResultSet rs = getMultiLineResultSet();
3931     infoS[i] = new DbDirectoryInfo(rs.getMultiLineResult());
3932     infoS[i].setName(dirS[i]);
3933     infoS[i].setParentDirectoryPath(dir);
3934     } catch (SocketTimeoutException e) {
3935     getLogger().log(Level.FINE, e.getMessage(), e);
3936     sb.append(e.getMessage()).append("\n");
3937     break;
3938     } catch (Exception e) {
3939     getLogger().log(Level.FINE, e.getMessage(), e);
3940     sb.append(e.getMessage()).append("\n");
3941     }
3942     }
3943    
3944     String details = sb.toString();
3945     if(details.length() > 0) {
3946     String err = LscpI18n.getLogMsg("Client.getInstrsInfoFailed!");
3947     throw new LSException(0, err, details);
3948     }
3949    
3950     return infoS;
3951     }*/
3952    
3953     /**
3954     * Renames the specified directory.
3955     * @param dir The absolute path name of the directory to rename.
3956     * @param name The new name for the directory.
3957     * @throws IOException If some I/O error occurs.
3958     * @throws LSException If the renaming of the directory failed.
3959     * @throws LscpException If LSCP protocol corruption occurs.
3960     */
3961     public synchronized void
3962     renameDbDirectory(String dir, String name) throws IOException, LSException, LscpException {
3963     verifyConnection();
3964     out.writeLine("SET DB_INSTRUMENT_DIRECTORY NAME '" + dir + "' '" + name + "'");
3965     if(getPrintOnlyMode()) return;
3966    
3967     ResultSet rs = getEmptyResultSet();
3968     }
3969    
3970     /**
3971     * Moves the specified directory into the specified location.
3972     * @param dir The absolute path name of the directory to move.
3973     * @param dst The location where the directory will be moved to.
3974     * @throws IOException If some I/O error occurs.
3975     * @throws LSException If the operation failed.
3976     * @throws LscpException If LSCP protocol corruption occurs.
3977     */
3978     public synchronized void
3979     moveDbDirectory(String dir, String dst) throws IOException, LSException, LscpException {
3980     verifyConnection();
3981     out.writeLine("MOVE DB_INSTRUMENT_DIRECTORY '" + dir + "' '" + dst + "'");
3982     if(getPrintOnlyMode()) return;
3983    
3984     ResultSet rs = getEmptyResultSet();
3985     }
3986    
3987     /**
3988     * Moves the specified directories into the specified location.
3989     * @param dirs The absolute path names of the directories to move.
3990     * @param dst The location where the directories will be moved to.
3991     * @throws IOException If some I/O error occurs.
3992     * @throws LSException If the operation failed.
3993     * @throws LscpException If LSCP protocol corruption occurs.
3994     */
3995     public synchronized void
3996     moveDbDirectories(String dirs[], String dst) throws IOException, LSException, LscpException {
3997     verifyConnection();
3998     for(String s : dirs) {
3999     out.writeLine("MOVE DB_INSTRUMENT_DIRECTORY '" + s + "' '" + dst + "'");
4000     }
4001     if(getPrintOnlyMode()) return;
4002    
4003     getEmptyResultSets(dirs.length, "Client.dirMovingFailed!");
4004     }
4005    
4006     /**
4007     * Copies the specified directory into the specified location.
4008     * @param dir The absolute path name of the directory to copy.
4009     * @param dst The location where the directory will be copied to.
4010     * @throws IOException If some I/O error occurs.
4011     * @throws LSException If the operation failed.
4012     * @throws LscpException If LSCP protocol corruption occurs.
4013     */
4014     public synchronized void
4015     copyDbDirectory(String dir, String dst) throws IOException, LSException, LscpException {
4016     verifyConnection();
4017     out.writeLine("COPY DB_INSTRUMENT_DIRECTORY '" + dir + "' '" + dst + "'");
4018     if(getPrintOnlyMode()) return;
4019    
4020     ResultSet rs = getEmptyResultSet();
4021     }
4022    
4023     /**
4024     * Copies the specified directories into the specified location.
4025     * @param dirs The absolute path names of the directories to copy.
4026     * @param dst The location where the directories will be copied to.
4027     * @throws IOException If some I/O error occurs.
4028     * @throws LSException If the operation failed.
4029     * @throws LscpException If LSCP protocol corruption occurs.
4030     */
4031     public synchronized void
4032     copyDbDirectories(String[] dirs, String dst) throws IOException, LSException, LscpException {
4033     verifyConnection();
4034     for(String s : dirs) {
4035     out.writeLine("COPY DB_INSTRUMENT_DIRECTORY '" + s + "' '" + dst + "'");
4036     }
4037     if(getPrintOnlyMode()) return;
4038    
4039     getEmptyResultSets(dirs.length, "Client.dirCopyingFailed!");
4040     }
4041    
4042     /**
4043     * Changes the description of the specified directory.
4044     * @param dir The absolute path name of the directory.
4045     * @param desc The new description for the directory.
4046     * @throws IOException If some I/O error occurs.
4047     * @throws LSException If failed to change the description.
4048     * @throws LscpException If LSCP protocol corruption occurs.
4049     */
4050     public synchronized void
4051     setDbDirectoryDescription(String dir, String desc)
4052     throws IOException, LSException, LscpException {
4053    
4054     verifyConnection();
4055     String s = "SET DB_INSTRUMENT_DIRECTORY DESCRIPTION '";
4056     out.writeLine(s + dir + "' '" + desc + "'");
4057     if(getPrintOnlyMode()) return;
4058    
4059     ResultSet rs = getEmptyResultSet();
4060     }
4061    
4062     public static enum ScanMode {
4063     RECURSIVE, NON_RECURSIVE, FLAT
4064     }
4065    
4066     /**
4067     * Adds the specified instrument to the specified instruments database directory.
4068     * @param dbDir The absolute path name of the database directory in which the
4069     * specified instrument will be added.
4070     * @param filePath The absolute path name of the instrument file.
4071     * @param instrIndex The index of the instrument (in the given instrument file) to add.
4072     * @throws IOException If some I/O error occurs.
4073     * @throws LSException If the operation failed.
4074     * @throws LscpException If LSCP protocol corruption occurs.
4075     */
4076     public synchronized void
4077     addDbInstrument(String dbDir, String filePath, int instrIndex)
4078     throws IOException, LSException, LscpException {
4079    
4080     addDbInstrument(dbDir, filePath, instrIndex, false);
4081     }
4082    
4083     /**
4084     * Adds the specified instrument to the specified instruments database directory.
4085     * @param dbDir The absolute path name of the database directory in which the
4086     * specified instrument will be added.
4087     * @param filePath The absolute path name of the instrument file.
4088     * @param instrIndex The index of the instrument (in the given instrument file) to add.
4089     * @param background If <code>true</code>, the scan will be done
4090     * in background and this method may return before the job is finished.
4091     * @return If <code>background</code> is <code>true</code>, the ID
4092     * of the scan job.
4093     * @throws IOException If some I/O error occurs.
4094     * @throws LSException If the operation failed.
4095     * @throws LscpException If LSCP protocol corruption occurs.
4096     * @see #addInstrumentsDbListener
4097     */
4098     public synchronized int
4099     addDbInstrument(String dbDir, String filePath, int instrIndex, boolean background)
4100     throws IOException, LSException, LscpException {
4101    
4102     verifyConnection();
4103     String s = "ADD DB_INSTRUMENTS";
4104     if(background) s += " NON_MODAL";
4105     s += " '" + dbDir + "' '" + filePath + "' ";
4106     out.writeLine(s + String.valueOf(instrIndex));
4107     if(getPrintOnlyMode()) return -1;
4108    
4109     ResultSet rs = getEmptyResultSet();
4110     return rs.getIndex();
4111     }
4112    
4113     /**
4114     * Adds the instruments in the specified file to the specified
4115     * instruments database directory.
4116     * @param dbDir The absolute path name of the database directory
4117     * in which the the supported instruments will be added.
4118     * @param filePath The absolute path name of the file to scan for instruments.
4119     * @throws IOException If some I/O error occurs.
4120     * @throws LSException If the operation failed.
4121     * @throws LscpException If LSCP protocol corruption occurs.
4122     */
4123     public synchronized void
4124     addDbInstruments(String dbDir, String filePath)
4125     throws IOException, LSException, LscpException {
4126    
4127     addDbInstruments(dbDir, filePath, false);
4128     }
4129    
4130     /**
4131     * Adds the instruments in the specified file to the specified
4132     * instruments database directory.
4133     * @param dbDir The absolute path name of the database directory
4134     * in which the the supported instruments will be added.
4135     * @param filePath The absolute path name of the file to scan for instruments.
4136     * @param background If <code>true</code>, the scan will be done
4137     * in background and this method may return before the job is finished.
4138     * @return If <code>background</code> is <code>true</code>, the ID
4139     * of the scan job.
4140     * @throws IOException If some I/O error occurs.
4141     * @throws LSException If the operation failed.
4142     * @throws LscpException If LSCP protocol corruption occurs.
4143     * @see #addInstrumentsDbListener
4144     */
4145     public synchronized int
4146     addDbInstruments(String dbDir, String filePath, boolean background)
4147     throws IOException, LSException, LscpException {
4148    
4149     verifyConnection();
4150     String s = "ADD DB_INSTRUMENTS";
4151     if(background) s += " NON_MODAL";
4152     out.writeLine(s + " '" + dbDir + "' '" + filePath + "'");
4153     if(getPrintOnlyMode()) return -1;
4154    
4155     ResultSet rs = getEmptyResultSet();
4156     return rs.getIndex();
4157     }
4158    
4159     /**
4160     * Adds the instruments in the specified file system directory
4161     * to the specified instruments database directory.
4162     * @param mode Determines the scanning mode. If RECURSIVE is
4163     * specified, all supported instruments in the specified file system
4164     * direcotry will be added to the specified instruments database
4165     * directory, including the instruments in subdirectories
4166     * of the supplied directory. If NON_RECURSIVE is specified,
4167     * the instruments in the subdirectories will not be processed.
4168     * If FLAT is specified, all supported instruments in the specified
4169     * file system direcotry will be added, including the instruments in
4170     * subdirectories of the supplied directory, but the respective
4171     * subdirectory structure will not be recreated in the instruments
4172     * database and all instruments will be added directly in the
4173     * specified database directory.
4174     * @param dbDir The absolute path name of the database directory
4175     * in which the supported instruments will be added.
4176     * @param fsDir The absolute path name of the file system directory.
4177     * @throws IOException If some I/O error occurs.
4178     * @throws LSException If the operation failed.
4179     * @throws LscpException If LSCP protocol corruption occurs.
4180     */
4181     public synchronized void
4182     addDbInstruments(ScanMode mode, String dbDir, String fsDir)
4183     throws IOException, LSException, LscpException {
4184    
4185     addDbInstruments(mode, dbDir, fsDir, false);
4186     }
4187    
4188     /**
4189     * Adds the instruments in the specified file system directory
4190     * to the specified instruments database directory.
4191     * @param mode Determines the scanning mode. If RECURSIVE is
4192     * specified, all supported instruments in the specified file system
4193     * direcotry will be added to the specified instruments database
4194     * directory, including the instruments in subdirectories
4195     * of the supplied directory. If NON_RECURSIVE is specified,
4196     * the instruments in the subdirectories will not be processed.
4197     * If FLAT is specified, all supported instruments in the specified
4198     * file system direcotry will be added, including the instruments in
4199     * subdirectories of the supplied directory, but the respective
4200     * subdirectory structure will not be recreated in the instruments
4201     * database and all instruments will be added directly in the
4202     * specified database directory.
4203     * @param dbDir The absolute path name of the database directory
4204     * in which the supported instruments will be added.
4205     * @param fsDir The absolute path name of the file system directory.
4206     * @param background If <code>true</code>, the scan will be done
4207     * in background and this method may return before the job is finished.
4208     * @return If <code>background</code> is <code>true</code>, the ID
4209     * of the scan job.
4210     * @throws IOException If some I/O error occurs.
4211     * @throws LSException If the operation failed.
4212     * @throws LscpException If LSCP protocol corruption occurs.
4213     * @see #addInstrumentsDbListener
4214     */
4215     public synchronized int
4216     addDbInstruments(ScanMode mode, String dbDir, String fsDir, boolean background)
4217     throws IOException, LSException, LscpException {
4218    
4219     verifyConnection();
4220     StringBuffer sb = new StringBuffer("ADD DB_INSTRUMENTS");
4221     if(background) sb.append(" NON_MODAL");
4222    
4223     switch(mode) {
4224     case RECURSIVE:
4225     sb.append(" RECURSIVE");
4226     break;
4227     case NON_RECURSIVE:
4228     sb.append(" NON_RECURSIVE");
4229     break;
4230     case FLAT:
4231     sb.append(" FLAT");
4232     break;
4233     }
4234    
4235     sb.append(" '").append(dbDir).append("' '").append(fsDir).append("'");
4236     out.writeLine(sb.toString());
4237     if(getPrintOnlyMode()) return -1;
4238    
4239     ResultSet rs = getEmptyResultSet();
4240     return rs.getIndex();
4241     }
4242    
4243     /**
4244     * Removes the specified instrument from the instruments database.
4245     * @param instr The absolute path name of the instrument to remove.
4246     * @throws IOException If some I/O error occurs.
4247     * @throws LscpException If LSCP protocol corruption occurs.
4248     * @throws LSException If the removing of the instrument failed.
4249     */
4250     public synchronized void
4251     removeDbInstrument(String instr) throws IOException, LscpException, LSException {
4252    
4253     verifyConnection();
4254     out.writeLine("REMOVE DB_INSTRUMENT '" + instr + "'");
4255     if(getPrintOnlyMode()) return;
4256    
4257     ResultSet rs = getEmptyResultSet();
4258     }
4259    
4260     /**
4261     * Removes the specified instruments from the instruments database.
4262     * @param instrs The absolute path names of the instruments to remove.
4263     * @throws IOException If some I/O error occurs.
4264     * @throws LscpException If LSCP protocol corruption occurs.
4265     * @throws LSException If the removing of the instruments failed.
4266     */
4267     public synchronized void
4268     removeDbInstruments(String[] instrs) throws IOException, LscpException, LSException {
4269     verifyConnection();
4270     for(String s : instrs) {
4271     out.writeLine("REMOVE DB_INSTRUMENT '" + s + "'");
4272     }
4273     if(getPrintOnlyMode()) return;
4274    
4275     getEmptyResultSets(instrs.length, "Client.instrDeletionFailed!");
4276     }
4277    
4278     /**
4279     * Gets the number of instruments in the specified directory.
4280     * @return The current number of instruments in the specified directory.
4281     * @param dir The absolute path name of the directory.
4282     * @throws IOException If some I/O error occurs.
4283     * @throws LscpException If LSCP protocol corruption occurs.
4284     * @throws LSException If some other error occurs.
4285     */
4286     public synchronized int
4287     getDbInstrumentCount(String dir) throws IOException, LscpException, LSException {
4288     return getDbInstrumentCount(dir, false);
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     * @param recursive If <code>true</code>, the number of all instruments
4296     * in the specified subtree will be returned.
4297     * @throws IOException If some I/O error occurs.
4298     * @throws LscpException If LSCP protocol corruption occurs.
4299     * @throws LSException If some other error occurs.
4300     */
4301     public synchronized int
4302     getDbInstrumentCount(String dir, boolean recursive)
4303     throws IOException, LscpException, LSException {
4304    
4305     verifyConnection();
4306     String s;
4307     if(recursive) s = "GET DB_INSTRUMENTS RECURSIVE '";
4308     else s = "GET DB_INSTRUMENTS '";
4309     out.writeLine(s + dir + "'");
4310     if(getPrintOnlyMode()) return -1;
4311    
4312     s = getSingleLineResultSet().getResult();
4313     return parseInt(s);
4314     }
4315    
4316     /**
4317     * Gets the list of instruments in the specified directory.
4318     * @param dir The absolute path name of the directory.
4319     * @return A <code>String</code> array providing the names of
4320     * all instruments in the specified directory.
4321     * @throws IOException If some I/O error occurs.
4322     * @throws LscpException If LSCP protocol corruption occurs.
4323     * @throws LSException If the specified path name is invalid.
4324     */
4325     public synchronized String[]
4326     getDbInstrumentNames(String dir) throws IOException, LscpException, LSException {
4327     verifyConnection();
4328     out.writeLine("LIST DB_INSTRUMENTS '" + dir + "'");
4329     if(getPrintOnlyMode()) return null;
4330    
4331     return parseStringList(getSingleLineResultSet().getResult());
4332     }
4333    
4334     /**
4335     * Gets information about the specified instrument.
4336     * @param instr The absolute path name of the instrument.
4337     * @return A <code>DbInstrumentInfo</code> instance providing information
4338     * about the specified instrument.
4339     * @throws IOException If some I/O error occurs.
4340     * @throws LscpException If LSCP protocol corruption occurs.
4341     * @throws LSException If the specified instrument is not found.
4342     */
4343     public synchronized DbInstrumentInfo
4344     getDbInstrumentInfo(String instr) throws IOException, LscpException, LSException {
4345     verifyConnection();
4346     out.writeLine("GET DB_INSTRUMENT INFO '" + instr + "'");
4347     if(getPrintOnlyMode()) return null;
4348    
4349     ResultSet rs = getMultiLineResultSet();
4350     DbInstrumentInfo info = new DbInstrumentInfo(rs.getMultiLineResult());
4351     int i = instr.lastIndexOf('/');
4352     if(i != -1 && i < instr.length() - 1) {
4353     info.setName(instr.substring(i + 1));
4354     if(i == 0) info.setDirectoryPath("/");
4355     else info.setDirectoryPath(instr.substring(0, i));
4356     }
4357    
4358     return info;
4359     }
4360    
4361     /**
4362     * Gets the list of instruments in the specified directory.
4363     * @param dir The absolute path name of the directory.
4364     * @return A <code>DbInstrumentInfo</code> array providing
4365     * information about all instruments in the specified directory.
4366     * @throws IOException If some I/O error occurs.
4367     * @throws LscpException If LSCP protocol corruption occurs.
4368     * @throws LSException If the specified path name is invalid.
4369     */
4370     public synchronized DbInstrumentInfo[]
4371     getDbInstruments(String dir) throws IOException, LscpException, LSException {
4372     String[] instrS = getDbInstrumentNames(dir);
4373     if(dir.charAt(dir.length() - 1) != '/') dir += "/";
4374    
4375     DbInstrumentInfo[] infoS = new DbInstrumentInfo[instrS.length];
4376     for(int i = 0; i < instrS.length; i++) {
4377     infoS[i] = getDbInstrumentInfo(dir + instrS[i]);
4378     }
4379     return infoS;
4380     }
4381    
4382     /**
4383     * Gets the list of instruments in the specified directory.
4384     * @param dir The absolute path name of the directory.
4385     * @return A <code>DbInstrumentInfo</code> array providing
4386     * information about all instruments in the specified directory.
4387     * @throws IOException If some I/O error occurs.
4388     * @throws LscpException If LSCP protocol corruption occurs.
4389     * @throws LSException If the specified path name is invalid.
4390     *
4391     public synchronized DbInstrumentInfo[]
4392     getDbInstruments(String dir) throws IOException, LscpException, LSException {
4393     String[] instrS = getDbInstrumentNames(dir);
4394     if(instrS.length == 0) return new DbInstrumentInfo[0];
4395    
4396     if(dir.charAt(dir.length() - 1) != '/') dir += "/";
4397    
4398     for(int i = 0; i < instrS.length; i++) {
4399     out.writeLine("GET DB_INSTRUMENT INFO '" + dir + instrS[i] + "'");
4400     }
4401    
4402     if(getPrintOnlyMode()) return null;
4403    
4404     if(dir.length() > 1) dir = dir.substring(0, dir.length() - 1);
4405     StringBuffer sb = new StringBuffer();
4406     DbInstrumentInfo[] infoS = new DbInstrumentInfo[instrS.length];
4407     for(int i = 0; i < instrS.length; i++) {
4408     try {
4409     ResultSet rs = getMultiLineResultSet();
4410     infoS[i] = new DbInstrumentInfo(rs.getMultiLineResult());
4411     infoS[i].setName(instrS[i]);
4412     infoS[i].setDirectoryPath(dir);
4413     } catch (SocketTimeoutException e) {
4414     getLogger().log(Level.FINE, e.getMessage(), e);
4415     sb.append(e.getMessage()).append("\n");
4416     break;
4417     } catch (Exception e) {
4418     getLogger().log(Level.FINE, e.getMessage(), e);
4419     sb.append(e.getMessage()).append("\n");
4420     }
4421     }
4422    
4423     String details = sb.toString();
4424     if(details.length() > 0) {
4425     String err = LscpI18n.getLogMsg("Client.getInstrsInfoFailed!");
4426     throw new LSException(0, err, details);
4427     }
4428    
4429     return infoS;
4430     }*/
4431    
4432     /**
4433     * Renames the specified instrument.
4434     * @param instr The absolute path name of the instrument to rename.
4435     * @param name The new name for the instrument.
4436     * @throws IOException If some I/O error occurs.
4437     * @throws LSException If the renaming of the instrument failed.
4438     * @throws LscpException If LSCP protocol corruption occurs.
4439     */
4440     public synchronized void
4441     renameDbInstrument(String instr, String name)
4442     throws IOException, LSException, LscpException {
4443    
4444     verifyConnection();
4445     out.writeLine("SET DB_INSTRUMENT NAME '" + instr + "' '" + name + "'");
4446     if(getPrintOnlyMode()) return;
4447    
4448     ResultSet rs = getEmptyResultSet();
4449     }
4450    
4451     /**
4452     * Moves the specified instrument into the specified location.
4453     * @param instr The absolute path name of the instrument to move.
4454     * @param dst The directory where the specified instrument will be moved to.
4455     * @throws IOException If some I/O error occurs.
4456     * @throws LSException If the operation failed.
4457     * @throws LscpException If LSCP protocol corruption occurs.
4458     */
4459     public synchronized void
4460     moveDbInstrument(String instr, String dst) throws IOException, LSException, LscpException {
4461     verifyConnection();
4462     out.writeLine("MOVE DB_INSTRUMENT '" + instr + "' '" + dst + "'");
4463     if(getPrintOnlyMode()) return;
4464    
4465     ResultSet rs = getEmptyResultSet();
4466     }
4467    
4468     /**
4469     * Moves the specified instruments into the specified location.
4470     * @param instrs The absolute path names of the instruments to move.
4471     * @param dst The directory where the specified instruments will be moved to.
4472     * @throws IOException If some I/O error occurs.
4473     * @throws LSException If the operation failed.
4474     * @throws LscpException If LSCP protocol corruption occurs.
4475     */
4476     public synchronized void
4477     moveDbInstruments(String[] instrs, String dst) throws IOException, LSException, LscpException {
4478     verifyConnection();
4479     for(String s : instrs) {
4480     out.writeLine("MOVE DB_INSTRUMENT '" + s + "' '" + dst + "'");
4481     }
4482     if(getPrintOnlyMode()) return;
4483    
4484     getEmptyResultSets(instrs.length, "Client.instrMovingFailed!");
4485     }
4486    
4487     /**
4488     * Copies the specified instrument into the specified location.
4489     * @param instr The absolute path name of the instrument to copy.
4490     * @param dst The directory where the specified instrument will be copied to.
4491     * @throws IOException If some I/O error occurs.
4492     * @throws LSException If the operation failed.
4493     * @throws LscpException If LSCP protocol corruption occurs.
4494     */
4495     public synchronized void
4496     copyDbInstrument(String instr, String dst) throws IOException, LSException, LscpException {
4497     verifyConnection();
4498     out.writeLine("COPY DB_INSTRUMENT '" + instr + "' '" + dst + "'");
4499     if(getPrintOnlyMode()) return;
4500    
4501     ResultSet rs = getEmptyResultSet();
4502     }
4503    
4504     /**
4505     * Copies the specified instruments into the specified location.
4506     * @param instrs The absolute path name of the instruments to copy.
4507     * @param dst The directory where the specified instruments will be copied to.
4508     * @throws IOException If some I/O error occurs.
4509     * @throws LSException If the operation failed.
4510     * @throws LscpException If LSCP protocol corruption occurs.
4511     */
4512     public synchronized void
4513     copyDbInstruments(String[] instrs, String dst) throws IOException, LSException, LscpException {
4514     verifyConnection();
4515     for(String s : instrs) {
4516     out.writeLine("COPY DB_INSTRUMENT '" + s + "' '" + dst + "'");
4517     }
4518     if(getPrintOnlyMode()) return;
4519    
4520     getEmptyResultSets(instrs.length, "Client.instrCopyingFailed!");
4521     }
4522    
4523     /**
4524     * Changes the description of the specified instrument.
4525     * @param instr The absolute path name of the instrument.
4526     * @param desc The new description for the instrument.
4527     * @throws IOException If some I/O error occurs.
4528     * @throws LSException If failed to change the description.
4529     * @throws LscpException If LSCP protocol corruption occurs.
4530     */
4531     public synchronized void
4532     setDbInstrumentDescription(String instr, String desc)
4533     throws IOException, LSException, LscpException {
4534    
4535     verifyConnection();
4536     out.writeLine("SET DB_INSTRUMENT DESCRIPTION '" + instr + "' '" + desc + "'");
4537     if(getPrintOnlyMode()) return;
4538    
4539     ResultSet rs = getEmptyResultSet();
4540     }
4541    
4542     /**
4543     * Finds all directories in the specified directory
4544     * that corresponds to the specified search criterias.
4545     * @param dir The absolute path name of the directory to search.
4546     * @param query Provides the search criterias.
4547     * @return A <code>DbDirectoryInfo</code> array providing
4548     * information about all directories that are found in the specified directory.
4549     * @throws IOException If some I/O error occurs.
4550     * @throws LscpException If LSCP protocol corruption occurs.
4551     * @throws LSException If the specified path name is invalid.
4552     */
4553     public synchronized DbDirectoryInfo[]
4554     findDbDirectories(String dir, DbSearchQuery query)
4555     throws IOException, LscpException, LSException {
4556    
4557     return findDbDirectories(dir, query, false);
4558     }
4559    
4560     /**
4561     * Finds all directories in the specified directory
4562     * that corresponds to the specified search criterias.
4563     * @param dir The absolute path name of the directory to search.
4564     * @param query Provides the search criterias.
4565     * @param nonRecursive If <code>true</code>, the search will be non-recursive.
4566     * @return A <code>DbDirectoryInfo</code> array providing
4567     * information about all directories that are found in the specified directory.
4568     * @throws IOException If some I/O error occurs.
4569     * @throws LscpException If LSCP protocol corruption occurs.
4570     * @throws LSException If the specified path name is invalid.
4571     */
4572     public synchronized DbDirectoryInfo[]
4573     findDbDirectories(String dir, DbSearchQuery query, boolean nonRecursive)
4574     throws IOException, LscpException, LSException {
4575    
4576     verifyConnection();
4577     StringBuffer sb = new StringBuffer();
4578     sb.append("FIND DB_INSTRUMENT_DIRECTORIES");
4579     if(nonRecursive) sb.append(" NON_RECURSIVE");
4580     sb.append(" '").append(dir).append("'");
4581    
4582     if(query.name != null && query.name.length() > 0) {
4583     sb.append(" NAME='").append(query.name).append("'");
4584     }
4585    
4586     String s = query.getCreatedAfter();
4587     String s2 = query.getCreatedBefore();
4588     if(s != null || s2 != null) {
4589     sb.append(" CREATED='");
4590     if(s != null) sb.append(s);
4591     sb.append("..");
4592     if(s2 != null) sb.append(s2);
4593     sb.append("'");
4594     }
4595    
4596     s = query.getModifiedAfter();
4597     s2 = query.getModifiedBefore();
4598     if(s != null || s2 != null) {
4599     sb.append(" MODIFIED='");
4600     if(s != null) sb.append(s);
4601     sb.append("..");
4602     if(s2 != null) sb.append(s2);
4603     sb.append("'");
4604     }
4605    
4606     if(query.description != null && query.description.length() > 0) {
4607     sb.append(" DESCRIPTION='").append(query.description).append("'");
4608     }
4609    
4610     out.writeLine(sb.toString());
4611     if(getPrintOnlyMode()) return null;
4612    
4613     String[] dirS = parseStringList(getSingleLineResultSet().getResult());
4614    
4615     DbDirectoryInfo[] infoS = new DbDirectoryInfo[dirS.length];
4616     for(int i = 0; i < dirS.length; i++) {
4617     infoS[i] = getDbDirectoryInfo(dirS[i]);
4618     }
4619     return infoS;
4620     }
4621    
4622     /**
4623     * Finds all instruments in the specified directory
4624     * that corresponds to the specified search criterias.
4625     * @param dir The absolute path name of the directory to search.
4626     * @param query Provides the search criterias.
4627     * @return A <code>DbInstrumentInfo</code> array providing
4628     * information about all instruments that are found in the specified directory.
4629     * @throws IOException If some I/O error occurs.
4630     * @throws LscpException If LSCP protocol corruption occurs.
4631     * @throws LSException If the specified path name is invalid.
4632     */
4633     public synchronized DbInstrumentInfo[]
4634     findDbInstruments(String dir, DbSearchQuery query)
4635     throws IOException, LscpException, LSException {
4636    
4637     return findDbInstruments(dir, query, false);
4638     }
4639    
4640     /**
4641     * Finds all instruments in the specified directory
4642     * that corresponds to the specified search criterias.
4643     * @param dir The absolute path name of the directory to search.
4644     * @param query Provides the search criterias.
4645     * @param nonRecursive If <code>true</code>, the search will be non-recursive.
4646     * @return A <code>DbInstrumentInfo</code> array providing
4647     * information about all instruments that are found in the specified directory.
4648     * @throws IOException If some I/O error occurs.
4649     * @throws LscpException If LSCP protocol corruption occurs.
4650     * @throws LSException If the specified path name is invalid.
4651     */
4652     public synchronized DbInstrumentInfo[]
4653     findDbInstruments(String dir, DbSearchQuery query, boolean nonRecursive)
4654     throws IOException, LscpException, LSException {
4655    
4656     verifyConnection();
4657     StringBuffer sb = new StringBuffer();
4658     sb.append("FIND DB_INSTRUMENTS");
4659     if(nonRecursive) sb.append(" NON_RECURSIVE");
4660     sb.append(" '").append(dir).append("'");
4661    
4662     if(query.name != null && query.name.length() > 0) {
4663     sb.append(" NAME='").append(query.name).append("'");
4664     }
4665    
4666     if(query.formatFamilies.size() > 0) {
4667     sb.append(" FORMAT_FAMILIES='").append(query.formatFamilies.get(0));
4668     for(int i = 1; i < query.formatFamilies.size(); i++) {
4669     sb.append(',').append(query.formatFamilies.get(i));
4670     }
4671     sb.append("'");
4672     }
4673    
4674     if(query.minSize != -1 || query.maxSize != -1) {
4675     sb.append(" SIZE='");
4676     if(query.minSize != -1) sb.append(query.minSize);
4677     sb.append("..");
4678     if(query.maxSize != -1) sb.append(query.maxSize);
4679     sb.append("'");
4680     }
4681    
4682     String s = query.getCreatedAfter();
4683     String s2 = query.getCreatedBefore();
4684     if(s != null || s2 != null) {
4685     sb.append(" CREATED='");
4686     if(s != null) sb.append(s);
4687     sb.append("..");
4688     if(s2 != null) sb.append(s2);
4689     sb.append("'");
4690     }
4691    
4692     s = query.getModifiedAfter();
4693     s2 = query.getModifiedBefore();
4694     if(s != null || s2 != null) {
4695     sb.append(" MODIFIED='");
4696     if(s != null) sb.append(s);
4697     sb.append("..");
4698     if(s2 != null) sb.append(s2);
4699     sb.append("'");
4700     }
4701    
4702     if(query.description != null && query.description.length() > 0) {
4703     sb.append(" DESCRIPTION='").append(query.description).append("'");
4704     }
4705    
4706     if(query.instrumentType != DbSearchQuery.InstrumentType.BOTH) {
4707     sb.append(" IS_DRUM=");
4708     if(query.instrumentType == DbSearchQuery.InstrumentType.DRUM) {
4709     sb.append("'true'");
4710     } else {
4711     sb.append("'false'");
4712     }
4713     }
4714    
4715     if(query.product != null && query.product.length() > 0) {
4716     sb.append(" PRODUCT='").append(query.product).append("'");
4717     }
4718    
4719     if(query.artists != null && query.artists.length() > 0) {
4720     sb.append(" ARTISTS='").append(query.artists).append("'");
4721     }
4722    
4723     if(query.keywords != null && query.keywords.length() > 0) {
4724     sb.append(" KEYWORDS='").append(query.keywords).append("'");
4725     }
4726    
4727     out.writeLine(sb.toString());
4728     if(getPrintOnlyMode()) return null;
4729    
4730     String[] instrS = parseStringList(getSingleLineResultSet().getResult());
4731    
4732     DbInstrumentInfo[] infoS = new DbInstrumentInfo[instrS.length];
4733     for(int i = 0; i < instrS.length; i++) {
4734     infoS[i] = getDbInstrumentInfo(instrS[i]);
4735     }
4736     return infoS;
4737     }
4738    
4739     /**
4740     * Gets status information about the specified job.
4741     * @param jobId The ID of the job.
4742     * @return A <code>ScanJobInfo</code> instance providing information
4743     * about the specified job.
4744     * @throws IOException If some I/O error occurs.
4745     * @throws LscpException If LSCP protocol corruption occurs.
4746     * @throws LSException If the specified job is not found.
4747     */
4748     public synchronized ScanJobInfo
4749     getDbInstrumentsJobInfo(int jobId) throws IOException, LscpException, LSException {
4750     verifyConnection();
4751     out.writeLine("GET DB_INSTRUMENTS_JOB INFO " + String.valueOf(jobId));
4752     if(getPrintOnlyMode()) return null;
4753    
4754     ResultSet rs = getMultiLineResultSet();
4755     ScanJobInfo info = new ScanJobInfo(rs.getMultiLineResult());
4756    
4757     return info;
4758     }
4759    
4760     /**
4761 iliev 596 * Resets the specified sampler channel.
4762     *
4763     * @param samplerChn The sampler channel number.
4764     *
4765     * @throws IOException If some I/O error occurs.
4766     * @throws LscpException If LSCP protocol corruption occurs.
4767     * @throws LSException If <code>samplerChn</code> is not a valid channel number or if
4768     * there is no engine assigned yet to the specified sampler channel.
4769     * @see #getSamplerChannels
4770     */
4771     public synchronized void
4772     resetChannel(int samplerChn) throws IOException, LscpException, LSException {
4773     verifyConnection();
4774     out.writeLine("RESET CHANNEL " + samplerChn);
4775 iliev 1139 if(getPrintOnlyMode()) return;
4776 iliev 596
4777     ResultSet rs = getEmptyResultSet();
4778     }
4779    
4780     /**
4781     * Resets the whole sampler.
4782     *
4783     * @throws IOException If some I/O error occurs.
4784     * @throws LscpException If LSCP protocol corruption occurs.
4785     */
4786     public synchronized void
4787     resetSampler() throws IOException, LscpException {
4788     verifyConnection();
4789     out.writeLine("RESET");
4790 iliev 1139 if(getPrintOnlyMode()) return;
4791    
4792 iliev 596 try { ResultSet rs = getEmptyResultSet(); }
4793     catch(LSException x) { getLogger().warning(x.getMessage()); }
4794     }
4795    
4796     /**
4797 iliev 784 * Gets the current number of all active voices.
4798     * @return The current number of all active voices.
4799     * @throws IOException If some I/O error occurs.
4800     * @throws LscpException If LSCP protocol corruption occurs.
4801     * @throws LSException If some other error occurs.
4802     */
4803     public synchronized int
4804     getTotalVoiceCount() throws IOException, LscpException, LSException {
4805     verifyConnection();
4806     out.writeLine("GET TOTAL_VOICE_COUNT");
4807 iliev 1139 if(getPrintOnlyMode()) return -1;
4808    
4809 iliev 784 String s = getSingleLineResultSet().getResult();
4810     return parseInt(s);
4811     }
4812    
4813     /**
4814     * Gets the maximum number of active voices.
4815     * @return The maximum number of active voices.
4816     * @throws IOException If some I/O error occurs.
4817     * @throws LscpException If LSCP protocol corruption occurs.
4818     * @throws LSException If some other error occurs.
4819     */
4820     public synchronized int
4821     getTotalVoiceCountMax() throws IOException, LscpException, LSException {
4822     verifyConnection();
4823     out.writeLine("GET TOTAL_VOICE_COUNT_MAX");
4824 iliev 1139 if(getPrintOnlyMode()) return -1;
4825    
4826 iliev 784 String s = getSingleLineResultSet().getResult();
4827     return parseInt(s);
4828     }
4829    
4830     /**
4831 iliev 596 * Gets information about the LinuxSampler instance.
4832     *
4833     * @return <code>ServerInfo</code> instance containing
4834     * information about the LinuxSampler instance.
4835     *
4836     * @throws IOException If an I/O error occurs.
4837     * @throws LscpException If LSCP protocol corruption occurs.
4838     * @throws LSException If some other error occurs.
4839     */
4840     public synchronized ServerInfo
4841     getServerInfo() throws IOException, LscpException, LSException {
4842     verifyConnection();
4843     out.writeLine("GET SERVER INFO");
4844 iliev 1139 if(getPrintOnlyMode()) return null;
4845    
4846 iliev 596 ResultSet rs = getMultiLineResultSet();
4847     return new ServerInfo(rs.getMultiLineResult());
4848     }
4849    
4850     /**
4851 iliev 1139 * Gets the golobal volume of the sampler.
4852     * @return The golobal volume of the sampler.
4853     * @throws IOException If some I/O error occurs.
4854     * @throws LscpException If LSCP protocol corruption occurs.
4855     * @throws LSException If some other error occurs.
4856     */
4857     public synchronized float
4858     getVolume() throws IOException, LscpException, LSException {
4859     verifyConnection();
4860     out.writeLine("GET VOLUME");
4861     if(getPrintOnlyMode()) return -1;
4862    
4863     String s = getSingleLineResultSet().getResult();
4864     return parseFloat(s);
4865     }
4866    
4867     /**
4868     * Sets the global volume of the sampler.
4869     * @param volume The new volume value.
4870     * @throws IOException If some I/O error occurs.
4871     * @throws LscpException If LSCP protocol corruption occurs.
4872     * @throws LSException If some other error occurs.
4873     * @see #getVolume
4874     */
4875     public synchronized void
4876     setVolume(float volume) throws IOException, LscpException, LSException {
4877    
4878     verifyConnection();
4879     out.writeLine("SET VOLUME " + volume);
4880     if(getPrintOnlyMode()) return;
4881    
4882     ResultSet rs = getEmptyResultSet();
4883     }
4884    
4885 iliev 1202 private void
4886     getEmptyResultSets(int count, String err) throws LSException {
4887     StringBuffer sb = new StringBuffer();
4888     for(int i = 0; i < count; i++) {
4889     try { getEmptyResultSet(); }
4890     catch (SocketTimeoutException e) {
4891     getLogger().log(Level.FINE, e.getMessage(), e);
4892     sb.append(e.getMessage()).append("\n");
4893     break;
4894     } catch (Exception e) {
4895     getLogger().log(Level.FINE, e.getMessage(), e);
4896     sb.append(e.getMessage()).append("\n");
4897     }
4898     }
4899    
4900     String details = sb.toString();
4901     if(details.length() > 0) {
4902     String s = LscpI18n.getLogMsg(err);
4903     throw new LSException(0, s, details);
4904     }
4905     }
4906    
4907 iliev 1139 /**
4908 iliev 596 * Returns the logger for this library.
4909     * @return The logger for this library.
4910     */
4911     protected static Logger
4912     getLogger() { return Logger.getLogger("org.linuxsampler.lscp"); }
4913     }

  ViewVC Help
Powered by ViewVC