/[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 1718 - (show annotations) (download)
Wed Mar 19 10:05:33 2008 UTC (16 years, 1 month ago) by iliev
File size: 178298 byte(s)
* Client: added new method - getMidiInstrumentEntries
* fixed a bug in DB_INSTRUMENTS_JOB_INFO notifications

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

  ViewVC Help
Powered by ViewVC