/[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 1605 - (show annotations) (download)
Mon Dec 31 15:42:55 2007 UTC (16 years, 3 months ago) by iliev
File size: 176801 byte(s)
* null parameters and parameters with null names are now not sent
  to LinuxSampler

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

  ViewVC Help
Powered by ViewVC