/[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 2242 - (show annotations) (download)
Wed Aug 17 09:06:46 2011 UTC (12 years, 7 months ago) by iliev
File size: 210528 byte(s)
* fixed engine cache

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

  ViewVC Help
Powered by ViewVC