/[svn]/jsampler/trunk/src/org/jsampler/DefaultLSConsoleModel.java
ViewVC logotype

Annotation of /jsampler/trunk/src/org/jsampler/DefaultLSConsoleModel.java

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1688 - (hide annotations) (download)
Thu Feb 14 16:52:36 2008 UTC (16 years, 2 months ago) by iliev
File size: 14519 byte(s)
* Implemented a backend list with option to manually choose a backend
  to connect on startup(Edit/Preferences, then click the `Backend' tab)
  and option to change the backend without restarting JSampler
  (Actions/Change Backend or Ctrl + B)

* Added confirmation messages for removing sampler channels and
  audio/MIDI devices (Edit/Preferences, then click the `View' tab)

1 iliev 913 /*
2     * JSampler - a java front-end for LinuxSampler
3     *
4 iliev 1143 * Copyright (C) 2005-2006 Grigor Iliev <grigor@grigoriliev.com>
5 iliev 913 *
6     * This file is part of JSampler.
7     *
8     * JSampler 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     * JSampler 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 JSampler; 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.jsampler;
24    
25     import java.awt.event.ActionEvent;
26     import java.awt.event.ActionListener;
27    
28     import java.io.InputStream;
29     import java.io.IOException;
30     import java.io.OutputStream;
31     import java.io.UnsupportedEncodingException;
32    
33     import java.net.Socket;
34    
35     import java.util.LinkedList;
36     import java.util.Vector;
37    
38     import java.util.logging.Level;
39    
40     import javax.swing.SwingUtilities;
41    
42     import net.sf.juife.event.TaskEvent;
43     import net.sf.juife.event.TaskListener;
44    
45     import org.jsampler.event.LSConsoleEvent;
46     import org.jsampler.event.LSConsoleListener;
47    
48     import org.jsampler.task.LSConsoleConnect;
49    
50     import static org.jsampler.JSI18n.i18n;
51    
52    
53     /**
54     * This class provides default implementation of the <code>LSConsoleModel</code> interface.
55     * @author Grigor Iliev
56     */
57     public class DefaultLSConsoleModel implements LSConsoleModel {
58     private Socket socket;
59     private LscpOutputStream out;
60    
61     private final String[] cmdList = LscpUtils.getCommandList();
62    
63     private String cmdLine = "";
64    
65     /**
66     * Contains the global command history, excluding blank lines and comments.
67     */
68     private final LinkedList<String> cmdHistory = new LinkedList<String>();
69    
70     private int cmdHistoryIdx = -1;
71    
72     private int commandHistorySize = 1000;
73    
74     private final LSConsoleThread lsConsoleThread = new LSConsoleThread();
75    
76     /**
77     * Contains the command history of the current
78     * session, including blank lines and comments.
79     */
80     private final Vector<String> sessionHistory = new Vector<String>();
81    
82     /** Used to hold the current command when browsing through command history, etc. */
83     private String currentCmd = "";
84    
85     private final Vector<LSConsoleListener> listeners = new Vector<LSConsoleListener>();
86    
87    
88     /** Creates a new instance of <code>DefaultLSConsoleModel</code>. */
89     public
90     DefaultLSConsoleModel() {
91     CC.addReconnectListener(new ActionListener() {
92     public void
93     actionPerformed(ActionEvent e) { reconnect(); }
94     });
95    
96     lsConsoleThread.start();
97     }
98    
99     private Socket
100     getSocket() { return socket; }
101    
102     private void
103     setSocket(Socket socket) { this.socket = socket; }
104    
105     private void
106     reconnect() {
107     final LSConsoleConnect cnt = new LSConsoleConnect(getSocket());
108    
109     cnt.addTaskListener(new TaskListener() {
110     public void
111     taskPerformed(TaskEvent e) { changeSocket(cnt.getResult()); }
112     });
113    
114     CC.getTaskQueue().add(cnt);
115     }
116    
117     private void
118     changeSocket(Socket sock) {
119     setSocket(sock);
120    
121     try {
122     LscpInputStream in;
123     in = sock == null ? null : new LscpInputStream(sock.getInputStream());
124     out = sock == null ? null : new LscpOutputStream(sock.getOutputStream());
125    
126     lsConsoleThread.setInputStream(in);
127     } catch(Exception x) { CC.getLogger().log(Level.INFO, HF.getErrorMessage(x), x); }
128     }
129    
130     /**
131     * Registers the specified listener for receiving event messages.
132     * @param l The <code>LSConsoleListener</code> to register.
133     */
134     public void
135     addLSConsoleListener(LSConsoleListener l) { listeners.add(l); }
136    
137     /**
138     * Removes the specified listener.
139     * @param l The <code>LSConsoleListener</code> to remove.
140     */
141     public void
142     removeLSConsoleListener(LSConsoleListener l) { listeners.remove(l); }
143    
144     /** Executes the command specified in the command line. */
145     public void
146     execCommand() {
147     String cmd = getCommandLineText();
148     sessionHistory.add(cmd);
149     if(cmd.trim().length() > 0 && !cmd.startsWith("#")) addToCommandHistory(cmd);
150     while(cmdHistory.size() > getCommandHistorySize()) cmdHistory.removeFirst();
151    
152     setCommandLineText("");
153     currentCmd = "";
154     cmdHistoryIdx = -1;
155    
156     if( getSocket() == null || getSocket().isClosed() || !getSocket().isConnected()
157     || getSocket().isOutputShutdown() || out == null ) {
158    
159     fireResponseReceived(i18n.getMessage("DefaultLSConsoleModel.notConnected"));
160     } else {
161     CC.getTaskQueue().add(new LSConsoleExecCommand(cmd));
162     }
163    
164     fireCommandExecuted();
165     }
166    
167     /**
168     * Gets the last executed command.
169     * @return The last command executed in the LS Console.
170     */
171     public String
172     getLastExecutedCommand() {
173     int size = sessionHistory.size();
174     return size == 0 ? "" : sessionHistory.get(size - 1);
175     }
176    
177     /**
178     * Sets the text in the command line.
179     * @param cmdLine The new command line text.
180     */
181     public void
182     setCommandLineText(String cmdLine) {
183     if(this.cmdLine.equals(cmdLine)) return;
184    
185     String oldCmdLine = this.cmdLine;
186     this.cmdLine = cmdLine;
187     fireCommandLineTextChanged(oldCmdLine);
188     }
189    
190     /**
191     * Gets the text in the command line.
192     * @return The command line's text.
193     */
194     public String
195     getCommandLineText() { return cmdLine; }
196    
197     /**
198     * Gets the command history of the current session, including blank lines and comments.
199     * @return The command history of the current session, including blank lines and comments.
200     */
201     public String[]
202     getSessionHistory() {
203     return sessionHistory.toArray(new String[sessionHistory.size()]);
204     }
205    
206     /**
207     * Clears the session history.
208     * @see #getSessionHistory
209     */
210     public void
211     clearSessionHistory() { sessionHistory.removeAllElements(); }
212    
213     /**
214     * Adds the specified <code>command</code> to command history.
215     * @param command The command to be added to command history.
216     */
217     public void
218     addToCommandHistory(String command) { cmdHistory.add(command); }
219    
220     /**
221     * Gets the complete command history, excluding blank lines and comments.
222     * @return The complete command history, excluding blank lines and comments.
223     */
224     public String[]
225     getCommandHistory() {
226     return cmdHistory.toArray(new String[cmdHistory.size()]);
227     }
228    
229     /**
230     * Clears the complete/multisession command history.
231     * @see #getCommandHistory
232     */
233     public void
234     clearCommandHistory() {
235     cmdHistory.clear();
236     cmdHistoryIdx = -1;
237     }
238    
239     /**
240     * Determines the maximum number of lines to be kept in the command history.
241     * @return The maximum number of lines to be kept in the command history.
242     */
243     public int
244     getCommandHistorySize() { return commandHistorySize; }
245    
246     /**
247     * Sets the maximum number of lines to be kept in the command history.
248     * @param size Determines the maximum number of lines to be kept in the command history.
249     */
250     public void
251     setCommandHistorySize(int size) { commandHistorySize = size; }
252    
253     /**
254     * Gets a list of all LSCP commands.
255     * @return A list of all LSCP commands.
256     */
257     public String[]
258     getCommandList() { return cmdList; }
259    
260     /** Browses the command history one line up. */
261     public void
262     browseCommandHistoryUp() {
263     if(cmdHistory.size() == 0) return;
264    
265     if(cmdHistoryIdx == -1) {
266     currentCmd = getCommandLineText();
267     cmdHistoryIdx = cmdHistory.size() - 1;
268     setCommandLineText(cmdHistory.get(cmdHistoryIdx));
269     return;
270     }
271    
272     if(cmdHistoryIdx == 0) return;
273    
274     setCommandLineText(cmdHistory.get(--cmdHistoryIdx));
275     }
276    
277     /** Browses the command history one line down. */
278     public void
279     browseCommandHistoryDown() {
280     if(cmdHistory.size() == 0 || cmdHistoryIdx == -1) return;
281     if(cmdHistoryIdx == cmdHistory.size() - 1) {
282     cmdHistoryIdx = -1;
283     setCommandLineText(currentCmd);
284     currentCmd = "";
285     return;
286     }
287    
288     setCommandLineText(cmdHistory.get(++cmdHistoryIdx));
289     }
290    
291     /** Browses to the first line of the command history. */
292     public void
293     browseCommandHistoryFirst() {
294     if(cmdHistory.size() == 0) return;
295     cmdHistoryIdx = 0;
296     setCommandLineText(cmdHistory.get(cmdHistoryIdx));
297     }
298    
299     /** Browses to the last line of the command history. */
300     public void
301     browseCommandHistoryLast() {
302     if(cmdHistory.size() == 0) return;
303     cmdHistoryIdx = cmdHistory.size() - 1;
304     setCommandLineText(cmdHistory.get(cmdHistoryIdx));
305     }
306    
307     private Vector<String> tmpVector = new Vector<String>();
308    
309     /**
310     * Searches the command history for commands
311     * containing the string returned by {@link #getCommandLineText}.
312     * @return All commands that contains the string returned by {@link #getCommandLineText}.
313     * @see #getCommandHistory
314     */
315     public String[]
316     searchCommandHistory() { return searchCommandHistory(getCommandLineText()); }
317    
318     /**
319     * Searches the command history for commands containing <code>substring</code>.
320     * @param substring The substring to be used to perform the search.
321     * @return All commands that contains <code>substring</code>.
322     * @see #getCommandList
323     */
324     public String[]
325     searchCommandHistory(String substring) {
326     tmpVector.removeAllElements();
327     for(String s : cmdHistory) if(s.indexOf(substring) != -1) tmpVector.add(s);
328    
329     return tmpVector.toArray(new String[tmpVector.size()]);
330     }
331    
332     /**
333     * Searches the LSCP command list for commands
334     * containing the string returned by {@link #getCommandLineText}.
335     * @return All commands that contains the string returned by {@link #getCommandLineText}.
336     * @see #getCommandList
337     */
338     public String[]
339     searchCommandList() { return searchCommandList(getCommandLineText()); }
340    
341     /**
342     * Searches the LSCP command list for commands containing <code>substring</code>.
343     * @param substring The substring to be used to perform the search.
344     * @return All commands that contains <code>substring</code>.
345     * @see #getCommandList
346     */
347     public String[]
348     searchCommandList(String substring) {
349     tmpVector.removeAllElements();
350     for(String s : cmdList) if(s.indexOf(substring) != -1) tmpVector.add(s);
351    
352     return tmpVector.toArray(new String[tmpVector.size()]);
353     }
354    
355     /** Notifies listeners that the text in the command line has changed. */
356     private void
357     fireCommandLineTextChanged(String oldCmdLine) {
358     LSConsoleEvent e = new LSConsoleEvent(this, null, oldCmdLine);
359     for(LSConsoleListener l : listeners) l.commandLineTextChanged(e);
360     }
361    
362     /** Notifies listeners that the command in the command line has been executed. */
363     private void
364     fireCommandExecuted() {
365     LSConsoleEvent e = new LSConsoleEvent(this);
366     for(LSConsoleListener l : listeners) l.commandExecuted(e);
367     }
368    
369     /**
370     * Notifies listeners that response is received from LinuxSampler.
371     * @param response The response received from LinuxSampler.
372     */
373     private void
374     fireResponseReceived(final String response) {
375     SwingUtilities.invokeLater(new Runnable() {
376     public void
377     run() {
378     LSConsoleEvent e = new LSConsoleEvent(this, response);
379     for(LSConsoleListener l : listeners) l.responseReceived(e);
380     }
381     });
382     }
383    
384     /** Executes LS Console command. */
385     private class LSConsoleExecCommand extends org.jsampler.task.EnhancedTask {
386     private String cmd;
387    
388     /** Creates a new instance of <code>LSConsoleExecCommand</code>. */
389     public
390     LSConsoleExecCommand(String cmd) {
391     setTitle("LSConsoleExecCommand_task");
392     setDescription(i18n.getMessage("LSConsoleExecCommand.description"));
393     this.cmd = cmd;
394     }
395    
396     /** The entry point of the task. */
397     public void
398     run() {
399     try { out.writeLine(cmd); }
400     catch(Exception x) {
401     setErrorMessage(getDescription() + ": " + HF.getErrorMessage(x));
402     CC.getLogger().log(Level.FINE, getErrorMessage(), x);
403     }
404     }
405     }
406    
407     class LSConsoleThread extends Thread {
408     LscpInputStream in;
409     private boolean terminate = false;
410    
411     LSConsoleThread() {super("LS-Console-Thread"); }
412    
413     public void
414     run() {
415     while(!mustTerminate()) {
416     try { processInput(); }
417     catch(Exception x) {
418     CC.getLogger().log(Level.INFO, HF.getErrorMessage(x), x);
419     }
420    
421     try { synchronized(this) { wait(100); } }
422     catch(Exception x) {
423     CC.getLogger().log(Level.INFO, HF.getErrorMessage(x), x);
424     }
425     }
426     }
427    
428     private synchronized boolean
429     mustTerminate() { return terminate; }
430    
431     public synchronized void
432     terminate() {
433     terminate = true;
434     this.notifyAll();
435     }
436    
437     /** Processes the input sent by LinuxSampler */
438     private synchronized void
439     processInput() throws IOException {
440     while(in != null && in.available() > 0) {
441     String response = in.readLine();
442     fireResponseReceived(response);
443     }
444     }
445    
446     public synchronized void
447     setInputStream(LscpInputStream in) { this.in = in; }
448     }
449    
450     class LscpInputStream {
451     private InputStream in;
452     private StringBuffer buf = new StringBuffer();
453    
454     /**
455     * Creates a new instance of LscpInputStream.
456     *
457     */
458     public
459     LscpInputStream(InputStream in) {
460     this.in = in;
461     }
462    
463     /**
464     * Reads a line.
465     * This method is thread safe.
466     *
467     * @return A string containing the next line readed from the stream or
468     * <code>null</code> if the end of the stream has been reached.
469     * @throws IOException If an I/O error occurs.
470     */
471     public synchronized String
472     readLine() throws IOException {
473     int i;
474     buf.setLength(0);
475    
476     while((i = in.read()) != -1) {
477     if(i == '\r') {
478     checkLF();
479     break;
480     }
481     buf.append((char)i);
482     }
483    
484     if(i == -1) {
485     if(buf.length() > 0)
486     throw new IOException("Unexpected end of line!");
487     return null;
488     }
489     return buf.toString();
490     }
491    
492     /**
493     * Returns the number of bytes that can
494     * be read from this input stream without blocking.
495     *
496     * @return The number of bytes that can
497     * be read from this input stream without blocking.
498     * @throws IOException If an I/O error occurs.
499     */
500     public synchronized int
501     available() throws IOException { return in.available(); }
502    
503     private void
504     checkLF() throws IOException {
505     int i = in.read();
506     if(i == -1) throw new IOException("Unexpected end of file!");
507     if(i != '\n') throw new IOException("Unexpected end of line!");
508     }
509     }
510    
511     class LscpOutputStream {
512     private OutputStream out;
513    
514     /** Creates a new instance of LscpOutputStream */
515     public
516     LscpOutputStream(OutputStream out) { this.out = out; }
517    
518     /*
519     * Writes a line.
520     * @param line a string to be written.
521     */
522     public void
523     writeLine(String line) throws IOException {
524     try {
525     out.write(line.getBytes("US-ASCII"));
526     out.write('\r');
527     out.write('\n');
528     out.flush();
529     } catch(UnsupportedEncodingException x) {
530     CC.getLogger().log(Level.INFO, HF.getErrorMessage(x), x);
531     }
532     }
533     }
534     }

  ViewVC Help
Powered by ViewVC