/[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 2194 - (show annotations) (download)
Tue Jun 28 22:08:23 2011 UTC (12 years, 9 months ago) by iliev
File size: 210216 byte(s)
* added three new methods to EffectParameter class -
  getEffectInstanceId, getIndex, toString

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

  ViewVC Help
Powered by ViewVC