/[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 1139 - (hide annotations) (download)
Mon Apr 2 20:43:58 2007 UTC (17 years ago) by iliev
File size: 124868 byte(s)
* upgraded to version 0.4a

1 iliev 596 /*
2     * jlscp - a java LinuxSampler control protocol API
3     *
4 iliev 1139 * Copyright (C) 2005-2007 Grigor Iliev <grigor@grigoriliev.com>
5 iliev 596 *
6     * This file is part of jlscp.
7     *
8     * jlscp is free software; you can redistribute it and/or modify
9     * it under the terms of the GNU General Public License version 2
10     * as published by the Free Software Foundation.
11     *
12     * jlscp is distributed in the hope that it will be useful,
13     * but WITHOUT ANY WARRANTY; without even the implied warranty of
14     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15     * GNU General Public License for more details.
16     *
17     * You should have received a copy of the GNU General Public License
18     * along with jlscp; if not, write to the Free Software
19     * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
20     * MA 02111-1307 USA
21     */
22    
23     package org.linuxsampler.lscp;
24    
25     import java.io.IOException;
26 iliev 1139 import java.io.OutputStream;
27 iliev 596
28     import java.net.InetSocketAddress;
29     import java.net.Socket;
30     import java.net.SocketTimeoutException;
31     import java.net.UnknownHostException;
32    
33     import java.util.Vector;
34     import java.util.logging.Level;
35     import java.util.logging.Logger;
36    
37     import static org.linuxsampler.lscp.Parser.*;
38     import org.linuxsampler.lscp.event.*;
39    
40    
41     /**
42     * This class is the abstraction representing a client endpoint for communication with LinuxSampler
43 iliev 1139 * instance. Since it implements all commands specified in the LSCP protocol v1.1, for more
44 iliev 671 * information look at the
45 iliev 1139 * <a href=http://www.linuxsampler.org/api/lscp-1.1.html>LSCP</a> specification.
46 iliev 596 *
47     * <p> The following code establishes connection to LinuxSampler instance and gets the
48     * LinuxSampler version:
49     * <pre>
50     * try {
51     * Client client = new Client();
52     * client.connect();
53     *
54     * String version = client.getServerInfo().getVersion();
55     * System.out.println(version);
56     *
57     * client.disconnect();
58     * } catch(Exception x) { x.printStackTrace(); }
59     * </pre>
60     * </p>
61     *
62     * <p>For more examples look at the <code>examples</code> directory
63     * located in the <b>jlscp</b> distribution.</p>
64     *
65     * All methods are thread safe.
66     * @author Grigor Iliev
67     */
68     public class Client {
69     private String address;
70     private int port;
71     private Socket sock = null;
72     private int soTimeout = 10000;
73    
74     private LscpInputStream in = null;
75     private LscpOutputStream out = null;
76    
77     private EventThread eventThread;
78    
79 iliev 1139 private boolean printOnlyMode = false;
80    
81 iliev 596 class EventThread extends Thread {
82     private boolean terminate = false;
83    
84     EventThread() { super("LSCP-Event-Thread"); }
85    
86     public void
87     run() {
88     while(!mustTerminate()) {
89     try { processNotifications(); }
90     catch(Exception x) {
91     getLogger().log(Level.FINE, x.getMessage(), x);
92     }
93     try { synchronized(this) { wait(100); } }
94     catch(Exception x) {
95     getLogger().log(Level.FINE, x.getMessage(), x);
96     }
97     }
98     }
99    
100     private synchronized boolean
101     mustTerminate() { return terminate; }
102    
103     public synchronized void
104     terminate() {
105     terminate = true;
106     this.notifyAll();
107     }
108     }
109    
110     /**
111     * Creates a new instance of Client with default server address and port.
112     * The default server address and port are 127.0.0.1:8888.
113     */
114     public
115     Client() { this("127.0.0.1"); }
116    
117     /**
118     * Creates a new instance of Client with the specified address and default port.
119     * The default port is 8888.
120     * @param address The address of linux sampler server.
121     */
122     public
123     Client(String address) { this(address, 8888); }
124    
125     /**
126     * Creates a new instance of Client with the specified address and port.
127     * @param address The address of the Linux Sampler.
128     * @param port The Linux Sampler port number.
129     */
130     public
131     Client(String address, int port) {
132     setServerAddress(address);
133     setServerPort(port);
134    
135     eventThread = new EventThread();
136     }
137    
138     /**
139 iliev 1139 * Creates a new instance of Client.
140     * @param printOnlyMode Determines whether the client will be in print-only mode.
141     */
142     public
143     Client(boolean printOnlyMode) {
144     if(printOnlyMode) setPrintOnlyMode(true);
145     }
146    
147     /**
148     * Determines whether the client is in print-only mode.
149     * Print-only mode means that the client will just print all
150     * LSCP commands to the specified output stream or to the standard output stream
151     * (<code>java.lang.System.out</code>) if no output stream is specified,
152     * without taking any further actions. Thus, in print-only mode all returned
153     * values by <code>Client</code>'s methods are meaningless and should be discarded.
154     * @return <code>true</code> if the client is in
155     * print-only mode, <code>false</code> otherwise.
156     * @see #setPrintOnlyModeOutputStream
157     */
158     public synchronized boolean
159     getPrintOnlyMode() { return printOnlyMode; }
160    
161     /**
162     * Sets the print-only mode. Note that in print-only mode all returned
163     * values by <code>Client</code>'s methods are meaningless and should be discarded.
164     * The default output stream in print-only mode is <code>java.lang.System.out</code>.
165     * @param b If <code>true</code> all LSCP commands will be sent
166     * to the specified output stream or to the standard output stream
167     * (<code>java.lang.System.out</code>) if no output stream is specified,
168     * and no further actions will be taken.
169     * @throws IllegalStateException If the client is connected.
170     * @see #setPrintOnlyModeOutputStream
171     */
172     public synchronized void
173     setPrintOnlyMode(boolean b) {
174     if(printOnlyMode == b) return;
175     if(isConnected()) throw new IllegalStateException();
176    
177     printOnlyMode = b;
178     if(b) out = new LscpOutputStream(System.out);
179     }
180    
181     /**
182     * Sets the output stream to be used in print-only mode.
183     * @param out The output stream to be used in print-only mode.
184     * @throws IllegalStateException If the client is not in print-only mode.
185     * @throws IllegalArgumentException if <code>out</code> is <code>null</code>.
186     * @see #setPrintOnlyMode
187     */
188     public synchronized void
189     setPrintOnlyModeOutputStream(OutputStream out) {
190     if(!getPrintOnlyMode()) throw new IllegalStateException("Not in print-only mode");
191     if(out == null) throw new IllegalArgumentException("out must be non-null");
192     this.out = new LscpOutputStream(out);
193     }
194    
195     /**
196 iliev 596 * Specifies the jlscp version.
197     * @return The jlscp version.
198     */
199     public static String
200 iliev 671 getClientVersion() {
201     return Package.getPackage("org.linuxsampler.lscp").getImplementationVersion();
202     }
203 iliev 596
204     /**
205     * Gets the Linux Sampler address.
206     * @return The Linux Sampler address.
207     */
208     public synchronized String
209     getServerAddress() { return address; }
210    
211     /**
212     * Sets the Linux Sampler address.
213     * @param address The Linux Sampler address.
214     * If <code>address</code> is <code>null</code> sets to default address - 127.0.0.1.
215     */
216     public synchronized void
217     setServerAddress(String address) {
218     this.address = (address == null ? "127.0.0.1" : address);
219     }
220    
221     /**
222     * Gets the Linux Sampler port number.
223     * @return The Linux Sampler port number.
224     */
225     public synchronized int
226     getServerPort() { return port; }
227    
228     /**
229     * Sets the Linux Sampler port number.
230     * @param port The Linux Sampler port number.
231     */
232     public synchronized void
233     setServerPort(int port) { this.port = port; }
234    
235     /**
236     * Connects to the LinuxSampler. If there is already established connection then
237     * the currently available connection is closed berfore connecting.
238     * @throws LscpException If timeout occurs or any other I/O exception.
239     */
240     public synchronized void
241     connect() throws LscpException {
242     if(sock != null) disconnect();
243 iliev 1139 if(getPrintOnlyMode()) return;
244 iliev 596
245     // Initializing LSCP event thread
246     if(eventThread.isAlive()) {
247     getLogger().warning("LSCP event thread already running!");
248     eventThread.terminate();
249     }
250    
251     if(eventThread.getState() != Thread.State.NEW) eventThread = new EventThread();
252     ///////
253    
254     InetSocketAddress sockAddr = null;
255    
256     try { sockAddr = new InetSocketAddress(address, port); }
257     catch(IllegalArgumentException x) {
258     String s = String.valueOf(port);
259     throw new LscpException(LscpI18n.getLogMsg("Client.invalidPort!", s), x);
260     }
261    
262     if(sockAddr.isUnresolved()) throw new LscpException (
263     LscpI18n.getLogMsg("Client.unknownHost!", address)
264     );
265    
266     try {
267     sock = new Socket();
268     sock.bind(null);
269     sock.connect(sockAddr, soTimeout);
270     sock.setSoTimeout(soTimeout);
271 iliev 784 sock.setTcpNoDelay(true);
272 iliev 596
273     in = new LscpInputStream(sock.getInputStream());
274     out = new LscpOutputStream(sock.getOutputStream());
275     } catch(SocketTimeoutException x) {
276     throw new LscpException(LscpI18n.getLogMsg("Client.conTimeout!"), x);
277     } catch(Exception x) {
278     throw new LscpException (
279     LscpI18n.getLogMsg("Client.connectionFailed!"), x
280     );
281     }
282    
283 iliev 671 String s = Package.getPackage("org.linuxsampler.lscp").getSpecificationVersion();
284     String s2, sv, sv2;
285    
286     try {
287     s2 = s.substring(0, s.indexOf('.'));
288     sv = getServerInfo().getProtocolVersion();
289     sv2 = sv.substring(0, sv.indexOf('.'));
290     } catch(Exception x) {
291     disconnect();
292    
293     throw new LscpException (
294     LscpI18n.getLogMsg("Client.connectionFailed!"), x
295     );
296     }
297    
298     if(!sv2.equals(s2)) {
299     disconnect();
300    
301     throw new LscpException (
302     LscpI18n.getLogMsg("Client.incompatibleLscpVersion!", sv)
303     );
304     }
305    
306     s2 = s.substring(s.indexOf('.'));
307     sv2 = sv.substring(sv.indexOf('.'));
308    
309     if(sv2.compareToIgnoreCase(s2) < 0) getLogger().info (
310     LscpI18n.getLogMsg("Client.incompatibleLscpMinVersion!", sv)
311     );
312    
313 iliev 596 if(hasSubscriptions()) eventThread.start();
314    
315     if(!llM.isEmpty()) subscribe("MISCELLANEOUS");
316 iliev 1139 if(!llAODC.isEmpty()) subscribe("AUDIO_OUTPUT_DEVICE_COUNT");
317     if(!llAODI.isEmpty()) subscribe("AUDIO_OUTPUT_DEVICE_INFO");
318     if(!llMIDC.isEmpty()) subscribe("MIDI_INPUT_DEVICE_COUNT");
319     if(!llMIDI.isEmpty()) subscribe("MIDI_INPUT_DEVICE_INFO");
320 iliev 596 if(!llBF.isEmpty()) subscribe("BUFFER_FILL");
321     if(!llCC.isEmpty()) subscribe("CHANNEL_COUNT");
322     if(!llCI.isEmpty()) subscribe("CHANNEL_INFO");
323 iliev 1139 if(!llFSC.isEmpty()) subscribe("FX_SEND_COUNT");
324     if(!llFSI.isEmpty()) subscribe("FX_SEND_INFO");
325 iliev 596 if(!llSC.isEmpty()) subscribe("STREAM_COUNT");
326     if(!llVC.isEmpty()) subscribe("VOICE_COUNT");
327 iliev 784 if(!llTVC.isEmpty()) subscribe("TOTAL_VOICE_COUNT");
328 iliev 1139 if(!llMIMC.isEmpty()) subscribe("MIDI_INSTRUMENT_MAP_COUNT");
329     if(!llMIMI.isEmpty()) subscribe("MIDI_INSTRUMENT_MAP_INFO");
330     if(!llMIC.isEmpty()) subscribe("MIDI_INSTRUMENT_COUNT");
331     if(!llMII.isEmpty()) subscribe("MIDI_INSTRUMENT_INFO");
332     if(!llGI.isEmpty()) subscribe("GLOBAL_INFO");
333 iliev 596 }
334    
335     /**
336     * Closes the connection to LinuxSampler.
337     */
338     public synchronized void
339     disconnect() {
340 iliev 1139 if(getPrintOnlyMode()) return;
341 iliev 596 try { if(sock != null) sock.close(); }
342     catch(Exception x) { getLogger().log(Level.FINE, x.getMessage(), x); }
343     sock = null;
344    
345     if(eventThread.getState() != Thread.State.NEW) {
346     eventThread.terminate();
347     eventThread = new EventThread();
348     }
349     }
350    
351     /**
352     * Determines whether the client is connected.
353     * @return <code>true</code> if there is established connection,
354     * <code>false</code> otherwise.
355     */
356     public synchronized boolean
357     isConnected() {
358     if(sock == null) return false;
359     else return sock.isConnected();
360     }
361    
362     /**
363     * Verifies that there is established connection.
364     * @throws IOException If the connection is not established.
365     */
366     private void
367     verifyConnection() throws IOException {
368 iliev 1139 if(getPrintOnlyMode()) return;
369    
370 iliev 596 if(!isConnected())
371     throw new IOException(LscpI18n.getLogMsg("Client.notConnected!"));
372     }
373    
374     private String
375     getLine() throws IOException, LscpException {
376     String s;
377     for(;;) {
378     s = in.readLine();
379     if(s.startsWith("NOTIFY:")) fireEvent(s.substring("NOTIFY:".length()));
380     else break;
381     }
382     return s;
383     }
384    
385 iliev 1139 /** Processes the notifications sent by LinuxSampler */
386 iliev 596 private synchronized void
387     processNotifications() throws IOException, LscpException {
388     while(in.available() > 0) {
389     String s = in.readLine();
390     if(s.startsWith("NOTIFY:")) fireEvent(s.substring("NOTIFY:".length()));
391     else getLogger().severe("Unknown notification format: " + s);
392     }
393     }
394    
395     /**
396     * Gets empty result set.
397     * @return <code>ResultSet</code> instance.
398     */
399     private ResultSet
400     getEmptyResultSet() throws IOException, LscpException, LSException {
401     return parseEmptyResultSet(getLine());
402     }
403    
404     private ResultSet
405     getSingleLineResultSet() throws IOException, LscpException, LSException {
406     ResultSet rs = new ResultSet();
407     String ln = getLine();
408    
409     if(ln.startsWith("WRN")) {
410     parseWarning(ln, rs);
411     getLogger().warning(rs.getMessage());
412     return rs;
413     } else if(ln.startsWith("ERR")) {
414     parseError(ln, rs);
415     throw new LSException(rs.getCode(), rs.getMessage());
416     } else {
417     rs.setResult(ln);
418     return rs;
419     }
420     }
421    
422     private ResultSet
423     getMultiLineResultSet() throws IOException, LscpException, LSException {
424     ResultSet rs = new ResultSet();
425     String ln = getLine();
426    
427     if(ln.startsWith("WRN")) {
428     parseWarning(ln, rs);
429     getLogger().warning(rs.getMessage());
430     return rs;
431     } else if(ln.startsWith("ERR")) {
432     parseError(ln, rs);
433     throw new LSException(rs.getCode(), rs.getMessage());
434     }
435    
436     while(!ln.equals(".")) {
437     rs.addLine(ln);
438     ln = getLine();
439     }
440    
441     return rs;
442     }
443    
444 iliev 1139 /** Audio output device count listeners */
445     private final Vector<ItemCountListener> llAODC = new Vector<ItemCountListener>();
446     /** Audio output device info listeners */
447     private final Vector<ItemInfoListener> llAODI = new Vector<ItemInfoListener>();
448 iliev 596 private final Vector<BufferFillListener> llBF = new Vector<BufferFillListener>();
449     private final Vector<ChannelCountListener> llCC = new Vector<ChannelCountListener>();
450     private final Vector<ChannelInfoListener> llCI = new Vector<ChannelInfoListener>();
451 iliev 1139 private final Vector<FxSendCountListener> llFSC = new Vector<FxSendCountListener>();
452     private final Vector<FxSendInfoListener> llFSI = new Vector<FxSendInfoListener>();
453 iliev 596 private final Vector<MiscellaneousListener> llM = new Vector<MiscellaneousListener>();
454 iliev 1139 /** MIDI input device count listeners */
455     private final Vector<ItemCountListener> llMIDC = new Vector<ItemCountListener>();
456     /** MIDI input device info listeners */
457     private final Vector<ItemInfoListener> llMIDI = new Vector<ItemInfoListener>();
458 iliev 596 private final Vector<StreamCountListener> llSC = new Vector<StreamCountListener>();
459     private final Vector<VoiceCountListener> llVC = new Vector<VoiceCountListener>();
460 iliev 784 private final Vector<TotalVoiceCountListener> llTVC = new Vector<TotalVoiceCountListener>();
461 iliev 596
462 iliev 1139 /** MIDI instrument map count listeners */
463     private final Vector<ItemCountListener> llMIMC = new Vector<ItemCountListener>();
464     /** MIDI instrument map info listeners */
465     private final Vector<ItemInfoListener> llMIMI = new Vector<ItemInfoListener>();
466     /** MIDI instrument count listeners */
467     private final Vector<MidiInstrumentCountListener> llMIC =
468     new Vector<MidiInstrumentCountListener>();
469     /** MIDI instrument info listeners */
470     private final Vector<MidiInstrumentInfoListener> llMII =
471     new Vector<MidiInstrumentInfoListener>();
472     private final Vector<GlobalInfoListener> llGI = new Vector<GlobalInfoListener>();
473    
474    
475 iliev 596 /**
476     * Determines whether there is at least one subscription for notification events.
477     * Do not forget to check for additional listeners if the LSCP specification
478 iliev 784 * is extended in the future.
479 iliev 596 * @return <code>true</code> if there is at least one subscription for notification events,
480     * <code>false</code> otherwise.
481     */
482     private boolean
483     hasSubscriptions() {
484 iliev 1139 return !llAODC.isEmpty() ||
485     !llAODI.isEmpty() ||
486     !llBF.isEmpty() ||
487     !llCC.isEmpty() ||
488     !llCI.isEmpty() ||
489     !llFSC.isEmpty() ||
490     !llFSI.isEmpty() ||
491     !llM.isEmpty() ||
492     !llMIDC.isEmpty() ||
493     !llMIDI.isEmpty() ||
494     !llSC.isEmpty() ||
495     !llVC.isEmpty() ||
496     !llTVC.isEmpty() ||
497     !llMIMC.isEmpty() ||
498     !llMIMI.isEmpty() ||
499     !llMIC.isEmpty() ||
500     !llMII.isEmpty() ||
501     !llGI.isEmpty();
502 iliev 596 }
503    
504     private void
505     fireEvent(String s) {
506     if(s.startsWith("CHANNEL_COUNT:")) {
507     try {
508     int i = Integer.parseInt(s.substring("CHANNEL_COUNT:".length()));
509     ChannelCountEvent e = new ChannelCountEvent(this, i);
510     for(ChannelCountListener l : llCC) l.channelCountChanged(e);
511     } catch(NumberFormatException x) {
512     getLogger().log (
513     Level.WARNING, LscpI18n.getLogMsg("CommandFailed!"), x
514     );
515     }
516     } else if(s.startsWith("VOICE_COUNT:")) {
517     try {
518     s = s.substring("VOICE_COUNT:".length());
519 iliev 1139 Integer[] i = parseIntList(s, ' ');
520     if(i.length != 2) {
521 iliev 596 getLogger().warning("Unknown VOICE_COUNT format");
522     return;
523     }
524 iliev 1139 VoiceCountEvent e = new VoiceCountEvent(this, i[0], i[1]);
525 iliev 596 for(VoiceCountListener l : llVC) l.voiceCountChanged(e);
526 iliev 1139 } catch(Exception x) {
527 iliev 596 getLogger().log(Level.WARNING, "Unknown VOICE_COUNT format", x);
528     }
529     } else if(s.startsWith("STREAM_COUNT:")) {
530     try {
531     s = s.substring("STREAM_COUNT:".length());
532 iliev 1139 Integer[] i = parseIntList(s, ' ');
533     if(i.length != 2) {
534 iliev 596 getLogger().warning("Unknown STREAM_COUNT format");
535     return;
536     }
537 iliev 1139 StreamCountEvent e = new StreamCountEvent(this, i[0], i[1]);
538 iliev 596 for(StreamCountListener l : llSC) l.streamCountChanged(e);
539 iliev 1139 } catch(Exception x) {
540 iliev 596 getLogger().log(Level.WARNING, "Unknown STREAM_COUNT format", x);
541     }
542     } else if(s.startsWith("BUFFER_FILL:")) {
543     try {
544     s = s.substring("BUFFER_FILL:".length());
545     int i = s.indexOf(' ');
546     if(i == -1) {
547 iliev 1139 getLogger().warning("Unknown BUFFER_FILL format");
548 iliev 596 return;
549     }
550     int j = Integer.parseInt(s.substring(0, i));
551     Vector<BufferFill> v =
552     getChannelBufferFillPercentage(s.substring(i + 1));
553     BufferFillEvent e = new BufferFillEvent(this, j, v);
554     for(BufferFillListener l : llBF) l.bufferFillChanged(e);
555     } catch(Exception x) {
556 iliev 1139 getLogger().log(Level.WARNING, "Unknown BUFFER_FILL format", x);
557 iliev 596 }
558     } else if(s.startsWith("CHANNEL_INFO:")) {
559     try {
560     int i = Integer.parseInt(s.substring("CHANNEL_INFO:".length()));
561     ChannelInfoEvent e = new ChannelInfoEvent(this, i);
562     for(ChannelInfoListener l : llCI) l.channelInfoChanged(e);
563     } catch(NumberFormatException x) {
564 iliev 1139 getLogger().log(Level.WARNING, "Unknown CHANNEL_INFO format", x);
565 iliev 596 }
566 iliev 784 } else if(s.startsWith("TOTAL_VOICE_COUNT:")) {
567     try {
568     s = s.substring("TOTAL_VOICE_COUNT:".length());
569     int i = Integer.parseInt(s);
570     TotalVoiceCountEvent e = new TotalVoiceCountEvent(this, i);
571     for(TotalVoiceCountListener l : llTVC) l.totalVoiceCountChanged(e);
572     } catch(NumberFormatException x) {
573     getLogger().log (
574     Level.WARNING, "Unknown TOTAL_VOICE_COUNT format", x
575     );
576     }
577 iliev 1139 } else if(s.startsWith("AUDIO_OUTPUT_DEVICE_COUNT:")) {
578     try {
579     s = s.substring("AUDIO_OUTPUT_DEVICE_COUNT:".length());
580     int i = Integer.parseInt(s);
581     ItemCountEvent e = new ItemCountEvent(this, i);
582     for(ItemCountListener l : llAODC) l.itemCountChanged(e);
583     } catch(NumberFormatException x) {
584     getLogger().log (
585     Level.WARNING, "Unknown AUDIO_OUTPUT_DEVICE_COUNT format", x
586     );
587     }
588     } else if(s.startsWith("AUDIO_OUTPUT_DEVICE_INFO:")) {
589     try {
590     s = s.substring("AUDIO_OUTPUT_DEVICE_INFO:".length());
591     int i = Integer.parseInt(s);
592     ItemInfoEvent e = new ItemInfoEvent(this, i);
593     for(ItemInfoListener l : llAODI) l.itemInfoChanged(e);
594     } catch(NumberFormatException x) {
595     getLogger().log (
596     Level.WARNING, "Unknown AUDIO_OUTPUT_DEVICE_INFO format", x
597     );
598     }
599     } else if(s.startsWith("MIDI_INPUT_DEVICE_COUNT:")) {
600     try {
601     s = s.substring("MIDI_INPUT_DEVICE_COUNT:".length());
602     int i = Integer.parseInt(s);
603     ItemCountEvent e = new ItemCountEvent(this, i);
604     for(ItemCountListener l : llMIDC) l.itemCountChanged(e);
605     } catch(NumberFormatException x) {
606     getLogger().log (
607     Level.WARNING, "Unknown MIDI_INPUT_DEVICE_COUNT format", x
608     );
609     }
610     } else if(s.startsWith("MIDI_INPUT_DEVICE_INFO:")) {
611     try {
612     s = s.substring("MIDI_INPUT_DEVICE_INFO:".length());
613     int i = Integer.parseInt(s);
614     ItemInfoEvent e = new ItemInfoEvent(this, i);
615     for(ItemInfoListener l : llMIDI) l.itemInfoChanged(e);
616     } catch(NumberFormatException x) {
617     getLogger().log (
618     Level.WARNING, "Unknown MIDI_INPUT_DEVICE_INFO format", x
619     );
620     }
621     } else if(s.startsWith("MIDI_INSTRUMENT_MAP_COUNT:")) {
622     try {
623     s = s.substring("MIDI_INSTRUMENT_MAP_COUNT:".length());
624     int i = Integer.parseInt(s);
625     ItemCountEvent e = new ItemCountEvent(this, i);
626     for(ItemCountListener l : llMIMC) l.itemCountChanged(e);
627     } catch(NumberFormatException x) {
628     getLogger().log (
629     Level.WARNING, "Unknown MIDI_INSTRUMENT_MAP_COUNT format", x
630     );
631     }
632     } else if(s.startsWith("MIDI_INSTRUMENT_MAP_INFO:")) {
633     try {
634     s = s.substring("MIDI_INSTRUMENT_MAP_INFO:".length());
635     int i = Integer.parseInt(s);
636     ItemInfoEvent e = new ItemInfoEvent(this, i);
637     for(ItemInfoListener l : llMIMI) l.itemInfoChanged(e);
638     } catch(NumberFormatException x) {
639     getLogger().log (
640     Level.WARNING, "Unknown MIDI_INSTRUMENT_MAP_INFO format", x
641     );
642     }
643     } else if(s.startsWith("MIDI_INSTRUMENT_COUNT:")) {
644     try {
645     s = s.substring("MIDI_INSTRUMENT_COUNT:".length());
646     Integer[] i = parseIntList(s, ' ');
647     if(i.length != 2) {
648     getLogger().warning("Unknown MIDI_INSTRUMENT_COUNT format");
649     return;
650     }
651    
652     MidiInstrumentCountEvent e =
653     new MidiInstrumentCountEvent(this, i[0], i[1]);
654    
655     for(MidiInstrumentCountListener l : llMIC) {
656     l.instrumentCountChanged(e);
657     }
658     } catch(Exception x) {
659     getLogger().log (
660     Level.WARNING, "Unknown MIDI_INSTRUMENT_COUNT format", x
661     );
662     }
663     } else if(s.startsWith("MIDI_INSTRUMENT_INFO:")) {
664     try {
665     s = s.substring("MIDI_INSTRUMENT_INFO:".length());
666     Integer[] i = parseIntList(s, ' ');
667     if(i.length != 3) {
668     getLogger().warning("Unknown MIDI_INSTRUMENT_INFO format");
669     return;
670     }
671    
672     MidiInstrumentInfoEvent e =
673     new MidiInstrumentInfoEvent(this, i[0], i[1], i[2]);
674     for(MidiInstrumentInfoListener l : llMII) {
675     l.instrumentInfoChanged(e);
676     }
677     } catch(Exception x) {
678     getLogger().log (
679     Level.WARNING, "Unknown MIDI_INSTRUMENT_INFO format", x
680     );
681     }
682     } else if(s.startsWith("FX_SEND_COUNT:")) {
683     try {
684     s = s.substring("FX_SEND_COUNT:".length());
685     Integer[] i = parseIntList(s, ' ');
686     if(i.length != 2) {
687     getLogger().warning("Unknown FX_SEND_COUNT format");
688     return;
689     }
690    
691     FxSendCountEvent e = new FxSendCountEvent(this, i[0], i[1]);
692    
693     for(FxSendCountListener l : llFSC) l.fxSendCountChanged(e);
694     } catch(Exception x) {
695     getLogger().log(Level.WARNING, "Unknown FX_SEND_COUNT format", x);
696     }
697     } else if(s.startsWith("FX_SEND_INFO:")) {
698     try {
699     s = s.substring("FX_SEND_INFO:".length());
700     Integer[] i = parseIntList(s, ' ');
701     if(i.length != 2) {
702     getLogger().warning("Unknown FX_SEND_INFO format");
703     return;
704     }
705    
706     FxSendInfoEvent e = new FxSendInfoEvent(this, i[0], i[1]);
707     for(FxSendInfoListener l : llFSI) {
708     l.fxSendInfoChanged(e);
709     }
710     } catch(Exception x) {
711     getLogger().log(Level.WARNING, "Unknown FX_SEND_INFO format", x);
712     }
713     } else if(s.startsWith("GLOBAL_INFO:")) {
714     handleGlobalInfoEvent(s.substring("GLOBAL_INFO:".length()));
715 iliev 596 } else if(s.startsWith("MISCELLANEOUS:")) {
716     s = s.substring("MISCELLANEOUS:".length());
717     MiscellaneousEvent e = new MiscellaneousEvent(this, s);
718     for(MiscellaneousListener l : llM) l.miscEventOccured(e);
719     }
720     }
721    
722     private void
723 iliev 1139 handleGlobalInfoEvent(String s) {
724     try {
725     if(s.startsWith("VOLUME ")) {
726     float f = Float.parseFloat(s.substring("VOLUME ".length()));
727     GlobalInfoEvent e = new GlobalInfoEvent(this, f);
728     for(GlobalInfoListener l : llGI) l.volumeChanged(e);
729     }
730     } catch(NumberFormatException x) {
731     getLogger().log(Level.WARNING, "Unknown GLOBAL_INFO format", x);
732     }
733     }
734    
735     private void
736 iliev 596 subscribe(String event) {
737 iliev 1139 if(!getPrintOnlyMode()) {
738     if(!isConnected()) return;
739 iliev 596
740 iliev 1139 if(!eventThread.isAlive()) eventThread.start();
741     }
742 iliev 596
743     try {
744     out.writeLine("SUBSCRIBE " + event);
745 iliev 1139 if(!getPrintOnlyMode()) getEmptyResultSet();
746 iliev 596 } catch(Exception x) {
747     getLogger().log (
748     Level.WARNING,
749     LscpI18n.getLogMsg("Client.subscriptionFailed!", event),
750     x
751     );
752     }
753     }
754    
755     private void
756     unsubscribe(String event) {
757 iliev 1139 if(!getPrintOnlyMode() && !isConnected()) return;
758 iliev 596
759     try {
760     out.writeLine("UNSUBSCRIBE " + event);
761 iliev 1139 if(!getPrintOnlyMode()) getEmptyResultSet();
762 iliev 596 } catch(Exception x) {
763     getLogger().log (
764     Level.WARNING,
765     LscpI18n.getLogMsg("Client.unsubscriptionFailed!", event),
766     x
767     );
768     }
769     }
770    
771     /**
772     * Registers the specified listener for receiving event messages.
773 iliev 1139 * Listeners can be registered regardless of the connection state.
774     * @param l The <code>ItemCountListener</code> to register.
775     */
776     public synchronized void
777     addAudioDeviceCountListener(ItemCountListener l) {
778     if(llAODC.isEmpty()) subscribe("AUDIO_OUTPUT_DEVICE_COUNT");
779     llAODC.add(l);
780     }
781    
782     /**
783     * Removes the specified listener.
784 iliev 596 * Listeners can be removed regardless of the connection state.
785 iliev 1139 * @param l The <code>ItemCountListener</code> to remove.
786     */
787     public synchronized void
788     removeAudioDeviceCountListener(ItemCountListener l) {
789     boolean b = llAODC.remove(l);
790     if(b && llAODC.isEmpty()) unsubscribe("AUDIO_OUTPUT_DEVICE_COUNT");
791     }
792    
793     /**
794     * Registers the specified listener for receiving event messages.
795     * Listeners can be registered regardless of the connection state.
796     * @param l The <code>ItemInfoListener</code> to register.
797     */
798     public synchronized void
799     addAudioDeviceInfoListener(ItemInfoListener l) {
800     if(llAODI.isEmpty()) subscribe("AUDIO_OUTPUT_DEVICE_INFO");
801     llAODI.add(l);
802     }
803    
804     /**
805     * Removes the specified listener.
806     * Listeners can be removed regardless of the connection state.
807     * @param l The <code>ItemInfoListener</code> to remove.
808     */
809     public synchronized void
810     removeAudioDeviceInfoListener(ItemInfoListener l) {
811     boolean b = llAODI.remove(l);
812     if(b && llAODI.isEmpty()) unsubscribe("AUDIO_OUTPUT_DEVICE_INFO");
813     }
814    
815     /**
816     * Registers the specified listener for receiving event messages.
817     * Listeners can be removed regardless of the connection state.
818 iliev 596 * @param l The <code>BufferFillListener</code> to register.
819     */
820     public synchronized void
821     addBufferFillListener(BufferFillListener l) {
822     if(llBF.isEmpty()) subscribe("BUFFER_FILL");
823     llBF.add(l);
824     }
825    
826     /**
827     * Removes the specified listener.
828     * Listeners can be removed regardless of the connection state.
829     * @param l The <code>BufferFillListener</code> to remove.
830     */
831     public synchronized void
832     removeBufferFillListener(BufferFillListener l) {
833     boolean b = llBF.remove(l);
834     if(b && llBF.isEmpty()) unsubscribe("BUFFER_FILL");
835     }
836    
837     /**
838     * Registers the specified listener for receiving event messages.
839     * Listeners can be registered regardless of the connection state.
840     * @param l The <code>ChannelCountListener</code> to register.
841     */
842     public synchronized void
843     addChannelCountListener(ChannelCountListener l) {
844     if(llCC.isEmpty()) subscribe("CHANNEL_COUNT");
845     llCC.add(l);
846     }
847    
848     /**
849     * Removes the specified listener.
850     * Listeners can be removed regardless of the connection state.
851     * @param l The <code>ChannelCountListener</code> to remove.
852     */
853     public synchronized void
854     removeChannelCountListener(ChannelCountListener l) {
855     boolean b = llCC.remove(l);
856     if(b && llCC.isEmpty()) unsubscribe("CHANNEL_COUNT");
857     }
858    
859     /**
860     * Registers the specified listener for receiving event messages.
861     * Listeners can be registered regardless of the connection state.
862     * @param l The <code>ChannelInfoListener</code> to register.
863     */
864     public synchronized void
865     addChannelInfoListener(ChannelInfoListener l) {
866     if(llCI.isEmpty()) subscribe("CHANNEL_INFO");
867     llCI.add(l);
868     }
869    
870     /**
871     * Removes the specified listener.
872     * Listeners can be removed regardless of the connection state.
873     * @param l The <code>ChannelInfoListener</code> to remove.
874     */
875     public synchronized void
876     removeChannelInfoListener(ChannelInfoListener l) {
877     boolean b = llCI.remove(l);
878     if(b && llCI.isEmpty()) unsubscribe("CHANNEL_INFO");
879     }
880    
881     /**
882     * Registers the specified listener for receiving event messages.
883     * Listeners can be registered regardless of the connection state.
884 iliev 1139 * @param l The <code>FxSendCountListener</code> to register.
885     */
886     public synchronized void
887     addFxSendCountListener(FxSendCountListener l) {
888     if(llFSC.isEmpty()) subscribe("FX_SEND_COUNT");
889     llFSC.add(l);
890     }
891    
892     /**
893     * Removes the specified listener.
894     * Listeners can be removed regardless of the connection state.
895     * @param l The <code>FxSendCountListener</code> to remove.
896     */
897     public synchronized void
898     removeFxSendCountListener(FxSendCountListener l) {
899     boolean b = llFSC.remove(l);
900     if(b && llFSC.isEmpty()) unsubscribe("FX_SEND_COUNT");
901     }
902    
903     /**
904     * Registers the specified listener for receiving event messages.
905     * Listeners can be registered regardless of the connection state.
906     * @param l The <code>FxSendInfoListener</code> to register.
907     */
908     public synchronized void
909     addFxSendInfoListener(FxSendInfoListener l) {
910     if(llFSI.isEmpty()) subscribe("FX_SEND_INFO");
911     llFSI.add(l);
912     }
913    
914     /**
915     * Removes the specified listener.
916     * Listeners can be removed regardless of the connection state.
917     * @param l The <code>FxSendInfoListener</code> to remove.
918     */
919     public synchronized void
920     removeFxSendInfoListener(FxSendInfoListener l) {
921     boolean b = llFSI.remove(l);
922     if(b && llFSI.isEmpty()) unsubscribe("FX_SEND_INFO");
923     }
924    
925     /**
926     * Registers the specified listener for receiving event messages.
927     * Listeners can be registered regardless of the connection state.
928     * @param l The <code>ItemCountListener</code> to register.
929     */
930     public synchronized void
931     addMidiDeviceCountListener(ItemCountListener l) {
932     if(llMIDC.isEmpty()) subscribe("MIDI_INPUT_DEVICE_COUNT");
933     llMIDC.add(l);
934     }
935    
936     /**
937     * Removes the specified listener.
938     * Listeners can be removed regardless of the connection state.
939     * @param l The <code>ItemCountListener</code> to remove.
940     */
941     public synchronized void
942     removeMidiDeviceCountListener(ItemCountListener l) {
943     boolean b = llMIDC.remove(l);
944     if(b && llMIDC.isEmpty()) unsubscribe("MIDI_INPUT_DEVICE_COUNT");
945     }
946    
947     /**
948     * Registers the specified listener for receiving event messages.
949     * Listeners can be registered regardless of the connection state.
950     * @param l The <code>ItemInfoListener</code> to register.
951     */
952     public synchronized void
953     addMidiDeviceInfoListener(ItemInfoListener l) {
954     if(llMIDI.isEmpty()) subscribe("MIDI_INPUT_DEVICE_INFO");
955     llMIDI.add(l);
956     }
957    
958     /**
959     * Removes the specified listener.
960     * Listeners can be removed regardless of the connection state.
961     * @param l The <code>ItemInfoListener</code> to remove.
962     */
963     public synchronized void
964     removeMidiDeviceInfoListener(ItemInfoListener l) {
965     boolean b = llMIDI.remove(l);
966     if(b && llMIDI.isEmpty()) unsubscribe("MIDI_INPUT_DEVICE_INFO");
967     }
968    
969     /**
970     * Registers the specified listener for receiving event messages.
971     * Listeners can be registered regardless of the connection state.
972 iliev 596 * @param l The <code>MiscellaneousListener</code> to register.
973     */
974     public synchronized void
975     addMiscellaneousListener(MiscellaneousListener l) {
976     if(llM.isEmpty()) subscribe("MISCELLANEOUS");
977     llM.add(l);
978     }
979    
980     /**
981     * Removes the specified listener.
982     * Listeners can be removed regardless of the connection state.
983     * @param l The <code>MiscellaneousListener</code> to remove.
984     */
985     public synchronized void
986     removeMiscellaneousListener(MiscellaneousListener l) {
987     boolean b = llM.remove(l);
988     if(b && llM.isEmpty()) unsubscribe("MISCELLANEOUS");
989     }
990    
991     /**
992     * Registers the specified listener for receiving event messages.
993     * Listeners can be registered regardless of the connection state.
994     * @param l The <code>StreamCountListener</code> to register.
995     */
996     public synchronized void
997     addStreamCountListener(StreamCountListener l) {
998     if(llSC.isEmpty()) subscribe("STREAM_COUNT");
999     llSC.add(l);
1000     }
1001    
1002     /**
1003     * Removes the specified listener.
1004     * Listeners can be removed regardless of the connection state.
1005     * @param l The <code>StreamCountListener</code> to remove.
1006     */
1007     public synchronized void
1008     removeStreamCountListener(StreamCountListener l) {
1009     boolean b = llSC.remove(l);
1010     if(b && llSC.isEmpty()) unsubscribe("STREAM_COUNT");
1011     }
1012    
1013     /**
1014     * Registers the specified listener for receiving event messages.
1015     * Listeners can be registered regardless of the connection state.
1016     * @param l The <code>VoiceCountListener</code> to register.
1017     */
1018     public synchronized void
1019     addVoiceCountListener(VoiceCountListener l) {
1020     if(llVC.isEmpty()) subscribe("VOICE_COUNT");
1021     llVC.add(l);
1022     }
1023    
1024     /**
1025     * Removes the specified listener.
1026     * Listeners can be removed regardless of the connection state.
1027     * @param l The <code>VoiceCountListener</code> to remove.
1028     */
1029     public synchronized void
1030     removeVoiceCountListener(VoiceCountListener l) {
1031     boolean b = llVC.remove(l);
1032     if(b && llVC.isEmpty()) unsubscribe("VOICE_COUNT");
1033     }
1034    
1035     /**
1036 iliev 784 * Registers the specified listener for receiving event messages.
1037     * Listeners can be registered regardless of the connection state.
1038     * @param l The <code>TotalVoiceCountListener</code> to register.
1039     */
1040     public synchronized void
1041     addTotalVoiceCountListener(TotalVoiceCountListener l) {
1042     if(llTVC.isEmpty()) subscribe("TOTAL_VOICE_COUNT");
1043     llTVC.add(l);
1044     }
1045    
1046     /**
1047     * Removes the specified listener.
1048     * Listeners can be removed regardless of the connection state.
1049     * @param l The <code>TotalVoiceCountListener</code> to remove.
1050     */
1051     public synchronized void
1052     removeTotalVoiceCountListener(TotalVoiceCountListener l) {
1053     boolean b = llTVC.remove(l);
1054     if(b && llTVC.isEmpty()) unsubscribe("TOTAL_VOICE_COUNT");
1055     }
1056    
1057     /**
1058 iliev 1139 * Registers the specified listener for receiving event messages.
1059     * Listeners can be registered regardless of the connection state.
1060     * @param l The <code>ItemCountListener</code> to register.
1061     */
1062     public synchronized void
1063     addMidiInstrumentMapCountListener(ItemCountListener l) {
1064     if(llMIMC.isEmpty()) subscribe("MIDI_INSTRUMENT_MAP_COUNT");
1065     llMIMC.add(l);
1066     }
1067    
1068     /**
1069     * Removes the specified listener.
1070     * Listeners can be removed regardless of the connection state.
1071     * @param l The <code>ItemCountListener</code> to remove.
1072     */
1073     public synchronized void
1074     removeMidiInstrumentMapCountListener(ItemCountListener l) {
1075     boolean b = llMIMC.remove(l);
1076     if(b && llMIMC.isEmpty()) unsubscribe("MIDI_INSTRUMENT_MAP_COUNT");
1077     }
1078    
1079     /**
1080     * Registers the specified listener for receiving event messages.
1081     * Listeners can be registered regardless of the connection state.
1082     * @param l The <code>ItemInfoListener</code> to register.
1083     */
1084     public synchronized void
1085     addMidiInstrumentMapInfoListener(ItemInfoListener l) {
1086     if(llMIMI.isEmpty()) subscribe("MIDI_INSTRUMENT_MAP_INFO");
1087     llMIMI.add(l);
1088     }
1089    
1090     /**
1091     * Removes the specified listener.
1092     * Listeners can be removed regardless of the connection state.
1093     * @param l The <code>ItemInfoListener</code> to remove.
1094     */
1095     public synchronized void
1096     removeMidiInstrumentMapInfoListener(ItemInfoListener l) {
1097     boolean b = llMIMI.remove(l);
1098     if(b && llMIMI.isEmpty()) unsubscribe("MIDI_INSTRUMENT_MAP_INFO");
1099     }
1100    
1101     /**
1102     * Registers the specified listener for receiving event messages.
1103     * Listeners can be registered regardless of the connection state.
1104     * @param l The <code>MidiInstrumentCountListener</code> to register.
1105     */
1106     public synchronized void
1107     addMidiInstrumentCountListener(MidiInstrumentCountListener l) {
1108     if(llMIC.isEmpty()) subscribe("MIDI_INSTRUMENT_COUNT");
1109     llMIC.add(l);
1110     }
1111    
1112     /**
1113     * Removes the specified listener.
1114     * Listeners can be removed regardless of the connection state.
1115     * @param l The <code>MidiInstrumentCountListener</code> to remove.
1116     */
1117     public synchronized void
1118     removeMidiInstrumentCountListener(MidiInstrumentCountListener l) {
1119     boolean b = llMIC.remove(l);
1120     if(b && llMIC.isEmpty()) unsubscribe("MIDI_INSTRUMENT_COUNT");
1121     }
1122    
1123     /**
1124     * Registers the specified listener for receiving event messages.
1125     * Listeners can be registered regardless of the connection state.
1126     * @param l The <code>MidiInstrumentInfoListener</code> to register.
1127     */
1128     public synchronized void
1129     addMidiInstrumentInfoListener(MidiInstrumentInfoListener l) {
1130     if(llMII.isEmpty()) subscribe("MIDI_INSTRUMENT_INFO");
1131     llMII.add(l);
1132     }
1133    
1134     /**
1135     * Removes the specified listener.
1136     * Listeners can be removed regardless of the connection state.
1137     * @param l The <code>MidiInstrumentInfoListener</code> to remove.
1138     */
1139     public synchronized void
1140     removeMidiInstrumentInfoListener(MidiInstrumentInfoListener l) {
1141     boolean b = llMII.remove(l);
1142     if(b && llMII.isEmpty()) unsubscribe("MIDI_INSTRUMENT_INFO");
1143     }
1144    
1145     /**
1146     * Registers the specified listener for receiving event messages.
1147     * Listeners can be registered regardless of the connection state.
1148     * @param l The <code>GlobalInfoListener</code> to register.
1149     */
1150     public synchronized void
1151     addGlobalInfoListener(GlobalInfoListener l) {
1152     if(llGI.isEmpty()) subscribe("GLOBAL_INFO");
1153     llGI.add(l);
1154     }
1155    
1156     /**
1157     * Removes the specified listener.
1158     * Listeners can be removed regardless of the connection state.
1159     * @param l The <code>GlobalInfoListener</code> to remove.
1160     */
1161     public synchronized void
1162     removeGlobalInfoListener(GlobalInfoListener l) {
1163     boolean b = llGI.remove(l);
1164     if(b && llGI.isEmpty()) unsubscribe("GLOBAL_INFO");
1165     }
1166    
1167     /**
1168 iliev 596 * Gets the number of all audio output drivers currently
1169     * available for the LinuxSampler instance.
1170     * @return The number of all audio output drivers currently
1171     * available for the LinuxSampler instance.
1172     * @throws IOException If some I/O error occurs.
1173     * @throws LscpException If LSCP protocol corruption occurs.
1174     * @throws LSException If some other error occurs.
1175     */
1176     public synchronized int
1177     getAudioOutputDriverCount() throws IOException, LscpException, LSException {
1178     verifyConnection();
1179     out.writeLine("GET AVAILABLE_AUDIO_OUTPUT_DRIVERS");
1180 iliev 1139
1181     if(getPrintOnlyMode()) return -1;
1182    
1183 iliev 596 String s = getSingleLineResultSet().getResult();
1184     return parseInt(s);
1185     }
1186 iliev 671
1187 iliev 596 /**
1188     * Gets all audio output drivers currently available for the LinuxSampler instance.
1189     *
1190 iliev 671 * @return <code>AudioOutputDriver</code> array containing all audio output drivers
1191     * currently available for the LinuxSampler instance.
1192 iliev 596 *
1193     * @throws IOException If an I/O error occurs.
1194     * @throws LscpException If LSCP protocol corruption occurs.
1195     * @throws LSException If some other error occurs.
1196     */
1197 iliev 671 public synchronized AudioOutputDriver[]
1198 iliev 596 getAudioOutputDrivers() throws IOException, LscpException, LSException {
1199 iliev 671 String[] drivers = getAudioOutputDriverNames();
1200 iliev 1139 if(getPrintOnlyMode()) return null;
1201    
1202 iliev 671 AudioOutputDriver[] aod = new AudioOutputDriver[drivers.length];
1203    
1204     for(int i = 0; i < aod.length; i++) aod[i] = getAudioOutputDriverInfo(drivers[i]);
1205    
1206     return aod;
1207     }
1208    
1209     /**
1210     * Gets all audio output drivers currently available for the LinuxSampler instance.
1211     *
1212     * @return <code>String</code> array containing all audio output drivers currently
1213     * available for the LinuxSampler instance.
1214     *
1215     * @throws IOException If an I/O error occurs.
1216     * @throws LscpException If LSCP protocol corruption occurs.
1217     * @throws LSException If some other error occurs.
1218     */
1219     private synchronized String[]
1220     getAudioOutputDriverNames() throws IOException, LscpException, LSException {
1221 iliev 596 verifyConnection();
1222     out.writeLine("LIST AVAILABLE_AUDIO_OUTPUT_DRIVERS");
1223 iliev 1139 if(getPrintOnlyMode()) return null;
1224 iliev 596 return parseList(getSingleLineResultSet().getResult());
1225     }
1226    
1227     /**
1228     * Gets detailed information about a specific audio output driver.
1229     * @param driverName The name of the audio output driver.
1230     *
1231     * @return An <code>AudioOutputDriver</code> object containing
1232     * information about the specified audio output driver.
1233     *
1234     * @throws IOException If an I/O error occurs.
1235     * @throws LscpException If LSCP protocol corruption occurs.
1236     * @throws LSException If there is no driver with name <code>driverName</code>.
1237     *
1238 iliev 671 * @see #getAudioOutputDriverNames
1239 iliev 596 */
1240 iliev 671 private synchronized AudioOutputDriver
1241 iliev 596 getAudioOutputDriverInfo(String driverName) throws IOException, LscpException, LSException {
1242     verifyConnection();
1243     out.writeLine("GET AUDIO_OUTPUT_DRIVER INFO " + driverName);
1244 iliev 1139 if(getPrintOnlyMode()) return null;
1245    
1246 iliev 596 ResultSet rs = getMultiLineResultSet();
1247     AudioOutputDriver aod = new AudioOutputDriver(rs.getMultiLineResult());
1248     aod.setName(driverName);
1249    
1250     for(String s : aod.getParameterNames())
1251     aod.addParameter(getAudioOutputDriverParameterInfo(driverName, s));
1252    
1253     return aod;
1254     }
1255    
1256     /**
1257     * Gets detailed information about a specific audio output driver parameter.
1258     *
1259     * @param driver The name of the audio output driver.
1260     * @param param A specific parameter name for which information should be obtained.
1261     * @param deplist An optional list of parameters on which the sought parameter
1262     * <code>param</code> depends on. <code>Parameter</code> instances can be
1263     * easily created using {@link ParameterFactory} factory.
1264     *
1265     * @return <code>Parameter</code> object containing
1266     * information about the specified audio output driver parameter.
1267     *
1268     * @throws IOException If an I/O error occurs.
1269     * @throws LscpException If LSCP protocol corruption occurs.
1270     * @throws LSException If <code>driver</code> is not a valid driver name
1271     * or <code>param</code> is not a valid parameter for the specified driver.
1272     *
1273     * @see #getAudioOutputDrivers
1274     * @see #getAudioOutputDriverInfo
1275     * @see ParameterFactory
1276     */
1277     public synchronized Parameter
1278     getAudioOutputDriverParameterInfo(String driver, String param, Parameter... deplist)
1279     throws IOException, LscpException, LSException {
1280    
1281     verifyConnection();
1282     StringBuffer args = new StringBuffer(driver);
1283     args.append(' ').append(param);
1284    
1285     for(Parameter p : deplist)
1286     args.append(' ').append(p.getName()).append('=').append(p.getStringValue());
1287    
1288     out.writeLine("GET AUDIO_OUTPUT_DRIVER_PARAMETER INFO " + args.toString());
1289 iliev 1139 if(getPrintOnlyMode()) return null;
1290 iliev 596
1291     ResultSet rs = getMultiLineResultSet();
1292    
1293     String[] lnS = rs.getMultiLineResult();
1294     ParameterType type = parseType(lnS);
1295     boolean multi = parseMultiplicity(lnS);
1296     Parameter prm;
1297    
1298     switch(type) {
1299     case BOOL:
1300     if(!multi) prm = new BoolParameter(lnS);
1301     else prm = new BoolListParameter(lnS);
1302     prm.setName(param);
1303 iliev 784 prm.setValue(prm.getDefault());
1304 iliev 596 return prm;
1305     case INT:
1306     if(!multi) prm = new IntParameter(lnS);
1307     else prm = new IntListParameter(lnS);
1308     prm.setName(param);
1309 iliev 784 prm.setValue(prm.getDefault());
1310 iliev 596 return prm;
1311     case FLOAT:
1312     if(!multi) prm = new FloatParameter(lnS);
1313     else prm = new FloatListParameter(lnS);
1314     prm.setName(param);
1315 iliev 784 prm.setValue(prm.getDefault());
1316 iliev 596 return prm;
1317     case STRING:
1318     if(!multi) prm = new StringParameter(lnS);
1319     else prm = new StringListParameter(lnS);
1320     prm.setName(param);
1321 iliev 784 prm.setValue(prm.getDefault());
1322 iliev 596 return prm;
1323     default: throw new LscpException(LscpI18n.getLogMsg("Client.unknownPrmType!"));
1324     }
1325     }
1326    
1327     /**
1328     * Creates a new audio output device for the desired audio output system.
1329     * @param aoDriver The desired audio output system.
1330     * @param paramList An optional list of driver specific parameters. <code>Parameter</code>
1331     * instances can be easily created using {@link ParameterFactory} factory.
1332     * @return The numerical ID of the newly created device.
1333     * @throws IOException If some I/O error occurs.
1334     * @throws LSException If the creation of the new audio output device failed.
1335     * @throws LscpException If LSCP protocol corruption occurs.
1336     * @see #getAudioOutputDrivers
1337     * @see #getAudioOutputDriverInfo
1338     * @see ParameterFactory
1339     */
1340     public synchronized int
1341     createAudioOutputDevice(String aoDriver, Parameter... paramList)
1342     throws IOException, LSException, LscpException {
1343    
1344     verifyConnection();
1345     StringBuffer args = new StringBuffer(aoDriver);
1346    
1347     for(Parameter p : paramList)
1348     args.append(' ').append(p.getName()).append('=').append(p.getStringValue());
1349    
1350     out.writeLine("CREATE AUDIO_OUTPUT_DEVICE " + args.toString());
1351 iliev 1139 if(getPrintOnlyMode()) return -1;
1352    
1353 iliev 596 ResultSet rs = getEmptyResultSet();
1354    
1355     return rs.getIndex();
1356     }
1357    
1358     /**
1359     * Destroys already created audio output device.
1360 iliev 1139 * @param deviceId The ID of the audio output device to be destroyed.
1361 iliev 596 * @throws IOException If some I/O error occurs.
1362     * @throws LSException If the destroying of the audio output device failed.
1363     * @throws LscpException If LSCP protocol corruption occurs.
1364     * @see #getAudioOutputDevices
1365     */
1366     public synchronized void
1367 iliev 1139 destroyAudioOutputDevice(int deviceId) throws IOException, LSException, LscpException {
1368 iliev 596 verifyConnection();
1369 iliev 1139 out.writeLine("DESTROY AUDIO_OUTPUT_DEVICE " + deviceId);
1370     if(getPrintOnlyMode()) return;
1371    
1372 iliev 596 ResultSet rs = getEmptyResultSet();
1373     }
1374    
1375 iliev 784 /**
1376     * Enables/disables the specified audio output device.
1377 iliev 1139 * @param deviceId The ID of the audio output device to be enabled/disabled.
1378 iliev 784 * @param enable If <code>true</code> the audio output device is enabled,
1379     * else the device is disabled.
1380     * @throws IOException If some I/O error occurs.
1381     * @throws LSException If there is no audio output
1382 iliev 1139 * device with numerical ID <code>deviceId</code>.
1383 iliev 784 * @throws LscpException If LSCP protocol corruption occurs.
1384     */
1385     public void
1386 iliev 1139 enableAudioOutputDevice(int deviceId, boolean enable)
1387 iliev 784 throws IOException, LSException, LscpException {
1388    
1389 iliev 1139 setAudioOutputDeviceParameter(deviceId, new BoolParameter("ACTIVE", enable));
1390 iliev 784 }
1391    
1392 iliev 596 /**
1393     * Gets the current number of all created audio output devices.
1394     * @return The current number of all created audio output devices.
1395     * @throws IOException If some I/O error occurs.
1396     * @throws LscpException If LSCP protocol corruption occurs.
1397     * @throws LSException If some other error occurs.
1398     */
1399     public synchronized int
1400     getAudioOutputDeviceCount() throws IOException, LscpException, LSException {
1401     verifyConnection();
1402     out.writeLine("GET AUDIO_OUTPUT_DEVICES");
1403 iliev 1139 if(getPrintOnlyMode()) return -1;
1404    
1405 iliev 596 String s = getSingleLineResultSet().getResult();
1406     return parseInt(s);
1407     }
1408    
1409     /**
1410 iliev 784 * Gets a list of all created audio output devices.
1411     * @return An <code>AudioOutputDevice</code> array
1412     * providing all created audio output devices.
1413     * @throws IOException If some I/O error occurs.
1414     * @throws LscpException If LSCP protocol corruption occurs.
1415     * @throws LSException If some other error occurs.
1416     */
1417     public synchronized AudioOutputDevice[]
1418     getAudioOutputDevices() throws IOException, LscpException, LSException {
1419     Integer[] idS = getAudioOutputDeviceIDs();
1420 iliev 1139 if(getPrintOnlyMode()) return null;
1421    
1422 iliev 784 AudioOutputDevice[] devices = new AudioOutputDevice[idS.length];
1423    
1424     for(int i = 0; i < devices.length; i++)
1425     devices[i] = getAudioOutputDeviceInfo(idS[i]);
1426    
1427     return devices;
1428     }
1429    
1430     /**
1431 iliev 596 * Gets a list of numerical IDs of all created audio output devices.
1432 iliev 784 * @return An <code>Integer</code> array providing the numerical IDs of
1433 iliev 596 * all created audio output devices.
1434     * @throws IOException If some I/O error occurs.
1435     * @throws LscpException If LSCP protocol corruption occurs.
1436     * @throws LSException If some other error occurs.
1437     */
1438     public synchronized Integer[]
1439 iliev 784 getAudioOutputDeviceIDs() throws IOException, LscpException, LSException {
1440 iliev 596 verifyConnection();
1441     out.writeLine("LIST AUDIO_OUTPUT_DEVICES");
1442 iliev 1139 if(getPrintOnlyMode()) return null;
1443    
1444 iliev 596 return parseIntList(getSingleLineResultSet().getResult());
1445     }
1446    
1447     /**
1448     * Gets the current settings of a specific, already created audio output device.
1449     *
1450 iliev 1139 * @param deviceId Specifies the numerical ID of the audio output device.
1451 iliev 596 *
1452     * @return An <code>AudioOutputDevice</code> instance containing information
1453     * about the specified device.
1454     *
1455     * @throws IOException If some I/O error occurs.
1456     * @throws LscpException If LSCP protocol corruption occurs.
1457     * @throws LSException If there is no audio output device
1458 iliev 1139 * with device id <code>deviceId</code>.
1459 iliev 596 *
1460     * @see #getAudioOutputDevices
1461     */
1462     public synchronized AudioOutputDevice
1463 iliev 1139 getAudioOutputDeviceInfo(int deviceId) throws IOException, LscpException, LSException {
1464 iliev 596 verifyConnection();
1465 iliev 1139 out.writeLine("GET AUDIO_OUTPUT_DEVICE INFO " + deviceId);
1466     if(getPrintOnlyMode()) return null;
1467 iliev 596
1468     ResultSet rs = getMultiLineResultSet();
1469    
1470     String[] lnS = rs.getMultiLineResult();
1471    
1472     AudioOutputDevice aod = new AudioOutputDevice();
1473 iliev 1139 aod.setDeviceId(deviceId);
1474 iliev 596 Parameter<Integer> channels;
1475     Parameter<Integer> samplerate;
1476    
1477     String drv = getCategoryInfo(lnS, "DRIVER");
1478     aod.setDriverName(drv);
1479    
1480     for(String s : lnS) {
1481     if(s.startsWith("CHANNELS: ")) {
1482     channels = (Parameter<Integer>)
1483     getAudioOutputDriverParameterInfo(drv, "CHANNELS");
1484    
1485     s = s.substring("CHANNELS: ".length(), s.length());
1486     channels.parseValue(s);
1487     aod.setChannelsParameter(channels);
1488 iliev 784 int count = channels.getValue() > 0 ? channels.getValue() : 0;
1489     AudioOutputChannel[] aoc = new AudioOutputChannel[count];
1490     for(int i = 0; i < count; i++) {
1491 iliev 1139 aoc[i] = getAudioOutputChannelInfo(deviceId, i);
1492 iliev 784 }
1493     aod.setAudioChannels(aoc);
1494 iliev 596 } else if(s.startsWith("SAMPLERATE: ")) {
1495     samplerate = (Parameter<Integer>)
1496     getAudioOutputDriverParameterInfo(drv, "SAMPLERATE");
1497    
1498     s = s.substring("SAMPLERATE: ".length(), s.length());
1499     samplerate.parseValue(s);
1500     aod.setSampleRateParameter(samplerate);
1501     } else if(s.startsWith("ACTIVE: ")) {
1502     s = s.substring("ACTIVE: ".length(), s.length());
1503     aod.setActive(Boolean.parseBoolean(s));
1504     } else if(s.startsWith("DRIVER: ")) {
1505    
1506     } else {
1507     int i = s.indexOf(": ");
1508     if(i == -1) throw new LscpException (
1509     LscpI18n.getLogMsg("CommandFailed!")
1510     );
1511    
1512     Parameter prm =
1513     getAudioOutputDriverParameterInfo(drv, s.substring(0, i));
1514    
1515     s = s.substring(i + 2);
1516     prm.parseValue(s);
1517    
1518     aod.addParameter(prm);
1519     }
1520     }
1521    
1522     return aod;
1523     }
1524    
1525     /**
1526     * Alters a specific setting of a created audio output device.
1527     *
1528 iliev 1139 * @param deviceId The numerical ID of the audio output device.
1529 iliev 596 * @param prm A <code>Parameter</code> instance containing the name of the parameter
1530     * and the new value for this parameter.
1531     *
1532     * @throws IOException If some I/O error occurs.
1533     * @throws LscpException If LSCP protocol corruption occurs.
1534     * @throws LSException If
1535     * <ul>
1536 iliev 1139 * <li>There is no audio output device with numerical ID <code>deviceId</code>;
1537 iliev 596 * <li>There is no device parameter with the specified name;
1538     * <li>The device parameter is readonly;
1539     * <li>The device parameter is from different type.
1540     * </ul>
1541     *
1542     * @see #getAudioOutputDevices
1543     * @see #getAudioOutputDeviceInfo
1544     */
1545     public synchronized void
1546 iliev 1139 setAudioOutputDeviceParameter(int deviceId, Parameter prm)
1547 iliev 596 throws IOException, LscpException, LSException {
1548    
1549     verifyConnection();
1550     String kv = prm.getName() + '=' + prm.getStringValue();
1551 iliev 1139 out.writeLine("SET AUDIO_OUTPUT_DEVICE_PARAMETER " + deviceId + ' ' + kv);
1552     if(getPrintOnlyMode()) return;
1553 iliev 596
1554     ResultSet rs = getEmptyResultSet();
1555     }
1556    
1557     /**
1558 iliev 1139 * Changes the channel number of the speicifed audio output device.
1559     * @param deviceId The numerical ID of the audio output device.
1560 iliev 784 * @param channels The new number of audio output channels.
1561     *
1562     * @throws IOException If an I/O error occurs.
1563     * @throws LscpException If LSCP protocol corruption occurs.
1564 iliev 1139 * @throws LSException If there is no device with ID <code>deviceId</code> or
1565 iliev 784 * if <code>channels</code> number is out of range.
1566     *
1567     * @see #getAudioOutputChannelInfo
1568     */
1569     public synchronized void
1570 iliev 1139 setAudioOutputChannelCount(int deviceId, int channels)
1571 iliev 784 throws IOException, LscpException, LSException {
1572    
1573 iliev 1139 setAudioOutputDeviceParameter(deviceId, new IntParameter("CHANNELS", channels));
1574 iliev 784 }
1575    
1576     /**
1577 iliev 596 * Gets information about an audio channel.
1578     *
1579 iliev 1139 * @param deviceId The numerical ID of the audio output device.
1580 iliev 596 * @param audioChn The audio channel number.
1581     *
1582     * @return An <code>AudioOutputChannel</code> instance containing the
1583     * information about the specified audio output channel.
1584     *
1585     * @throws IOException If some I/O error occurs.
1586     * @throws LscpException If LSCP protocol corruption occurs.
1587     * @throws LSException If
1588     * <ul>
1589 iliev 1139 * <li>There is no audio output device with numerical ID <code>deviceId</code>;
1590 iliev 596 * <li><code>audioChn</code> is not a valid channel number;
1591     * </ul>
1592     *
1593     * @see #getAudioOutputDevices
1594     * @see #getAudioOutputDeviceInfo
1595     */
1596     public synchronized AudioOutputChannel
1597 iliev 1139 getAudioOutputChannelInfo(int deviceId, int audioChn)
1598 iliev 596 throws IOException, LscpException, LSException {
1599    
1600     verifyConnection();
1601 iliev 1139 out.writeLine("GET AUDIO_OUTPUT_CHANNEL INFO " + deviceId + ' ' + audioChn);
1602     if(getPrintOnlyMode()) return null;
1603 iliev 596
1604     ResultSet rs = getMultiLineResultSet();
1605    
1606     AudioOutputChannel aoc = new AudioOutputChannel();
1607    
1608     String[] lnS = rs.getMultiLineResult();
1609     for(String s : lnS) {
1610     if(s.startsWith("NAME: ")) {
1611 iliev 784 s = s.substring("NAME: ".length());
1612     Parameter<String> prm = getAudioOutputChannelParameterInfo (
1613 iliev 1139 deviceId, audioChn, "NAME"
1614 iliev 784 );
1615     prm.setValue(removeQuotation(s));
1616     aoc.setNameParameter(prm);
1617 iliev 596 } else if(s.startsWith("IS_MIX_CHANNEL: ")) {
1618     s = s.substring("IS_MIX_CHANNEL: ".length());
1619 iliev 784 Parameter<Boolean> prm = getAudioOutputChannelParameterInfo (
1620 iliev 1139 deviceId, audioChn, "IS_MIX_CHANNEL"
1621 iliev 784 );
1622     prm.setValue(Boolean.parseBoolean(s));
1623     aoc.setMixChannelParameter(prm);
1624 iliev 596 } else if(s.startsWith("MIX_CHANNEL_DESTINATION: ")) {
1625     s = s.substring("MIX_CHANNEL_DESTINATION: ".length());
1626 iliev 784 Parameter<Integer> prm = getAudioOutputChannelParameterInfo (
1627 iliev 1139 deviceId, audioChn, "MIX_CHANNEL_DESTINATION"
1628 iliev 784 );
1629     prm.setValue(parseInt(s));
1630     aoc.setMixChannelDestParameter(prm);
1631 iliev 596 } else {
1632     int i = s.indexOf(": ");
1633     if(i == -1) throw new LscpException (
1634     LscpI18n.getLogMsg("CommandFailed!")
1635     );
1636    
1637     Parameter prm = getAudioOutputChannelParameterInfo (
1638 iliev 1139 deviceId, audioChn, s.substring(0, i)
1639 iliev 596 );
1640    
1641     s = s.substring(i + 2);
1642     prm.parseValue(s);
1643    
1644     aoc.addParameter(prm);
1645     }
1646     }
1647    
1648     return aoc;
1649     }
1650    
1651     /**
1652     * Gets detailed information about a specific audio output channel parameter.
1653     *
1654 iliev 1139 * @param devId The numerical ID of the audio output device.
1655 iliev 596 * @param chan The audio channel number.
1656     * @param param a specific channel parameter name for which information should be obtained.
1657     *
1658     * @return An <code>Parameter</code> instance containing
1659     * information about the specified audio output channel parameter.
1660     *
1661     * @throws IOException If an I/O error occurs.
1662     * @throws LscpException If LSCP protocol corruption occurs.
1663     * @throws LSException If
1664     * <ul>
1665 iliev 1139 * <li><code>devId</code> is not a valid device ID;
1666 iliev 596 * <li><code>chan</code> is not a valid channel number;
1667     * <li>There is no channel parameter with the specified name.
1668     * </ul>
1669     *
1670     * @see #getAudioOutputDevices
1671     * @see #getAudioOutputChannelInfo
1672     */
1673     public synchronized Parameter
1674 iliev 1139 getAudioOutputChannelParameterInfo(int devId, int chan, String param)
1675 iliev 596 throws IOException, LscpException, LSException {
1676    
1677     verifyConnection();
1678 iliev 1139 String args = devId + " " + chan + " " + param;
1679 iliev 596 out.writeLine("GET AUDIO_OUTPUT_CHANNEL_PARAMETER INFO " + args);
1680 iliev 1139 if(getPrintOnlyMode()) return null;
1681 iliev 596
1682     ResultSet rs = getMultiLineResultSet();
1683    
1684     String[] lnS = rs.getMultiLineResult();
1685     ParameterType type = parseType(lnS);
1686     boolean multi = parseMultiplicity(lnS);
1687     Parameter prm;
1688    
1689     switch(type) {
1690     case BOOL:
1691     if(!multi) prm = new BoolParameter(lnS);
1692     else prm = new BoolListParameter(lnS);
1693     prm.setName(param);
1694     return prm;
1695     case INT:
1696     if(!multi) prm = new IntParameter(lnS);
1697     else prm = new IntListParameter(lnS);
1698     prm.setName(param);
1699     return prm;
1700     case FLOAT:
1701     if(!multi) prm = new FloatParameter(lnS);
1702     else prm = new FloatListParameter(lnS);
1703     prm.setName(param);
1704     return prm;
1705     case STRING:
1706     if(!multi) prm = new StringParameter(lnS);
1707     else prm = new StringListParameter(lnS);
1708     prm.setName(param);
1709     return prm;
1710     default: throw new LscpException(LscpI18n.getLogMsg("Client.unknownPrmType!"));
1711     }
1712     }
1713    
1714     /**
1715     * Alters a specific setting of an audio output channel.
1716     *
1717 iliev 1139 * @param devId The numerical ID of the audio device.
1718 iliev 596 * @param chn The audio channel number.
1719     * @param prm A <code>Parameter</code> instance containing the name of the parameter
1720     * and the new value for this parameter.
1721     *
1722     * @throws IOException If some I/O error occurs.
1723     * @throws LscpException If LSCP protocol corruption occurs.
1724     * @throws LSException If
1725     * <ul>
1726 iliev 1139 * <li>There is no audio output device with numerical ID <code>devId</code>;
1727 iliev 596 * <li><code>chn</code> is not a valid channel number;
1728     * <li>There is no channel parameter with the specified name;
1729     * <li>The channel parameter is readonly;
1730     * <li>The channel parameter is from different type.
1731     * </ul>
1732     *
1733     * @see #getAudioOutputDevices
1734     * @see #getAudioOutputChannelInfo
1735     */
1736     public synchronized void
1737 iliev 1139 setAudioOutputChannelParameter(int devId, int chn, Parameter prm)
1738 iliev 596 throws IOException, LscpException, LSException {
1739    
1740     verifyConnection();
1741 iliev 1139 String args = devId + " " + chn + " " + prm.getName() + '=' + prm.getStringValue();
1742 iliev 596 out.writeLine("SET AUDIO_OUTPUT_CHANNEL_PARAMETER " + args);
1743 iliev 1139 if(getPrintOnlyMode()) return;
1744 iliev 596
1745     ResultSet rs = getEmptyResultSet();
1746     }
1747    
1748     /**
1749     * Gets the current number of all MIDI input drivers.
1750     * @return The current number of all MIDI input drivers.
1751     * @throws IOException If some I/O error occurs.
1752     * @throws LscpException If LSCP protocol corruption occurs.
1753     * @throws LSException If some other error occurs.
1754     */
1755     public synchronized int
1756     getMidiInputDriverCount() throws IOException, LscpException, LSException {
1757     verifyConnection();
1758     out.writeLine("GET AVAILABLE_MIDI_INPUT_DRIVERS");
1759 iliev 1139 if(getPrintOnlyMode()) return -1;
1760    
1761 iliev 596 String s = getSingleLineResultSet().getResult();
1762     return parseInt(s);
1763     }
1764    
1765     /**
1766     * Gets all MIDI input drivers currently available for the LinuxSampler instance.
1767     *
1768 iliev 671 * @return <code>MidiInputDriver</code> array containing all MIDI input drivers currently
1769     * available for the LinuxSampler instance.
1770 iliev 596 *
1771     * @throws IOException If an I/O error occurs.
1772     * @throws LscpException If LSCP protocol corruption occurs.
1773     * @throws LSException If some other error occurs.
1774     */
1775 iliev 671 public synchronized MidiInputDriver[]
1776 iliev 596 getMidiInputDrivers() throws IOException, LscpException, LSException {
1777 iliev 671 String[] drivers = getMidiInputDriverNames();
1778 iliev 1139 if(getPrintOnlyMode()) return null;
1779    
1780 iliev 671 MidiInputDriver[] mid = new MidiInputDriver[drivers.length];
1781    
1782     for(int i = 0; i < mid.length; i++) mid[i] = getMidiInputDriverInfo(drivers[i]);
1783    
1784     return mid;
1785     }
1786    
1787     /**
1788     * Gets all MIDI input drivers currently available for the LinuxSampler instance.
1789     *
1790     * @return <code>String</code> array containing all MIDI input drivers currently available
1791     * for the LinuxSampler instance.
1792     *
1793     * @throws IOException If an I/O error occurs.
1794     * @throws LscpException If LSCP protocol corruption occurs.
1795     * @throws LSException If some other error occurs.
1796     */
1797     private synchronized String[]
1798     getMidiInputDriverNames() throws IOException, LscpException, LSException {
1799 iliev 596 verifyConnection();
1800     out.writeLine("LIST AVAILABLE_MIDI_INPUT_DRIVERS");
1801 iliev 1139 if(getPrintOnlyMode()) return null;
1802    
1803 iliev 596 return parseList(getSingleLineResultSet().getResult());
1804     }
1805    
1806     /**
1807     * Gets detailed information about a specific MIDI input driver.
1808     * @param driverName The name of the MIDI input driver.
1809     *
1810 iliev 671 * @return A <code>MidiInputDriver</code> object containing
1811 iliev 596 * information about the specified MIDI input driver.
1812     *
1813     * @throws IOException If an I/O error occurs.
1814     * @throws LscpException If LSCP protocol corruption occurs.
1815     * @throws LSException If there is no driver with name <code>driverName</code>.
1816     *
1817 iliev 671 * @see #getMidiInputDriverNames
1818 iliev 596 */
1819 iliev 671 private synchronized MidiInputDriver
1820 iliev 596 getMidiInputDriverInfo(String driverName) throws IOException, LscpException, LSException {
1821     verifyConnection();
1822     out.writeLine("GET MIDI_INPUT_DRIVER INFO " + driverName);
1823 iliev 1139 if(getPrintOnlyMode()) return null;
1824    
1825 iliev 596 ResultSet rs = getMultiLineResultSet();
1826    
1827     MidiInputDriver mid = new MidiInputDriver(rs.getMultiLineResult());
1828     mid.setName(driverName);
1829    
1830     for(String s : mid.getParameterNames())
1831     mid.addParameter(getMidiInputDriverParameterInfo(driverName, s));
1832    
1833     return mid;
1834     }
1835    
1836     /**
1837     * Gets detailed information about a specific MIDI input driver parameter.
1838     *
1839     * @param driver The name of the MIDI input driver.
1840     * @param param a specific parameter name for which information should be obtained.
1841     * @param deplist An optional list of parameters on which the sought parameter
1842     * <code>param</code> depends on. <code>Parameter</code> instances can be
1843     * easily created using {@link ParameterFactory} factory.
1844     *
1845 iliev 671 * @return A <code>Parameter</code> object containing
1846 iliev 596 * information about the specified MIDI input driver parameter.
1847     *
1848     * @throws IOException If an I/O error occurs.
1849     * @throws LscpException If LSCP protocol corruption occurs.
1850     * @throws LSException If <code>driver</code> is not a valid driver name
1851     * or <code>param</code> is not a valid parameter for the specified driver.
1852     *
1853     * @see #getMidiInputDrivers
1854     * @see #getMidiInputDriverInfo
1855     * @see ParameterFactory
1856     */
1857     public synchronized Parameter
1858     getMidiInputDriverParameterInfo(String driver, String param, Parameter... deplist)
1859     throws IOException, LscpException, LSException {
1860    
1861     verifyConnection();
1862     StringBuffer args = new StringBuffer(driver);
1863     args.append(' ').append(param);
1864    
1865     for(Parameter p : deplist)
1866     args.append(' ').append(p.getName()).append('=').append(p.getStringValue());
1867    
1868     out.writeLine("GET MIDI_INPUT_DRIVER_PARAMETER INFO " + args.toString());
1869 iliev 1139 if(getPrintOnlyMode()) return null;
1870 iliev 596
1871     ResultSet rs = getMultiLineResultSet();
1872    
1873     String[] lnS = rs.getMultiLineResult();
1874     ParameterType type = parseType(lnS);
1875     boolean multi = parseMultiplicity(lnS);
1876     Parameter prm;
1877    
1878     switch(type) {
1879     case BOOL:
1880     if(!multi) prm = new BoolParameter(lnS);
1881     else prm = new BoolListParameter(lnS);
1882     prm.setName(param);
1883 iliev 784 prm.setValue(prm.getDefault());
1884 iliev 596 return prm;
1885     case INT:
1886     if(!multi) prm = new IntParameter(lnS);
1887     else prm = new IntListParameter(lnS);
1888     prm.setName(param);
1889 iliev 784 prm.setValue(prm.getDefault());
1890 iliev 596 return prm;
1891     case FLOAT:
1892     if(!multi) prm = new FloatParameter(lnS);
1893     else prm = new FloatListParameter(lnS);
1894     prm.setName(param);
1895 iliev 784 prm.setValue(prm.getDefault());
1896 iliev 596 return prm;
1897     case STRING:
1898     if(!multi) prm = new StringParameter(lnS);
1899     else prm = new StringListParameter(lnS);
1900     prm.setName(param);
1901 iliev 784 prm.setValue(prm.getDefault());
1902 iliev 596 return prm;
1903     default: throw new LscpException(LscpI18n.getLogMsg("Client.unknownPrmType!"));
1904     }
1905     }
1906    
1907     /**
1908     * Creates a new MIDI input device.
1909     * @param miDriver The desired MIDI input system.
1910     * @param paramList An optional list of driver specific parameters. <code>Parameter</code>
1911     * instances can be easily created using {@link ParameterFactory} factory.
1912     * @return The numerical ID of the newly created device.
1913     * @throws IOException If some I/O error occurs.
1914     * @throws LSException If the creation of the new MIDI input device failed.
1915     * @throws LscpException If LSCP protocol corruption occurs.
1916     *
1917     * @see #getMidiInputDrivers
1918     * @see #getMidiInputDriverInfo
1919     * @see ParameterFactory
1920     */
1921     public synchronized int
1922     createMidiInputDevice(String miDriver, Parameter... paramList)
1923     throws IOException, LSException, LscpException {
1924    
1925     verifyConnection();
1926     StringBuffer args = new StringBuffer(miDriver);
1927    
1928     for(Parameter p : paramList)
1929     args.append(' ').append(p.getName()).append('=').append(p.getStringValue());
1930    
1931     out.writeLine("CREATE MIDI_INPUT_DEVICE " + args.toString());
1932 iliev 1139 if(getPrintOnlyMode()) return -1;
1933    
1934 iliev 596 ResultSet rs = getEmptyResultSet();
1935    
1936     return rs.getIndex();
1937     }
1938    
1939     /**
1940     * Destroys already created MIDI input device.
1941 iliev 1139 * @param deviceId The numerical ID of the MIDI input device to be destroyed.
1942 iliev 596 * @throws IOException If some I/O error occurs.
1943     * @throws LSException If the destroying of the MIDI input device failed.
1944     * @throws LscpException If LSCP protocol corruption occurs.
1945     * @see #createMidiInputDevice
1946     * @see #getMidiInputDevices
1947     */
1948     public synchronized void
1949 iliev 1139 destroyMidiInputDevice(int deviceId) throws IOException, LSException, LscpException {
1950 iliev 596 verifyConnection();
1951 iliev 1139 out.writeLine("DESTROY MIDI_INPUT_DEVICE " + deviceId);
1952     if(getPrintOnlyMode()) return;
1953    
1954 iliev 596 ResultSet rs = getEmptyResultSet();
1955     }
1956    
1957 iliev 784 /**
1958     * Enables/disables the specified MIDI input device.
1959 iliev 1139 * @param deviceId The ID of the MIDI input device to be enabled/disabled.
1960 iliev 784 * @param enable If <code>true</code> the MIDI input device is enabled,
1961     * else the device is disabled.
1962     * @throws IOException If some I/O error occurs.
1963     * @throws LSException If there is no MIDI input
1964 iliev 1139 * device with numerical ID <code>deviceId</code>.
1965 iliev 784 * @throws LscpException If LSCP protocol corruption occurs.
1966     */
1967     public void
1968 iliev 1139 enableMidiInputDevice(int deviceId, boolean enable)
1969 iliev 784 throws IOException, LSException, LscpException {
1970    
1971 iliev 1139 setMidiInputDeviceParameter(deviceId, new BoolParameter("ACTIVE", enable));
1972 iliev 784 }
1973    
1974 iliev 596 /**
1975     * Gets the current number of all created MIDI input devices.
1976     * @return The current number of all created MIDI input devices.
1977     * @throws IOException If some I/O error occurs.
1978     * @throws LscpException If LSCP protocol corruption occurs.
1979     * @throws LSException If some other error occurs.
1980     */
1981     public synchronized int
1982     getMidiInputDeviceCount() throws IOException, LscpException, LSException {
1983     verifyConnection();
1984     out.writeLine("GET MIDI_INPUT_DEVICES");
1985 iliev 1139 if(getPrintOnlyMode()) return -1;
1986    
1987 iliev 596 String s = getSingleLineResultSet().getResult();
1988     return parseInt(s);
1989     }
1990    
1991     /**
1992 iliev 784 * Gets a list of all created MIDI input devices.
1993     * @return A <code>MidiInputDevice</code> array
1994     * providing all created MIDI input devices.
1995     * @throws IOException If some I/O error occurs.
1996     * @throws LscpException If LSCP protocol corruption occurs.
1997     * @throws LSException If some other error occurs.
1998     *
1999     * @see #createMidiInputDevice
2000     * @see #destroyMidiInputDevice
2001     */
2002     public synchronized MidiInputDevice[]
2003     getMidiInputDevices() throws IOException, LscpException, LSException {
2004     Integer[] idS = getMidiInputDeviceIDs();
2005 iliev 1139 if(getPrintOnlyMode()) return null;
2006    
2007 iliev 784 MidiInputDevice[] devices = new MidiInputDevice[idS.length];
2008    
2009     for(int i = 0; i < devices.length; i++)
2010     devices[i] = getMidiInputDeviceInfo(idS[i]);
2011    
2012     return devices;
2013     }
2014    
2015     /**
2016 iliev 596 * Gets a list of numerical IDs of all created MIDI input devices.
2017 iliev 784 * @return An <code>Integer</code> array providing the numerical IDs of
2018 iliev 596 * all created MIDI input devices.
2019     * @throws IOException If some I/O error occurs.
2020     * @throws LscpException If LSCP protocol corruption occurs.
2021     * @throws LSException If some other error occurs.
2022     *
2023     * @see #createMidiInputDevice
2024     * @see #destroyMidiInputDevice
2025     */
2026     public synchronized Integer[]
2027 iliev 784 getMidiInputDeviceIDs() throws IOException, LscpException, LSException {
2028 iliev 596 verifyConnection();
2029     out.writeLine("LIST MIDI_INPUT_DEVICES");
2030 iliev 1139 if(getPrintOnlyMode()) return null;
2031    
2032 iliev 596 return parseIntList(getSingleLineResultSet().getResult());
2033     }
2034    
2035     /**
2036     * Gets the current settings of a specific, already created MIDI input device.
2037     *
2038 iliev 1139 * @param deviceId Specifies the numerical ID of the MIDI input device.
2039 iliev 596 *
2040 iliev 1139 * @return A <code>MidiInputDevice</code> instance containing information
2041 iliev 596 * about the specified device.
2042     *
2043     * @throws IOException If some I/O error occurs.
2044     * @throws LscpException If LSCP protocol corruption occurs.
2045     * @throws LSException If there is no MIDI input device
2046 iliev 1139 * with device id <code>deviceId</code>.
2047 iliev 596 *
2048     * @see #getMidiInputDevices
2049     */
2050     public synchronized MidiInputDevice
2051 iliev 1139 getMidiInputDeviceInfo(int deviceId) throws IOException, LscpException, LSException {
2052 iliev 596 verifyConnection();
2053 iliev 1139 out.writeLine("GET MIDI_INPUT_DEVICE INFO " + deviceId);
2054     if(getPrintOnlyMode()) return null;
2055 iliev 596
2056     ResultSet rs = getMultiLineResultSet();
2057    
2058     String[] lnS = rs.getMultiLineResult();
2059    
2060     MidiInputDevice mid = new MidiInputDevice();
2061 iliev 1139 mid.setDeviceId(deviceId);
2062 iliev 596
2063     String drv = getCategoryInfo(lnS, "DRIVER");
2064     mid.setDriverName(drv);
2065    
2066     for(String s : lnS) {
2067     if(s.startsWith("DRIVER: ")) {
2068    
2069     } else if(s.startsWith("ACTIVE: ")) {
2070     s = s.substring("ACTIVE: ".length());
2071     mid.setActive(Boolean.parseBoolean(s));
2072 iliev 784 } else if(s.startsWith("PORTS: ")) {
2073     s = s.substring("PORTS: ".length());
2074     int ports = Parser.parseInt(s);
2075     MidiPort[] midiPorts = new MidiPort[ports > 0 ? ports : 0];
2076    
2077     for(int i = 0; i < midiPorts.length; i++)
2078 iliev 1139 midiPorts[i] = getMidiInputPortInfo(deviceId, i);
2079 iliev 784
2080     mid.setMidiPorts(midiPorts);
2081 iliev 596 } else {
2082     int i = s.indexOf(": ");
2083     if(i == -1) throw new LscpException (
2084     LscpI18n.getLogMsg("CommandFailed!")
2085     );
2086    
2087     Parameter prm =
2088     getMidiInputDriverParameterInfo(drv, s.substring(0, i));
2089    
2090     s = s.substring(i + 2);
2091     prm.parseValue(s);
2092    
2093     mid.addParameter(prm);
2094     }
2095     }
2096    
2097     return mid;
2098     }
2099    
2100     /**
2101     * Alters a specific setting of a created MIDI input device.
2102     *
2103 iliev 1139 * @param deviceId The numerical ID of the MIDI input device.
2104 iliev 596 * @param prm A <code>Parameter</code> instance containing the name of the parameter
2105     * and the new value for this parameter.
2106     *
2107     * @throws IOException If some I/O error occurs.
2108     * @throws LscpException If LSCP protocol corruption occurs.
2109     * @throws LSException If
2110     * <ul>
2111 iliev 1139 * <li>There is no MIDI input device with numerical ID <code>deviceId</code>;
2112 iliev 596 * <li>There is no device parameter with the specified name;
2113     * <li>The device parameter is readonly;
2114     * <li>The device parameter is from different type.
2115     * </ul>
2116     *
2117     * @see #getMidiInputDevices
2118     * @see #getMidiInputDeviceInfo
2119     */
2120     public synchronized void
2121 iliev 1139 setMidiInputDeviceParameter(int deviceId, Parameter prm)
2122 iliev 596 throws IOException, LscpException, LSException {
2123    
2124     verifyConnection();
2125     String kv = prm.getName() + '=' + prm.getStringValue();
2126 iliev 1139 out.writeLine("SET MIDI_INPUT_DEVICE_PARAMETER " + deviceId + ' ' + kv);
2127     if(getPrintOnlyMode()) return;
2128 iliev 596
2129     ResultSet rs = getEmptyResultSet();
2130     }
2131    
2132 iliev 784
2133 iliev 596 /**
2134 iliev 1139 * Changes the port number of the speicified MIDI input device.
2135     * @param deviceId The numerical ID of the MIDI input device.
2136 iliev 784 * @param ports The new number of MIDI input ports.
2137     *
2138     * @throws IOException If an I/O error occurs.
2139     * @throws LscpException If LSCP protocol corruption occurs.
2140 iliev 1139 * @throws LSException If there is no device with ID <code>deviceId</code> or
2141 iliev 784 * if <code>ports</code> number is out of range.
2142     *
2143     * @see #getMidiInputPortInfo
2144     */
2145     public synchronized void
2146 iliev 1139 setMidiInputPortCount(int deviceId, int ports)
2147 iliev 784 throws IOException, LscpException, LSException {
2148    
2149 iliev 1139 setMidiInputDeviceParameter(deviceId, new IntParameter("PORTS", ports));
2150 iliev 784 }
2151    
2152     /**
2153 iliev 596 * Gets detailed information about a specific MIDI input port.
2154 iliev 1139 * @param deviceId The numerical ID of the MIDI input device.
2155 iliev 596 * @param midiPort The MIDI input port number.
2156     *
2157     * @return A <code>MidiPort</code> instance containing
2158     * information about the specified MIDI input port.
2159     *
2160     * @throws IOException If an I/O error occurs.
2161     * @throws LscpException If LSCP protocol corruption occurs.
2162 iliev 1139 * @throws LSException If there is no device with ID <code>deviceId</code> or
2163 iliev 596 * if <code>midiPort</code> is not a valid MIDI port number.
2164     *
2165     * @see #getMidiInputDevices
2166     */
2167     public synchronized MidiPort
2168 iliev 1139 getMidiInputPortInfo(int deviceId, int midiPort)
2169 iliev 596 throws IOException, LscpException, LSException {
2170    
2171     verifyConnection();
2172 iliev 1139 out.writeLine("GET MIDI_INPUT_PORT INFO " + deviceId + " " + midiPort);
2173     if(getPrintOnlyMode()) return null;
2174    
2175 iliev 596 ResultSet rs = getMultiLineResultSet();
2176    
2177     MidiPort mp = new MidiPort();
2178     String[] lnS = rs.getMultiLineResult();
2179    
2180     for(String s : lnS) {
2181     if(s.startsWith("NAME: ")) {
2182 iliev 784 s = s.substring("NAME: ".length());
2183     Parameter prm = getMidiInputPortParameterInfo (
2184 iliev 1139 deviceId, midiPort, "NAME"
2185 iliev 784 );
2186     prm.setValue(removeQuotation(s));
2187     mp.setNameParameter(prm);
2188 iliev 596 } else {
2189     int i = s.indexOf(": ");
2190     if(i == -1) throw new LscpException (
2191     LscpI18n.getLogMsg("CommandFailed!")
2192     );
2193    
2194     Parameter prm = getMidiInputPortParameterInfo (
2195 iliev 1139 deviceId, midiPort, s.substring(0, i)
2196 iliev 596 );
2197    
2198     s = s.substring(i + 2);
2199     prm.parseValue(s);
2200    
2201     mp.addParameter(prm);
2202     }
2203     }
2204    
2205     return mp;
2206     }
2207    
2208     /**
2209     * Gets detailed information about a specific MIDI input port parameter.
2210     *
2211 iliev 1139 * @param deviceId The numerical ID of the MIDI input device.
2212 iliev 596 * @param port The MIDI port number.
2213     * @param param A specific parameter name for which information should be obtained.
2214     *
2215     * @return A <code>Parameter</code> instance containing
2216     * information about the specified MIDI input port parameter.
2217     *
2218     * @throws IOException If an I/O error occurs.
2219     * @throws LscpException If LSCP protocol corruption occurs.
2220     * @throws LSException If
2221     * <ul>
2222 iliev 1139 * <li>There is no MIDI input device with numerical ID <code>deviceId</code>;
2223 iliev 596 * <li> <code>port</code> is not a valid MIDI port number;
2224     * <li><code>param</code> is not a valid parameter for the specified MIDI port.
2225     * </ul>
2226     *
2227     * @see #getMidiInputDevices
2228     * @see #getMidiInputPortInfo
2229     */
2230     public synchronized Parameter
2231 iliev 1139 getMidiInputPortParameterInfo(int deviceId, int port, String param)
2232 iliev 596 throws IOException, LscpException, LSException {
2233    
2234     verifyConnection();
2235 iliev 1139 String args = deviceId + " " + port + " " + param;
2236 iliev 596 out.writeLine("GET MIDI_INPUT_PORT_PARAMETER INFO " + args);
2237 iliev 1139 if(getPrintOnlyMode()) return null;
2238 iliev 596
2239     ResultSet rs = getMultiLineResultSet();
2240    
2241     String[] lnS = rs.getMultiLineResult();
2242     ParameterType type = parseType(lnS);
2243     boolean multi = parseMultiplicity(lnS);
2244     Parameter prm;
2245    
2246     switch(type) {
2247     case BOOL:
2248     if(!multi) prm = new BoolParameter(lnS);
2249     else prm = new BoolListParameter(lnS);
2250     prm.setName(param);
2251     return prm;
2252     case INT:
2253     if(!multi) prm = new IntParameter(lnS);
2254     else prm = new IntListParameter(lnS);
2255     prm.setName(param);
2256     return prm;
2257     case FLOAT:
2258     if(!multi) prm = new FloatParameter(lnS);
2259     else prm = new FloatListParameter(lnS);
2260     prm.setName(param);
2261     return prm;
2262     case STRING:
2263     if(!multi) prm = new StringParameter(lnS);
2264     else prm = new StringListParameter(lnS);
2265     prm.setName(param);
2266     return prm;
2267     default: throw new LscpException(LscpI18n.getLogMsg("Client.unknownPrmType!"));
2268     }
2269     }
2270    
2271     /**
2272     * Alters a specific setting of a MIDI input port.
2273     *
2274 iliev 1139 * @param deviceId The numerical ID of the MIDI device.
2275 iliev 596 * @param port The MIDI port number.
2276     * @param prm A <code>Parameter</code> instance containing the name of the parameter
2277     * and the new value for this parameter.
2278     *
2279     * @throws IOException If some I/O error occurs.
2280     * @throws LscpException If LSCP protocol corruption occurs.
2281     * @throws LSException If
2282     * <ul>
2283 iliev 1139 * <li>There is no MIDI device with numerical ID <code>deviceId</code>;
2284 iliev 596 * <li><code>port</code> is not a valid MIDI port number;
2285     * <li><code>prm</code> is not a valid parameter;
2286     * <li>The parameter is readonly;
2287     * <li>The parameter is from different type.
2288     * </ul>
2289     *
2290     * @see #getMidiInputDevices
2291     * @see #getMidiInputPortInfo
2292     */
2293     public synchronized void
2294 iliev 1139 setMidiInputPortParameter(int deviceId, int port, Parameter prm)
2295 iliev 596 throws IOException, LscpException, LSException {
2296    
2297     verifyConnection();
2298 iliev 1139 String args = deviceId + " " + port + " " +
2299 iliev 596 prm.getName() + '=' + prm.getStringValue();
2300     out.writeLine("SET MIDI_INPUT_PORT_PARAMETER " + args);
2301 iliev 1139 if(getPrintOnlyMode()) return;
2302 iliev 596
2303     ResultSet rs = getEmptyResultSet();
2304     }
2305    
2306     /**
2307 iliev 1139 * Adds a new MIDI instrument map.
2308     * @param name The name of this MIDI instrument map.
2309     * @return The number of the newly MIDI instrument map.
2310     * @throws IOException If some I/O error occurs.
2311     * @throws LSException If the creation of the new MIDI instrument map failed.
2312     * @throws LscpException If LSCP protocol corruption occurs.
2313     * @see #removeMidiInstrumentMap
2314     */
2315     public synchronized int
2316     addMidiInstrumentMap(String name) throws IOException, LSException, LscpException {
2317     verifyConnection();
2318     out.writeLine("ADD MIDI_INSTRUMENT_MAP '" + name + "'");
2319     if(getPrintOnlyMode()) return -1;
2320    
2321     ResultSet rs = getEmptyResultSet();
2322    
2323     return rs.getIndex();
2324     }
2325    
2326     /**
2327     * Removes the specified MIDI instrument map.
2328     * @param mapId The numerical ID of the MIDI instrument map to be removed.
2329     * @throws IOException If some I/O error occurs.
2330     * @throws LscpException If LSCP protocol corruption occurs.
2331     * @throws LSException If the removing of the MIDI instrument map failed.
2332     * @see #addMidiInstrumentMap
2333     * @see #getMidiInstrumentMapIDs
2334     */
2335     public synchronized void
2336     removeMidiInstrumentMap(int mapId) throws IOException, LscpException, LSException {
2337     verifyConnection();
2338     out.writeLine("REMOVE MIDI_INSTRUMENT_MAP " + mapId);
2339     if(getPrintOnlyMode()) return;
2340    
2341     ResultSet rs = getEmptyResultSet();
2342     }
2343    
2344     /**
2345     * Removes the all MIDI instrument maps.
2346     * @throws IOException If some I/O error occurs.
2347     * @throws LscpException If LSCP protocol corruption occurs.
2348     * @throws LSException If the removing of the MIDI instrument maps failed.
2349     */
2350     public synchronized void
2351     removeAllMidiInstrumentMaps() throws IOException, LscpException, LSException {
2352     verifyConnection();
2353     out.writeLine("REMOVE MIDI_INSTRUMENT_MAP ALL");
2354     if(getPrintOnlyMode()) return;
2355    
2356     ResultSet rs = getEmptyResultSet();
2357     }
2358    
2359     /**
2360     * Gets the current number of all MIDI instrument maps.
2361     * @return The current number of all MIDI instrument maps.
2362     * @throws IOException If some I/O error occurs.
2363     * @throws LscpException If LSCP protocol corruption occurs.
2364     * @throws LSException If some other error occurs.
2365     */
2366     public synchronized int
2367     getMidiInstrumentMapCount() throws IOException, LscpException, LSException {
2368     verifyConnection();
2369     out.writeLine("GET MIDI_INSTRUMENT_MAPS");
2370     if(getPrintOnlyMode()) return -1;
2371    
2372     String s = getSingleLineResultSet().getResult();
2373     return parseInt(s);
2374     }
2375    
2376     /**
2377     * Gets a list of numerical IDs of all created MIDI instrument maps.
2378     * @return An <code>Integer</code> array providing the numerical IDs of
2379     * all created MIDI instrument maps.
2380     * @throws IOException If some I/O error occurs.
2381     * @throws LscpException If LSCP protocol corruption occurs.
2382     * @throws LSException If some other error occurs.
2383     * @see #addMidiInstrumentMap
2384     * @see #removeMidiInstrumentMap
2385     */
2386     public synchronized Integer[]
2387     getMidiInstrumentMapIDs() throws IOException, LscpException, LSException {
2388     verifyConnection();
2389     out.writeLine("LIST MIDI_INSTRUMENT_MAPS");
2390     if(getPrintOnlyMode()) return null;
2391    
2392     return parseIntList(getSingleLineResultSet().getResult());
2393     }
2394    
2395     /**
2396     * Gets the current settings of a specific, already created MIDI instrument map.
2397     * @param mapId Specifies the numerical ID of the MIDI instrument map.
2398     * @return A <code>MidiInstrumentMapInfo</code> instance containing information
2399     * about the specified device.
2400     * @throws IOException If some I/O error occurs.
2401     * @throws LscpException If LSCP protocol corruption occurs.
2402     * @throws LSException If there is no MIDI instrument map
2403     * with map id <code>mapId</code>.
2404     * @see #getMidiInstrumentMaps
2405     */
2406     public synchronized MidiInstrumentMapInfo
2407     getMidiInstrumentMapInfo(int mapId) throws IOException, LscpException, LSException {
2408     verifyConnection();
2409     out.writeLine("GET MIDI_INSTRUMENT_MAP INFO " + mapId);
2410     if(getPrintOnlyMode()) return null;
2411    
2412     ResultSet rs = getMultiLineResultSet();
2413    
2414     String[] lnS = rs.getMultiLineResult();
2415    
2416     String name = "";
2417     boolean b = false;
2418    
2419     for(String s : lnS) {
2420     if(s.startsWith("NAME: ")) {
2421     name = s.substring("NAME: ".length());
2422     } else if(s.startsWith("DEFAULT: ")) {
2423     b = Boolean.parseBoolean(s.substring("DEFAULT: ".length()));
2424     } else {
2425     getLogger().info(LscpI18n.getLogMsg("unknownLine", s));
2426     }
2427     }
2428    
2429     return new MidiInstrumentMapInfo(mapId, name, b);
2430     }
2431    
2432     /**
2433     * Gets an information of all created MIDI instrument maps.
2434     * @return A <code>MidiInstrumentMap</code> array
2435     * providing information for all created MIDI instrument maps.
2436     * @throws IOException If some I/O error occurs.
2437     * @throws LscpException If LSCP protocol corruption occurs.
2438     * @throws LSException If some other error occurs.
2439     * @see #addMidiInstrumentMap
2440     * @see #removeMidiInstrumentMap
2441     */
2442     public synchronized MidiInstrumentMapInfo[]
2443     getMidiInstrumentMaps() throws IOException, LscpException, LSException {
2444     Integer[] idS = getMidiInstrumentMapIDs();
2445     if(getPrintOnlyMode()) return null;
2446    
2447     MidiInstrumentMapInfo[] maps = new MidiInstrumentMapInfo[idS.length];
2448    
2449     for(int i = 0; i < maps.length; i++)
2450     maps[i] = getMidiInstrumentMapInfo(idS[i]);
2451    
2452     return maps;
2453     }
2454    
2455     /**
2456     * Sets the name of the specified MIDI instrument map.
2457     * @param mapId The numerical ID of the MIDI instrument map.
2458     * @param name The new name for the specified MIDI instrument map.
2459     * @throws IOException If some I/O error occurs.
2460     * @throws LscpException If LSCP protocol corruption occurs.
2461     * @throws LSException If <code>mapId</code> is not a valid MIDI
2462     * instrument map number or <code>name</code> is not a valid name;
2463     */
2464     public synchronized void
2465     setMidiInstrumentMapName(int mapId, String name)
2466     throws IOException, LscpException, LSException {
2467    
2468     verifyConnection();
2469     out.writeLine("SET MIDI_INSTRUMENT_MAP NAME " + + mapId + " '" + name + "'");
2470     if(getPrintOnlyMode()) return;
2471    
2472     ResultSet rs = getEmptyResultSet();
2473     }
2474    
2475     /**
2476     * Creates or replaces a MIDI instrument map entry.
2477     * @param mapId The ID of the map, where this instrument should be mapped.
2478     * @param entry Specifies the position of the MIDI instrument in the MIDI instrument map.
2479     * @param info Provides the needed information of the
2480     * MIDI instrument, which will be mapped to the specified MIDI instrument map.
2481     * @throws IOException If some I/O error occurs.
2482     * @throws LSException If the mapping failed.
2483     * @throws LscpException If LSCP protocol corruption occurs.
2484     * @see #unmapMidiInstrument
2485     */
2486     public synchronized void
2487     mapMidiInstrument(int mapId, MidiInstrumentEntry entry, MidiInstrumentInfo info)
2488     throws IOException, LSException, LscpException {
2489    
2490     verifyConnection();
2491     StringBuffer cmd = new StringBuffer("MAP MIDI_INSTRUMENT ");
2492     cmd.append(mapId).append(' ');
2493     cmd.append(entry.getMidiBank()).append(' ');
2494     cmd.append(entry.getMidiProgram()).append(' ');
2495     cmd.append(info.getEngine()).append(" '");
2496     cmd.append(info.getFileName()).append("' ");
2497     cmd.append(info.getInstrumentIndex()).append(' ');
2498     cmd.append(info.getVolume());
2499     if(!info.getLoadMode().name().equals("DEFAULT")) {
2500     cmd.append(' ').append(info.getLoadMode().name());
2501     }
2502     if(info.getName() != null) cmd.append(" '").append(info.getName()).append("'");
2503    
2504     out.writeLine(cmd.toString());
2505     if(getPrintOnlyMode()) return;
2506    
2507     ResultSet rs = getEmptyResultSet();
2508     }
2509    
2510     /**
2511     * Removes an entry MIDI instrument map.
2512     * @param mapId The ID of the map, from which
2513     * the specified MIDI instrument should be removed.
2514     * @param entry The entry to remove from the specified MIDI instrument map.
2515     * @throws IOException If some I/O error occurs.
2516     * @throws LSException If the unmapping failed.
2517     * @throws LscpException If LSCP protocol corruption occurs.
2518     * @see #mapMidiInstrument
2519     */
2520     public synchronized void
2521     unmapMidiInstrument(int mapId, MidiInstrumentEntry entry)
2522     throws IOException, LSException, LscpException {
2523    
2524     verifyConnection();
2525     StringBuffer cmd = new StringBuffer("UNMAP MIDI_INSTRUMENT ");
2526     cmd.append(mapId).append(' ');
2527     cmd.append(entry.getMidiBank()).append(' ');
2528     cmd.append(entry.getMidiProgram());
2529    
2530     out.writeLine(cmd.toString());
2531     if(getPrintOnlyMode()) return;
2532    
2533     ResultSet rs = getEmptyResultSet();
2534     }
2535    
2536     /**
2537     * Gets the current number of all MIDI instrument in all maps.
2538     * @return The current number of all MIDI instrument in all maps.
2539     * @throws IOException If some I/O error occurs.
2540     * @throws LscpException If LSCP protocol corruption occurs.
2541     * @throws LSException If some other error occurs.
2542     */
2543     public synchronized int
2544     getMidiInstrumentCount() throws IOException, LscpException, LSException {
2545     verifyConnection();
2546     out.writeLine("GET MIDI_INSTRUMENTS ALL");
2547     if(getPrintOnlyMode()) return -1;
2548    
2549     String s = getSingleLineResultSet().getResult();
2550     return parseInt(s);
2551     }
2552    
2553     /**
2554     * Gets the current number of MIDI instrument in the specified map.
2555     * @param mapId The ID of the map.
2556     * @return The current number of MIDI instrument in the specified map.
2557     * @throws IOException If some I/O error occurs.
2558     * @throws LscpException If LSCP protocol corruption occurs.
2559     * @throws LSException If some other error occurs.
2560     */
2561     public synchronized int
2562     getMidiInstrumentCount(int mapId) throws IOException, LscpException, LSException {
2563     verifyConnection();
2564     out.writeLine("GET MIDI_INSTRUMENTS " + String.valueOf(mapId));
2565     if(getPrintOnlyMode()) return -1;
2566    
2567     String s = getSingleLineResultSet().getResult();
2568     return parseInt(s);
2569     }
2570    
2571     /**
2572     * Gets all MIDI instrument from all maps.
2573     * @return A <code>MidiInstrumentInfo</code> array providing
2574     * all MIDI instruments from all MIDI instrument maps.
2575     * @throws IOException If some I/O error occurs.
2576     * @throws LscpException If LSCP protocol corruption occurs.
2577     * @throws LSException If some other error occurs.
2578     */
2579     public synchronized MidiInstrumentInfo[]
2580     getMidiInstruments() throws IOException, LscpException, LSException {
2581     verifyConnection();
2582     out.writeLine("LIST MIDI_INSTRUMENTS ALL");
2583     if(getPrintOnlyMode()) return null;
2584    
2585     String[] entries = parseArray(getSingleLineResultSet().getResult());
2586    
2587     return getMidiInstruments(entries);
2588     }
2589    
2590     /**
2591     * Gets all MIDI instrument contained int the specified MIDI instrument map.
2592     * @param mapId The ID of the map, which instruments should be obtained.
2593     * @return A <code>MidiInstrumentInfo</code> array providing
2594     * all MIDI instruments from all MIDI instrument maps.
2595     * @throws IOException If some I/O error occurs.
2596     * @throws LscpException If LSCP protocol corruption occurs.
2597     * @throws LSException If some other error occurs.
2598     */
2599     public synchronized MidiInstrumentInfo[]
2600     getMidiInstruments(int mapId) throws IOException, LscpException, LSException {
2601     verifyConnection();
2602     out.writeLine("LIST MIDI_INSTRUMENTS " + String.valueOf(mapId));
2603     if(getPrintOnlyMode()) return null;
2604    
2605     String[] entries = parseArray(getSingleLineResultSet().getResult());
2606    
2607     return getMidiInstruments(entries);
2608     }
2609    
2610     private MidiInstrumentInfo[]
2611     getMidiInstruments(String[] entries) throws IOException, LscpException, LSException {
2612     Vector<MidiInstrumentInfo> v = new Vector<MidiInstrumentInfo>();
2613    
2614     for(String s : entries) {
2615     Integer[] vals = parseIntList(s);
2616     if(vals.length != 3) {
2617     throw new LscpException(LscpI18n.getLogMsg("CommandFailed!"));
2618     }
2619    
2620     v.add(getMidiInstrumentInfo(vals[0], vals[1], vals[2]));
2621     }
2622    
2623     return v.toArray(new MidiInstrumentInfo[v.size()]);
2624     }
2625    
2626     /**
2627     * Gets the current settings of the specified MIDI instrument.
2628     * @param mapId The ID of the map.
2629     * @param bank The index of the MIDI bank.
2630     * @param program The MIDI program number of the instrument.
2631     * @return <code>MidiInstrumentInfo</code> instance containing
2632     * the current settings of the specified MIDI instrument.
2633     * @throws IOException If an I/O error occurs.
2634     * @throws LscpException If LSCP protocol corruption occurs.
2635     * @throws LSException If the specified MIDI instrument is missing.
2636     */
2637     public synchronized MidiInstrumentInfo
2638     getMidiInstrumentInfo(int mapId, int bank, int program)
2639     throws IOException, LscpException, LSException {
2640    
2641     verifyConnection();
2642     StringBuffer cmd = new StringBuffer("GET MIDI_INSTRUMENT INFO ");
2643     cmd.append(mapId).append(' ');
2644     cmd.append(bank).append(' ');
2645     cmd.append(program);
2646    
2647     out.writeLine(cmd.toString());
2648     if(getPrintOnlyMode()) return null;
2649    
2650     ResultSet rs = getMultiLineResultSet();
2651     MidiInstrumentEntry entry = new MidiInstrumentEntry(bank, program);
2652     return new MidiInstrumentInfo(mapId, entry, rs.getMultiLineResult());
2653     }
2654    
2655     /**
2656 iliev 596 * Loads and assigns an instrument to a sampler channel. Notice that this function will
2657     * return after the instrument is fully loaded and the channel is ready to be used.
2658     * @param filename The name of the instrument file
2659     * on the LinuxSampler instance's host system.
2660     * @param instrIdx The index of the instrument in the instrument file.
2661     * @param samplerChn The number of the sampler channel the instrument should be assigned to.
2662     * @throws IOException If some I/O error occurs.
2663     * @throws LscpException If LSCP protocol corruption occurs.
2664     * @throws LSException If the loading of the instrument failed.
2665     * @see #loadInstrument(String, int, int, boolean)
2666     * @see #getSamplerChannels
2667     */
2668     public synchronized void
2669     loadInstrument(String filename, int instrIdx, int samplerChn)
2670     throws IOException, LscpException, LSException {
2671    
2672     verifyConnection();
2673     loadInstrument(filename, instrIdx, samplerChn, false);
2674     }
2675    
2676     /**
2677     * Loads and assigns an instrument to a sampler channel.
2678     *
2679     * @param filename The name of the instrument file
2680     * on the LinuxSampler instance's host system.
2681     * @param instrIdx The index of the instrument in the instrument file.
2682     * @param samplerChn The number of the sampler channel the instrument should be assigned to.
2683     * @param nonModal If <code>false</code> the function will return after the instrument
2684     * has been fully loaded and the channel is ready to be used. If <code>true</code>
2685     * the function returns immediately.
2686     *
2687     * @throws IOException If some I/O error occurs.
2688     * @throws LscpException If LSCP protocol corruption occurs.
2689     * @throws LSException If the loading of the instrument failed.
2690     *
2691     * @see #loadInstrument(String, int, int)
2692     * @see #getSamplerChannels
2693     */
2694     public synchronized void
2695     loadInstrument(String filename, int instrIdx, int samplerChn, boolean nonModal)
2696     throws IOException, LscpException, LSException {
2697    
2698     String cmd = nonModal ? "LOAD INSTRUMENT NON_MODAL " : "LOAD INSTRUMENT ";
2699     String args = '\'' + filename + "' " + instrIdx + ' ' + samplerChn;
2700    
2701     out.writeLine(cmd + args);
2702 iliev 1139 if(getPrintOnlyMode()) return;
2703 iliev 596
2704     ResultSet rs = getEmptyResultSet();
2705     }
2706    
2707     /**
2708     * Loads a sampler engine to a specific sampler channel.
2709     * @param engineName The name of the engine.
2710     * @param samplerChn The number of the sampler channel
2711     * the deployed engine should be assigned to.
2712     *
2713     * @throws IOException If some I/O error occurs.
2714     * @throws LscpException If LSCP protocol corruption occurs.
2715     * @throws LSException If the loading of the sampler engine failed.
2716     * @see #getEngines
2717     * @see #getSamplerChannels
2718     */
2719     public synchronized void
2720     loadSamplerEngine(String engineName, int samplerChn)
2721     throws IOException, LscpException, LSException {
2722    
2723     verifyConnection();
2724     out.writeLine("LOAD ENGINE " + engineName + ' ' + samplerChn);
2725 iliev 1139 if(getPrintOnlyMode()) return;
2726 iliev 596
2727     ResultSet rs = getEmptyResultSet();
2728     }
2729    
2730     /**
2731     * Gets the current number of all created sampler channels.
2732     * @return The current number of all created sampler channels.
2733     * @throws IOException If some I/O error occurs.
2734     * @throws LscpException If LSCP protocol corruption occurs.
2735     * @throws LSException If some other error occurs.
2736     */
2737     public synchronized int
2738     getSamplerChannelCount() throws IOException, LscpException, LSException {
2739     verifyConnection();
2740     out.writeLine("GET CHANNELS");
2741 iliev 1139 if(getPrintOnlyMode()) return -1;
2742    
2743 iliev 596 String s = getSingleLineResultSet().getResult();
2744     return parseInt(s);
2745     }
2746    
2747     /**
2748 iliev 784 * Gets a list of all created sampler channels.
2749     * @return A <code>SamplerChannel</code> array providing all created sampler channels.
2750     * @throws IOException If some I/O error occurs.
2751     * @throws LscpException If LSCP protocol corruption occurs.
2752     * @throws LSException If some other error occurs.
2753     * @see #addSamplerChannel
2754     * @see #removeSamplerChannel
2755     */
2756     public synchronized SamplerChannel[]
2757     getSamplerChannels() throws IOException, LscpException, LSException {
2758     Integer[] idS = getSamplerChannelIDs();
2759 iliev 1139 if(getPrintOnlyMode()) return null;
2760    
2761 iliev 784 SamplerChannel[] channels = new SamplerChannel[idS.length];
2762    
2763     for(int i = 0; i < channels.length; i++)
2764     channels[i] = getSamplerChannelInfo(idS[i]);
2765    
2766     return channels;
2767     }
2768    
2769     /**
2770 iliev 596 * Gets a list with numerical IDs of all created sampler channels.
2771 iliev 784 * @return An <code>Integer</code> array providing
2772     * the numerical IDs of all created sampler channels.
2773 iliev 596 * @throws IOException If some I/O error occurs.
2774     * @throws LscpException If LSCP protocol corruption occurs.
2775     * @throws LSException If some other error occurs.
2776     * @see #addSamplerChannel
2777     * @see #removeSamplerChannel
2778     */
2779     public synchronized Integer[]
2780 iliev 784 getSamplerChannelIDs() throws IOException, LscpException, LSException {
2781 iliev 596 verifyConnection();
2782     out.writeLine("LIST CHANNELS");
2783 iliev 1139 if(getPrintOnlyMode()) return null;
2784    
2785 iliev 596 return parseIntList(getSingleLineResultSet().getResult());
2786     }
2787    
2788     /**
2789     * Adds a new sampler channel. This method will increment the sampler channel count by one
2790     * and the new sampler channel will be appended to the end of the sampler channel list.
2791     *
2792     * @return The number of the newly created sampler channel.
2793     * @throws IOException If some I/O error occurs.
2794     * @throws LSException If the creation of the new sampler channel failed.
2795     * @throws LscpException If LSCP protocol corruption occurs.
2796     * @see #removeSamplerChannel
2797     */
2798     public synchronized int
2799     addSamplerChannel() throws IOException, LSException, LscpException {
2800     verifyConnection();
2801     out.writeLine("ADD CHANNEL");
2802 iliev 1139 if(getPrintOnlyMode()) return -1;
2803    
2804 iliev 596 ResultSet rs = getEmptyResultSet();
2805    
2806     return rs.getIndex();
2807     }
2808    
2809     /**
2810     * Removes the specified sampler channel.
2811     *
2812     * @param samplerChn The numerical ID of the sampler channel to be removed.
2813     *
2814     * @throws IOException If some I/O error occurs.
2815     * @throws LscpException If LSCP protocol corruption occurs.
2816     * @throws LSException If the removing of the sampler channel failed.
2817     * @see #addSamplerChannel
2818     * @see #getSamplerChannels
2819     */
2820     public synchronized void
2821     removeSamplerChannel(int samplerChn) throws IOException, LscpException, LSException {
2822     verifyConnection();
2823     out.writeLine("REMOVE CHANNEL " + samplerChn);
2824 iliev 1139 if(getPrintOnlyMode()) return;
2825 iliev 596
2826     ResultSet rs = getEmptyResultSet();
2827     }
2828    
2829     /**
2830     * Gets the number of all available engines.
2831     * @return The number of all available engines.
2832     * @throws IOException If some I/O error occurs.
2833     * @throws LscpException If LSCP protocol corruption occurs.
2834     * @throws LSException If some other error occurs.
2835     */
2836     public synchronized int
2837     getEngineCount() throws IOException, LscpException, LSException {
2838     verifyConnection();
2839     out.writeLine("GET AVAILABLE_ENGINES");
2840 iliev 1139 if(getPrintOnlyMode()) return -1;
2841    
2842 iliev 596 String s = getSingleLineResultSet().getResult();
2843     return parseInt(s);
2844     }
2845    
2846     /**
2847 iliev 671 * Gets a list of all available engines.
2848     *
2849     * @return <code>SamplerEngine</code> array containing all available engines.
2850     * @throws IOException If some I/O error occurs.
2851     * @throws LscpException If LSCP protocol corruption occurs.
2852     * @throws LSException If some other error occurs.
2853     */
2854     public synchronized SamplerEngine[]
2855     getEngines() throws IOException, LscpException, LSException {
2856     String[] engines = getEngineNames();
2857 iliev 1139 if(getPrintOnlyMode()) return null;
2858    
2859 iliev 671 SamplerEngine[] se = new SamplerEngine[engines.length];
2860    
2861     for(int i = 0; i < engines.length; i++) se[i] = getEngineInfo(engines[i]);
2862    
2863     return se;
2864     }
2865    
2866     /**
2867 iliev 596 * Gets a list of all available engines' names.
2868     *
2869     * @return <code>String</code> array with all available engines' names.
2870     * @throws IOException If some I/O error occurs.
2871     * @throws LscpException If LSCP protocol corruption occurs.
2872     * @throws LSException If some other error occurs.
2873     */
2874 iliev 671 private synchronized String[]
2875     getEngineNames() throws IOException, LscpException, LSException {
2876 iliev 596 verifyConnection();
2877     out.writeLine("LIST AVAILABLE_ENGINES");
2878 iliev 1139 if(getPrintOnlyMode()) return null;
2879    
2880 iliev 596 return parseStringList(getSingleLineResultSet().getResult());
2881     }
2882    
2883     /**
2884     * Gets information about a specific sampler engine.
2885     * @param engineName The name of the sampler engine.
2886     *
2887     * @return <code>SamplerEngine</code> instance containing
2888     * information about the specified sampler engine.
2889     *
2890     * @throws IOException If an I/O error occurs.
2891     * @throws LscpException If LSCP protocol corruption occurs.
2892     * @throws LSException If there is no sampler engine with name <code>engineName</code>.
2893 iliev 671 * @see #getEngineNames
2894 iliev 596 */
2895 iliev 671 private synchronized SamplerEngine
2896 iliev 596 getEngineInfo(String engineName) throws IOException, LscpException, LSException {
2897     verifyConnection();
2898     out.writeLine("GET ENGINE INFO " + engineName);
2899 iliev 1139 if(getPrintOnlyMode()) return null;
2900    
2901 iliev 596 ResultSet rs = getMultiLineResultSet();
2902     SamplerEngine se = new SamplerEngine(rs.getMultiLineResult());
2903     se.setName(engineName);
2904     return se;
2905     }
2906    
2907     /**
2908     * Gets the current settings of the specified sampler channel.
2909     * @param samplerChn The sampler channel number.
2910     *
2911     * @return <code>SamplerChannel</code> instance containing
2912     * the current settings of the specified sampler channel.
2913     *
2914     * @throws IOException If an I/O error occurs.
2915     * @throws LscpException If LSCP protocol corruption occurs.
2916     * @throws LSException If there is no sampler channel with <code>samplerChn</code> number.
2917     * @see #getSamplerChannels
2918     */
2919     public synchronized SamplerChannel
2920     getSamplerChannelInfo(int samplerChn) throws IOException, LscpException, LSException {
2921     verifyConnection();
2922     out.writeLine("GET CHANNEL INFO " + samplerChn);
2923 iliev 1139 if(getPrintOnlyMode()) return null;
2924    
2925 iliev 596 ResultSet rs = getMultiLineResultSet();
2926     SamplerChannel sc = new SamplerChannel(rs.getMultiLineResult());
2927 iliev 1139 sc.setChannelId(samplerChn);
2928 iliev 784 if(sc.getEngine() != null) sc.setEngine(getEngineInfo(sc.getEngine().getName()));
2929 iliev 596
2930     return sc;
2931     }
2932    
2933     /**
2934     * Gets the current number of active voices on the specified sampler channel.
2935     *
2936     * @param samplerChn The sampler channel number.
2937     * @return The current number of active voices on the specified sampler channel.
2938     * @throws IOException If some I/O error occurs.
2939     * @throws LscpException If LSCP protocol corruption occurs.
2940     * @throws LSException If there is no sampler channel with number <code>samplerChn</code>.
2941     * @see #getSamplerChannels
2942     */
2943     public synchronized int
2944     getChannelVoiceCount(int samplerChn) throws IOException, LscpException, LSException {
2945     verifyConnection();
2946     out.writeLine("GET CHANNEL VOICE_COUNT " + samplerChn);
2947 iliev 1139 if(getPrintOnlyMode()) return -1;
2948    
2949 iliev 596 ResultSet rs = getSingleLineResultSet();
2950    
2951     return parseInt(rs.getResult());
2952     }
2953    
2954     /**
2955     * Gets the current number of active disk streams on the specified sampler channel.
2956     *
2957     * @param samplerChn The sampler channel number.
2958     * @return The current number of active disk streams on the specified sampler channel
2959     * or -1 if the engine doesn't support disk streaming.
2960     * @throws IOException If some I/O error occurs.
2961     * @throws LscpException If LSCP protocol corruption occurs.
2962     * @throws LSException If there is no sampler channel with number <code>samplerChn</code>.
2963     * @see #getSamplerChannels
2964     */
2965     public synchronized int
2966     getChannelStreamCount(int samplerChn) throws IOException, LscpException, LSException {
2967     verifyConnection();
2968     out.writeLine("GET CHANNEL STREAM_COUNT " + samplerChn);
2969 iliev 1139 if(getPrintOnlyMode()) return -1;
2970    
2971 iliev 596 ResultSet rs = getSingleLineResultSet();
2972    
2973     if(rs.getResult().equals("NA")) return -1;
2974    
2975     return parseInt(rs.getResult());
2976     }
2977    
2978     /**
2979     * Gets the current fill state of all disk streams on the specified sampler channel
2980     * in bytes.
2981     *
2982     * @param samplerChn The sampler channel number.
2983     * @return The current fill state of all disk streams on the specified sampler channel
2984     * or <code>null</code> if the engine which is deployed doesn't support disk streaming.
2985     * @throws IOException If some I/O error occurs.
2986     * @throws LscpException If LSCP protocol corruption occurs.
2987     * @throws LSException If there is no sampler channel with number <code>samplerChn</code>.
2988     * @see #getChannelBufferFillPercentage
2989     * @see #getSamplerChannels
2990     */
2991     public synchronized Vector<BufferFill>
2992     getChannelBufferFillBytes(int samplerChn) throws IOException, LscpException, LSException {
2993     verifyConnection();
2994     out.writeLine("GET CHANNEL BUFFER_FILL BYTES " + samplerChn);
2995 iliev 1139 if(getPrintOnlyMode()) return null;
2996    
2997 iliev 596 ResultSet rs = getSingleLineResultSet();
2998    
2999     if(rs.getResult().equals("NA")) return null;
3000    
3001     Vector<BufferFill> v = new Vector<BufferFill>();
3002     String[] args = parseList(rs.getResult());
3003    
3004     for(String s : args) {
3005     if(s.charAt(0) != '[')
3006     throw new LscpException(LscpI18n.getLogMsg("CommandFailed!"));
3007    
3008     int i = s.indexOf(']');
3009     if(i == -1) throw new LscpException(LscpI18n.getLogMsg("CommandFailed!"));
3010    
3011     BufferFill bf = new BufferFill();
3012 iliev 1139 bf.setStreamId(parseInt(s.substring(1, i)));
3013 iliev 596 bf.setValue(parseInt(s.substring(i + 1)));
3014     v.add(bf);
3015     }
3016    
3017     return v;
3018     }
3019    
3020     /**
3021     * Gets the current fill state of all disk streams on the specified sampler channel
3022     * in percent.
3023     *
3024     * @param samplerChn The sampler channel number.
3025     * @return The current fill state of all disk streams on the specified sampler channel
3026     * or <code>null</code> if the engine which is deployed doesn't support disk streaming.
3027     * @throws IOException If some I/O error occurs.
3028     * @throws LscpException If LSCP protocol corruption occurs.
3029     * @throws LSException If there is no sampler channel with number <code>samplerChn</code>.
3030     * @see #getChannelBufferFillBytes
3031     * @see #getSamplerChannels
3032     */
3033     public synchronized Vector<BufferFill>
3034     getChannelBufferFillPercentage(int samplerChn)
3035     throws IOException, LscpException, LSException {
3036    
3037     verifyConnection();
3038     out.writeLine("GET CHANNEL BUFFER_FILL PERCENTAGE " + samplerChn);
3039 iliev 1139 if(getPrintOnlyMode()) return null;
3040    
3041 iliev 596 ResultSet rs = getSingleLineResultSet();
3042    
3043     return getChannelBufferFillPercentage(rs.getResult());
3044     }
3045    
3046     private Vector<BufferFill>
3047     getChannelBufferFillPercentage(String ln) throws LscpException {
3048     if(ln.equals("NA")) return null;
3049    
3050     Vector<BufferFill> v = new Vector<BufferFill>();
3051     String[] args = parseList(ln);
3052    
3053     for(String s : args) {
3054     if(s.charAt(0) != '[')
3055     throw new LscpException(LscpI18n.getLogMsg("CommandFailed!"));
3056    
3057     int i = s.indexOf(']');
3058     if(i == -1) throw new LscpException(LscpI18n.getLogMsg("CommandFailed!"));
3059    
3060     if(s.charAt(s.length() - 1) != '%')
3061     throw new LscpException(LscpI18n.getLogMsg("CommandFailed!"));
3062    
3063     BufferFill bf = new BufferFill();
3064 iliev 1139 bf.setStreamId(parseInt(s.substring(1, i)));
3065 iliev 596 bf.setValue(parseInt(s.substring(i + 1, s.length() - 1)));
3066     v.add(bf);
3067     }
3068    
3069     return v;
3070     }
3071    
3072     /**
3073     * Sets the audio output device on the specified sampler channel.
3074     *
3075     * @param samplerChn The sampler channel number.
3076 iliev 1139 * @param devId The numerical ID of the audio output device.
3077 iliev 596 *
3078     * @throws IOException If some I/O error occurs.
3079     * @throws LscpException If LSCP protocol corruption occurs.
3080     * @throws LSException If
3081     * <ul>
3082     * <li><code>samplerChn</code> is not a valid channel number;
3083 iliev 1139 * <li><code>devId</code> is not a valid audio output device ID;
3084 iliev 596 * </ul>
3085     *
3086     * @see #getSamplerChannels
3087     * @see #getAudioOutputDevices
3088     */
3089     public synchronized void
3090 iliev 1139 setChannelAudioOutputDevice(int samplerChn, int devId)
3091 iliev 596 throws IOException, LscpException, LSException {
3092    
3093     verifyConnection();
3094 iliev 1139 out.writeLine("SET CHANNEL AUDIO_OUTPUT_DEVICE " + samplerChn + ' ' + devId);
3095     if(getPrintOnlyMode()) return;
3096 iliev 596
3097     ResultSet rs = getEmptyResultSet();
3098     }
3099    
3100     /**
3101     * Sets the audio output channel on the specified sampler channel.
3102     *
3103     * @param samplerChn The sampler channel number.
3104     * @param audioOut The sampler channel's audio output channel which should be rerouted.
3105     * @param audioIn The audio channel of the selected audio output device
3106     * where <code>audioOut</code> should be routed to.
3107     *
3108     * @throws IOException If some I/O error occurs.
3109     * @throws LscpException If LSCP protocol corruption occurs.
3110     * @throws LSException If
3111     * <ul>
3112     * <li><code>samplerChn</code> is not a valid channel number;
3113     * <li>There is no engine assigned yet to the specified sampler channel.
3114     * <li> There is no audio output device connected to the specified sampler channel.
3115     * </ul>
3116     *
3117     * @see #getSamplerChannels
3118     */
3119     public synchronized void
3120     setChannelAudioOutputChannel(int samplerChn, int audioOut, int audioIn)
3121     throws IOException, LscpException, LSException {
3122    
3123     verifyConnection();
3124     String args = " " + samplerChn + ' ' + audioOut + ' ' + audioIn;
3125     out.writeLine("SET CHANNEL AUDIO_OUTPUT_CHANNEL" + args);
3126 iliev 1139 if(getPrintOnlyMode()) return;
3127 iliev 596
3128     ResultSet rs = getEmptyResultSet();
3129     }
3130    
3131     /**
3132     * Sets the MIDI input device on the specified sampler channel.
3133     *
3134     * @param samplerChn The sampler channel number.
3135 iliev 1139 * @param devId The numerical ID of the MIDI input device.
3136 iliev 596 *
3137     * @throws IOException If some I/O error occurs.
3138     * @throws LscpException If LSCP protocol corruption occurs.
3139     * @throws LSException If
3140     * <ul>
3141     * <li><code>samplerChn</code> is not a valid channel number;
3142 iliev 1139 * <li><code>devId</code> is not a valid MIDI input device ID;
3143 iliev 596 * </ul>
3144     *
3145     * @see #getSamplerChannels
3146     * @see #getMidiInputDevices
3147     */
3148     public synchronized void
3149 iliev 1139 setChannelMidiInputDevice(int samplerChn, int devId)
3150 iliev 596 throws IOException, LscpException, LSException {
3151    
3152     verifyConnection();
3153 iliev 1139 out.writeLine("SET CHANNEL MIDI_INPUT_DEVICE " + samplerChn + ' ' + devId);
3154     if(getPrintOnlyMode()) return;
3155 iliev 596
3156     ResultSet rs = getEmptyResultSet();
3157     }
3158    
3159     /**
3160     * Sets the MIDI input port on the specified sampler channel.
3161     *
3162     * @param samplerChn The sampler channel number.
3163     * @param port The MIDI input port number of
3164     * the MIDI input device connected to the specified sampler channel.
3165     *
3166     * @throws IOException If some I/O error occurs.
3167     * @throws LscpException If LSCP protocol corruption occurs.
3168     * @throws LSException If <code>samplerChn</code> is not a valid channel number.
3169     * @see #getSamplerChannels
3170     */
3171     public synchronized void
3172     setChannelMidiInputPort(int samplerChn, int port)
3173     throws IOException, LscpException, LSException {
3174    
3175     verifyConnection();
3176     out.writeLine("SET CHANNEL MIDI_INPUT_PORT " + samplerChn + ' ' + port);
3177 iliev 1139 if(getPrintOnlyMode()) return;
3178 iliev 596
3179     ResultSet rs = getEmptyResultSet();
3180     }
3181    
3182     /**
3183     * Sets the MIDI input channel the specified sampler channel should listen to.
3184     *
3185     * @param samplerChn The sampler channel number.
3186     * @param midiChn The number of the new MIDI input channel where
3187     * <code>samplerChn</code> should listen to or -1 to listen on all 16 MIDI channels.
3188     *
3189     * @throws IOException If some I/O error occurs.
3190     * @throws LscpException If LSCP protocol corruption occurs.
3191     * @throws LSException If <code>samplerChn</code> is not a valid channel number.
3192     * @see #getSamplerChannels
3193     */
3194     public synchronized void
3195     setChannelMidiInputChannel(int samplerChn, int midiChn)
3196     throws IOException, LscpException, LSException {
3197    
3198     verifyConnection();
3199     String args = String.valueOf(samplerChn) + ' ';
3200     args += (midiChn == -1 ? "ALL" : String.valueOf(midiChn));
3201     out.writeLine("SET CHANNEL MIDI_INPUT_CHANNEL " + args);
3202 iliev 1139 if(getPrintOnlyMode()) return;
3203 iliev 596
3204     ResultSet rs = getEmptyResultSet();
3205     }
3206    
3207     /**
3208 iliev 1139 * Sets the MIDI instrument map to be used on the specified sampler channel.
3209     *
3210     * @param samplerChn The sampler channel number.
3211     * @param mapId Specifies the numerical ID of the MIDI instrument
3212     * map to assign. To remove the current map binding use <code>-1</code>.
3213     * To set the current map to be the default map use <code>-2</code>.
3214     *
3215     * @throws IOException If some I/O error occurs.
3216     * @throws LscpException If LSCP protocol corruption occurs.
3217     * @throws LSException If
3218     * <ul>
3219     * <li><code>samplerChn</code> is not a valid channel number;
3220     * <li><code>mapId</code> is not a valid MIDI instrument map ID;
3221     * </ul>
3222     *
3223     * @see #getSamplerChannels
3224     * @see #getMidiInstrumentMaps
3225     */
3226     public synchronized void
3227     setChannelMidiInstrumentMap(int samplerChn, int mapId)
3228     throws IOException, LscpException, LSException {
3229    
3230     verifyConnection();
3231     String s;
3232     if(mapId == -1) {
3233     s = " NONE";
3234     } else if(mapId == -2) {
3235     s = " DEFAULT";
3236     } else {
3237     s = " " + String.valueOf(mapId);
3238     }
3239     out.writeLine("SET CHANNEL MIDI_INSTRUMENT_MAP " + samplerChn + s);
3240     if(getPrintOnlyMode()) return;
3241    
3242     ResultSet rs = getEmptyResultSet();
3243     }
3244    
3245     /**
3246 iliev 596 * Sets the volume of the specified sampler channel.
3247     *
3248     * @param samplerChn The sampler channel number.
3249     * @param volume The new volume value.
3250     *
3251     * @throws IOException If some I/O error occurs.
3252     * @throws LscpException If LSCP protocol corruption occurs.
3253     * @throws LSException If <code>samplerChn</code> is not a valid channel number or if
3254     * there is no engine assigned yet to the specified sampler channel.
3255     * @see #getSamplerChannels
3256     */
3257     public synchronized void
3258     setChannelVolume(int samplerChn, float volume)
3259     throws IOException, LscpException, LSException {
3260    
3261     verifyConnection();
3262     out.writeLine("SET CHANNEL VOLUME " + samplerChn + ' ' + volume);
3263 iliev 1139 if(getPrintOnlyMode()) return;
3264 iliev 596
3265     ResultSet rs = getEmptyResultSet();
3266     }
3267    
3268     /**
3269 iliev 784 * Mute/unmute the specified sampler channel.
3270     *
3271     * @param samplerChn The sampler channel number.
3272     * @param mute If <code>true</code> the specified channel is muted, else the channel
3273     * is unmuted.
3274     *
3275     * @throws IOException If some I/O error occurs.
3276     * @throws LscpException If LSCP protocol corruption occurs.
3277     * @throws LSException If <code>samplerChn</code> is not a valid channel number or if
3278     * there is no engine assigned yet to the specified sampler channel.
3279     * @see #getSamplerChannels
3280     */
3281     public synchronized void
3282     setChannelMute(int samplerChn, boolean mute)
3283     throws IOException, LscpException, LSException {
3284    
3285     verifyConnection();
3286     out.writeLine("SET CHANNEL MUTE " + samplerChn + ' ' + (mute ? 1 : 0));
3287 iliev 1139 if(getPrintOnlyMode()) return;
3288 iliev 784
3289     ResultSet rs = getEmptyResultSet();
3290     }
3291    
3292     /**
3293     * Solo/unsolo the specified sampler channel.
3294     *
3295     * @param samplerChn The sampler channel number.
3296     * @param solo <code>true</code> to solo the specified channel, <code>false</code>
3297     * otherwise.
3298     *
3299     * @throws IOException If some I/O error occurs.
3300     * @throws LscpException If LSCP protocol corruption occurs.
3301     * @throws LSException If <code>samplerChn</code> is not a valid channel number or if
3302     * there is no engine assigned yet to the specified sampler channel.
3303     * @see #getSamplerChannels
3304     */
3305     public synchronized void
3306     setChannelSolo(int samplerChn, boolean solo)
3307     throws IOException, LscpException, LSException {
3308    
3309     verifyConnection();
3310     out.writeLine("SET CHANNEL SOLO " + samplerChn + ' ' + (solo ? 1 : 0));
3311 iliev 1139 if(getPrintOnlyMode()) return;
3312 iliev 784
3313     ResultSet rs = getEmptyResultSet();
3314     }
3315    
3316     /**
3317 iliev 1139 * Creates an additional effect send on the specified sampler channel.
3318     * @param channel The sampler channel, on which a new effect send should be added.
3319     * @param midiCtrl Defines the MIDI controller, which
3320     * will be able alter the effect send level.
3321     * @return The unique ID of the newly created effect send entity.
3322     * @throws IOException If some I/O error occurs.
3323     * @throws LSException If the creation of the effect send failed.
3324     * @throws LscpException If LSCP protocol corruption occurs.
3325     * @see #destroyFxSend
3326     */
3327     public synchronized int
3328     createFxSend(int channel, int midiCtrl)
3329     throws IOException, LSException, LscpException {
3330    
3331     return createFxSend(channel, midiCtrl, null);
3332     }
3333    
3334     /**
3335     * Creates an additional effect send on the specified sampler channel.
3336     * @param channel The sampler channel, on which the effect send should be created on.
3337     * @param midiCtrl Defines the MIDI controller, which can alter the effect send level.
3338     * @param name The name of the effect send entity. The name does not have to be unique.
3339     * @return The unique ID of the newly created effect send entity.
3340     * @throws IOException If some I/O error occurs.
3341     * @throws LSException If the creation of the effect send failed.
3342     * @throws LscpException If LSCP protocol corruption occurs.
3343     * @see #destroyFxSend
3344     */
3345     public synchronized int
3346     createFxSend(int channel, int midiCtrl, String name)
3347     throws IOException, LSException, LscpException {
3348    
3349     verifyConnection();
3350     String s = String.valueOf(channel) + " " + String.valueOf(midiCtrl);
3351     if(name != null) s += " '" + name + "'";
3352     out.writeLine("CREATE FX_SEND " + s);
3353     if(getPrintOnlyMode()) return -1;
3354    
3355     ResultSet rs = getEmptyResultSet();
3356    
3357     return rs.getIndex();
3358     }
3359    
3360     /**
3361     * Destroys the specified effect send on the specified sampler channel.
3362     * @param channel The sampler channel, from which
3363     * the specified effect send should be removed.
3364     * @param fxSend The ID of the effect send that should be removed.
3365     * @throws LSException If some other error occurs.
3366     * @throws LscpException If LSCP protocol corruption occurs.
3367     * @see #createFxSend
3368     */
3369     public synchronized void
3370     destroyFxSend(int channel, int fxSend)
3371     throws IOException, LSException, LscpException {
3372    
3373     verifyConnection();
3374     String s = String.valueOf(channel) + " " + String.valueOf(fxSend);
3375     out.writeLine("DESTROY FX_SEND " + s);
3376     if(getPrintOnlyMode()) return;
3377    
3378     ResultSet rs = getEmptyResultSet();
3379     }
3380    
3381     /**
3382     * Gets the current number of effect sends on the specified sampler channel.
3383     * @param channel The ID of the sampler channel.
3384     * @return The current number of effect sends on the specified sampler channels.
3385     * @throws IOException If some I/O error occurs.
3386     * @throws LscpException If LSCP protocol corruption occurs.
3387     * @throws LSException If some other error occurs.
3388     */
3389     public synchronized int
3390     getFxSoundCount(int channel) throws IOException, LscpException, LSException {
3391     verifyConnection();
3392     out.writeLine("GET FX_SENDS " + String.valueOf(channel));
3393     if(getPrintOnlyMode()) return -1;
3394    
3395     String s = getSingleLineResultSet().getResult();
3396     return parseInt(s);
3397     }
3398    
3399     /**
3400     * Gets a list of all created effect sends on the specified sampler channel.
3401     * @param channel The sampler channel number.
3402     * @return A <code>FxSend</code> array providing all created
3403     * effect sends on the specified sampler channel.
3404     * @throws IOException If some I/O error occurs.
3405     * @throws LscpException If LSCP protocol corruption occurs.
3406     * @throws LSException If <code>channel</code> is not a valid sampler channel ID.
3407     * @see #createFxSend
3408     * @see #destroyFxSend
3409     */
3410     public synchronized FxSend[]
3411     getFxSends(int channel) throws IOException, LscpException, LSException {
3412     Integer[] idS = getFxSendIDs(channel);
3413     if(getPrintOnlyMode()) return null;
3414    
3415     FxSend[] fxSends = new FxSend[idS.length];
3416    
3417     for(int i = 0; i < fxSends.length; i++)
3418     fxSends[i] = getFxSendInfo(channel, idS[i]);
3419    
3420     return fxSends;
3421     }
3422    
3423     /**
3424     * Gets a list of effect sends on the specified sampler channel.
3425     * @param channel The sampler channel number.
3426     * @return An <code>Integer</code> array providing
3427     * the numerical IDs of all effect sends on the specified sampler channel.
3428     * @throws IOException If some I/O error occurs.
3429     * @throws LscpException If LSCP protocol corruption occurs.
3430     * @throws LSException If <code>channel</code> is not a valid sampler channel ID.
3431     * @see #createFxSend
3432     * @see #destroyFxSend
3433     */
3434     public synchronized Integer[]
3435     getFxSendIDs(int channel) throws IOException, LscpException, LSException {
3436     verifyConnection();
3437     out.writeLine("LIST FX_SENDS " + channel);
3438     if(getPrintOnlyMode()) return null;
3439    
3440     return parseIntList(getSingleLineResultSet().getResult());
3441     }
3442    
3443     /**
3444     * Gets the current settings of the specified effect send entity.
3445     * @param channel The sampler channel number.
3446     * @param fxSend The numerical ID of the effect send entity.
3447     * @return <code>FxSend</code> instance containing
3448     * the current settings of the specified effect send entity.
3449     * @throws IOException If an I/O error occurs.
3450     * @throws LscpException If LSCP protocol corruption occurs.
3451     * @throws LSException If the sampler channel and/or the effect send number are invalid.
3452     */
3453     public synchronized FxSend
3454     getFxSendInfo(int channel, int fxSend) throws IOException, LscpException, LSException {
3455     verifyConnection();
3456     String s = String.valueOf(channel) + " " + String.valueOf(fxSend);
3457     out.writeLine("GET FX_SEND INFO " + s);
3458     if(getPrintOnlyMode()) return null;
3459    
3460     ResultSet rs = getMultiLineResultSet();
3461     FxSend fxs = new FxSend(rs.getMultiLineResult());
3462     fxs.setFxSendId(fxSend);
3463    
3464     return fxs;
3465     }
3466    
3467     /**
3468     * Sets the name of the specified effect send.
3469     * @param channel The sampler channel number.
3470     * @param fxSend The numerical ID of the effect send entity.
3471     * @param name The new name for the specified effect send.
3472     * @throws IOException If some I/O error occurs.
3473     * @throws LscpException If LSCP protocol corruption occurs.
3474     * @throws LSException If <code>channel</code> is not a valid channel
3475     * number or <code>fxSend</code> is not a valid effect send ID;
3476     */
3477     public synchronized void
3478     setFxSendName(int channel, int fxSend, String name)
3479     throws IOException, LscpException, LSException {
3480    
3481     verifyConnection();
3482     String args = " " + channel + " " + fxSend + " '" + name + "'";
3483     out.writeLine("SET FX_SEND NAME" + args);
3484     if(getPrintOnlyMode()) return;
3485    
3486     ResultSet rs = getEmptyResultSet();
3487     }
3488    
3489     /**
3490     * Sets the destination of an effect send's audio channel in the specified sampler channel.
3491     * @param channel The sampler channel number.
3492     * @param fxSend The numerical ID of the effect send entity to be rerouted.
3493     * @param audioSrc The numerical ID of the effect send's audio output channel,
3494     * which should be rerouted.
3495     * @param audioDst The audio channel of the selected audio output device
3496     * where <code>audioSrc</code> should be routed to.
3497     * @throws IOException If some I/O error occurs.
3498     * @throws LscpException If LSCP protocol corruption occurs.
3499     * @throws LSException If
3500     * <ul>
3501     * <li><code>channel</code> is not a valid channel number;
3502     * <li><code>fxSend</code> is not a valid effect send ID;
3503     * <li>There is no engine assigned yet to the specified sampler channel;
3504     * <li>There is no audio output device connected to the specified sampler channel.
3505     * </ul>
3506     */
3507     public synchronized void
3508     setFxSendAudioOutputChannel(int channel, int fxSend, int audioSrc, int audioDst)
3509     throws IOException, LscpException, LSException {
3510    
3511     verifyConnection();
3512     String args = " " + channel + " " + fxSend + " " + audioSrc + " " + audioDst;
3513     out.writeLine("SET FX_SEND AUDIO_OUTPUT_CHANNEL" + args);
3514     if(getPrintOnlyMode()) return;
3515    
3516     ResultSet rs = getEmptyResultSet();
3517     }
3518    
3519     /**
3520     * Sets the MIDI controller, which will be able to modify
3521     * the send level of the specified effect send in the specified sampler channel.
3522     * @param channel The sampler channel number.
3523     * @param fxSend The numerical ID of the effect send entity.
3524     * @param midiCtrl The MIDI controller which shall be
3525     * able to modify the effect send's send level.
3526     * @throws IOException If some I/O error occurs.
3527     * @throws LscpException If LSCP protocol corruption occurs.
3528     * @throws LSException If
3529     * <ul>
3530     * <li><code>channel</code> is not a valid channel number;
3531     * <li><code>fxSend</code> is not a valid effect send ID;
3532     * <li><code>midiCtrl</code> is not a valid controller;
3533     * </ul>
3534     */
3535     public synchronized void
3536     setFxSendMidiController(int channel, int fxSend, int midiCtrl)
3537     throws IOException, LscpException, LSException {
3538    
3539     verifyConnection();
3540     String args = " " + channel + " " + fxSend + " " + midiCtrl;
3541     out.writeLine("SET FX_SEND MIDI_CONTROLLER" + args);
3542     if(getPrintOnlyMode()) return;
3543    
3544     ResultSet rs = getEmptyResultSet();
3545     }
3546    
3547     /**
3548     * Sets the current send level of the specified
3549     * effect send entity in the specified sampler channel.
3550     * @param channel The sampler channel number.
3551     * @param fxSend The numerical ID of the effect send entity.
3552     * @param volume The new volume value (a value smaller than 1.0 means
3553     * attenuation, whereas a value greater than 1.0 means amplification).
3554     * @throws IOException If some I/O error occurs.
3555     * @throws LscpException If LSCP protocol corruption occurs.
3556     * @throws LSException If some other error occurs.
3557     */
3558     public synchronized void
3559     setFxSendLevel(int channel, int fxSend, float volume)
3560     throws IOException, LscpException, LSException {
3561    
3562     verifyConnection();
3563     String args = " " + channel + " " + fxSend + " " + String.valueOf(volume);
3564     out.writeLine("SET FX_SEND LEVEL" + args);
3565     if(getPrintOnlyMode()) return;
3566    
3567     ResultSet rs = getEmptyResultSet();
3568     }
3569    
3570     /**
3571 iliev 596 * Resets the specified sampler channel.
3572     *
3573     * @param samplerChn The sampler channel number.
3574     *
3575     * @throws IOException If some I/O error occurs.
3576     * @throws LscpException If LSCP protocol corruption occurs.
3577     * @throws LSException If <code>samplerChn</code> is not a valid channel number or if
3578     * there is no engine assigned yet to the specified sampler channel.
3579     * @see #getSamplerChannels
3580     */
3581     public synchronized void
3582     resetChannel(int samplerChn) throws IOException, LscpException, LSException {
3583     verifyConnection();
3584     out.writeLine("RESET CHANNEL " + samplerChn);
3585 iliev 1139 if(getPrintOnlyMode()) return;
3586 iliev 596
3587     ResultSet rs = getEmptyResultSet();
3588     }
3589    
3590     /**
3591     * Resets the whole sampler.
3592     *
3593     * @throws IOException If some I/O error occurs.
3594     * @throws LscpException If LSCP protocol corruption occurs.
3595     */
3596     public synchronized void
3597     resetSampler() throws IOException, LscpException {
3598     verifyConnection();
3599     out.writeLine("RESET");
3600 iliev 1139 if(getPrintOnlyMode()) return;
3601    
3602 iliev 596 try { ResultSet rs = getEmptyResultSet(); }
3603     catch(LSException x) { getLogger().warning(x.getMessage()); }
3604     }
3605    
3606     /**
3607 iliev 784 * Gets the current number of all active voices.
3608     * @return The current number of all active voices.
3609     * @throws IOException If some I/O error occurs.
3610     * @throws LscpException If LSCP protocol corruption occurs.
3611     * @throws LSException If some other error occurs.
3612     */
3613     public synchronized int
3614     getTotalVoiceCount() throws IOException, LscpException, LSException {
3615     verifyConnection();
3616     out.writeLine("GET TOTAL_VOICE_COUNT");
3617 iliev 1139 if(getPrintOnlyMode()) return -1;
3618    
3619 iliev 784 String s = getSingleLineResultSet().getResult();
3620     return parseInt(s);
3621     }
3622    
3623     /**
3624     * Gets the maximum number of active voices.
3625     * @return The maximum number of active voices.
3626     * @throws IOException If some I/O error occurs.
3627     * @throws LscpException If LSCP protocol corruption occurs.
3628     * @throws LSException If some other error occurs.
3629     */
3630     public synchronized int
3631     getTotalVoiceCountMax() throws IOException, LscpException, LSException {
3632     verifyConnection();
3633     out.writeLine("GET TOTAL_VOICE_COUNT_MAX");
3634 iliev 1139 if(getPrintOnlyMode()) return -1;
3635    
3636 iliev 784 String s = getSingleLineResultSet().getResult();
3637     return parseInt(s);
3638     }
3639    
3640     /**
3641 iliev 596 * Gets information about the LinuxSampler instance.
3642     *
3643     * @return <code>ServerInfo</code> instance containing
3644     * information about the LinuxSampler instance.
3645     *
3646     * @throws IOException If an I/O error occurs.
3647     * @throws LscpException If LSCP protocol corruption occurs.
3648     * @throws LSException If some other error occurs.
3649     */
3650     public synchronized ServerInfo
3651     getServerInfo() throws IOException, LscpException, LSException {
3652     verifyConnection();
3653     out.writeLine("GET SERVER INFO");
3654 iliev 1139 if(getPrintOnlyMode()) return null;
3655    
3656 iliev 596 ResultSet rs = getMultiLineResultSet();
3657     return new ServerInfo(rs.getMultiLineResult());
3658     }
3659    
3660     /**
3661 iliev 1139 * Gets the golobal volume of the sampler.
3662     * @return The golobal volume of the sampler.
3663     * @throws IOException If some I/O error occurs.
3664     * @throws LscpException If LSCP protocol corruption occurs.
3665     * @throws LSException If some other error occurs.
3666     */
3667     public synchronized float
3668     getVolume() throws IOException, LscpException, LSException {
3669     verifyConnection();
3670     out.writeLine("GET VOLUME");
3671     if(getPrintOnlyMode()) return -1;
3672    
3673     String s = getSingleLineResultSet().getResult();
3674     return parseFloat(s);
3675     }
3676    
3677     /**
3678     * Sets the global volume of the sampler.
3679     * @param volume The new volume value.
3680     * @throws IOException If some I/O error occurs.
3681     * @throws LscpException If LSCP protocol corruption occurs.
3682     * @throws LSException If some other error occurs.
3683     * @see #getVolume
3684     */
3685     public synchronized void
3686     setVolume(float volume) throws IOException, LscpException, LSException {
3687    
3688     verifyConnection();
3689     out.writeLine("SET VOLUME " + volume);
3690     if(getPrintOnlyMode()) return;
3691    
3692     ResultSet rs = getEmptyResultSet();
3693     }
3694    
3695     /**
3696 iliev 596 * Returns the logger for this library.
3697     * @return The logger for this library.
3698     */
3699     protected static Logger
3700     getLogger() { return Logger.getLogger("org.linuxsampler.lscp"); }
3701     }

  ViewVC Help
Powered by ViewVC