/[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 2193 - (show annotations) (download)
Tue Jun 28 20:35:21 2011 UTC (12 years, 10 months ago) by iliev
File size: 210144 byte(s)
* minor refactoring

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

  ViewVC Help
Powered by ViewVC