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

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

  ViewVC Help
Powered by ViewVC