/[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 1346 - (hide annotations) (download)
Thu Sep 13 22:02:03 2007 UTC (16 years, 7 months ago) by iliev
File size: 171176 byte(s)
* added support for escape sequences to all
  instruments db related methods

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

  ViewVC Help
Powered by ViewVC