/[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 1728 - (show annotations) (download)
Tue Apr 29 16:04:42 2008 UTC (15 years, 11 months ago) by iliev
File size: 180757 byte(s)
* Client: added new methods - findLostDbInstrumentFiles,
  setDbInstrumentFilePath, getExtendedCharacterEscaping,
  setExtendedCharacterEscaping
* Parser: added new method - toExtendedEscapeSequence
* fixed bug #75

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

  ViewVC Help
Powered by ViewVC