/[svn]/jlscp/branches/jlscp_0_3a/src/org/linuxsampler/lscp/Client.java
ViewVC logotype

Contents of /jlscp/branches/jlscp_0_3a/src/org/linuxsampler/lscp/Client.java

Parent Directory Parent Directory | Revision Log Revision Log


Revision 785 - (show annotations) (download)
Mon Oct 10 14:55:45 2005 UTC (18 years, 5 months ago) by (unknown author)
File size: 80515 byte(s)
This commit was manufactured by cvs2svn to create branch 'jlscp_0_3a'.
1 /*
2 * jlscp - a java LinuxSampler control protocol API
3 *
4 * Copyright (C) 2005 Grigor Kirilov Iliev
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
27 import java.net.InetSocketAddress;
28 import java.net.Socket;
29 import java.net.SocketTimeoutException;
30 import java.net.UnknownHostException;
31
32 import java.util.Vector;
33 import java.util.logging.Level;
34 import java.util.logging.Logger;
35
36 import static org.linuxsampler.lscp.Parser.*;
37 import org.linuxsampler.lscp.event.*;
38
39
40 /**
41 * This class is the abstraction representing a client endpoint for communication with LinuxSampler
42 * instance. Since it implements all commands specified in the LSCP protocol v1.0, for more
43 * information look at the
44 * <a href=http://www.linuxsampler.org/api/lscp-1.0.html>LSCP</a> specification.
45 *
46 * <p> The following code establishes connection to LinuxSampler instance and gets the
47 * LinuxSampler version:
48 * <pre>
49 * try {
50 * Client client = new Client();
51 * client.connect();
52 *
53 * String version = client.getServerInfo().getVersion();
54 * System.out.println(version);
55 *
56 * client.disconnect();
57 * } catch(Exception x) { x.printStackTrace(); }
58 * </pre>
59 * </p>
60 *
61 * <p>For more examples look at the <code>examples</code> directory
62 * located in the <b>jlscp</b> distribution.</p>
63 *
64 * All methods are thread safe.
65 * @author Grigor Iliev
66 */
67 public class Client {
68 private String address;
69 private int port;
70 private Socket sock = null;
71 private int soTimeout = 10000;
72
73 private LscpInputStream in = null;
74 private LscpOutputStream out = null;
75
76 private EventThread eventThread;
77
78 class EventThread extends Thread {
79 private boolean terminate = false;
80
81 EventThread() { super("LSCP-Event-Thread"); }
82
83 public void
84 run() {
85 while(!mustTerminate()) {
86 try { processNotifications(); }
87 catch(Exception x) {
88 getLogger().log(Level.FINE, x.getMessage(), x);
89 }
90 try { synchronized(this) { wait(100); } }
91 catch(Exception x) {
92 getLogger().log(Level.FINE, x.getMessage(), x);
93 }
94 }
95 }
96
97 private synchronized boolean
98 mustTerminate() { return terminate; }
99
100 public synchronized void
101 terminate() {
102 terminate = true;
103 this.notifyAll();
104 }
105 }
106
107 /**
108 * Creates a new instance of Client with default server address and port.
109 * The default server address and port are 127.0.0.1:8888.
110 */
111 public
112 Client() { this("127.0.0.1"); }
113
114 /**
115 * Creates a new instance of Client with the specified address and default port.
116 * The default port is 8888.
117 * @param address The address of linux sampler server.
118 */
119 public
120 Client(String address) { this(address, 8888); }
121
122 /**
123 * Creates a new instance of Client with the specified address and port.
124 * @param address The address of the Linux Sampler.
125 * @param port The Linux Sampler port number.
126 */
127 public
128 Client(String address, int port) {
129 setServerAddress(address);
130 setServerPort(port);
131
132 eventThread = new EventThread();
133 }
134
135 /**
136 * Specifies the jlscp version.
137 * @return The jlscp version.
138 */
139 public static String
140 getClientVersion() {
141 return Package.getPackage("org.linuxsampler.lscp").getImplementationVersion();
142 }
143
144 /**
145 * Gets the Linux Sampler address.
146 * @return The Linux Sampler address.
147 */
148 public synchronized String
149 getServerAddress() { return address; }
150
151 /**
152 * Sets the Linux Sampler address.
153 * @param address The Linux Sampler address.
154 * If <code>address</code> is <code>null</code> sets to default address - 127.0.0.1.
155 */
156 public synchronized void
157 setServerAddress(String address) {
158 this.address = (address == null ? "127.0.0.1" : address);
159 }
160
161 /**
162 * Gets the Linux Sampler port number.
163 * @return The Linux Sampler port number.
164 */
165 public synchronized int
166 getServerPort() { return port; }
167
168 /**
169 * Sets the Linux Sampler port number.
170 * @param port The Linux Sampler port number.
171 */
172 public synchronized void
173 setServerPort(int port) { this.port = port; }
174
175 /**
176 * Connects to the LinuxSampler. If there is already established connection then
177 * the currently available connection is closed berfore connecting.
178 * @throws LscpException If timeout occurs or any other I/O exception.
179 */
180 public synchronized void
181 connect() throws LscpException {
182 if(sock != null) disconnect();
183
184 // Initializing LSCP event thread
185 if(eventThread.isAlive()) {
186 getLogger().warning("LSCP event thread already running!");
187 eventThread.terminate();
188 }
189
190 if(eventThread.getState() != Thread.State.NEW) eventThread = new EventThread();
191 ///////
192
193 InetSocketAddress sockAddr = null;
194
195 try { sockAddr = new InetSocketAddress(address, port); }
196 catch(IllegalArgumentException x) {
197 String s = String.valueOf(port);
198 throw new LscpException(LscpI18n.getLogMsg("Client.invalidPort!", s), x);
199 }
200
201 if(sockAddr.isUnresolved()) throw new LscpException (
202 LscpI18n.getLogMsg("Client.unknownHost!", address)
203 );
204
205 try {
206 sock = new Socket();
207 sock.bind(null);
208 sock.connect(sockAddr, soTimeout);
209 sock.setSoTimeout(soTimeout);
210 sock.setTcpNoDelay(true);
211
212 in = new LscpInputStream(sock.getInputStream());
213 out = new LscpOutputStream(sock.getOutputStream());
214 } catch(SocketTimeoutException x) {
215 throw new LscpException(LscpI18n.getLogMsg("Client.conTimeout!"), x);
216 } catch(Exception x) {
217 throw new LscpException (
218 LscpI18n.getLogMsg("Client.connectionFailed!"), x
219 );
220 }
221
222 String s = Package.getPackage("org.linuxsampler.lscp").getSpecificationVersion();
223 String s2, sv, sv2;
224
225 try {
226 s2 = s.substring(0, s.indexOf('.'));
227 sv = getServerInfo().getProtocolVersion();
228 sv2 = sv.substring(0, sv.indexOf('.'));
229 } catch(Exception x) {
230 disconnect();
231
232 throw new LscpException (
233 LscpI18n.getLogMsg("Client.connectionFailed!"), x
234 );
235 }
236
237 if(!sv2.equals(s2)) {
238 disconnect();
239
240 throw new LscpException (
241 LscpI18n.getLogMsg("Client.incompatibleLscpVersion!", sv)
242 );
243 }
244
245 s2 = s.substring(s.indexOf('.'));
246 sv2 = sv.substring(sv.indexOf('.'));
247
248 if(sv2.compareToIgnoreCase(s2) < 0) getLogger().info (
249 LscpI18n.getLogMsg("Client.incompatibleLscpMinVersion!", sv)
250 );
251
252 if(hasSubscriptions()) eventThread.start();
253
254 if(!llM.isEmpty()) subscribe("MISCELLANEOUS");
255 if(!llBF.isEmpty()) subscribe("BUFFER_FILL");
256 if(!llCC.isEmpty()) subscribe("CHANNEL_COUNT");
257 if(!llCI.isEmpty()) subscribe("CHANNEL_INFO");
258 if(!llSC.isEmpty()) subscribe("STREAM_COUNT");
259 if(!llVC.isEmpty()) subscribe("VOICE_COUNT");
260 if(!llTVC.isEmpty()) subscribe("TOTAL_VOICE_COUNT");
261 }
262
263 /**
264 * Closes the connection to LinuxSampler.
265 */
266 public synchronized void
267 disconnect() {
268 try { if(sock != null) sock.close(); }
269 catch(Exception x) { getLogger().log(Level.FINE, x.getMessage(), x); }
270 sock = null;
271
272 if(eventThread.getState() != Thread.State.NEW) {
273 eventThread.terminate();
274 eventThread = new EventThread();
275 }
276 }
277
278 /**
279 * Determines whether the client is connected.
280 * @return <code>true</code> if there is established connection,
281 * <code>false</code> otherwise.
282 */
283 public synchronized boolean
284 isConnected() {
285 if(sock == null) return false;
286 else return sock.isConnected();
287 }
288
289 /**
290 * Verifies that there is established connection.
291 * @throws IOException If the connection is not established.
292 */
293 private void
294 verifyConnection() throws IOException {
295 if(!isConnected())
296 throw new IOException(LscpI18n.getLogMsg("Client.notConnected!"));
297 }
298
299 private String
300 getLine() throws IOException, LscpException {
301 String s;
302 for(;;) {
303 s = in.readLine();
304 if(s.startsWith("NOTIFY:")) fireEvent(s.substring("NOTIFY:".length()));
305 else break;
306 }
307 return s;
308 }
309
310 /** Processes the notifications send by LinuxSampler */
311 private synchronized void
312 processNotifications() throws IOException, LscpException {
313 while(in.available() > 0) {
314 String s = in.readLine();
315 if(s.startsWith("NOTIFY:")) fireEvent(s.substring("NOTIFY:".length()));
316 else getLogger().severe("Unknown notification format: " + s);
317 }
318 }
319
320 /**
321 * Gets empty result set.
322 * @return <code>ResultSet</code> instance.
323 */
324 private ResultSet
325 getEmptyResultSet() throws IOException, LscpException, LSException {
326 return parseEmptyResultSet(getLine());
327 }
328
329 private ResultSet
330 getSingleLineResultSet() throws IOException, LscpException, LSException {
331 ResultSet rs = new ResultSet();
332 String ln = getLine();
333
334 if(ln.startsWith("WRN")) {
335 parseWarning(ln, rs);
336 getLogger().warning(rs.getMessage());
337 return rs;
338 } else if(ln.startsWith("ERR")) {
339 parseError(ln, rs);
340 throw new LSException(rs.getCode(), rs.getMessage());
341 } else {
342 rs.setResult(ln);
343 return rs;
344 }
345 }
346
347 private ResultSet
348 getMultiLineResultSet() throws IOException, LscpException, LSException {
349 ResultSet rs = new ResultSet();
350 String ln = getLine();
351
352 if(ln.startsWith("WRN")) {
353 parseWarning(ln, rs);
354 getLogger().warning(rs.getMessage());
355 return rs;
356 } else if(ln.startsWith("ERR")) {
357 parseError(ln, rs);
358 throw new LSException(rs.getCode(), rs.getMessage());
359 }
360
361 while(!ln.equals(".")) {
362 rs.addLine(ln);
363 ln = getLine();
364 }
365
366 return rs;
367 }
368
369 private final Vector<BufferFillListener> llBF = new Vector<BufferFillListener>();
370 private final Vector<ChannelCountListener> llCC = new Vector<ChannelCountListener>();
371 private final Vector<ChannelInfoListener> llCI = new Vector<ChannelInfoListener>();
372 private final Vector<MiscellaneousListener> llM = new Vector<MiscellaneousListener>();
373 private final Vector<StreamCountListener> llSC = new Vector<StreamCountListener>();
374 private final Vector<VoiceCountListener> llVC = new Vector<VoiceCountListener>();
375 private final Vector<TotalVoiceCountListener> llTVC = new Vector<TotalVoiceCountListener>();
376
377 /**
378 * Determines whether there is at least one subscription for notification events.
379 * Do not forget to check for additional listeners if the LSCP specification
380 * is extended in the future.
381 * @return <code>true</code> if there is at least one subscription for notification events,
382 * <code>false</code> otherwise.
383 */
384 private boolean
385 hasSubscriptions() {
386 return !llBF.isEmpty() ||
387 !llCC.isEmpty() ||
388 !llCI.isEmpty() ||
389 !llM.isEmpty() ||
390 !llSC.isEmpty() ||
391 !llVC.isEmpty() ||
392 !llTVC.isEmpty();
393 }
394
395 private void
396 fireEvent(String s) {
397 if(s.startsWith("CHANNEL_COUNT:")) {
398 try {
399 int i = Integer.parseInt(s.substring("CHANNEL_COUNT:".length()));
400 ChannelCountEvent e = new ChannelCountEvent(this, i);
401 for(ChannelCountListener l : llCC) l.channelCountChanged(e);
402 } catch(NumberFormatException x) {
403 getLogger().log (
404 Level.WARNING, LscpI18n.getLogMsg("CommandFailed!"), x
405 );
406 }
407 } else if(s.startsWith("VOICE_COUNT:")) {
408 try {
409 s = s.substring("VOICE_COUNT:".length());
410 int i = s.indexOf(' ');
411 if(i == -1) {
412 getLogger().warning("Unknown VOICE_COUNT format");
413 return;
414 }
415 int j = Integer.parseInt(s.substring(0, i));
416 i = Integer.parseInt(s.substring(i + 1));
417 VoiceCountEvent e = new VoiceCountEvent(this, j, i);
418 for(VoiceCountListener l : llVC) l.voiceCountChanged(e);
419 } catch(NumberFormatException x) {
420 getLogger().log(Level.WARNING, "Unknown VOICE_COUNT format", x);
421 }
422 } else if(s.startsWith("STREAM_COUNT:")) {
423 try {
424 s = s.substring("STREAM_COUNT:".length());
425 int i = s.indexOf(' ');
426 if(i == -1) {
427 getLogger().warning("Unknown STREAM_COUNT format");
428 return;
429 }
430 int j = Integer.parseInt(s.substring(0, i));
431 i = Integer.parseInt(s.substring(i + 1));
432 StreamCountEvent e = new StreamCountEvent(this, j, i);
433 for(StreamCountListener l : llSC) l.streamCountChanged(e);
434 } catch(NumberFormatException x) {
435 getLogger().log(Level.WARNING, "Unknown STREAM_COUNT format", x);
436 }
437 } else if(s.startsWith("BUFFER_FILL:")) {
438 try {
439 s = s.substring("BUFFER_FILL:".length());
440 int i = s.indexOf(' ');
441 if(i == -1) {
442 getLogger().warning("Unknown STREAM_COUNT format");
443 return;
444 }
445 int j = Integer.parseInt(s.substring(0, i));
446 Vector<BufferFill> v =
447 getChannelBufferFillPercentage(s.substring(i + 1));
448 BufferFillEvent e = new BufferFillEvent(this, j, v);
449 for(BufferFillListener l : llBF) l.bufferFillChanged(e);
450 } catch(Exception x) {
451 getLogger().log(Level.WARNING, "Unknown STREAM_COUNT format", x);
452 }
453 } else if(s.startsWith("CHANNEL_INFO:")) {
454 try {
455 int i = Integer.parseInt(s.substring("CHANNEL_INFO:".length()));
456 ChannelInfoEvent e = new ChannelInfoEvent(this, i);
457 for(ChannelInfoListener l : llCI) l.channelInfoChanged(e);
458 } catch(NumberFormatException x) {
459 getLogger().log(Level.WARNING, "Unknown STREAM_COUNT format", x);
460 }
461 } else if(s.startsWith("TOTAL_VOICE_COUNT:")) {
462 try {
463 s = s.substring("TOTAL_VOICE_COUNT:".length());
464 int i = Integer.parseInt(s);
465 TotalVoiceCountEvent e = new TotalVoiceCountEvent(this, i);
466 for(TotalVoiceCountListener l : llTVC) l.totalVoiceCountChanged(e);
467 } catch(NumberFormatException x) {
468 getLogger().log (
469 Level.WARNING, "Unknown TOTAL_VOICE_COUNT format", x
470 );
471 }
472 } else if(s.startsWith("MISCELLANEOUS:")) {
473 s = s.substring("MISCELLANEOUS:".length());
474 MiscellaneousEvent e = new MiscellaneousEvent(this, s);
475 for(MiscellaneousListener l : llM) l.miscEventOccured(e);
476 }
477 }
478
479 private void
480 subscribe(String event) {
481 if(!isConnected()) return;
482
483 if(!eventThread.isAlive()) eventThread.start();
484
485 try {
486 out.writeLine("SUBSCRIBE " + event);
487 ResultSet rs = getEmptyResultSet();
488 } catch(Exception x) {
489 getLogger().log (
490 Level.WARNING,
491 LscpI18n.getLogMsg("Client.subscriptionFailed!", event),
492 x
493 );
494 }
495 }
496
497 private void
498 unsubscribe(String event) {
499 if(!isConnected()) return;
500
501 try {
502 out.writeLine("UNSUBSCRIBE " + event);
503 ResultSet rs = getEmptyResultSet();
504 } catch(Exception x) {
505 getLogger().log (
506 Level.WARNING,
507 LscpI18n.getLogMsg("Client.unsubscriptionFailed!", event),
508 x
509 );
510 }
511 }
512
513 /**
514 * Registers the specified listener for receiving event messages.
515 * Listeners can be removed regardless of the connection state.
516 * @param l The <code>BufferFillListener</code> to register.
517 */
518 public synchronized void
519 addBufferFillListener(BufferFillListener l) {
520 if(llBF.isEmpty()) subscribe("BUFFER_FILL");
521 llBF.add(l);
522 }
523
524 /**
525 * Removes the specified listener.
526 * Listeners can be removed regardless of the connection state.
527 * @param l The <code>BufferFillListener</code> to remove.
528 */
529 public synchronized void
530 removeBufferFillListener(BufferFillListener l) {
531 boolean b = llBF.remove(l);
532 if(b && llBF.isEmpty()) unsubscribe("BUFFER_FILL");
533 }
534
535 /**
536 * Registers the specified listener for receiving event messages.
537 * Listeners can be registered regardless of the connection state.
538 * @param l The <code>ChannelCountListener</code> to register.
539 */
540 public synchronized void
541 addChannelCountListener(ChannelCountListener l) {
542 if(llCC.isEmpty()) subscribe("CHANNEL_COUNT");
543 llCC.add(l);
544 }
545
546 /**
547 * Removes the specified listener.
548 * Listeners can be removed regardless of the connection state.
549 * @param l The <code>ChannelCountListener</code> to remove.
550 */
551 public synchronized void
552 removeChannelCountListener(ChannelCountListener l) {
553 boolean b = llCC.remove(l);
554 if(b && llCC.isEmpty()) unsubscribe("CHANNEL_COUNT");
555 }
556
557 /**
558 * Registers the specified listener for receiving event messages.
559 * Listeners can be registered regardless of the connection state.
560 * @param l The <code>ChannelInfoListener</code> to register.
561 */
562 public synchronized void
563 addChannelInfoListener(ChannelInfoListener l) {
564 if(llCI.isEmpty()) subscribe("CHANNEL_INFO");
565 llCI.add(l);
566 }
567
568 /**
569 * Removes the specified listener.
570 * Listeners can be removed regardless of the connection state.
571 * @param l The <code>ChannelInfoListener</code> to remove.
572 */
573 public synchronized void
574 removeChannelInfoListener(ChannelInfoListener l) {
575 boolean b = llCI.remove(l);
576 if(b && llCI.isEmpty()) unsubscribe("CHANNEL_INFO");
577 }
578
579 /**
580 * Registers the specified listener for receiving event messages.
581 * Listeners can be registered regardless of the connection state.
582 * @param l The <code>MiscellaneousListener</code> to register.
583 */
584 public synchronized void
585 addMiscellaneousListener(MiscellaneousListener l) {
586 if(llM.isEmpty()) subscribe("MISCELLANEOUS");
587 llM.add(l);
588 }
589
590 /**
591 * Removes the specified listener.
592 * Listeners can be removed regardless of the connection state.
593 * @param l The <code>MiscellaneousListener</code> to remove.
594 */
595 public synchronized void
596 removeMiscellaneousListener(MiscellaneousListener l) {
597 boolean b = llM.remove(l);
598 if(b && llM.isEmpty()) unsubscribe("MISCELLANEOUS");
599 }
600
601 /**
602 * Registers the specified listener for receiving event messages.
603 * Listeners can be registered regardless of the connection state.
604 * @param l The <code>StreamCountListener</code> to register.
605 */
606 public synchronized void
607 addStreamCountListener(StreamCountListener l) {
608 if(llSC.isEmpty()) subscribe("STREAM_COUNT");
609 llSC.add(l);
610 }
611
612 /**
613 * Removes the specified listener.
614 * Listeners can be removed regardless of the connection state.
615 * @param l The <code>StreamCountListener</code> to remove.
616 */
617 public synchronized void
618 removeStreamCountListener(StreamCountListener l) {
619 boolean b = llSC.remove(l);
620 if(b && llSC.isEmpty()) unsubscribe("STREAM_COUNT");
621 }
622
623 /**
624 * Registers the specified listener for receiving event messages.
625 * Listeners can be registered regardless of the connection state.
626 * @param l The <code>VoiceCountListener</code> to register.
627 */
628 public synchronized void
629 addVoiceCountListener(VoiceCountListener l) {
630 if(llVC.isEmpty()) subscribe("VOICE_COUNT");
631 llVC.add(l);
632 }
633
634 /**
635 * Removes the specified listener.
636 * Listeners can be removed regardless of the connection state.
637 * @param l The <code>VoiceCountListener</code> to remove.
638 */
639 public synchronized void
640 removeVoiceCountListener(VoiceCountListener l) {
641 boolean b = llVC.remove(l);
642 if(b && llVC.isEmpty()) unsubscribe("VOICE_COUNT");
643 }
644
645 /**
646 * Registers the specified listener for receiving event messages.
647 * Listeners can be registered regardless of the connection state.
648 * @param l The <code>TotalVoiceCountListener</code> to register.
649 */
650 public synchronized void
651 addTotalVoiceCountListener(TotalVoiceCountListener l) {
652 if(llTVC.isEmpty()) subscribe("TOTAL_VOICE_COUNT");
653 llTVC.add(l);
654 }
655
656 /**
657 * Removes the specified listener.
658 * Listeners can be removed regardless of the connection state.
659 * @param l The <code>TotalVoiceCountListener</code> to remove.
660 */
661 public synchronized void
662 removeTotalVoiceCountListener(TotalVoiceCountListener l) {
663 boolean b = llTVC.remove(l);
664 if(b && llTVC.isEmpty()) unsubscribe("TOTAL_VOICE_COUNT");
665 }
666
667 /**
668 * Gets the number of all audio output drivers currently
669 * available for the LinuxSampler instance.
670 * @return The number of all audio output drivers currently
671 * available for the LinuxSampler instance.
672 * @throws IOException If some I/O error occurs.
673 * @throws LscpException If LSCP protocol corruption occurs.
674 * @throws LSException If some other error occurs.
675 */
676 public synchronized int
677 getAudioOutputDriverCount() throws IOException, LscpException, LSException {
678 verifyConnection();
679 out.writeLine("GET AVAILABLE_AUDIO_OUTPUT_DRIVERS");
680 String s = getSingleLineResultSet().getResult();
681 return parseInt(s);
682 }
683
684 /**
685 * Gets all audio output drivers currently available for the LinuxSampler instance.
686 *
687 * @return <code>AudioOutputDriver</code> array containing all audio output drivers
688 * currently available for the LinuxSampler instance.
689 *
690 * @throws IOException If an I/O error occurs.
691 * @throws LscpException If LSCP protocol corruption occurs.
692 * @throws LSException If some other error occurs.
693 */
694 public synchronized AudioOutputDriver[]
695 getAudioOutputDrivers() throws IOException, LscpException, LSException {
696 String[] drivers = getAudioOutputDriverNames();
697 AudioOutputDriver[] aod = new AudioOutputDriver[drivers.length];
698
699 for(int i = 0; i < aod.length; i++) aod[i] = getAudioOutputDriverInfo(drivers[i]);
700
701 return aod;
702 }
703
704 /**
705 * Gets all audio output drivers currently available for the LinuxSampler instance.
706 *
707 * @return <code>String</code> array containing all audio output drivers currently
708 * available for the LinuxSampler instance.
709 *
710 * @throws IOException If an I/O error occurs.
711 * @throws LscpException If LSCP protocol corruption occurs.
712 * @throws LSException If some other error occurs.
713 */
714 private synchronized String[]
715 getAudioOutputDriverNames() throws IOException, LscpException, LSException {
716 verifyConnection();
717 out.writeLine("LIST AVAILABLE_AUDIO_OUTPUT_DRIVERS");
718 return parseList(getSingleLineResultSet().getResult());
719 }
720
721 /**
722 * Gets detailed information about a specific audio output driver.
723 * @param driverName The name of the audio output driver.
724 *
725 * @return An <code>AudioOutputDriver</code> object containing
726 * information about the specified audio output driver.
727 *
728 * @throws IOException If an I/O error occurs.
729 * @throws LscpException If LSCP protocol corruption occurs.
730 * @throws LSException If there is no driver with name <code>driverName</code>.
731 *
732 * @see #getAudioOutputDriverNames
733 */
734 private synchronized AudioOutputDriver
735 getAudioOutputDriverInfo(String driverName) throws IOException, LscpException, LSException {
736 verifyConnection();
737 out.writeLine("GET AUDIO_OUTPUT_DRIVER INFO " + driverName);
738 ResultSet rs = getMultiLineResultSet();
739 AudioOutputDriver aod = new AudioOutputDriver(rs.getMultiLineResult());
740 aod.setName(driverName);
741
742 for(String s : aod.getParameterNames())
743 aod.addParameter(getAudioOutputDriverParameterInfo(driverName, s));
744
745 return aod;
746 }
747
748 /**
749 * Gets detailed information about a specific audio output driver parameter.
750 *
751 * @param driver The name of the audio output driver.
752 * @param param A specific parameter name for which information should be obtained.
753 * @param deplist An optional list of parameters on which the sought parameter
754 * <code>param</code> depends on. <code>Parameter</code> instances can be
755 * easily created using {@link ParameterFactory} factory.
756 *
757 * @return <code>Parameter</code> object containing
758 * information about the specified audio output driver parameter.
759 *
760 * @throws IOException If an I/O error occurs.
761 * @throws LscpException If LSCP protocol corruption occurs.
762 * @throws LSException If <code>driver</code> is not a valid driver name
763 * or <code>param</code> is not a valid parameter for the specified driver.
764 *
765 * @see #getAudioOutputDrivers
766 * @see #getAudioOutputDriverInfo
767 * @see ParameterFactory
768 */
769 public synchronized Parameter
770 getAudioOutputDriverParameterInfo(String driver, String param, Parameter... deplist)
771 throws IOException, LscpException, LSException {
772
773 verifyConnection();
774 StringBuffer args = new StringBuffer(driver);
775 args.append(' ').append(param);
776
777 for(Parameter p : deplist)
778 args.append(' ').append(p.getName()).append('=').append(p.getStringValue());
779
780 out.writeLine("GET AUDIO_OUTPUT_DRIVER_PARAMETER INFO " + args.toString());
781
782 ResultSet rs = getMultiLineResultSet();
783
784 String[] lnS = rs.getMultiLineResult();
785 ParameterType type = parseType(lnS);
786 boolean multi = parseMultiplicity(lnS);
787 Parameter prm;
788
789 switch(type) {
790 case BOOL:
791 if(!multi) prm = new BoolParameter(lnS);
792 else prm = new BoolListParameter(lnS);
793 prm.setName(param);
794 prm.setValue(prm.getDefault());
795 return prm;
796 case INT:
797 if(!multi) prm = new IntParameter(lnS);
798 else prm = new IntListParameter(lnS);
799 prm.setName(param);
800 prm.setValue(prm.getDefault());
801 return prm;
802 case FLOAT:
803 if(!multi) prm = new FloatParameter(lnS);
804 else prm = new FloatListParameter(lnS);
805 prm.setName(param);
806 prm.setValue(prm.getDefault());
807 return prm;
808 case STRING:
809 if(!multi) prm = new StringParameter(lnS);
810 else prm = new StringListParameter(lnS);
811 prm.setName(param);
812 prm.setValue(prm.getDefault());
813 return prm;
814 default: throw new LscpException(LscpI18n.getLogMsg("Client.unknownPrmType!"));
815 }
816 }
817
818 /**
819 * Creates a new audio output device for the desired audio output system.
820 * @param aoDriver The desired audio output system.
821 * @param paramList An optional list of driver specific parameters. <code>Parameter</code>
822 * instances can be easily created using {@link ParameterFactory} factory.
823 * @return The numerical ID of the newly created device.
824 * @throws IOException If some I/O error occurs.
825 * @throws LSException If the creation of the new audio output device failed.
826 * @throws LscpException If LSCP protocol corruption occurs.
827 * @see #getAudioOutputDrivers
828 * @see #getAudioOutputDriverInfo
829 * @see ParameterFactory
830 */
831 public synchronized int
832 createAudioOutputDevice(String aoDriver, Parameter... paramList)
833 throws IOException, LSException, LscpException {
834
835 verifyConnection();
836 StringBuffer args = new StringBuffer(aoDriver);
837
838 for(Parameter p : paramList)
839 args.append(' ').append(p.getName()).append('=').append(p.getStringValue());
840
841 out.writeLine("CREATE AUDIO_OUTPUT_DEVICE " + args.toString());
842 ResultSet rs = getEmptyResultSet();
843
844 return rs.getIndex();
845 }
846
847 /**
848 * Destroys already created audio output device.
849 * @param deviceID The ID of the audio output device to be destroyed.
850 * @throws IOException If some I/O error occurs.
851 * @throws LSException If the destroying of the audio output device failed.
852 * @throws LscpException If LSCP protocol corruption occurs.
853 * @see #getAudioOutputDevices
854 */
855 public synchronized void
856 destroyAudioOutputDevice(int deviceID) throws IOException, LSException, LscpException {
857 verifyConnection();
858 out.writeLine("DESTROY AUDIO_OUTPUT_DEVICE " + deviceID);
859 ResultSet rs = getEmptyResultSet();
860 }
861
862 /**
863 * Enables/disables the specified audio output device.
864 * @param deviceID The ID of the audio output device to be enabled/disabled.
865 * @param enable If <code>true</code> the audio output device is enabled,
866 * else the device is disabled.
867 * @throws IOException If some I/O error occurs.
868 * @throws LSException If there is no audio output
869 * device with numerical ID <code>deviceID</code>.
870 * @throws LscpException If LSCP protocol corruption occurs.
871 */
872 public void
873 enableAudioOutputDevice(int deviceID, boolean enable)
874 throws IOException, LSException, LscpException {
875
876 setAudioOutputDeviceParameter(deviceID, new BoolParameter("ACTIVE", enable));
877 }
878
879 /**
880 * Gets the current number of all created audio output devices.
881 * @return The current number of all created audio output devices.
882 * @throws IOException If some I/O error occurs.
883 * @throws LscpException If LSCP protocol corruption occurs.
884 * @throws LSException If some other error occurs.
885 */
886 public synchronized int
887 getAudioOutputDeviceCount() throws IOException, LscpException, LSException {
888 verifyConnection();
889 out.writeLine("GET AUDIO_OUTPUT_DEVICES");
890 String s = getSingleLineResultSet().getResult();
891 return parseInt(s);
892 }
893
894 /**
895 * Gets a list of all created audio output devices.
896 * @return An <code>AudioOutputDevice</code> array
897 * providing all created audio output devices.
898 * @throws IOException If some I/O error occurs.
899 * @throws LscpException If LSCP protocol corruption occurs.
900 * @throws LSException If some other error occurs.
901 */
902 public synchronized AudioOutputDevice[]
903 getAudioOutputDevices() throws IOException, LscpException, LSException {
904 Integer[] idS = getAudioOutputDeviceIDs();
905 AudioOutputDevice[] devices = new AudioOutputDevice[idS.length];
906
907 for(int i = 0; i < devices.length; i++)
908 devices[i] = getAudioOutputDeviceInfo(idS[i]);
909
910 return devices;
911 }
912
913 /**
914 * Gets a list of numerical IDs of all created audio output devices.
915 * @return An <code>Integer</code> array providing the numerical IDs of
916 * all created audio output devices.
917 * @throws IOException If some I/O error occurs.
918 * @throws LscpException If LSCP protocol corruption occurs.
919 * @throws LSException If some other error occurs.
920 */
921 public synchronized Integer[]
922 getAudioOutputDeviceIDs() throws IOException, LscpException, LSException {
923 verifyConnection();
924 out.writeLine("LIST AUDIO_OUTPUT_DEVICES");
925 return parseIntList(getSingleLineResultSet().getResult());
926 }
927
928 /**
929 * Gets the current settings of a specific, already created audio output device.
930 *
931 * @param deviceID Specifies the numerical ID of the audio output device.
932 *
933 * @return An <code>AudioOutputDevice</code> instance containing information
934 * about the specified device.
935 *
936 * @throws IOException If some I/O error occurs.
937 * @throws LscpException If LSCP protocol corruption occurs.
938 * @throws LSException If there is no audio output device
939 * with device id <code>deviceID</code>.
940 *
941 * @see #getAudioOutputDevices
942 */
943 public synchronized AudioOutputDevice
944 getAudioOutputDeviceInfo(int deviceID) throws IOException, LscpException, LSException {
945 verifyConnection();
946 out.writeLine("GET AUDIO_OUTPUT_DEVICE INFO " + deviceID);
947
948 ResultSet rs = getMultiLineResultSet();
949
950 String[] lnS = rs.getMultiLineResult();
951
952 AudioOutputDevice aod = new AudioOutputDevice();
953 aod.setDeviceID(deviceID);
954 Parameter<Integer> channels;
955 Parameter<Integer> samplerate;
956
957 String drv = getCategoryInfo(lnS, "DRIVER");
958 aod.setDriverName(drv);
959
960 for(String s : lnS) {
961 if(s.startsWith("CHANNELS: ")) {
962 channels = (Parameter<Integer>)
963 getAudioOutputDriverParameterInfo(drv, "CHANNELS");
964
965 s = s.substring("CHANNELS: ".length(), s.length());
966 channels.parseValue(s);
967 aod.setChannelsParameter(channels);
968 int count = channels.getValue() > 0 ? channels.getValue() : 0;
969 AudioOutputChannel[] aoc = new AudioOutputChannel[count];
970 for(int i = 0; i < count; i++) {
971 aoc[i] = this.getAudioOutputChannelInfo(deviceID, i);
972 }
973 aod.setAudioChannels(aoc);
974 } else if(s.startsWith("SAMPLERATE: ")) {
975 samplerate = (Parameter<Integer>)
976 getAudioOutputDriverParameterInfo(drv, "SAMPLERATE");
977
978 s = s.substring("SAMPLERATE: ".length(), s.length());
979 samplerate.parseValue(s);
980 aod.setSampleRateParameter(samplerate);
981 } else if(s.startsWith("ACTIVE: ")) {
982 s = s.substring("ACTIVE: ".length(), s.length());
983 aod.setActive(Boolean.parseBoolean(s));
984 } else if(s.startsWith("DRIVER: ")) {
985
986 } else {
987 int i = s.indexOf(": ");
988 if(i == -1) throw new LscpException (
989 LscpI18n.getLogMsg("CommandFailed!")
990 );
991
992 Parameter prm =
993 getAudioOutputDriverParameterInfo(drv, s.substring(0, i));
994
995 s = s.substring(i + 2);
996 prm.parseValue(s);
997
998 aod.addParameter(prm);
999 }
1000 }
1001
1002 return aod;
1003 }
1004
1005 /**
1006 * Alters a specific setting of a created audio output device.
1007 *
1008 * @param deviceID The numerical ID of the audio output device.
1009 * @param prm A <code>Parameter</code> instance containing the name of the parameter
1010 * and the new value for this parameter.
1011 *
1012 * @throws IOException If some I/O error occurs.
1013 * @throws LscpException If LSCP protocol corruption occurs.
1014 * @throws LSException If
1015 * <ul>
1016 * <li>There is no audio output device with numerical ID <code>deviceID</code>;
1017 * <li>There is no device parameter with the specified name;
1018 * <li>The device parameter is readonly;
1019 * <li>The device parameter is from different type.
1020 * </ul>
1021 *
1022 * @see #getAudioOutputDevices
1023 * @see #getAudioOutputDeviceInfo
1024 */
1025 public synchronized void
1026 setAudioOutputDeviceParameter(int deviceID, Parameter prm)
1027 throws IOException, LscpException, LSException {
1028
1029 verifyConnection();
1030 String kv = prm.getName() + '=' + prm.getStringValue();
1031 out.writeLine("SET AUDIO_OUTPUT_DEVICE_PARAMETER " + deviceID + ' ' + kv);
1032
1033 ResultSet rs = getEmptyResultSet();
1034 }
1035
1036 /**
1037 * Changes the channels number of the speicifed audio output device.
1038 * @param deviceID The numerical ID of the audio output device.
1039 * @param channels The new number of audio output channels.
1040 *
1041 * @throws IOException If an I/O error occurs.
1042 * @throws LscpException If LSCP protocol corruption occurs.
1043 * @throws LSException If there is no device with ID <code>deviceID</code> or
1044 * if <code>channels</code> number is out of range.
1045 *
1046 * @see #getAudioOutputChannelInfo
1047 */
1048 public synchronized void
1049 setAudioOutputChannelCount(int deviceID, int channels)
1050 throws IOException, LscpException, LSException {
1051
1052 setAudioOutputDeviceParameter(deviceID, new IntParameter("CHANNELS", channels));
1053 }
1054
1055 /**
1056 * Gets information about an audio channel.
1057 *
1058 * @param deviceID The numerical ID of the audio output device.
1059 * @param audioChn The audio channel number.
1060 *
1061 * @return An <code>AudioOutputChannel</code> instance containing the
1062 * information about the specified audio output channel.
1063 *
1064 * @throws IOException If some I/O error occurs.
1065 * @throws LscpException If LSCP protocol corruption occurs.
1066 * @throws LSException If
1067 * <ul>
1068 * <li>There is no audio output device with numerical ID <code>deviceID</code>;
1069 * <li><code>audioChn</code> is not a valid channel number;
1070 * </ul>
1071 *
1072 * @see #getAudioOutputDevices
1073 * @see #getAudioOutputDeviceInfo
1074 */
1075 public synchronized AudioOutputChannel
1076 getAudioOutputChannelInfo(int deviceID, int audioChn)
1077 throws IOException, LscpException, LSException {
1078
1079 verifyConnection();
1080 out.writeLine("GET AUDIO_OUTPUT_CHANNEL INFO " + deviceID + ' ' + audioChn);
1081
1082 ResultSet rs = getMultiLineResultSet();
1083
1084 AudioOutputChannel aoc = new AudioOutputChannel();
1085
1086 String[] lnS = rs.getMultiLineResult();
1087 for(String s : lnS) {
1088 if(s.startsWith("NAME: ")) {
1089 s = s.substring("NAME: ".length());
1090 Parameter<String> prm = getAudioOutputChannelParameterInfo (
1091 deviceID, audioChn, "NAME"
1092 );
1093 prm.setValue(removeQuotation(s));
1094 aoc.setNameParameter(prm);
1095 } else if(s.startsWith("IS_MIX_CHANNEL: ")) {
1096 s = s.substring("IS_MIX_CHANNEL: ".length());
1097 Parameter<Boolean> prm = getAudioOutputChannelParameterInfo (
1098 deviceID, audioChn, "IS_MIX_CHANNEL"
1099 );
1100 prm.setValue(Boolean.parseBoolean(s));
1101 aoc.setMixChannelParameter(prm);
1102 } else if(s.startsWith("MIX_CHANNEL_DESTINATION: ")) {
1103 s = s.substring("MIX_CHANNEL_DESTINATION: ".length());
1104 Parameter<Integer> prm = getAudioOutputChannelParameterInfo (
1105 deviceID, audioChn, "MIX_CHANNEL_DESTINATION"
1106 );
1107 prm.setValue(parseInt(s));
1108 aoc.setMixChannelDestParameter(prm);
1109 } else {
1110 int i = s.indexOf(": ");
1111 if(i == -1) throw new LscpException (
1112 LscpI18n.getLogMsg("CommandFailed!")
1113 );
1114
1115 Parameter prm = getAudioOutputChannelParameterInfo (
1116 deviceID, audioChn, s.substring(0, i)
1117 );
1118
1119 s = s.substring(i + 2);
1120 prm.parseValue(s);
1121
1122 aoc.addParameter(prm);
1123 }
1124 }
1125
1126 return aoc;
1127 }
1128
1129 /**
1130 * Gets detailed information about a specific audio output channel parameter.
1131 *
1132 * @param devID The numerical ID of the audio output device.
1133 * @param chan The audio channel number.
1134 * @param param a specific channel parameter name for which information should be obtained.
1135 *
1136 * @return An <code>Parameter</code> instance containing
1137 * information about the specified audio output channel parameter.
1138 *
1139 * @throws IOException If an I/O error occurs.
1140 * @throws LscpException If LSCP protocol corruption occurs.
1141 * @throws LSException If
1142 * <ul>
1143 * <li><code>devID</code> is not a valid device ID;
1144 * <li><code>chan</code> is not a valid channel number;
1145 * <li>There is no channel parameter with the specified name.
1146 * </ul>
1147 *
1148 * @see #getAudioOutputDevices
1149 * @see #getAudioOutputChannelInfo
1150 */
1151 public synchronized Parameter
1152 getAudioOutputChannelParameterInfo(int devID, int chan, String param)
1153 throws IOException, LscpException, LSException {
1154
1155 verifyConnection();
1156 String args = devID + " " + chan + " " + param;
1157 out.writeLine("GET AUDIO_OUTPUT_CHANNEL_PARAMETER INFO " + args);
1158
1159 ResultSet rs = getMultiLineResultSet();
1160
1161 String[] lnS = rs.getMultiLineResult();
1162 ParameterType type = parseType(lnS);
1163 boolean multi = parseMultiplicity(lnS);
1164 Parameter prm;
1165
1166 switch(type) {
1167 case BOOL:
1168 if(!multi) prm = new BoolParameter(lnS);
1169 else prm = new BoolListParameter(lnS);
1170 prm.setName(param);
1171 return prm;
1172 case INT:
1173 if(!multi) prm = new IntParameter(lnS);
1174 else prm = new IntListParameter(lnS);
1175 prm.setName(param);
1176 return prm;
1177 case FLOAT:
1178 if(!multi) prm = new FloatParameter(lnS);
1179 else prm = new FloatListParameter(lnS);
1180 prm.setName(param);
1181 return prm;
1182 case STRING:
1183 if(!multi) prm = new StringParameter(lnS);
1184 else prm = new StringListParameter(lnS);
1185 prm.setName(param);
1186 return prm;
1187 default: throw new LscpException(LscpI18n.getLogMsg("Client.unknownPrmType!"));
1188 }
1189 }
1190
1191 /**
1192 * Alters a specific setting of an audio output channel.
1193 *
1194 * @param devID The numerical ID of the audio device.
1195 * @param chn The audio channel number.
1196 * @param prm A <code>Parameter</code> instance containing the name of the parameter
1197 * and the new value for this parameter.
1198 *
1199 * @throws IOException If some I/O error occurs.
1200 * @throws LscpException If LSCP protocol corruption occurs.
1201 * @throws LSException If
1202 * <ul>
1203 * <li>There is no audio output device with numerical ID <code>devID</code>;
1204 * <li><code>chn</code> is not a valid channel number;
1205 * <li>There is no channel parameter with the specified name;
1206 * <li>The channel parameter is readonly;
1207 * <li>The channel parameter is from different type.
1208 * </ul>
1209 *
1210 * @see #getAudioOutputDevices
1211 * @see #getAudioOutputChannelInfo
1212 */
1213 public synchronized void
1214 setAudioOutputChannelParameter(int devID, int chn, Parameter prm)
1215 throws IOException, LscpException, LSException {
1216
1217 verifyConnection();
1218 String args = devID + " " + chn + " " + prm.getName() + '=' + prm.getStringValue();
1219 out.writeLine("SET AUDIO_OUTPUT_CHANNEL_PARAMETER " + args);
1220
1221 ResultSet rs = getEmptyResultSet();
1222 }
1223
1224 /**
1225 * Gets the current number of all MIDI input drivers.
1226 * @return The current number of all MIDI input drivers.
1227 * @throws IOException If some I/O error occurs.
1228 * @throws LscpException If LSCP protocol corruption occurs.
1229 * @throws LSException If some other error occurs.
1230 */
1231 public synchronized int
1232 getMidiInputDriverCount() throws IOException, LscpException, LSException {
1233 verifyConnection();
1234 out.writeLine("GET AVAILABLE_MIDI_INPUT_DRIVERS");
1235 String s = getSingleLineResultSet().getResult();
1236 return parseInt(s);
1237 }
1238
1239 /**
1240 * Gets all MIDI input drivers currently available for the LinuxSampler instance.
1241 *
1242 * @return <code>MidiInputDriver</code> array containing all MIDI input drivers currently
1243 * available for the LinuxSampler instance.
1244 *
1245 * @throws IOException If an I/O error occurs.
1246 * @throws LscpException If LSCP protocol corruption occurs.
1247 * @throws LSException If some other error occurs.
1248 */
1249 public synchronized MidiInputDriver[]
1250 getMidiInputDrivers() throws IOException, LscpException, LSException {
1251 String[] drivers = getMidiInputDriverNames();
1252 MidiInputDriver[] mid = new MidiInputDriver[drivers.length];
1253
1254 for(int i = 0; i < mid.length; i++) mid[i] = getMidiInputDriverInfo(drivers[i]);
1255
1256 return mid;
1257 }
1258
1259 /**
1260 * Gets all MIDI input drivers currently available for the LinuxSampler instance.
1261 *
1262 * @return <code>String</code> array containing all MIDI input drivers currently available
1263 * for the LinuxSampler instance.
1264 *
1265 * @throws IOException If an I/O error occurs.
1266 * @throws LscpException If LSCP protocol corruption occurs.
1267 * @throws LSException If some other error occurs.
1268 */
1269 private synchronized String[]
1270 getMidiInputDriverNames() throws IOException, LscpException, LSException {
1271 verifyConnection();
1272 out.writeLine("LIST AVAILABLE_MIDI_INPUT_DRIVERS");
1273 return parseList(getSingleLineResultSet().getResult());
1274 }
1275
1276 /**
1277 * Gets detailed information about a specific MIDI input driver.
1278 * @param driverName The name of the MIDI input driver.
1279 *
1280 * @return A <code>MidiInputDriver</code> object containing
1281 * information about the specified MIDI input driver.
1282 *
1283 * @throws IOException If an I/O error occurs.
1284 * @throws LscpException If LSCP protocol corruption occurs.
1285 * @throws LSException If there is no driver with name <code>driverName</code>.
1286 *
1287 * @see #getMidiInputDriverNames
1288 */
1289 private synchronized MidiInputDriver
1290 getMidiInputDriverInfo(String driverName) throws IOException, LscpException, LSException {
1291 verifyConnection();
1292 out.writeLine("GET MIDI_INPUT_DRIVER INFO " + driverName);
1293 ResultSet rs = getMultiLineResultSet();
1294
1295 MidiInputDriver mid = new MidiInputDriver(rs.getMultiLineResult());
1296 mid.setName(driverName);
1297
1298 for(String s : mid.getParameterNames())
1299 mid.addParameter(getMidiInputDriverParameterInfo(driverName, s));
1300
1301 return mid;
1302 }
1303
1304 /**
1305 * Gets detailed information about a specific MIDI input driver parameter.
1306 *
1307 * @param driver The name of the MIDI input driver.
1308 * @param param a specific parameter name for which information should be obtained.
1309 * @param deplist An optional list of parameters on which the sought parameter
1310 * <code>param</code> depends on. <code>Parameter</code> instances can be
1311 * easily created using {@link ParameterFactory} factory.
1312 *
1313 * @return A <code>Parameter</code> object containing
1314 * information about the specified MIDI input driver parameter.
1315 *
1316 * @throws IOException If an I/O error occurs.
1317 * @throws LscpException If LSCP protocol corruption occurs.
1318 * @throws LSException If <code>driver</code> is not a valid driver name
1319 * or <code>param</code> is not a valid parameter for the specified driver.
1320 *
1321 * @see #getMidiInputDrivers
1322 * @see #getMidiInputDriverInfo
1323 * @see ParameterFactory
1324 */
1325 public synchronized Parameter
1326 getMidiInputDriverParameterInfo(String driver, String param, Parameter... deplist)
1327 throws IOException, LscpException, LSException {
1328
1329 verifyConnection();
1330 StringBuffer args = new StringBuffer(driver);
1331 args.append(' ').append(param);
1332
1333 for(Parameter p : deplist)
1334 args.append(' ').append(p.getName()).append('=').append(p.getStringValue());
1335
1336 out.writeLine("GET MIDI_INPUT_DRIVER_PARAMETER INFO " + args.toString());
1337
1338 ResultSet rs = getMultiLineResultSet();
1339
1340 String[] lnS = rs.getMultiLineResult();
1341 ParameterType type = parseType(lnS);
1342 boolean multi = parseMultiplicity(lnS);
1343 Parameter prm;
1344
1345 switch(type) {
1346 case BOOL:
1347 if(!multi) prm = new BoolParameter(lnS);
1348 else prm = new BoolListParameter(lnS);
1349 prm.setName(param);
1350 prm.setValue(prm.getDefault());
1351 return prm;
1352 case INT:
1353 if(!multi) prm = new IntParameter(lnS);
1354 else prm = new IntListParameter(lnS);
1355 prm.setName(param);
1356 prm.setValue(prm.getDefault());
1357 return prm;
1358 case FLOAT:
1359 if(!multi) prm = new FloatParameter(lnS);
1360 else prm = new FloatListParameter(lnS);
1361 prm.setName(param);
1362 prm.setValue(prm.getDefault());
1363 return prm;
1364 case STRING:
1365 if(!multi) prm = new StringParameter(lnS);
1366 else prm = new StringListParameter(lnS);
1367 prm.setName(param);
1368 prm.setValue(prm.getDefault());
1369 return prm;
1370 default: throw new LscpException(LscpI18n.getLogMsg("Client.unknownPrmType!"));
1371 }
1372 }
1373
1374 /**
1375 * Creates a new MIDI input device.
1376 * @param miDriver The desired MIDI input system.
1377 * @param paramList An optional list of driver specific parameters. <code>Parameter</code>
1378 * instances can be easily created using {@link ParameterFactory} factory.
1379 * @return The numerical ID of the newly created device.
1380 * @throws IOException If some I/O error occurs.
1381 * @throws LSException If the creation of the new MIDI input device failed.
1382 * @throws LscpException If LSCP protocol corruption occurs.
1383 *
1384 * @see #getMidiInputDrivers
1385 * @see #getMidiInputDriverInfo
1386 * @see ParameterFactory
1387 */
1388 public synchronized int
1389 createMidiInputDevice(String miDriver, Parameter... paramList)
1390 throws IOException, LSException, LscpException {
1391
1392 verifyConnection();
1393 StringBuffer args = new StringBuffer(miDriver);
1394
1395 for(Parameter p : paramList)
1396 args.append(' ').append(p.getName()).append('=').append(p.getStringValue());
1397
1398 out.writeLine("CREATE MIDI_INPUT_DEVICE " + args.toString());
1399 ResultSet rs = getEmptyResultSet();
1400
1401 return rs.getIndex();
1402 }
1403
1404 /**
1405 * Destroys already created MIDI input device.
1406 * @param deviceID The numerical ID of the MIDI input device to be destroyed.
1407 * @throws IOException If some I/O error occurs.
1408 * @throws LSException If the destroying of the MIDI input device failed.
1409 * @throws LscpException If LSCP protocol corruption occurs.
1410 * @see #createMidiInputDevice
1411 * @see #getMidiInputDevices
1412 */
1413 public synchronized void
1414 destroyMidiInputDevice(int deviceID) throws IOException, LSException, LscpException {
1415 verifyConnection();
1416 out.writeLine("DESTROY MIDI_INPUT_DEVICE " + deviceID);
1417 ResultSet rs = getEmptyResultSet();
1418 }
1419
1420 /**
1421 * Enables/disables the specified MIDI input device.
1422 * @param deviceID The ID of the MIDI input device to be enabled/disabled.
1423 * @param enable If <code>true</code> the MIDI input device is enabled,
1424 * else the device is disabled.
1425 * @throws IOException If some I/O error occurs.
1426 * @throws LSException If there is no MIDI input
1427 * device with numerical ID <code>deviceID</code>.
1428 * @throws LscpException If LSCP protocol corruption occurs.
1429 */
1430 public void
1431 enableMidiInputDevice(int deviceID, boolean enable)
1432 throws IOException, LSException, LscpException {
1433
1434 setMidiInputDeviceParameter(deviceID, new BoolParameter("ACTIVE", enable));
1435 }
1436
1437 /**
1438 * Gets the current number of all created MIDI input devices.
1439 * @return The current number of all created MIDI input devices.
1440 * @throws IOException If some I/O error occurs.
1441 * @throws LscpException If LSCP protocol corruption occurs.
1442 * @throws LSException If some other error occurs.
1443 */
1444 public synchronized int
1445 getMidiInputDeviceCount() throws IOException, LscpException, LSException {
1446 verifyConnection();
1447 out.writeLine("GET MIDI_INPUT_DEVICES");
1448 String s = getSingleLineResultSet().getResult();
1449 return parseInt(s);
1450 }
1451
1452 /**
1453 * Gets a list of all created MIDI input devices.
1454 * @return A <code>MidiInputDevice</code> array
1455 * providing all created MIDI input devices.
1456 * @throws IOException If some I/O error occurs.
1457 * @throws LscpException If LSCP protocol corruption occurs.
1458 * @throws LSException If some other error occurs.
1459 *
1460 * @see #createMidiInputDevice
1461 * @see #destroyMidiInputDevice
1462 */
1463 public synchronized MidiInputDevice[]
1464 getMidiInputDevices() throws IOException, LscpException, LSException {
1465 Integer[] idS = getMidiInputDeviceIDs();
1466 MidiInputDevice[] devices = new MidiInputDevice[idS.length];
1467
1468 for(int i = 0; i < devices.length; i++)
1469 devices[i] = getMidiInputDeviceInfo(idS[i]);
1470
1471 return devices;
1472 }
1473
1474 /**
1475 * Gets a list of numerical IDs of all created MIDI input devices.
1476 * @return An <code>Integer</code> array providing the numerical IDs of
1477 * all created MIDI input devices.
1478 * @throws IOException If some I/O error occurs.
1479 * @throws LscpException If LSCP protocol corruption occurs.
1480 * @throws LSException If some other error occurs.
1481 *
1482 * @see #createMidiInputDevice
1483 * @see #destroyMidiInputDevice
1484 */
1485 public synchronized Integer[]
1486 getMidiInputDeviceIDs() throws IOException, LscpException, LSException {
1487 verifyConnection();
1488 out.writeLine("LIST MIDI_INPUT_DEVICES");
1489 return parseIntList(getSingleLineResultSet().getResult());
1490 }
1491
1492 /**
1493 * Gets the current settings of a specific, already created MIDI input device.
1494 *
1495 * @param deviceID Specifies the numerical ID of the MIDI input device.
1496 *
1497 * @return An <code>MidiInputDevice</code> instance containing information
1498 * about the specified device.
1499 *
1500 * @throws IOException If some I/O error occurs.
1501 * @throws LscpException If LSCP protocol corruption occurs.
1502 * @throws LSException If there is no MIDI input device
1503 * with device id <code>deviceID</code>.
1504 *
1505 * @see #getMidiInputDevices
1506 */
1507 public synchronized MidiInputDevice
1508 getMidiInputDeviceInfo(int deviceID) throws IOException, LscpException, LSException {
1509 verifyConnection();
1510 out.writeLine("GET MIDI_INPUT_DEVICE INFO " + deviceID);
1511
1512 ResultSet rs = getMultiLineResultSet();
1513
1514 String[] lnS = rs.getMultiLineResult();
1515
1516 MidiInputDevice mid = new MidiInputDevice();
1517 mid.setDeviceID(deviceID);
1518
1519 String drv = getCategoryInfo(lnS, "DRIVER");
1520 mid.setDriverName(drv);
1521
1522 for(String s : lnS) {
1523 if(s.startsWith("DRIVER: ")) {
1524
1525 } else if(s.startsWith("ACTIVE: ")) {
1526 s = s.substring("ACTIVE: ".length());
1527 mid.setActive(Boolean.parseBoolean(s));
1528 } else if(s.startsWith("PORTS: ")) {
1529 s = s.substring("PORTS: ".length());
1530 int ports = Parser.parseInt(s);
1531 MidiPort[] midiPorts = new MidiPort[ports > 0 ? ports : 0];
1532
1533 for(int i = 0; i < midiPorts.length; i++)
1534 midiPorts[i] = getMidiInputPortInfo(deviceID, i);
1535
1536 mid.setMidiPorts(midiPorts);
1537 } else {
1538 int i = s.indexOf(": ");
1539 if(i == -1) throw new LscpException (
1540 LscpI18n.getLogMsg("CommandFailed!")
1541 );
1542
1543 Parameter prm =
1544 getMidiInputDriverParameterInfo(drv, s.substring(0, i));
1545
1546 s = s.substring(i + 2);
1547 prm.parseValue(s);
1548
1549 mid.addParameter(prm);
1550 }
1551 }
1552
1553 return mid;
1554 }
1555
1556 /**
1557 * Alters a specific setting of a created MIDI input device.
1558 *
1559 * @param deviceID The numerical ID of the MIDI input device.
1560 * @param prm A <code>Parameter</code> instance containing the name of the parameter
1561 * and the new value for this parameter.
1562 *
1563 * @throws IOException If some I/O error occurs.
1564 * @throws LscpException If LSCP protocol corruption occurs.
1565 * @throws LSException If
1566 * <ul>
1567 * <li>There is no MIDI input device with numerical ID <code>deviceID</code>;
1568 * <li>There is no device parameter with the specified name;
1569 * <li>The device parameter is readonly;
1570 * <li>The device parameter is from different type.
1571 * </ul>
1572 *
1573 * @see #getMidiInputDevices
1574 * @see #getMidiInputDeviceInfo
1575 */
1576 public synchronized void
1577 setMidiInputDeviceParameter(int deviceID, Parameter prm)
1578 throws IOException, LscpException, LSException {
1579
1580 verifyConnection();
1581 String kv = prm.getName() + '=' + prm.getStringValue();
1582 out.writeLine("SET MIDI_INPUT_DEVICE_PARAMETER " + deviceID + ' ' + kv);
1583
1584 ResultSet rs = getEmptyResultSet();
1585 }
1586
1587
1588 /**
1589 * Changes the ports number of the speicifed MIDI input device.
1590 * @param deviceID The numerical ID of the MIDI input device.
1591 * @param ports The new number of MIDI input ports.
1592 *
1593 * @throws IOException If an I/O error occurs.
1594 * @throws LscpException If LSCP protocol corruption occurs.
1595 * @throws LSException If there is no device with ID <code>deviceID</code> or
1596 * if <code>ports</code> number is out of range.
1597 *
1598 * @see #getMidiInputPortInfo
1599 */
1600 public synchronized void
1601 setMidiInputPortCount(int deviceID, int ports)
1602 throws IOException, LscpException, LSException {
1603
1604 setMidiInputDeviceParameter(deviceID, new IntParameter("PORTS", ports));
1605 }
1606
1607 /**
1608 * Gets detailed information about a specific MIDI input port.
1609 * @param deviceID The numerical ID of the MIDI input device.
1610 * @param midiPort The MIDI input port number.
1611 *
1612 * @return A <code>MidiPort</code> instance containing
1613 * information about the specified MIDI input port.
1614 *
1615 * @throws IOException If an I/O error occurs.
1616 * @throws LscpException If LSCP protocol corruption occurs.
1617 * @throws LSException If there is no device with ID <code>deviceID</code> or
1618 * if <code>midiPort</code> is not a valid MIDI port number.
1619 *
1620 * @see #getMidiInputDevices
1621 */
1622 public synchronized MidiPort
1623 getMidiInputPortInfo(int deviceID, int midiPort)
1624 throws IOException, LscpException, LSException {
1625
1626 verifyConnection();
1627 out.writeLine("GET MIDI_INPUT_PORT INFO " + deviceID + " " + midiPort);
1628 ResultSet rs = getMultiLineResultSet();
1629
1630 MidiPort mp = new MidiPort();
1631 String[] lnS = rs.getMultiLineResult();
1632
1633 for(String s : lnS) {
1634 if(s.startsWith("NAME: ")) {
1635 s = s.substring("NAME: ".length());
1636 Parameter prm = getMidiInputPortParameterInfo (
1637 deviceID, midiPort, "NAME"
1638 );
1639 prm.setValue(removeQuotation(s));
1640 mp.setNameParameter(prm);
1641 } else {
1642 int i = s.indexOf(": ");
1643 if(i == -1) throw new LscpException (
1644 LscpI18n.getLogMsg("CommandFailed!")
1645 );
1646
1647 Parameter prm = getMidiInputPortParameterInfo (
1648 deviceID, midiPort, s.substring(0, i)
1649 );
1650
1651 s = s.substring(i + 2);
1652 prm.parseValue(s);
1653
1654 mp.addParameter(prm);
1655 }
1656 }
1657
1658 return mp;
1659 }
1660
1661 /**
1662 * Gets detailed information about a specific MIDI input port parameter.
1663 *
1664 * @param deviceID The numerical ID of the MIDI input device.
1665 * @param port The MIDI port number.
1666 * @param param A specific parameter name for which information should be obtained.
1667 *
1668 * @return A <code>Parameter</code> instance containing
1669 * information about the specified MIDI input port parameter.
1670 *
1671 * @throws IOException If an I/O error occurs.
1672 * @throws LscpException If LSCP protocol corruption occurs.
1673 * @throws LSException If
1674 * <ul>
1675 * <li>There is no MIDI input device with numerical ID <code>deviceID</code>;
1676 * <li> <code>port</code> is not a valid MIDI port number;
1677 * <li><code>param</code> is not a valid parameter for the specified MIDI port.
1678 * </ul>
1679 *
1680 * @see #getMidiInputDevices
1681 * @see #getMidiInputPortInfo
1682 */
1683 public synchronized Parameter
1684 getMidiInputPortParameterInfo(int deviceID, int port, String param)
1685 throws IOException, LscpException, LSException {
1686
1687 verifyConnection();
1688 String args = deviceID + " " + port + " " + param;
1689 out.writeLine("GET MIDI_INPUT_PORT_PARAMETER INFO " + args);
1690
1691 ResultSet rs = getMultiLineResultSet();
1692
1693 String[] lnS = rs.getMultiLineResult();
1694 ParameterType type = parseType(lnS);
1695 boolean multi = parseMultiplicity(lnS);
1696 Parameter prm;
1697
1698 switch(type) {
1699 case BOOL:
1700 if(!multi) prm = new BoolParameter(lnS);
1701 else prm = new BoolListParameter(lnS);
1702 prm.setName(param);
1703 return prm;
1704 case INT:
1705 if(!multi) prm = new IntParameter(lnS);
1706 else prm = new IntListParameter(lnS);
1707 prm.setName(param);
1708 return prm;
1709 case FLOAT:
1710 if(!multi) prm = new FloatParameter(lnS);
1711 else prm = new FloatListParameter(lnS);
1712 prm.setName(param);
1713 return prm;
1714 case STRING:
1715 if(!multi) prm = new StringParameter(lnS);
1716 else prm = new StringListParameter(lnS);
1717 prm.setName(param);
1718 return prm;
1719 default: throw new LscpException(LscpI18n.getLogMsg("Client.unknownPrmType!"));
1720 }
1721 }
1722
1723 /**
1724 * Alters a specific setting of a MIDI input port.
1725 *
1726 * @param deviceID The numerical ID of the MIDI device.
1727 * @param port The MIDI port number.
1728 * @param prm A <code>Parameter</code> instance containing the name of the parameter
1729 * and the new value for this parameter.
1730 *
1731 * @throws IOException If some I/O error occurs.
1732 * @throws LscpException If LSCP protocol corruption occurs.
1733 * @throws LSException If
1734 * <ul>
1735 * <li>There is no MIDI device with numerical ID <code>deviceID</code>;
1736 * <li><code>port</code> is not a valid MIDI port number;
1737 * <li><code>prm</code> is not a valid parameter;
1738 * <li>The parameter is readonly;
1739 * <li>The parameter is from different type.
1740 * </ul>
1741 *
1742 * @see #getMidiInputDevices
1743 * @see #getMidiInputPortInfo
1744 */
1745 public synchronized void
1746 setMidiInputPortParameter(int deviceID, int port, Parameter prm)
1747 throws IOException, LscpException, LSException {
1748
1749 verifyConnection();
1750 String args = deviceID + " " + port + " " +
1751 prm.getName() + '=' + prm.getStringValue();
1752 out.writeLine("SET MIDI_INPUT_PORT_PARAMETER " + args);
1753
1754 ResultSet rs = getEmptyResultSet();
1755 }
1756
1757 /**
1758 * Loads and assigns an instrument to a sampler channel. Notice that this function will
1759 * return after the instrument is fully loaded and the channel is ready to be used.
1760 *
1761 * @param filename The name of the instrument file
1762 * on the LinuxSampler instance's host system.
1763 * @param instrIdx The index of the instrument in the instrument file.
1764 * @param samplerChn The number of the sampler channel the instrument should be assigned to.
1765 *
1766 * @throws IOException If some I/O error occurs.
1767 * @throws LscpException If LSCP protocol corruption occurs.
1768 * @throws LSException If the loading of the instrument failed.
1769 *
1770 * @see #loadInstrument(String, int, int, boolean)
1771 * @see #getSamplerChannels
1772 */
1773 public synchronized void
1774 loadInstrument(String filename, int instrIdx, int samplerChn)
1775 throws IOException, LscpException, LSException {
1776
1777 verifyConnection();
1778 loadInstrument(filename, instrIdx, samplerChn, false);
1779 }
1780
1781 /**
1782 * Loads and assigns an instrument to a sampler channel.
1783 *
1784 * @param filename The name of the instrument file
1785 * on the LinuxSampler instance's host system.
1786 * @param instrIdx The index of the instrument in the instrument file.
1787 * @param samplerChn The number of the sampler channel the instrument should be assigned to.
1788 * @param nonModal If <code>false</code> the function will return after the instrument
1789 * has been fully loaded and the channel is ready to be used. If <code>true</code>
1790 * the function returns immediately.
1791 *
1792 * @throws IOException If some I/O error occurs.
1793 * @throws LscpException If LSCP protocol corruption occurs.
1794 * @throws LSException If the loading of the instrument failed.
1795 *
1796 * @see #loadInstrument(String, int, int)
1797 * @see #getSamplerChannels
1798 */
1799 public synchronized void
1800 loadInstrument(String filename, int instrIdx, int samplerChn, boolean nonModal)
1801 throws IOException, LscpException, LSException {
1802
1803 String cmd = nonModal ? "LOAD INSTRUMENT NON_MODAL " : "LOAD INSTRUMENT ";
1804 String args = '\'' + filename + "' " + instrIdx + ' ' + samplerChn;
1805
1806 out.writeLine(cmd + args);
1807
1808 ResultSet rs = getEmptyResultSet();
1809 }
1810
1811 /**
1812 * Loads a sampler engine to a specific sampler channel.
1813 * @param engineName The name of the engine.
1814 * @param samplerChn The number of the sampler channel
1815 * the deployed engine should be assigned to.
1816 *
1817 * @throws IOException If some I/O error occurs.
1818 * @throws LscpException If LSCP protocol corruption occurs.
1819 * @throws LSException If the loading of the sampler engine failed.
1820 * @see #getEngines
1821 * @see #getSamplerChannels
1822 */
1823 public synchronized void
1824 loadSamplerEngine(String engineName, int samplerChn)
1825 throws IOException, LscpException, LSException {
1826
1827 verifyConnection();
1828 out.writeLine("LOAD ENGINE " + engineName + ' ' + samplerChn);
1829
1830 ResultSet rs = getEmptyResultSet();
1831 }
1832
1833 /**
1834 * Gets the current number of all created sampler channels.
1835 * @return The current number of all created sampler channels.
1836 * @throws IOException If some I/O error occurs.
1837 * @throws LscpException If LSCP protocol corruption occurs.
1838 * @throws LSException If some other error occurs.
1839 */
1840 public synchronized int
1841 getSamplerChannelCount() throws IOException, LscpException, LSException {
1842 verifyConnection();
1843 out.writeLine("GET CHANNELS");
1844 String s = getSingleLineResultSet().getResult();
1845 return parseInt(s);
1846 }
1847
1848 /**
1849 * Gets a list of all created sampler channels.
1850 * @return A <code>SamplerChannel</code> array providing all created sampler channels.
1851 * @throws IOException If some I/O error occurs.
1852 * @throws LscpException If LSCP protocol corruption occurs.
1853 * @throws LSException If some other error occurs.
1854 * @see #addSamplerChannel
1855 * @see #removeSamplerChannel
1856 */
1857 public synchronized SamplerChannel[]
1858 getSamplerChannels() throws IOException, LscpException, LSException {
1859 Integer[] idS = getSamplerChannelIDs();
1860 SamplerChannel[] channels = new SamplerChannel[idS.length];
1861
1862 for(int i = 0; i < channels.length; i++)
1863 channels[i] = getSamplerChannelInfo(idS[i]);
1864
1865 return channels;
1866 }
1867
1868 /**
1869 * Gets a list with numerical IDs of all created sampler channels.
1870 * @return An <code>Integer</code> array providing
1871 * the numerical IDs of all created sampler channels.
1872 * @throws IOException If some I/O error occurs.
1873 * @throws LscpException If LSCP protocol corruption occurs.
1874 * @throws LSException If some other error occurs.
1875 * @see #addSamplerChannel
1876 * @see #removeSamplerChannel
1877 */
1878 public synchronized Integer[]
1879 getSamplerChannelIDs() throws IOException, LscpException, LSException {
1880 verifyConnection();
1881 out.writeLine("LIST CHANNELS");
1882 return parseIntList(getSingleLineResultSet().getResult());
1883 }
1884
1885 /**
1886 * Adds a new sampler channel. This method will increment the sampler channel count by one
1887 * and the new sampler channel will be appended to the end of the sampler channel list.
1888 *
1889 * @return The number of the newly created sampler channel.
1890 * @throws IOException If some I/O error occurs.
1891 * @throws LSException If the creation of the new sampler channel failed.
1892 * @throws LscpException If LSCP protocol corruption occurs.
1893 * @see #removeSamplerChannel
1894 */
1895 public synchronized int
1896 addSamplerChannel() throws IOException, LSException, LscpException {
1897 verifyConnection();
1898 out.writeLine("ADD CHANNEL");
1899 ResultSet rs = getEmptyResultSet();
1900
1901 return rs.getIndex();
1902 }
1903
1904 /**
1905 * Removes the specified sampler channel.
1906 *
1907 * @param samplerChn The numerical ID of the sampler channel to be removed.
1908 *
1909 * @throws IOException If some I/O error occurs.
1910 * @throws LscpException If LSCP protocol corruption occurs.
1911 * @throws LSException If the removing of the sampler channel failed.
1912 * @see #addSamplerChannel
1913 * @see #getSamplerChannels
1914 */
1915 public synchronized void
1916 removeSamplerChannel(int samplerChn) throws IOException, LscpException, LSException {
1917 verifyConnection();
1918 out.writeLine("REMOVE CHANNEL " + samplerChn);
1919
1920 ResultSet rs = getEmptyResultSet();
1921 }
1922
1923 /**
1924 * Gets the number of all available engines.
1925 * @return The number of all available engines.
1926 * @throws IOException If some I/O error occurs.
1927 * @throws LscpException If LSCP protocol corruption occurs.
1928 * @throws LSException If some other error occurs.
1929 */
1930 public synchronized int
1931 getEngineCount() throws IOException, LscpException, LSException {
1932 verifyConnection();
1933 out.writeLine("GET AVAILABLE_ENGINES");
1934 String s = getSingleLineResultSet().getResult();
1935 return parseInt(s);
1936 }
1937
1938 /**
1939 * Gets a list of all available engines.
1940 *
1941 * @return <code>SamplerEngine</code> array containing all available engines.
1942 * @throws IOException If some I/O error occurs.
1943 * @throws LscpException If LSCP protocol corruption occurs.
1944 * @throws LSException If some other error occurs.
1945 */
1946 public synchronized SamplerEngine[]
1947 getEngines() throws IOException, LscpException, LSException {
1948 String[] engines = getEngineNames();
1949 SamplerEngine[] se = new SamplerEngine[engines.length];
1950
1951 for(int i = 0; i < engines.length; i++) se[i] = getEngineInfo(engines[i]);
1952
1953 return se;
1954 }
1955
1956 /**
1957 * Gets a list of all available engines' names.
1958 *
1959 * @return <code>String</code> array with all available engines' names.
1960 * @throws IOException If some I/O error occurs.
1961 * @throws LscpException If LSCP protocol corruption occurs.
1962 * @throws LSException If some other error occurs.
1963 */
1964 private synchronized String[]
1965 getEngineNames() throws IOException, LscpException, LSException {
1966 verifyConnection();
1967 out.writeLine("LIST AVAILABLE_ENGINES");
1968 return parseStringList(getSingleLineResultSet().getResult());
1969 }
1970
1971 /**
1972 * Gets information about a specific sampler engine.
1973 * @param engineName The name of the sampler engine.
1974 *
1975 * @return <code>SamplerEngine</code> instance containing
1976 * information about the specified sampler engine.
1977 *
1978 * @throws IOException If an I/O error occurs.
1979 * @throws LscpException If LSCP protocol corruption occurs.
1980 * @throws LSException If there is no sampler engine with name <code>engineName</code>.
1981 * @see #getEngineNames
1982 */
1983 private synchronized SamplerEngine
1984 getEngineInfo(String engineName) throws IOException, LscpException, LSException {
1985 verifyConnection();
1986 out.writeLine("GET ENGINE INFO " + engineName);
1987 ResultSet rs = getMultiLineResultSet();
1988 SamplerEngine se = new SamplerEngine(rs.getMultiLineResult());
1989 se.setName(engineName);
1990 return se;
1991 }
1992
1993 /**
1994 * Gets the current settings of the specified sampler channel.
1995 * @param samplerChn The sampler channel number.
1996 *
1997 * @return <code>SamplerChannel</code> instance containing
1998 * the current settings of the specified sampler channel.
1999 *
2000 * @throws IOException If an I/O error occurs.
2001 * @throws LscpException If LSCP protocol corruption occurs.
2002 * @throws LSException If there is no sampler channel with <code>samplerChn</code> number.
2003 * @see #getSamplerChannels
2004 */
2005 public synchronized SamplerChannel
2006 getSamplerChannelInfo(int samplerChn) throws IOException, LscpException, LSException {
2007 verifyConnection();
2008 out.writeLine("GET CHANNEL INFO " + samplerChn);
2009 ResultSet rs = getMultiLineResultSet();
2010 SamplerChannel sc = new SamplerChannel(rs.getMultiLineResult());
2011 sc.setChannelID(samplerChn);
2012 if(sc.getEngine() != null) sc.setEngine(getEngineInfo(sc.getEngine().getName()));
2013
2014 return sc;
2015 }
2016
2017 /**
2018 * Gets the current number of active voices on the specified sampler channel.
2019 *
2020 * @param samplerChn The sampler channel number.
2021 * @return The current number of active voices on the specified sampler channel.
2022 * @throws IOException If some I/O error occurs.
2023 * @throws LscpException If LSCP protocol corruption occurs.
2024 * @throws LSException If there is no sampler channel with number <code>samplerChn</code>.
2025 * @see #getSamplerChannels
2026 */
2027 public synchronized int
2028 getChannelVoiceCount(int samplerChn) throws IOException, LscpException, LSException {
2029 verifyConnection();
2030 out.writeLine("GET CHANNEL VOICE_COUNT " + samplerChn);
2031 ResultSet rs = getSingleLineResultSet();
2032
2033 return parseInt(rs.getResult());
2034 }
2035
2036 /**
2037 * Gets the current number of active disk streams on the specified sampler channel.
2038 *
2039 * @param samplerChn The sampler channel number.
2040 * @return The current number of active disk streams on the specified sampler channel
2041 * or -1 if the engine doesn't support disk streaming.
2042 * @throws IOException If some I/O error occurs.
2043 * @throws LscpException If LSCP protocol corruption occurs.
2044 * @throws LSException If there is no sampler channel with number <code>samplerChn</code>.
2045 * @see #getSamplerChannels
2046 */
2047 public synchronized int
2048 getChannelStreamCount(int samplerChn) throws IOException, LscpException, LSException {
2049 verifyConnection();
2050 out.writeLine("GET CHANNEL STREAM_COUNT " + samplerChn);
2051 ResultSet rs = getSingleLineResultSet();
2052
2053 if(rs.getResult().equals("NA")) return -1;
2054
2055 return parseInt(rs.getResult());
2056 }
2057
2058 /**
2059 * Gets the current fill state of all disk streams on the specified sampler channel
2060 * in bytes.
2061 *
2062 * @param samplerChn The sampler channel number.
2063 * @return The current fill state of all disk streams on the specified sampler channel
2064 * or <code>null</code> if the engine which is deployed doesn't support disk streaming.
2065 * @throws IOException If some I/O error occurs.
2066 * @throws LscpException If LSCP protocol corruption occurs.
2067 * @throws LSException If there is no sampler channel with number <code>samplerChn</code>.
2068 * @see #getChannelBufferFillPercentage
2069 * @see #getSamplerChannels
2070 */
2071 public synchronized Vector<BufferFill>
2072 getChannelBufferFillBytes(int samplerChn) throws IOException, LscpException, LSException {
2073 verifyConnection();
2074 out.writeLine("GET CHANNEL BUFFER_FILL BYTES " + samplerChn);
2075 ResultSet rs = getSingleLineResultSet();
2076
2077 if(rs.getResult().equals("NA")) return null;
2078
2079 Vector<BufferFill> v = new Vector<BufferFill>();
2080 String[] args = parseList(rs.getResult());
2081
2082 for(String s : args) {
2083 if(s.charAt(0) != '[')
2084 throw new LscpException(LscpI18n.getLogMsg("CommandFailed!"));
2085
2086 int i = s.indexOf(']');
2087 if(i == -1) throw new LscpException(LscpI18n.getLogMsg("CommandFailed!"));
2088
2089 BufferFill bf = new BufferFill();
2090 bf.setStreamID(parseInt(s.substring(1, i)));
2091 bf.setValue(parseInt(s.substring(i + 1)));
2092 v.add(bf);
2093 }
2094
2095 return v;
2096 }
2097
2098 /**
2099 * Gets the current fill state of all disk streams on the specified sampler channel
2100 * in percent.
2101 *
2102 * @param samplerChn The sampler channel number.
2103 * @return The current fill state of all disk streams on the specified sampler channel
2104 * or <code>null</code> if the engine which is deployed doesn't support disk streaming.
2105 * @throws IOException If some I/O error occurs.
2106 * @throws LscpException If LSCP protocol corruption occurs.
2107 * @throws LSException If there is no sampler channel with number <code>samplerChn</code>.
2108 * @see #getChannelBufferFillBytes
2109 * @see #getSamplerChannels
2110 */
2111 public synchronized Vector<BufferFill>
2112 getChannelBufferFillPercentage(int samplerChn)
2113 throws IOException, LscpException, LSException {
2114
2115 verifyConnection();
2116 out.writeLine("GET CHANNEL BUFFER_FILL PERCENTAGE " + samplerChn);
2117 ResultSet rs = getSingleLineResultSet();
2118
2119 return getChannelBufferFillPercentage(rs.getResult());
2120 }
2121
2122 private Vector<BufferFill>
2123 getChannelBufferFillPercentage(String ln) throws LscpException {
2124 if(ln.equals("NA")) return null;
2125
2126 Vector<BufferFill> v = new Vector<BufferFill>();
2127 String[] args = parseList(ln);
2128
2129 for(String s : args) {
2130 if(s.charAt(0) != '[')
2131 throw new LscpException(LscpI18n.getLogMsg("CommandFailed!"));
2132
2133 int i = s.indexOf(']');
2134 if(i == -1) throw new LscpException(LscpI18n.getLogMsg("CommandFailed!"));
2135
2136 if(s.charAt(s.length() - 1) != '%')
2137 throw new LscpException(LscpI18n.getLogMsg("CommandFailed!"));
2138
2139 BufferFill bf = new BufferFill();
2140 bf.setStreamID(parseInt(s.substring(1, i)));
2141 bf.setValue(parseInt(s.substring(i + 1, s.length() - 1)));
2142 v.add(bf);
2143 }
2144
2145 return v;
2146 }
2147
2148 /**
2149 * Sets the audio output device on the specified sampler channel.
2150 *
2151 * @param samplerChn The sampler channel number.
2152 * @param devID The numerical ID of the audio output device.
2153 *
2154 * @throws IOException If some I/O error occurs.
2155 * @throws LscpException If LSCP protocol corruption occurs.
2156 * @throws LSException If
2157 * <ul>
2158 * <li><code>samplerChn</code> is not a valid channel number;
2159 * <li><code>devID</code> is not a valid audio output device ID;
2160 * </ul>
2161 *
2162 * @see #getSamplerChannels
2163 * @see #getAudioOutputDevices
2164 */
2165 public synchronized void
2166 setChannelAudioOutputDevice(int samplerChn, int devID)
2167 throws IOException, LscpException, LSException {
2168
2169 verifyConnection();
2170 out.writeLine("SET CHANNEL AUDIO_OUTPUT_DEVICE " + samplerChn + ' ' + devID);
2171
2172 ResultSet rs = getEmptyResultSet();
2173 }
2174
2175 /**
2176 * Sets the audio output channel on the specified sampler channel.
2177 *
2178 * @param samplerChn The sampler channel number.
2179 * @param audioOut The sampler channel's audio output channel which should be rerouted.
2180 * @param audioIn The audio channel of the selected audio output device
2181 * where <code>audioOut</code> should be routed to.
2182 *
2183 * @throws IOException If some I/O error occurs.
2184 * @throws LscpException If LSCP protocol corruption occurs.
2185 * @throws LSException If
2186 * <ul>
2187 * <li><code>samplerChn</code> is not a valid channel number;
2188 * <li>There is no engine assigned yet to the specified sampler channel.
2189 * <li> There is no audio output device connected to the specified sampler channel.
2190 * </ul>
2191 *
2192 * @see #getSamplerChannels
2193 */
2194 public synchronized void
2195 setChannelAudioOutputChannel(int samplerChn, int audioOut, int audioIn)
2196 throws IOException, LscpException, LSException {
2197
2198 verifyConnection();
2199 String args = " " + samplerChn + ' ' + audioOut + ' ' + audioIn;
2200 out.writeLine("SET CHANNEL AUDIO_OUTPUT_CHANNEL" + args);
2201
2202 ResultSet rs = getEmptyResultSet();
2203 }
2204
2205 /**
2206 * Sets the MIDI input device on the specified sampler channel.
2207 *
2208 * @param samplerChn The sampler channel number.
2209 * @param devID The numerical ID of the MIDI input device.
2210 *
2211 * @throws IOException If some I/O error occurs.
2212 * @throws LscpException If LSCP protocol corruption occurs.
2213 * @throws LSException If
2214 * <ul>
2215 * <li><code>samplerChn</code> is not a valid channel number;
2216 * <li><code>devID</code> is not a valid MIDI input device ID;
2217 * </ul>
2218 *
2219 * @see #getSamplerChannels
2220 * @see #getMidiInputDevices
2221 */
2222 public synchronized void
2223 setChannelMidiInputDevice(int samplerChn, int devID)
2224 throws IOException, LscpException, LSException {
2225
2226 verifyConnection();
2227 out.writeLine("SET CHANNEL MIDI_INPUT_DEVICE " + samplerChn + ' ' + devID);
2228
2229 ResultSet rs = getEmptyResultSet();
2230 }
2231
2232 /**
2233 * Sets the MIDI input port on the specified sampler channel.
2234 *
2235 * @param samplerChn The sampler channel number.
2236 * @param port The MIDI input port number of
2237 * the MIDI input device connected to the specified sampler channel.
2238 *
2239 * @throws IOException If some I/O error occurs.
2240 * @throws LscpException If LSCP protocol corruption occurs.
2241 * @throws LSException If <code>samplerChn</code> is not a valid channel number.
2242 * @see #getSamplerChannels
2243 */
2244 public synchronized void
2245 setChannelMidiInputPort(int samplerChn, int port)
2246 throws IOException, LscpException, LSException {
2247
2248 verifyConnection();
2249 out.writeLine("SET CHANNEL MIDI_INPUT_PORT " + samplerChn + ' ' + port);
2250
2251 ResultSet rs = getEmptyResultSet();
2252 }
2253
2254 /**
2255 * Sets the MIDI input channel the specified sampler channel should listen to.
2256 *
2257 * @param samplerChn The sampler channel number.
2258 * @param midiChn The number of the new MIDI input channel where
2259 * <code>samplerChn</code> should listen to or -1 to listen on all 16 MIDI channels.
2260 *
2261 * @throws IOException If some I/O error occurs.
2262 * @throws LscpException If LSCP protocol corruption occurs.
2263 * @throws LSException If <code>samplerChn</code> is not a valid channel number.
2264 * @see #getSamplerChannels
2265 */
2266 public synchronized void
2267 setChannelMidiInputChannel(int samplerChn, int midiChn)
2268 throws IOException, LscpException, LSException {
2269
2270 verifyConnection();
2271 String args = String.valueOf(samplerChn) + ' ';
2272 args += (midiChn == -1 ? "ALL" : String.valueOf(midiChn));
2273 out.writeLine("SET CHANNEL MIDI_INPUT_CHANNEL " + args);
2274
2275 ResultSet rs = getEmptyResultSet();
2276 }
2277
2278 /**
2279 * Sets the volume of the specified sampler channel.
2280 *
2281 * @param samplerChn The sampler channel number.
2282 * @param volume The new volume value.
2283 *
2284 * @throws IOException If some I/O error occurs.
2285 * @throws LscpException If LSCP protocol corruption occurs.
2286 * @throws LSException If <code>samplerChn</code> is not a valid channel number or if
2287 * there is no engine assigned yet to the specified sampler channel.
2288 * @see #getSamplerChannels
2289 */
2290 public synchronized void
2291 setChannelVolume(int samplerChn, float volume)
2292 throws IOException, LscpException, LSException {
2293
2294 verifyConnection();
2295 out.writeLine("SET CHANNEL VOLUME " + samplerChn + ' ' + volume);
2296
2297 ResultSet rs = getEmptyResultSet();
2298 }
2299
2300 /**
2301 * Mute/unmute the specified sampler channel.
2302 *
2303 * @param samplerChn The sampler channel number.
2304 * @param mute If <code>true</code> the specified channel is muted, else the channel
2305 * is unmuted.
2306 *
2307 * @throws IOException If some I/O error occurs.
2308 * @throws LscpException If LSCP protocol corruption occurs.
2309 * @throws LSException If <code>samplerChn</code> is not a valid channel number or if
2310 * there is no engine assigned yet to the specified sampler channel.
2311 * @see #getSamplerChannels
2312 */
2313 public synchronized void
2314 setChannelMute(int samplerChn, boolean mute)
2315 throws IOException, LscpException, LSException {
2316
2317 verifyConnection();
2318 out.writeLine("SET CHANNEL MUTE " + samplerChn + ' ' + (mute ? 1 : 0));
2319
2320 ResultSet rs = getEmptyResultSet();
2321 }
2322
2323 /**
2324 * Solo/unsolo the specified sampler channel.
2325 *
2326 * @param samplerChn The sampler channel number.
2327 * @param solo <code>true</code> to solo the specified channel, <code>false</code>
2328 * otherwise.
2329 *
2330 * @throws IOException If some I/O error occurs.
2331 * @throws LscpException If LSCP protocol corruption occurs.
2332 * @throws LSException If <code>samplerChn</code> is not a valid channel number or if
2333 * there is no engine assigned yet to the specified sampler channel.
2334 * @see #getSamplerChannels
2335 */
2336 public synchronized void
2337 setChannelSolo(int samplerChn, boolean solo)
2338 throws IOException, LscpException, LSException {
2339
2340 verifyConnection();
2341 out.writeLine("SET CHANNEL SOLO " + samplerChn + ' ' + (solo ? 1 : 0));
2342
2343 ResultSet rs = getEmptyResultSet();
2344 }
2345
2346 /**
2347 * Resets the specified sampler channel.
2348 *
2349 * @param samplerChn The sampler channel number.
2350 *
2351 * @throws IOException If some I/O error occurs.
2352 * @throws LscpException If LSCP protocol corruption occurs.
2353 * @throws LSException If <code>samplerChn</code> is not a valid channel number or if
2354 * there is no engine assigned yet to the specified sampler channel.
2355 * @see #getSamplerChannels
2356 */
2357 public synchronized void
2358 resetChannel(int samplerChn) throws IOException, LscpException, LSException {
2359 verifyConnection();
2360 out.writeLine("RESET CHANNEL " + samplerChn);
2361
2362 ResultSet rs = getEmptyResultSet();
2363 }
2364
2365 /**
2366 * Resets the whole sampler.
2367 *
2368 * @throws IOException If some I/O error occurs.
2369 * @throws LscpException If LSCP protocol corruption occurs.
2370 */
2371 public synchronized void
2372 resetSampler() throws IOException, LscpException {
2373 verifyConnection();
2374 out.writeLine("RESET");
2375 try { ResultSet rs = getEmptyResultSet(); }
2376 catch(LSException x) { getLogger().warning(x.getMessage()); }
2377 }
2378
2379 /**
2380 * Gets the current number of all active voices.
2381 * @return The current number of all active voices.
2382 * @throws IOException If some I/O error occurs.
2383 * @throws LscpException If LSCP protocol corruption occurs.
2384 * @throws LSException If some other error occurs.
2385 */
2386 public synchronized int
2387 getTotalVoiceCount() throws IOException, LscpException, LSException {
2388 verifyConnection();
2389 out.writeLine("GET TOTAL_VOICE_COUNT");
2390 String s = getSingleLineResultSet().getResult();
2391 return parseInt(s);
2392 }
2393
2394 /**
2395 * Gets the maximum number of active voices.
2396 * @return The maximum number of active voices.
2397 * @throws IOException If some I/O error occurs.
2398 * @throws LscpException If LSCP protocol corruption occurs.
2399 * @throws LSException If some other error occurs.
2400 */
2401 public synchronized int
2402 getTotalVoiceCountMax() throws IOException, LscpException, LSException {
2403 verifyConnection();
2404 out.writeLine("GET TOTAL_VOICE_COUNT_MAX");
2405 String s = getSingleLineResultSet().getResult();
2406 return parseInt(s);
2407 }
2408
2409 /**
2410 * Gets information about the LinuxSampler instance.
2411 *
2412 * @return <code>ServerInfo</code> instance containing
2413 * information about the LinuxSampler instance.
2414 *
2415 * @throws IOException If an I/O error occurs.
2416 * @throws LscpException If LSCP protocol corruption occurs.
2417 * @throws LSException If some other error occurs.
2418 */
2419 public synchronized ServerInfo
2420 getServerInfo() throws IOException, LscpException, LSException {
2421 verifyConnection();
2422 out.writeLine("GET SERVER INFO");
2423 ResultSet rs = getMultiLineResultSet();
2424 return new ServerInfo(rs.getMultiLineResult());
2425 }
2426
2427 /**
2428 * Returns the logger for this library.
2429 * @return The logger for this library.
2430 */
2431 protected static Logger
2432 getLogger() { return Logger.getLogger("org.linuxsampler.lscp"); }
2433 }

  ViewVC Help
Powered by ViewVC