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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1688 - (show 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 /*
2 * JSampler - a java front-end for LinuxSampler
3 *
4 * Copyright (C) 2005-2006 Grigor Iliev <grigor@grigoriliev.com>
5 *
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