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

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

  ViewVC Help
Powered by ViewVC