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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1139 - (show 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 /*
2 * jlscp - a java LinuxSampler control protocol API
3 *
4 * Copyright (C) 2005-2007 Grigor Iliev <grigor@grigoriliev.com>
5 *
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 import java.io.OutputStream;
27
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 * instance. Since it implements all commands specified in the LSCP protocol v1.1, for more
44 * information look at the
45 * <a href=http://www.linuxsampler.org/api/lscp-1.1.html>LSCP</a> specification.
46 *
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 private boolean printOnlyMode = false;
80
81 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 * 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 * Specifies the jlscp version.
197 * @return The jlscp version.
198 */
199 public static String
200 getClientVersion() {
201 return Package.getPackage("org.linuxsampler.lscp").getImplementationVersion();
202 }
203
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 if(getPrintOnlyMode()) return;
244
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 sock.setTcpNoDelay(true);
272
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 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 if(hasSubscriptions()) eventThread.start();
314
315 if(!llM.isEmpty()) subscribe("MISCELLANEOUS");
316 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 if(!llBF.isEmpty()) subscribe("BUFFER_FILL");
321 if(!llCC.isEmpty()) subscribe("CHANNEL_COUNT");
322 if(!llCI.isEmpty()) subscribe("CHANNEL_INFO");
323 if(!llFSC.isEmpty()) subscribe("FX_SEND_COUNT");
324 if(!llFSI.isEmpty()) subscribe("FX_SEND_INFO");
325 if(!llSC.isEmpty()) subscribe("STREAM_COUNT");
326 if(!llVC.isEmpty()) subscribe("VOICE_COUNT");
327 if(!llTVC.isEmpty()) subscribe("TOTAL_VOICE_COUNT");
328 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 }
334
335 /**
336 * Closes the connection to LinuxSampler.
337 */
338 public synchronized void
339 disconnect() {
340 if(getPrintOnlyMode()) return;
341 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 if(getPrintOnlyMode()) return;
369
370 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 /** Processes the notifications sent by LinuxSampler */
386 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 /** 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 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 private final Vector<FxSendCountListener> llFSC = new Vector<FxSendCountListener>();
452 private final Vector<FxSendInfoListener> llFSI = new Vector<FxSendInfoListener>();
453 private final Vector<MiscellaneousListener> llM = new Vector<MiscellaneousListener>();
454 /** 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 private final Vector<StreamCountListener> llSC = new Vector<StreamCountListener>();
459 private final Vector<VoiceCountListener> llVC = new Vector<VoiceCountListener>();
460 private final Vector<TotalVoiceCountListener> llTVC = new Vector<TotalVoiceCountListener>();
461
462 /** 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 /**
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 * is extended in the future.
479 * @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 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 }
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 Integer[] i = parseIntList(s, ' ');
520 if(i.length != 2) {
521 getLogger().warning("Unknown VOICE_COUNT format");
522 return;
523 }
524 VoiceCountEvent e = new VoiceCountEvent(this, i[0], i[1]);
525 for(VoiceCountListener l : llVC) l.voiceCountChanged(e);
526 } catch(Exception x) {
527 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 Integer[] i = parseIntList(s, ' ');
533 if(i.length != 2) {
534 getLogger().warning("Unknown STREAM_COUNT format");
535 return;
536 }
537 StreamCountEvent e = new StreamCountEvent(this, i[0], i[1]);
538 for(StreamCountListener l : llSC) l.streamCountChanged(e);
539 } catch(Exception x) {
540 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 getLogger().warning("Unknown BUFFER_FILL format");
548 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 getLogger().log(Level.WARNING, "Unknown BUFFER_FILL format", x);
557 }
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 getLogger().log(Level.WARNING, "Unknown CHANNEL_INFO format", x);
565 }
566 } 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 } 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 } 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 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 subscribe(String event) {
737 if(!getPrintOnlyMode()) {
738 if(!isConnected()) return;
739
740 if(!eventThread.isAlive()) eventThread.start();
741 }
742
743 try {
744 out.writeLine("SUBSCRIBE " + event);
745 if(!getPrintOnlyMode()) getEmptyResultSet();
746 } 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 if(!getPrintOnlyMode() && !isConnected()) return;
758
759 try {
760 out.writeLine("UNSUBSCRIBE " + event);
761 if(!getPrintOnlyMode()) getEmptyResultSet();
762 } 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 * 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 * Listeners can be removed regardless of the connection state.
785 * @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 * @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 * @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 * @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 * 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 * 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 * 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
1181 if(getPrintOnlyMode()) return -1;
1182
1183 String s = getSingleLineResultSet().getResult();
1184 return parseInt(s);
1185 }
1186
1187 /**
1188 * Gets all audio output drivers currently available for the LinuxSampler instance.
1189 *
1190 * @return <code>AudioOutputDriver</code> array containing all audio output drivers
1191 * currently available for the LinuxSampler instance.
1192 *
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 public synchronized AudioOutputDriver[]
1198 getAudioOutputDrivers() throws IOException, LscpException, LSException {
1199 String[] drivers = getAudioOutputDriverNames();
1200 if(getPrintOnlyMode()) return null;
1201
1202 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 verifyConnection();
1222 out.writeLine("LIST AVAILABLE_AUDIO_OUTPUT_DRIVERS");
1223 if(getPrintOnlyMode()) return null;
1224 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 * @see #getAudioOutputDriverNames
1239 */
1240 private synchronized AudioOutputDriver
1241 getAudioOutputDriverInfo(String driverName) throws IOException, LscpException, LSException {
1242 verifyConnection();
1243 out.writeLine("GET AUDIO_OUTPUT_DRIVER INFO " + driverName);
1244 if(getPrintOnlyMode()) return null;
1245
1246 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 if(getPrintOnlyMode()) return null;
1290
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 prm.setValue(prm.getDefault());
1304 return prm;
1305 case INT:
1306 if(!multi) prm = new IntParameter(lnS);
1307 else prm = new IntListParameter(lnS);
1308 prm.setName(param);
1309 prm.setValue(prm.getDefault());
1310 return prm;
1311 case FLOAT:
1312 if(!multi) prm = new FloatParameter(lnS);
1313 else prm = new FloatListParameter(lnS);
1314 prm.setName(param);
1315 prm.setValue(prm.getDefault());
1316 return prm;
1317 case STRING:
1318 if(!multi) prm = new StringParameter(lnS);
1319 else prm = new StringListParameter(lnS);
1320 prm.setName(param);
1321 prm.setValue(prm.getDefault());
1322 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 if(getPrintOnlyMode()) return -1;
1352
1353 ResultSet rs = getEmptyResultSet();
1354
1355 return rs.getIndex();
1356 }
1357
1358 /**
1359 * Destroys already created audio output device.
1360 * @param deviceId The ID of the audio output device to be destroyed.
1361 * @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 destroyAudioOutputDevice(int deviceId) throws IOException, LSException, LscpException {
1368 verifyConnection();
1369 out.writeLine("DESTROY AUDIO_OUTPUT_DEVICE " + deviceId);
1370 if(getPrintOnlyMode()) return;
1371
1372 ResultSet rs = getEmptyResultSet();
1373 }
1374
1375 /**
1376 * Enables/disables the specified audio output device.
1377 * @param deviceId The ID of the audio output device to be enabled/disabled.
1378 * @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 * device with numerical ID <code>deviceId</code>.
1383 * @throws LscpException If LSCP protocol corruption occurs.
1384 */
1385 public void
1386 enableAudioOutputDevice(int deviceId, boolean enable)
1387 throws IOException, LSException, LscpException {
1388
1389 setAudioOutputDeviceParameter(deviceId, new BoolParameter("ACTIVE", enable));
1390 }
1391
1392 /**
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 if(getPrintOnlyMode()) return -1;
1404
1405 String s = getSingleLineResultSet().getResult();
1406 return parseInt(s);
1407 }
1408
1409 /**
1410 * 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 if(getPrintOnlyMode()) return null;
1421
1422 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 * Gets a list of numerical IDs of all created audio output devices.
1432 * @return An <code>Integer</code> array providing the numerical IDs of
1433 * 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 getAudioOutputDeviceIDs() throws IOException, LscpException, LSException {
1440 verifyConnection();
1441 out.writeLine("LIST AUDIO_OUTPUT_DEVICES");
1442 if(getPrintOnlyMode()) return null;
1443
1444 return parseIntList(getSingleLineResultSet().getResult());
1445 }
1446
1447 /**
1448 * Gets the current settings of a specific, already created audio output device.
1449 *
1450 * @param deviceId Specifies the numerical ID of the audio output device.
1451 *
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 * with device id <code>deviceId</code>.
1459 *
1460 * @see #getAudioOutputDevices
1461 */
1462 public synchronized AudioOutputDevice
1463 getAudioOutputDeviceInfo(int deviceId) throws IOException, LscpException, LSException {
1464 verifyConnection();
1465 out.writeLine("GET AUDIO_OUTPUT_DEVICE INFO " + deviceId);
1466 if(getPrintOnlyMode()) return null;
1467
1468 ResultSet rs = getMultiLineResultSet();
1469
1470 String[] lnS = rs.getMultiLineResult();
1471
1472 AudioOutputDevice aod = new AudioOutputDevice();
1473 aod.setDeviceId(deviceId);
1474 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 int count = channels.getValue() > 0 ? channels.getValue() : 0;
1489 AudioOutputChannel[] aoc = new AudioOutputChannel[count];
1490 for(int i = 0; i < count; i++) {
1491 aoc[i] = getAudioOutputChannelInfo(deviceId, i);
1492 }
1493 aod.setAudioChannels(aoc);
1494 } 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 * @param deviceId The numerical ID of the audio output device.
1529 * @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 * <li>There is no audio output device with numerical ID <code>deviceId</code>;
1537 * <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 setAudioOutputDeviceParameter(int deviceId, Parameter prm)
1547 throws IOException, LscpException, LSException {
1548
1549 verifyConnection();
1550 String kv = prm.getName() + '=' + prm.getStringValue();
1551 out.writeLine("SET AUDIO_OUTPUT_DEVICE_PARAMETER " + deviceId + ' ' + kv);
1552 if(getPrintOnlyMode()) return;
1553
1554 ResultSet rs = getEmptyResultSet();
1555 }
1556
1557 /**
1558 * Changes the channel number of the speicifed audio output device.
1559 * @param deviceId The numerical ID of the audio output device.
1560 * @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 * @throws LSException If there is no device with ID <code>deviceId</code> or
1565 * if <code>channels</code> number is out of range.
1566 *
1567 * @see #getAudioOutputChannelInfo
1568 */
1569 public synchronized void
1570 setAudioOutputChannelCount(int deviceId, int channels)
1571 throws IOException, LscpException, LSException {
1572
1573 setAudioOutputDeviceParameter(deviceId, new IntParameter("CHANNELS", channels));
1574 }
1575
1576 /**
1577 * Gets information about an audio channel.
1578 *
1579 * @param deviceId The numerical ID of the audio output device.
1580 * @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 * <li>There is no audio output device with numerical ID <code>deviceId</code>;
1590 * <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 getAudioOutputChannelInfo(int deviceId, int audioChn)
1598 throws IOException, LscpException, LSException {
1599
1600 verifyConnection();
1601 out.writeLine("GET AUDIO_OUTPUT_CHANNEL INFO " + deviceId + ' ' + audioChn);
1602 if(getPrintOnlyMode()) return null;
1603
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 s = s.substring("NAME: ".length());
1612 Parameter<String> prm = getAudioOutputChannelParameterInfo (
1613 deviceId, audioChn, "NAME"
1614 );
1615 prm.setValue(removeQuotation(s));
1616 aoc.setNameParameter(prm);
1617 } else if(s.startsWith("IS_MIX_CHANNEL: ")) {
1618 s = s.substring("IS_MIX_CHANNEL: ".length());
1619 Parameter<Boolean> prm = getAudioOutputChannelParameterInfo (
1620 deviceId, audioChn, "IS_MIX_CHANNEL"
1621 );
1622 prm.setValue(Boolean.parseBoolean(s));
1623 aoc.setMixChannelParameter(prm);
1624 } else if(s.startsWith("MIX_CHANNEL_DESTINATION: ")) {
1625 s = s.substring("MIX_CHANNEL_DESTINATION: ".length());
1626 Parameter<Integer> prm = getAudioOutputChannelParameterInfo (
1627 deviceId, audioChn, "MIX_CHANNEL_DESTINATION"
1628 );
1629 prm.setValue(parseInt(s));
1630 aoc.setMixChannelDestParameter(prm);
1631 } else {
1632 int i = s.indexOf(": ");
1633 if(i == -1) throw new LscpException (
1634 LscpI18n.getLogMsg("CommandFailed!")
1635 );
1636
1637 Parameter prm = getAudioOutputChannelParameterInfo (
1638 deviceId, audioChn, s.substring(0, i)
1639 );
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 * @param devId The numerical ID of the audio output device.
1655 * @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 * <li><code>devId</code> is not a valid device ID;
1666 * <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 getAudioOutputChannelParameterInfo(int devId, int chan, String param)
1675 throws IOException, LscpException, LSException {
1676
1677 verifyConnection();
1678 String args = devId + " " + chan + " " + param;
1679 out.writeLine("GET AUDIO_OUTPUT_CHANNEL_PARAMETER INFO " + args);
1680 if(getPrintOnlyMode()) return null;
1681
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 * @param devId The numerical ID of the audio device.
1718 * @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 * <li>There is no audio output device with numerical ID <code>devId</code>;
1727 * <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 setAudioOutputChannelParameter(int devId, int chn, Parameter prm)
1738 throws IOException, LscpException, LSException {
1739
1740 verifyConnection();
1741 String args = devId + " " + chn + " " + prm.getName() + '=' + prm.getStringValue();
1742 out.writeLine("SET AUDIO_OUTPUT_CHANNEL_PARAMETER " + args);
1743 if(getPrintOnlyMode()) return;
1744
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 if(getPrintOnlyMode()) return -1;
1760
1761 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 * @return <code>MidiInputDriver</code> array containing all MIDI input drivers currently
1769 * available for the LinuxSampler instance.
1770 *
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 public synchronized MidiInputDriver[]
1776 getMidiInputDrivers() throws IOException, LscpException, LSException {
1777 String[] drivers = getMidiInputDriverNames();
1778 if(getPrintOnlyMode()) return null;
1779
1780 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 verifyConnection();
1800 out.writeLine("LIST AVAILABLE_MIDI_INPUT_DRIVERS");
1801 if(getPrintOnlyMode()) return null;
1802
1803 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 * @return A <code>MidiInputDriver</code> object containing
1811 * 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 * @see #getMidiInputDriverNames
1818 */
1819 private synchronized MidiInputDriver
1820 getMidiInputDriverInfo(String driverName) throws IOException, LscpException, LSException {
1821 verifyConnection();
1822 out.writeLine("GET MIDI_INPUT_DRIVER INFO " + driverName);
1823 if(getPrintOnlyMode()) return null;
1824
1825 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 * @return A <code>Parameter</code> object containing
1846 * 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 if(getPrintOnlyMode()) return null;
1870
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 prm.setValue(prm.getDefault());
1884 return prm;
1885 case INT:
1886 if(!multi) prm = new IntParameter(lnS);
1887 else prm = new IntListParameter(lnS);
1888 prm.setName(param);
1889 prm.setValue(prm.getDefault());
1890 return prm;
1891 case FLOAT:
1892 if(!multi) prm = new FloatParameter(lnS);
1893 else prm = new FloatListParameter(lnS);
1894 prm.setName(param);
1895 prm.setValue(prm.getDefault());
1896 return prm;
1897 case STRING:
1898 if(!multi) prm = new StringParameter(lnS);
1899 else prm = new StringListParameter(lnS);
1900 prm.setName(param);
1901 prm.setValue(prm.getDefault());
1902 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 if(getPrintOnlyMode()) return -1;
1933
1934 ResultSet rs = getEmptyResultSet();
1935
1936 return rs.getIndex();
1937 }
1938
1939 /**
1940 * Destroys already created MIDI input device.
1941 * @param deviceId The numerical ID of the MIDI input device to be destroyed.
1942 * @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 destroyMidiInputDevice(int deviceId) throws IOException, LSException, LscpException {
1950 verifyConnection();
1951 out.writeLine("DESTROY MIDI_INPUT_DEVICE " + deviceId);
1952 if(getPrintOnlyMode()) return;
1953
1954 ResultSet rs = getEmptyResultSet();
1955 }
1956
1957 /**
1958 * Enables/disables the specified MIDI input device.
1959 * @param deviceId The ID of the MIDI input device to be enabled/disabled.
1960 * @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 * device with numerical ID <code>deviceId</code>.
1965 * @throws LscpException If LSCP protocol corruption occurs.
1966 */
1967 public void
1968 enableMidiInputDevice(int deviceId, boolean enable)
1969 throws IOException, LSException, LscpException {
1970
1971 setMidiInputDeviceParameter(deviceId, new BoolParameter("ACTIVE", enable));
1972 }
1973
1974 /**
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 if(getPrintOnlyMode()) return -1;
1986
1987 String s = getSingleLineResultSet().getResult();
1988 return parseInt(s);
1989 }
1990
1991 /**
1992 * 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 if(getPrintOnlyMode()) return null;
2006
2007 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 * Gets a list of numerical IDs of all created MIDI input devices.
2017 * @return An <code>Integer</code> array providing the numerical IDs of
2018 * 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 getMidiInputDeviceIDs() throws IOException, LscpException, LSException {
2028 verifyConnection();
2029 out.writeLine("LIST MIDI_INPUT_DEVICES");
2030 if(getPrintOnlyMode()) return null;
2031
2032 return parseIntList(getSingleLineResultSet().getResult());
2033 }
2034
2035 /**
2036 * Gets the current settings of a specific, already created MIDI input device.
2037 *
2038 * @param deviceId Specifies the numerical ID of the MIDI input device.
2039 *
2040 * @return A <code>MidiInputDevice</code> instance containing information
2041 * 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 * with device id <code>deviceId</code>.
2047 *
2048 * @see #getMidiInputDevices
2049 */
2050 public synchronized MidiInputDevice
2051 getMidiInputDeviceInfo(int deviceId) throws IOException, LscpException, LSException {
2052 verifyConnection();
2053 out.writeLine("GET MIDI_INPUT_DEVICE INFO " + deviceId);
2054 if(getPrintOnlyMode()) return null;
2055
2056 ResultSet rs = getMultiLineResultSet();
2057
2058 String[] lnS = rs.getMultiLineResult();
2059
2060 MidiInputDevice mid = new MidiInputDevice();
2061 mid.setDeviceId(deviceId);
2062
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 } 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 midiPorts[i] = getMidiInputPortInfo(deviceId, i);
2079
2080 mid.setMidiPorts(midiPorts);
2081 } 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 * @param deviceId The numerical ID of the MIDI input device.
2104 * @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 * <li>There is no MIDI input device with numerical ID <code>deviceId</code>;
2112 * <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 setMidiInputDeviceParameter(int deviceId, Parameter prm)
2122 throws IOException, LscpException, LSException {
2123
2124 verifyConnection();
2125 String kv = prm.getName() + '=' + prm.getStringValue();
2126 out.writeLine("SET MIDI_INPUT_DEVICE_PARAMETER " + deviceId + ' ' + kv);
2127 if(getPrintOnlyMode()) return;
2128
2129 ResultSet rs = getEmptyResultSet();
2130 }
2131
2132
2133 /**
2134 * Changes the port number of the speicified MIDI input device.
2135 * @param deviceId The numerical ID of the MIDI input device.
2136 * @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 * @throws LSException If there is no device with ID <code>deviceId</code> or
2141 * if <code>ports</code> number is out of range.
2142 *
2143 * @see #getMidiInputPortInfo
2144 */
2145 public synchronized void
2146 setMidiInputPortCount(int deviceId, int ports)
2147 throws IOException, LscpException, LSException {
2148
2149 setMidiInputDeviceParameter(deviceId, new IntParameter("PORTS", ports));
2150 }
2151
2152 /**
2153 * Gets detailed information about a specific MIDI input port.
2154 * @param deviceId The numerical ID of the MIDI input device.
2155 * @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 * @throws LSException If there is no device with ID <code>deviceId</code> or
2163 * if <code>midiPort</code> is not a valid MIDI port number.
2164 *
2165 * @see #getMidiInputDevices
2166 */
2167 public synchronized MidiPort
2168 getMidiInputPortInfo(int deviceId, int midiPort)
2169 throws IOException, LscpException, LSException {
2170
2171 verifyConnection();
2172 out.writeLine("GET MIDI_INPUT_PORT INFO " + deviceId + " " + midiPort);
2173 if(getPrintOnlyMode()) return null;
2174
2175 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 s = s.substring("NAME: ".length());
2183 Parameter prm = getMidiInputPortParameterInfo (
2184 deviceId, midiPort, "NAME"
2185 );
2186 prm.setValue(removeQuotation(s));
2187 mp.setNameParameter(prm);
2188 } else {
2189 int i = s.indexOf(": ");
2190 if(i == -1) throw new LscpException (
2191 LscpI18n.getLogMsg("CommandFailed!")
2192 );
2193
2194 Parameter prm = getMidiInputPortParameterInfo (
2195 deviceId, midiPort, s.substring(0, i)
2196 );
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 * @param deviceId The numerical ID of the MIDI input device.
2212 * @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 * <li>There is no MIDI input device with numerical ID <code>deviceId</code>;
2223 * <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 getMidiInputPortParameterInfo(int deviceId, int port, String param)
2232 throws IOException, LscpException, LSException {
2233
2234 verifyConnection();
2235 String args = deviceId + " " + port + " " + param;
2236 out.writeLine("GET MIDI_INPUT_PORT_PARAMETER INFO " + args);
2237 if(getPrintOnlyMode()) return null;
2238
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 * @param deviceId The numerical ID of the MIDI device.
2275 * @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 * <li>There is no MIDI device with numerical ID <code>deviceId</code>;
2284 * <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 setMidiInputPortParameter(int deviceId, int port, Parameter prm)
2295 throws IOException, LscpException, LSException {
2296
2297 verifyConnection();
2298 String args = deviceId + " " + port + " " +
2299 prm.getName() + '=' + prm.getStringValue();
2300 out.writeLine("SET MIDI_INPUT_PORT_PARAMETER " + args);
2301 if(getPrintOnlyMode()) return;
2302
2303 ResultSet rs = getEmptyResultSet();
2304 }
2305
2306 /**
2307 * 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 * 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 if(getPrintOnlyMode()) return;
2703
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 if(getPrintOnlyMode()) return;
2726
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 if(getPrintOnlyMode()) return -1;
2742
2743 String s = getSingleLineResultSet().getResult();
2744 return parseInt(s);
2745 }
2746
2747 /**
2748 * 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 if(getPrintOnlyMode()) return null;
2760
2761 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 * Gets a list with numerical IDs of all created sampler channels.
2771 * @return An <code>Integer</code> array providing
2772 * the numerical IDs of all created sampler channels.
2773 * @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 getSamplerChannelIDs() throws IOException, LscpException, LSException {
2781 verifyConnection();
2782 out.writeLine("LIST CHANNELS");
2783 if(getPrintOnlyMode()) return null;
2784
2785 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 if(getPrintOnlyMode()) return -1;
2803
2804 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 if(getPrintOnlyMode()) return;
2825
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 if(getPrintOnlyMode()) return -1;
2841
2842 String s = getSingleLineResultSet().getResult();
2843 return parseInt(s);
2844 }
2845
2846 /**
2847 * 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 if(getPrintOnlyMode()) return null;
2858
2859 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 * 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 private synchronized String[]
2875 getEngineNames() throws IOException, LscpException, LSException {
2876 verifyConnection();
2877 out.writeLine("LIST AVAILABLE_ENGINES");
2878 if(getPrintOnlyMode()) return null;
2879
2880 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 * @see #getEngineNames
2894 */
2895 private synchronized SamplerEngine
2896 getEngineInfo(String engineName) throws IOException, LscpException, LSException {
2897 verifyConnection();
2898 out.writeLine("GET ENGINE INFO " + engineName);
2899 if(getPrintOnlyMode()) return null;
2900
2901 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 if(getPrintOnlyMode()) return null;
2924
2925 ResultSet rs = getMultiLineResultSet();
2926 SamplerChannel sc = new SamplerChannel(rs.getMultiLineResult());
2927 sc.setChannelId(samplerChn);
2928 if(sc.getEngine() != null) sc.setEngine(getEngineInfo(sc.getEngine().getName()));
2929
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 if(getPrintOnlyMode()) return -1;
2948
2949 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 if(getPrintOnlyMode()) return -1;
2970
2971 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 if(getPrintOnlyMode()) return null;
2996
2997 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 bf.setStreamId(parseInt(s.substring(1, i)));
3013 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 if(getPrintOnlyMode()) return null;
3040
3041 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 bf.setStreamId(parseInt(s.substring(1, i)));
3065 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 * @param devId The numerical ID of the audio output device.
3077 *
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 * <li><code>devId</code> is not a valid audio output device ID;
3084 * </ul>
3085 *
3086 * @see #getSamplerChannels
3087 * @see #getAudioOutputDevices
3088 */
3089 public synchronized void
3090 setChannelAudioOutputDevice(int samplerChn, int devId)
3091 throws IOException, LscpException, LSException {
3092
3093 verifyConnection();
3094 out.writeLine("SET CHANNEL AUDIO_OUTPUT_DEVICE " + samplerChn + ' ' + devId);
3095 if(getPrintOnlyMode()) return;
3096
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 if(getPrintOnlyMode()) return;
3127
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 * @param devId The numerical ID of the MIDI input device.
3136 *
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 * <li><code>devId</code> is not a valid MIDI input device ID;
3143 * </ul>
3144 *
3145 * @see #getSamplerChannels
3146 * @see #getMidiInputDevices
3147 */
3148 public synchronized void
3149 setChannelMidiInputDevice(int samplerChn, int devId)
3150 throws IOException, LscpException, LSException {
3151
3152 verifyConnection();
3153 out.writeLine("SET CHANNEL MIDI_INPUT_DEVICE " + samplerChn + ' ' + devId);
3154 if(getPrintOnlyMode()) return;
3155
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 if(getPrintOnlyMode()) return;
3178
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 if(getPrintOnlyMode()) return;
3203
3204 ResultSet rs = getEmptyResultSet();
3205 }
3206
3207 /**
3208 * 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 * 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 if(getPrintOnlyMode()) return;
3264
3265 ResultSet rs = getEmptyResultSet();
3266 }
3267
3268 /**
3269 * 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 if(getPrintOnlyMode()) return;
3288
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 if(getPrintOnlyMode()) return;
3312
3313 ResultSet rs = getEmptyResultSet();
3314 }
3315
3316 /**
3317 * 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 * 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 if(getPrintOnlyMode()) return;
3586
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 if(getPrintOnlyMode()) return;
3601
3602 try { ResultSet rs = getEmptyResultSet(); }
3603 catch(LSException x) { getLogger().warning(x.getMessage()); }
3604 }
3605
3606 /**
3607 * 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 if(getPrintOnlyMode()) return -1;
3618
3619 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 if(getPrintOnlyMode()) return -1;
3635
3636 String s = getSingleLineResultSet().getResult();
3637 return parseInt(s);
3638 }
3639
3640 /**
3641 * 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 if(getPrintOnlyMode()) return null;
3655
3656 ResultSet rs = getMultiLineResultSet();
3657 return new ServerInfo(rs.getMultiLineResult());
3658 }
3659
3660 /**
3661 * 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 * 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