/[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 1728 - (hide annotations) (download)
Tue Apr 29 16:04:42 2008 UTC (15 years, 11 months ago) by iliev
File size: 180757 byte(s)
* Client: added new methods - findLostDbInstrumentFiles,
  setDbInstrumentFilePath, getExtendedCharacterEscaping,
  setExtendedCharacterEscaping
* Parser: added new method - toExtendedEscapeSequence
* fixed bug #75

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

  ViewVC Help
Powered by ViewVC