/[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 1817 - (show annotations) (download)
Wed Dec 24 16:55:54 2008 UTC (15 years, 3 months ago) by iliev
File size: 190412 byte(s)
* Added support for controlling the global sampler-wide limit of
  maximum voices and disk streams

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

  ViewVC Help
Powered by ViewVC