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

Annotation of /jlscp/trunk/src/org/linuxsampler/lscp/Client.java

Parent Directory Parent Directory | Revision Log Revision Log


Revision 784 - (hide annotations) (download)
Mon Oct 10 14:55:44 2005 UTC (18 years, 6 months ago) by iliev
File size: 80515 byte(s)
* Updating to version 0.3a (see ChangeLog)

1 iliev 596 /*
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 iliev 671 * 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 iliev 596 *
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 iliev 671 getClientVersion() {
141     return Package.getPackage("org.linuxsampler.lscp").getImplementationVersion();
142     }
143 iliev 596
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 iliev 784 sock.setTcpNoDelay(true);
211 iliev 596
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 iliev 671 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 iliev 596 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 iliev 784 if(!llTVC.isEmpty()) subscribe("TOTAL_VOICE_COUNT");
261 iliev 596 }
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 iliev 784 private final Vector<TotalVoiceCountListener> llTVC = new Vector<TotalVoiceCountListener>();
376 iliev 596
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 iliev 784 * is extended in the future.
381 iliev 596 * @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 iliev 784 !llVC.isEmpty() ||
392     !llTVC.isEmpty();
393 iliev 596 }
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 iliev 784 } 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 iliev 596 } 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 iliev 784 * 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 iliev 596 * 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 iliev 671
684 iliev 596 /**
685     * Gets all audio output drivers currently available for the LinuxSampler instance.
686     *
687 iliev 671 * @return <code>AudioOutputDriver</code> array containing all audio output drivers
688     * currently available for the LinuxSampler instance.
689 iliev 596 *
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 iliev 671 public synchronized AudioOutputDriver[]
695 iliev 596 getAudioOutputDrivers() throws IOException, LscpException, LSException {
696 iliev 671 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 iliev 596 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 iliev 671 * @see #getAudioOutputDriverNames
733 iliev 596 */
734 iliev 671 private synchronized AudioOutputDriver
735 iliev 596 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 iliev 784 prm.setValue(prm.getDefault());
795 iliev 596 return prm;
796     case INT:
797     if(!multi) prm = new IntParameter(lnS);
798     else prm = new IntListParameter(lnS);
799     prm.setName(param);
800 iliev 784 prm.setValue(prm.getDefault());
801 iliev 596 return prm;
802     case FLOAT:
803     if(!multi) prm = new FloatParameter(lnS);
804     else prm = new FloatListParameter(lnS);
805     prm.setName(param);
806 iliev 784 prm.setValue(prm.getDefault());
807 iliev 596 return prm;
808     case STRING:
809     if(!multi) prm = new StringParameter(lnS);
810     else prm = new StringListParameter(lnS);
811     prm.setName(param);
812 iliev 784 prm.setValue(prm.getDefault());
813 iliev 596 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 iliev 784 /**
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 iliev 596 /**
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 iliev 784 * 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 iliev 596 * Gets a list of numerical IDs of all created audio output devices.
915 iliev 784 * @return An <code>Integer</code> array providing the numerical IDs of
916 iliev 596 * 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 iliev 784 getAudioOutputDeviceIDs() throws IOException, LscpException, LSException {
923 iliev 596 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 iliev 784 aod.setDeviceID(deviceID);
954 iliev 596 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 iliev 784 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 iliev 596 } 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 iliev 784 * 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 iliev 596 * 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 iliev 784 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 iliev 596 } else if(s.startsWith("IS_MIX_CHANNEL: ")) {
1096     s = s.substring("IS_MIX_CHANNEL: ".length());
1097 iliev 784 Parameter<Boolean> prm = getAudioOutputChannelParameterInfo (
1098     deviceID, audioChn, "IS_MIX_CHANNEL"
1099     );
1100     prm.setValue(Boolean.parseBoolean(s));
1101     aoc.setMixChannelParameter(prm);
1102 iliev 596 } else if(s.startsWith("MIX_CHANNEL_DESTINATION: ")) {
1103     s = s.substring("MIX_CHANNEL_DESTINATION: ".length());
1104 iliev 784 Parameter<Integer> prm = getAudioOutputChannelParameterInfo (
1105     deviceID, audioChn, "MIX_CHANNEL_DESTINATION"
1106     );
1107     prm.setValue(parseInt(s));
1108     aoc.setMixChannelDestParameter(prm);
1109 iliev 596 } 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 iliev 784 String args = devID + " " + chan + " " + param;
1157 iliev 596 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 iliev 784 String args = devID + " " + chn + " " + prm.getName() + '=' + prm.getStringValue();
1219 iliev 596 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 iliev 671 * @return <code>MidiInputDriver</code> array containing all MIDI input drivers currently
1243     * available for the LinuxSampler instance.
1244 iliev 596 *
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 iliev 671 public synchronized MidiInputDriver[]
1250 iliev 596 getMidiInputDrivers() throws IOException, LscpException, LSException {
1251 iliev 671 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 iliev 596 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 iliev 671 * @return A <code>MidiInputDriver</code> object containing
1281 iliev 596 * 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 iliev 671 * @see #getMidiInputDriverNames
1288 iliev 596 */
1289 iliev 671 private synchronized MidiInputDriver
1290 iliev 596 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 iliev 671 * @return A <code>Parameter</code> object containing
1314 iliev 596 * 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 iliev 784 prm.setValue(prm.getDefault());
1351 iliev 596 return prm;
1352     case INT:
1353     if(!multi) prm = new IntParameter(lnS);
1354     else prm = new IntListParameter(lnS);
1355     prm.setName(param);
1356 iliev 784 prm.setValue(prm.getDefault());
1357 iliev 596 return prm;
1358     case FLOAT:
1359     if(!multi) prm = new FloatParameter(lnS);
1360     else prm = new FloatListParameter(lnS);
1361     prm.setName(param);
1362 iliev 784 prm.setValue(prm.getDefault());
1363 iliev 596 return prm;
1364     case STRING:
1365     if(!multi) prm = new StringParameter(lnS);
1366     else prm = new StringListParameter(lnS);
1367     prm.setName(param);
1368 iliev 784 prm.setValue(prm.getDefault());
1369 iliev 596 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 iliev 784 /**
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 iliev 596 /**
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 iliev 784 * 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 iliev 596 * Gets a list of numerical IDs of all created MIDI input devices.
1476 iliev 784 * @return An <code>Integer</code> array providing the numerical IDs of
1477 iliev 596 * 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 iliev 784 getMidiInputDeviceIDs() throws IOException, LscpException, LSException {
1487 iliev 596 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 iliev 784 mid.setDeviceID(deviceID);
1518 iliev 596
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 iliev 784 } 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 iliev 596 } 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 iliev 784
1588 iliev 596 /**
1589 iliev 784 * 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 iliev 596 * 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 iliev 784 s = s.substring("NAME: ".length());
1636     Parameter prm = getMidiInputPortParameterInfo (
1637     deviceID, midiPort, "NAME"
1638     );
1639     prm.setValue(removeQuotation(s));
1640     mp.setNameParameter(prm);
1641 iliev 596 } 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 iliev 784 String args = deviceID + " " + port + " " +
1751 iliev 596 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 iliev 784 * 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 iliev 596 * Gets a list with numerical IDs of all created sampler channels.
1870 iliev 784 * @return An <code>Integer</code> array providing
1871     * the numerical IDs of all created sampler channels.
1872 iliev 596 * @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 iliev 784 getSamplerChannelIDs() throws IOException, LscpException, LSException {
1880 iliev 596 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 iliev 671 * 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 iliev 596 * 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 iliev 671 private synchronized String[]
1965     getEngineNames() throws IOException, LscpException, LSException {
1966 iliev 596 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 iliev 671 * @see #getEngineNames
1982 iliev 596 */
1983 iliev 671 private synchronized SamplerEngine
1984 iliev 596 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 iliev 784 if(sc.getEngine() != null) sc.setEngine(getEngineInfo(sc.getEngine().getName()));
2013 iliev 596
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 iliev 784 * 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 iliev 596 * 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 iliev 784 * 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 iliev 596 * 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