/[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 1775 - (show annotations) (download)
Thu Sep 11 18:18:21 2008 UTC (15 years, 7 months ago) by iliev
File size: 185736 byte(s)
* Added support for sending MIDI messages to sampler channels
* Added support for retrieving instrument's key mapping and
  keyswitch mapping

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

  ViewVC Help
Powered by ViewVC