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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1866 - (hide annotations) (download)
Sun Mar 15 19:40:29 2009 UTC (15 years, 1 month ago) by iliev
File size: 46488 byte(s)
* show controller names in fx sends dialogs
* save send levels when exporting sampler configuration
* ask when removing nonempty map
* fixed compilation error

1 iliev 787 /*
2     * JSampler - a java front-end for LinuxSampler
3     *
4 iliev 1864 * Copyright (C) 2005-2009 Grigor Iliev <grigor@grigoriliev.com>
5 iliev 787 *
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 iliev 911 import java.io.ByteArrayOutputStream;
29 iliev 1143 import java.io.File;
30     import java.io.FileInputStream;
31 iliev 787 import java.io.FileOutputStream;
32 iliev 1143 import java.io.InputStream;
33 iliev 787
34 iliev 911 import java.util.Vector;
35    
36 iliev 787 import java.util.logging.Handler;
37     import java.util.logging.Level;
38     import java.util.logging.Logger;
39     import java.util.logging.SimpleFormatter;
40     import java.util.logging.StreamHandler;
41    
42 iliev 1786 import javax.swing.SwingUtilities;
43 iliev 787 import javax.swing.Timer;
44    
45 iliev 1688 import javax.swing.event.ChangeEvent;
46     import javax.swing.event.ChangeListener;
47    
48 iliev 911 import net.sf.juife.Task;
49     import net.sf.juife.TaskQueue;
50    
51     import net.sf.juife.event.TaskEvent;
52     import net.sf.juife.event.TaskListener;
53     import net.sf.juife.event.TaskQueueEvent;
54     import net.sf.juife.event.TaskQueueListener;
55    
56 iliev 1143 import org.jsampler.event.ListEvent;
57     import org.jsampler.event.ListListener;
58 iliev 911 import org.jsampler.event.OrchestraEvent;
59     import org.jsampler.event.OrchestraListener;
60    
61 iliev 787 import org.jsampler.task.*;
62    
63     import org.jsampler.view.JSMainFrame;
64     import org.jsampler.view.JSProgress;
65 iliev 1285 import org.jsampler.view.JSViewConfig;
66 iliev 1204 import org.jsampler.view.InstrumentsDbTreeModel;
67 iliev 787
68 iliev 1143 import org.linuxsampler.lscp.AudioOutputChannel;
69     import org.linuxsampler.lscp.AudioOutputDevice;
70 iliev 787 import org.linuxsampler.lscp.Client;
71 iliev 1143 import org.linuxsampler.lscp.FxSend;
72     import org.linuxsampler.lscp.MidiInputDevice;
73     import org.linuxsampler.lscp.MidiPort;
74     import org.linuxsampler.lscp.Parameter;
75     import org.linuxsampler.lscp.SamplerChannel;
76    
77 iliev 787 import org.linuxsampler.lscp.event.*;
78    
79 iliev 911 import org.w3c.dom.Document;
80     import org.w3c.dom.Node;
81 iliev 787
82 iliev 1143 import static org.jsampler.JSI18n.i18n;
83 iliev 787
84 iliev 1143
85 iliev 787 /**
86 iliev 911 * This class serves as a 'Control Center' of the application.
87     * It also provides some fundamental routines and access to most used objects.
88 iliev 787 * @author Grigor Iliev
89     */
90     public class CC {
91     private static Handler handler;
92 iliev 911 private static FileOutputStream fos;
93 iliev 787
94 iliev 1285 private static JSViewConfig viewConfig = null;
95 iliev 787 private static JSMainFrame mainFrame = null;
96     private static JSProgress progress = null;
97    
98     private final static Client lsClient = new Client();
99    
100 iliev 1143 private static String jSamplerHome = null;
101    
102 iliev 787 private final static TaskQueue taskQueue = new TaskQueue();
103 iliev 911 private final static Timer timer = new Timer(2000, null);
104 iliev 787
105 iliev 1786 private static int connectionFailureCount = 0;
106    
107 iliev 1143 /** Forbits the instantiation of this class. */
108     private
109     CC() { }
110 iliev 787
111 iliev 911 /**
112     * Returns the logger to be used for logging events.
113     * @return The logger to be used for logging events.
114     */
115 iliev 787 public static Logger
116     getLogger() {
117     return Logger.getLogger (
118     "org.jsampler",
119     "org.jsampler.langprops.LogsBundle"
120     );
121     }
122    
123 iliev 911 /**
124     * Returns the task queue to be used for scheduling tasks
125     * for execution out of the event-dispatching thread.
126     * @return The task queue to be used for scheduling tasks
127     * for execution out of the event-dispatching thread.
128     */
129 iliev 1818 public static synchronized TaskQueue
130 iliev 787 getTaskQueue() { return taskQueue; }
131    
132 iliev 911 /**
133 iliev 1204 * Adds the specified task to the task queue. All task in the
134     * queue equal to the specified task are removed from the queue.
135     */
136 iliev 1818 public static synchronized void
137 iliev 1204 scheduleTask(Task t) {
138     while(getTaskQueue().removeTask(t)) { }
139    
140     getTaskQueue().add(t);
141     }
142    
143     /**
144 iliev 1734 * Adds the specified task to the task queue only if the last
145 iliev 1818 * task in the queue is not equal to <code>t</code>.
146 iliev 1734 */
147 iliev 1818 public static synchronized void
148 iliev 1734 addTask(Task t) {
149     Task[] tasks = getTaskQueue().getPendingTasks();
150     if(tasks.length > 0 && tasks[tasks.length - 1].equals(t)) return;
151     getTaskQueue().add(t);
152     }
153    
154     /**
155 iliev 1285 * Gets the configuration of the current view.
156     */
157     public static JSViewConfig
158     getViewConfig() { return viewConfig; }
159    
160 iliev 1767 public static JSPrefs
161 iliev 1688 preferences() { return getViewConfig().preferences(); }
162    
163 iliev 1285 /**
164     * Sets the configuration of the current view.
165     */
166     public static void
167     setViewConfig(JSViewConfig viewConfig) { CC.viewConfig = viewConfig; }
168    
169     /**
170 iliev 911 * Returns the main window of this application.
171     * @return The main window of this application.
172     */
173 iliev 787 public static JSMainFrame
174     getMainFrame() { return mainFrame; }
175    
176 iliev 911 /**
177     * Sets the main window of this application.
178     * @param mainFrame The main window of this application.
179     */
180 iliev 787 public static void
181     setMainFrame(JSMainFrame mainFrame) { CC.mainFrame = mainFrame; }
182    
183 iliev 911 /**
184     * Gets the progress indicator of this application.
185     * @return The progress indicator of this application.
186     */
187 iliev 787 public static JSProgress
188     getProgressIndicator() { return progress; }
189    
190 iliev 911 /**
191     * Sets the progress indicator to be used by this application.
192     * @param progress The progress indicator to be used by this application.
193     */
194 iliev 787 public static void
195     setProgressIndicator(JSProgress progress) { CC.progress = progress; }
196    
197 iliev 911 /**
198 iliev 1143 * Gets the absolute path to the JSampler's home location.
199     * @return The absolute path to the JSampler's home location
200     * or <code>null</code> if the JSampler's home location is not specified yet.
201     */
202     public static String
203     getJSamplerHome() { return jSamplerHome; }
204    
205     /**
206     * Sets the location of the JSampler's home.
207     * @param path The new absolute path to the JSampler's home location.
208     */
209     public static void
210     setJSamplerHome(String path) {
211     jSamplerHome = path;
212     Prefs.setJSamplerHome(jSamplerHome);
213     }
214    
215     /**
216 iliev 911 * This method does the initial preparation of the application.
217     */
218 iliev 787 protected static void
219     initJSampler() {
220     fos = null;
221 iliev 1143 setJSamplerHome(Prefs.getJSamplerHome());
222     String s = getJSamplerHome();
223     try {
224     if(s != null) {
225     s += File.separator + "jsampler.log";
226     File f = new File(s);
227     if(f.isFile()) HF.createBackup("jsampler.log", "jsampler.log.0");
228     fos = new FileOutputStream(s);
229     }
230     } catch(Exception x) { x.printStackTrace(); }
231 iliev 787
232     if(fos == null) handler = new StreamHandler(System.out, new SimpleFormatter());
233     else handler = new StreamHandler(fos, new SimpleFormatter());
234    
235     handler.setLevel(Level.FINE);
236     getLogger().addHandler(handler);
237     getLogger().setLevel(Level.FINE);
238 iliev 1204 Logger.getLogger("org.linuxsampler.lscp").setLevel(Level.FINE);
239 iliev 787 Logger.getLogger("org.linuxsampler.lscp").addHandler(handler);
240    
241     // Flushing logs on every second
242     new java.util.Timer().schedule(new java.util.TimerTask() {
243     public void
244     run() { if(handler != null) handler.flush(); }
245     }, 1000, 1000);
246    
247 iliev 1767 getLogger().fine("CC.jsStarted");
248 iliev 787
249     HF.setUIDefaultFont(Prefs.getInterfaceFont());
250    
251     timer.setRepeats(false);
252    
253     timer.addActionListener(new ActionListener() {
254     public void
255     actionPerformed(ActionEvent e) { CC.getProgressIndicator().start(); }
256     });
257    
258 iliev 1818 getTaskQueue().addTaskQueueListener(getHandler());
259 iliev 787
260 iliev 1818 getTaskQueue().start();
261 iliev 787
262 iliev 1143 getClient().removeChannelCountListener(getHandler());
263 iliev 911 getClient().addChannelCountListener(getHandler());
264 iliev 1143
265     getClient().removeChannelInfoListener(getHandler());
266 iliev 911 getClient().addChannelInfoListener(getHandler());
267 iliev 1143
268     getClient().removeFxSendCountListener(getHandler());
269     getClient().addFxSendCountListener(getHandler());
270    
271     getClient().removeFxSendInfoListener(getHandler());
272     getClient().addFxSendInfoListener(getHandler());
273    
274     getClient().removeStreamCountListener(getHandler());
275 iliev 911 getClient().addStreamCountListener(getHandler());
276 iliev 1143
277     getClient().removeVoiceCountListener(getHandler());
278 iliev 911 getClient().addVoiceCountListener(getHandler());
279 iliev 1143
280 iliev 1545 getClient().removeTotalStreamCountListener(getHandler());
281     getClient().addTotalStreamCountListener(getHandler());
282    
283 iliev 1143 getClient().removeTotalVoiceCountListener(getHandler());
284 iliev 911 getClient().addTotalVoiceCountListener(getHandler());
285    
286 iliev 1143 getClient().removeAudioDeviceCountListener(audioDeviceCountListener);
287     getClient().addAudioDeviceCountListener(audioDeviceCountListener);
288 iliev 911
289 iliev 1143 getClient().removeAudioDeviceInfoListener(audioDeviceInfoListener);
290     getClient().addAudioDeviceInfoListener(audioDeviceInfoListener);
291    
292     getClient().removeMidiDeviceCountListener(midiDeviceCountListener);
293     getClient().addMidiDeviceCountListener(midiDeviceCountListener);
294    
295     getClient().removeMidiDeviceInfoListener(midiDeviceInfoListener);
296     getClient().addMidiDeviceInfoListener(midiDeviceInfoListener);
297    
298     getClient().removeMidiInstrumentMapCountListener(midiInstrMapCountListener);
299     getClient().addMidiInstrumentMapCountListener(midiInstrMapCountListener);
300    
301     getClient().removeMidiInstrumentMapInfoListener(midiInstrMapInfoListener);
302     getClient().addMidiInstrumentMapInfoListener(midiInstrMapInfoListener);
303    
304     getClient().removeMidiInstrumentCountListener(getHandler());
305     getClient().addMidiInstrumentCountListener(getHandler());
306    
307     getClient().removeMidiInstrumentInfoListener(getHandler());
308     getClient().addMidiInstrumentInfoListener(getHandler());
309    
310     getClient().removeGlobalInfoListener(getHandler());
311     getClient().addGlobalInfoListener(getHandler());
312 iliev 1776
313     getClient().removeChannelMidiDataListener(getHandler());
314     getClient().addChannelMidiDataListener(getHandler());
315 iliev 1786
316     CC.addConnectionEstablishedListener(new ActionListener() {
317     public void
318     actionPerformed(ActionEvent e) {
319     connectionFailureCount = 0;
320     }
321     });
322 iliev 1143 }
323    
324     /**
325     * Checks whether the JSampler home directory is specified and exist.
326     * If the JSampler home directory is not specifed, or is specified
327     * but doesn't exist, a procedure of specifying a JSampler home
328     * directory is initiated.
329     * @see org.jsampler.view.JSMainFrame#installJSamplerHome
330     */
331     public static void
332     checkJSamplerHome() {
333     if(getJSamplerHome() != null) {
334     File f = new File(getJSamplerHome());
335 iliev 1285 if(f.exists() && f.isDirectory()) {
336     return;
337     }
338 iliev 911 }
339 iliev 1143
340 iliev 1767 getMainFrame().installJSamplerHome();
341 iliev 787 }
342    
343 iliev 1143 /**
344     * Changes the JSampler's home directory and moves all files from
345     * the old JSampler's home directory to the new one. If all files are
346     * moved succesfully, the old directory is deleted.
347     * @param path The location of the new JSampler's home directory. If
348     * the last directory in the path doesn't exist, it is created.
349     */
350     public static void
351     changeJSamplerHome(String path) {
352     File fNew = new File(path);
353 iliev 1285 if(fNew.exists() && fNew.isFile()) {
354 iliev 1143 HF.showErrorMessage(i18n.getError("CC.JSamplerHomeIsNotDir!"));
355     return;
356     }
357    
358 iliev 1285 if(!fNew.exists()) {
359 iliev 1143 if(!fNew.mkdir()) {
360     String s = fNew.getAbsolutePath();
361     HF.showErrorMessage(i18n.getError("CC.mkdirFailed", s));
362     return;
363     }
364     }
365    
366 iliev 1285 if(getJSamplerHome() == null || path.equals(getJSamplerHome())) {
367 iliev 1143 setJSamplerHome(fNew.getAbsolutePath());
368     return;
369     }
370    
371     File fOld = new File(getJSamplerHome());
372 iliev 1285 if(!fOld.exists() || !fOld.isDirectory()) {
373 iliev 1143 setJSamplerHome(fNew.getAbsolutePath());
374     return;
375     }
376    
377     File[] files = fOld.listFiles();
378     boolean b = true;
379     if(files != null) {
380     String s = fNew.getAbsolutePath() + File.separator;
381     for(File f : files) if(!f.renameTo(new File(s + f.getName()))) b = false;
382     }
383    
384     if(b) fOld.delete();
385     setJSamplerHome(fNew.getAbsolutePath());
386     }
387    
388 iliev 911 private final static OrchestraListModel orchestras = new DefaultOrchestraListModel();
389    
390     /**
391     * Returns a list containing all available orchestras.
392     * @return A list containing all available orchestras.
393     */
394     public static OrchestraListModel
395     getOrchestras() { return orchestras; }
396    
397 iliev 1688 private final static ServerList servers = new ServerList();
398    
399     /** Returns the server list. */
400     public static ServerList
401     getServerList() { return servers; }
402    
403     private static ServerListListener serverListListener = new ServerListListener();
404    
405     private static class ServerListListener implements ChangeListener {
406 iliev 1786 @Override
407 iliev 1688 public void
408     stateChanged(ChangeEvent e) {
409     saveServerList();
410     }
411     }
412    
413     private static final Vector<ChangeListener> idtmListeners = new Vector<ChangeListener>();
414 iliev 1204 private static InstrumentsDbTreeModel instrumentsDbTreeModel = null;
415 iliev 1688
416 iliev 1143 /**
417 iliev 1204 * Gets the tree model of the instruments database.
418     * If the currently used view doesn't have instruments
419     * database support the tree model is initialized on first use.
420     * @return The tree model of the instruments database or
421     * <code>null</code> if the backend doesn't have instruments database support.
422 iliev 1327 * @see org.jsampler.view.JSViewConfig#getInstrumentsDbSupport
423 iliev 1204 */
424     public static InstrumentsDbTreeModel
425     getInstrumentsDbTreeModel() {
426 iliev 1767 if(getSamplerModel().getServerInfo() == null) return null;
427     if(!getSamplerModel().getServerInfo().hasInstrumentsDbSupport()) return null;
428 iliev 1204
429     if(instrumentsDbTreeModel == null) {
430     instrumentsDbTreeModel = new InstrumentsDbTreeModel();
431 iliev 1688 for(ChangeListener l : idtmListeners) l.stateChanged(null);
432 iliev 1204 }
433    
434     return instrumentsDbTreeModel;
435     }
436    
437 iliev 1688 public static void
438     addInstrumentsDbChangeListener(ChangeListener l) {
439     idtmListeners.add(l);
440     }
441    
442     public static void
443     removeInstrumentsDbChangeListener(ChangeListener l) {
444     idtmListeners.remove(l);
445     }
446    
447 iliev 1729 private static final LostFilesModel lostFilesModel = new LostFilesModel();
448    
449     public static LostFilesModel
450     getLostFilesModel() { return lostFilesModel; }
451    
452 iliev 1204 /**
453 iliev 1143 * Loads the orchestras described in <code>&lt;jsampler_home&gt;/orchestras.xml</code>.
454     * If file with name <code>orchestras.xml.bkp</code> exist in the JSampler's home
455     * directory, this means that the last save has failed. In that case a recovery file
456     * <code>orchestras.xml.rec</code> is created and a recovery procedure
457     * will be initiated.
458     */
459     public static void
460     loadOrchestras() {
461     if(getJSamplerHome() == null) return;
462    
463     try {
464     String s = getJSamplerHome();
465    
466     File f = new File(s + File.separator + "orchestras.xml.bkp");
467     if(f.isFile()) HF.createBackup("orchestras.xml.bkp", "orchestras.xml.rec");
468    
469     FileInputStream fis;
470     fis = new FileInputStream(s + File.separator + "orchestras.xml");
471    
472     loadOrchestras(fis);
473     fis.close();
474     } catch(Exception x) {
475     getLogger().log(Level.INFO, HF.getErrorMessage(x), x);
476     }
477 iliev 1688
478     getOrchestras().addOrchestraListListener(getHandler());
479 iliev 1143 }
480    
481    
482 iliev 911 private static void
483 iliev 1143 loadOrchestras(InputStream in) {
484     Document doc = DOMUtils.readObject(in);
485    
486     try { getOrchestras().readObject(doc.getDocumentElement()); }
487     catch(Exception x) {
488     HF.showErrorMessage(x, "Loading orchestras: ");
489     return;
490     }
491    
492     for(int i = 0; i < getOrchestras().getOrchestraCount(); i++) {
493     getOrchestras().getOrchestra(i).addOrchestraListener(getHandler());
494     }
495     }
496    
497     private static void
498 iliev 911 saveOrchestras() {
499 iliev 1143 try {
500     String s = getJSamplerHome();
501     if(s == null) return;
502    
503     HF.createBackup("orchestras.xml", "orchestras.xml.bkp");
504    
505 iliev 1786 FileOutputStream fos2;
506     fos2 = new FileOutputStream(s + File.separator + "orchestras.xml", false);
507 iliev 1143
508     Document doc = DOMUtils.createEmptyDocument();
509 iliev 911
510 iliev 1143 Node node = doc.createElement("temp");
511     doc.appendChild(node);
512    
513     getOrchestras().writeObject(doc, doc.getDocumentElement());
514    
515     doc.replaceChild(node.getFirstChild(), node);
516 iliev 911
517 iliev 1786 DOMUtils.writeObject(doc, fos2);
518 iliev 1143
519 iliev 1786 fos2.close();
520 iliev 1143
521     HF.deleteFile("orchestras.xml.bkp");
522     } catch(Exception x) {
523     HF.showErrorMessage(x, "Saving orchestras: ");
524     return;
525     }
526 iliev 911 }
527    
528     /**
529 iliev 1688 * Loads the servers' info described in <code>&lt;jsampler_home&gt;/servers.xml</code>.
530     * If file with name <code>servers.xml.bkp</code> exist in the JSampler's home
531     * directory, this means that the last save has failed. In that case a recovery file
532     * <code>servers.xml.rec</code> is created and a recovery procedure
533     * will be initiated.
534     */
535     public static void
536     loadServerList() {
537     if(getJSamplerHome() == null) return;
538    
539     try {
540     String s = getJSamplerHome();
541    
542     File f = new File(s + File.separator + "servers.xml.bkp");
543     if(f.isFile()) HF.createBackup("servers.xml.bkp", "servers.xml.rec");
544    
545     FileInputStream fis;
546     fis = new FileInputStream(s + File.separator + "servers.xml");
547    
548     loadServerList(fis);
549     fis.close();
550     } catch(Exception x) {
551     getLogger().log(Level.INFO, HF.getErrorMessage(x), x);
552     }
553    
554     getServerList().addChangeListener(serverListListener);
555    
556     /* We should have at least one server to connect. */
557     if(getServerList().getServerCount() == 0) {
558     Server server = new Server();
559     server.setName("127.0.0.1:8888");
560     server.setAddress("127.0.0.1");
561     server.setPort(8888);
562     getServerList().addServer(server);
563     }
564     }
565    
566    
567     private static void
568     loadServerList(InputStream in) {
569     Document doc = DOMUtils.readObject(in);
570    
571     try { getServerList().readObject(doc.getDocumentElement()); }
572     catch(Exception x) {
573     HF.showErrorMessage(x, "Loading server list: ");
574     return;
575     }
576     }
577    
578     private static void
579     saveServerList() {
580     try {
581     String s = getJSamplerHome();
582     if(s == null) return;
583    
584     HF.createBackup("servers.xml", "servers.xml.bkp");
585    
586 iliev 1786 FileOutputStream fos2;
587     fos2 = new FileOutputStream(s + File.separator + "servers.xml", false);
588 iliev 1688
589     Document doc = DOMUtils.createEmptyDocument();
590    
591     Node node = doc.createElement("temp");
592     doc.appendChild(node);
593    
594     getServerList().writeObject(doc, doc.getDocumentElement());
595    
596     doc.replaceChild(node.getFirstChild(), node);
597    
598 iliev 1786 DOMUtils.writeObject(doc, fos2);
599 iliev 1688
600 iliev 1786 fos2.close();
601 iliev 1688
602     HF.deleteFile("servers.xml.bkp");
603     } catch(Exception x) {
604     HF.showErrorMessage(x, "Saving server list: ");
605     return;
606     }
607     }
608    
609     /**
610 iliev 911 * The exit point of the application which ensures clean exit with default exit status 0.
611     * @see #cleanExit(int i)
612     */
613 iliev 787 public static void
614     cleanExit() { cleanExit(0); }
615    
616 iliev 911 /**
617     * The exit point of the application which ensures clean exit.
618     * @param i The exit status.
619     */
620 iliev 787 public static void
621     cleanExit(int i) {
622 iliev 1767 getLogger().fine("CC.jsEnded");
623 iliev 1786 try { getClient().disconnect(); } // FIXME: this might block the EDT
624     catch(Exception x) { x.printStackTrace(); }
625     if(backendProcess != null) backendProcess.destroy();
626     backendProcess = null;
627     fireBackendProcessEvent();
628 iliev 787 System.exit(i);
629     }
630    
631 iliev 911 /**
632     * Gets the <code>Client</code> object that is used to communicate with the backend.
633     * @return The <code>Client</code> object that is used to communicate with the backend.
634     */
635 iliev 787 public static Client
636     getClient() { return lsClient; }
637    
638 iliev 911 private static final Vector<ActionListener> listeners = new Vector<ActionListener>();
639 iliev 787
640 iliev 911 /**
641     * Registers the specified listener to be notified when reconnecting to LinuxSampler.
642     * @param l The <code>ActionListener</code> to register.
643     */
644     public static void
645     addReconnectListener(ActionListener l) { listeners.add(l); }
646    
647     /**
648     * Removes the specified listener.
649     * @param l The <code>ActionListener</code> to remove.
650     */
651     public static void
652     removeReconnectListener(ActionListener l) { listeners.remove(l); }
653    
654     private static void
655     fireReconnectEvent() {
656     ActionEvent e = new ActionEvent(CC.class, ActionEvent.ACTION_PERFORMED, null);
657     for(ActionListener l : listeners) l.actionPerformed(e);
658     }
659    
660 iliev 1786 private static final Vector<ActionListener> ceListeners = new Vector<ActionListener>();
661    
662     /**
663     * Registers the specified listener to be notified when
664     * jsampler is connected successfully to LinuxSampler.
665     * @param l The <code>ActionListener</code> to register.
666     */
667     public static void
668     addConnectionEstablishedListener(ActionListener l) { ceListeners.add(l); }
669    
670     /**
671     * Removes the specified listener.
672     * @param l The <code>ActionListener</code> to remove.
673     */
674     public static void
675     removeConnectionEstablishedListener(ActionListener l) { ceListeners.remove(l); }
676    
677     private static void
678     fireConnectionEstablishedEvent() {
679     ActionEvent e = new ActionEvent(CC.class, ActionEvent.ACTION_PERFORMED, null);
680     for(ActionListener l : ceListeners) l.actionPerformed(e);
681     }
682    
683 iliev 787 private static final SamplerModel samplerModel = new DefaultSamplerModel();
684    
685     /**
686     * Gets the sampler model.
687     * @return The sampler model.
688     */
689     public static SamplerModel
690     getSamplerModel() { return samplerModel; }
691    
692 iliev 911 /**
693 iliev 1688 * Connects to LinuxSampler.
694     */
695     public static void
696     connect() { initSamplerModel(); }
697    
698     /**
699 iliev 911 * Reconnects to LinuxSampler.
700     */
701 iliev 787 public static void
702 iliev 1688 reconnect() { initSamplerModel(getCurrentServer()); }
703    
704     private static Server currentServer = null;
705    
706     /**
707     * Gets the server, to which the frontend is going to connect
708     * or is already connected.
709     */
710     public static Server
711     getCurrentServer() { return currentServer; }
712    
713     /**
714     * Sets the current server.
715     */
716     public static void
717 iliev 1786 setCurrentServer(Server server) {
718     if(server == currentServer) return;
719     connectionFailureCount = 0;
720     currentServer = server;
721     }
722 iliev 1688
723     /**
724 iliev 1767 * Sets the LSCP client's read timeout.
725     * @param timeout The new timeout value (in seconds).
726     */
727     public static void
728     setClientReadTimeout(int timeout) {
729     getTaskQueue().add(new Global.SetClientReadTimeout(timeout));
730     }
731    
732     /**
733 iliev 1688 * This method updates the information about the backend state.
734     */
735     private static void
736     initSamplerModel() {
737     Server srv = getMainFrame().getServer();
738     if(srv == null) return;
739     initSamplerModel(srv);
740 iliev 911 }
741    
742     /**
743     * This method updates the information about the backend state.
744     */
745 iliev 1688 private static void
746     initSamplerModel(Server srv) {
747     setCurrentServer(srv);
748     final SetServerAddress ssa = new SetServerAddress(srv.getAddress(), srv.getPort());
749    
750 iliev 787 final DefaultSamplerModel model = (DefaultSamplerModel)getSamplerModel();
751    
752 iliev 1204 final Global.GetServerInfo gsi = new Global.GetServerInfo();
753 iliev 787 gsi.addTaskListener(new TaskListener() {
754     public void
755     taskPerformed(TaskEvent e) {
756 iliev 1204 if(gsi.doneWithErrors()) return;
757    
758     model.setServerInfo(gsi.getResult());
759    
760 iliev 1285 if(CC.getViewConfig().getInstrumentsDbSupport()) {
761 iliev 1204 getInstrumentsDbTreeModel();
762     }
763 iliev 787 }
764     });
765    
766 iliev 1143 final Audio.GetDrivers gaod = new Audio.GetDrivers();
767 iliev 787 gaod.addTaskListener(new TaskListener() {
768     public void
769     taskPerformed(TaskEvent e) {
770     if(!gaod.doneWithErrors())
771     model.setAudioOutputDrivers(gaod.getResult());
772     }
773     });
774    
775     final GetEngines ge = new GetEngines();
776     ge.addTaskListener(new TaskListener() {
777     public void
778     taskPerformed(TaskEvent e) {
779     if(!ge.doneWithErrors()) model.setEngines(ge.getResult());
780     }
781     });
782    
783 iliev 1143 final Midi.GetDrivers gmid = new Midi.GetDrivers();
784 iliev 787 gmid.addTaskListener(new TaskListener() {
785     public void
786     taskPerformed(TaskEvent e) {
787     if(!gmid.doneWithErrors())
788     model.setMidiInputDrivers(gmid.getResult());
789     }
790     });
791    
792 iliev 1143 final Global.GetVolume gv = new Global.GetVolume();
793     gv.addTaskListener(new TaskListener() {
794     public void
795     taskPerformed(TaskEvent e) {
796     if(!gv.doneWithErrors())
797     model.setVolume(gv.getResult());
798     }
799     });
800    
801     final Midi.GetInstrumentMaps mgim = new Midi.GetInstrumentMaps();
802     mgim.addTaskListener(new TaskListener() {
803     public void
804     taskPerformed(TaskEvent e) {
805     if(mgim.doneWithErrors()) return;
806     model.removeAllMidiInstrumentMaps();
807    
808     for(MidiInstrumentMap map : mgim.getResult()) {
809     model.addMidiInstrumentMap(map);
810     }
811     }
812     });
813    
814     final UpdateChannels uc = new UpdateChannels();
815     uc.addTaskListener(new TaskListener() {
816     public void
817     taskPerformed(TaskEvent e) {
818 iliev 1204 for(SamplerChannelModel c : model.getChannels()) {
819 iliev 1143 if(c.getChannelInfo().getEngine() == null) continue;
820    
821     Channel.GetFxSends gfs = new Channel.GetFxSends();
822     gfs.setChannel(c.getChannelId());
823     gfs.addTaskListener(new GetFxSendsListener());
824     getTaskQueue().add(gfs);
825     }
826 iliev 1567
827     // TODO: This should be done after the fx sends are set
828     //CC.getSamplerModel().setModified(false);
829 iliev 1143 }
830     });
831    
832    
833 iliev 787 final Connect cnt = new Connect();
834 iliev 1786 boolean b = preferences().getBoolProperty(JSPrefs.LAUNCH_BACKEND_LOCALLY);
835     if(b && srv.isLocal() && backendProcess == null) cnt.setSilent(true);
836 iliev 787 cnt.addTaskListener(new TaskListener() {
837     public void
838     taskPerformed(TaskEvent e) {
839 iliev 1688 if(cnt.doneWithErrors()) {
840 iliev 1786 onConnectFailure();
841 iliev 1688 return;
842     }
843 iliev 787
844     getTaskQueue().add(gsi);
845     getTaskQueue().add(gaod);
846     getTaskQueue().add(gmid);
847     getTaskQueue().add(ge);
848 iliev 1143 getTaskQueue().add(gv);
849     getTaskQueue().add(mgim);
850     getTaskQueue().add(new Midi.UpdateDevices());
851     getTaskQueue().add(new Audio.UpdateDevices());
852 iliev 1734 addTask(uc);
853 iliev 1786
854 iliev 1818 int vl = preferences().getIntProperty(JSPrefs.GLOBAL_VOICE_LIMIT);
855     int sl = preferences().getIntProperty(JSPrefs.GLOBAL_STREAM_LIMIT);
856    
857     getTaskQueue().add(new Global.SetPolyphony(vl, sl));
858    
859 iliev 1786 fireConnectionEstablishedEvent();
860 iliev 787 }
861     });
862 iliev 1688
863     ssa.addTaskListener(new TaskListener() {
864     public void
865     taskPerformed(TaskEvent e) {
866 iliev 1767 int t = preferences().getIntProperty(JSPrefs.SOCKET_READ_TIMEOUT);
867     CC.setClientReadTimeout(t * 1000);
868 iliev 1688 CC.getTaskQueue().add(cnt);
869     }
870     });
871    
872     getSamplerModel().reset();
873     if(instrumentsDbTreeModel != null) {
874     instrumentsDbTreeModel.reset();
875     instrumentsDbTreeModel = null;
876     }
877    
878     getTaskQueue().removePendingTasks();
879     getTaskQueue().add(ssa);
880    
881     fireReconnectEvent();
882 iliev 787 }
883    
884 iliev 1688 private static void
885 iliev 1786 onConnectFailure() {
886     connectionFailureCount++;
887     if(connectionFailureCount > 50) { // to prevent eventual infinite loop
888     getLogger().warning("Reached maximum number of connection failures");
889     return;
890     }
891    
892     try {
893     if(launchBackend()) {
894     int i = preferences().getIntProperty(JSPrefs.BACKEND_LAUNCH_DELAY);
895     if(i < 1) {
896     initSamplerModel(getCurrentServer());
897     return;
898     }
899    
900     LaunchBackend lb = new LaunchBackend(i, getBackendMonitor());
901     //CC.getTaskQueue().add(lb);
902     new Thread(lb).start();
903     return;
904     }
905     } catch(Exception x) {
906     final String s = JSI18n.i18n.getError("CC.failedToLaunchBackend");
907     CC.getLogger().log(Level.INFO, s, x);
908    
909     SwingUtilities.invokeLater(new Runnable() {
910     public void
911     run() { HF.showErrorMessage(s); }
912     });
913     return;
914     }
915    
916     retryToConnect();
917     }
918    
919     private static void
920 iliev 1688 retryToConnect() {
921     javax.swing.SwingUtilities.invokeLater(new Runnable() {
922     public void
923     run() { changeBackend(); }
924     });
925     }
926    
927     public static void
928     changeBackend() {
929     Server s = getMainFrame().getServer(true);
930 iliev 1786 if(s != null) {
931     connectionFailureCount = 0; // cleared because this change due to user interaction
932     initSamplerModel(s);
933     }
934 iliev 1688 }
935    
936 iliev 1786 private static final Vector<ActionListener> pListeners = new Vector<ActionListener>();
937    
938     /**
939     * Registers the specified listener to be notified when
940     * backend process is created/terminated.
941     * @param l The <code>ActionListener</code> to register.
942     */
943     public static void
944     addBackendProcessListener(ActionListener l) { pListeners.add(l); }
945    
946     /**
947     * Removes the specified listener.
948     * @param l The <code>ActionListener</code> to remove.
949     */
950     public static void
951     removeBackendProcessListener(ActionListener l) { pListeners.remove(l); }
952    
953     private static void
954     fireBackendProcessEvent() {
955     ActionEvent e = new ActionEvent(CC.class, ActionEvent.ACTION_PERFORMED, null);
956     for(ActionListener l : pListeners) l.actionPerformed(e);
957     }
958    
959     private static Process backendProcess = null;
960    
961     public static Process
962     getBackendProcess() { return backendProcess; }
963    
964     private static final Object backendMonitor = new Object();
965    
966     public static Object
967     getBackendMonitor() { return backendMonitor; }
968    
969     private static boolean
970     launchBackend() throws Exception {
971     if(backendProcess != null) {
972     try {
973     int i = backendProcess.exitValue();
974     getLogger().info("Backend exited with exit value " + i);
975     backendProcess = null;
976     fireBackendProcessEvent();
977     } catch(IllegalThreadStateException x) { return false; }
978     }
979    
980     if(!preferences().getBoolProperty(JSPrefs.LAUNCH_BACKEND_LOCALLY)) return false;
981     if(connectionFailureCount > 1) return false;
982    
983     Server s = getCurrentServer();
984     if(s != null && s.isLocal()) {
985     String cmd = preferences().getStringProperty(JSPrefs.BACKEND_LAUNCH_COMMAND);
986     backendProcess = Runtime.getRuntime().exec(cmd);
987     fireBackendProcessEvent();
988     return true;
989     }
990    
991     return false;
992     }
993    
994 iliev 1143 private static class GetFxSendsListener implements TaskListener {
995 iliev 1786 @Override
996 iliev 1143 public void
997     taskPerformed(TaskEvent e) {
998     Channel.GetFxSends gfs = (Channel.GetFxSends)e.getSource();
999     if(gfs.doneWithErrors()) return;
1000 iliev 1204 SamplerChannelModel m = getSamplerModel().getChannelById(gfs.getChannel());
1001 iliev 1143 m.removeAllFxSends();
1002    
1003     for(FxSend fxs : gfs.getResult()) m.addFxSend(fxs);
1004     }
1005     }
1006    
1007     public static String
1008     exportInstrMapsToLscpScript() {
1009     StringBuffer sb = new StringBuffer("# Exported by: ");
1010     sb.append("JSampler - a java front-end for LinuxSampler\r\n# Version: ");
1011     sb.append(JSampler.VERSION).append("\r\n");
1012     sb.append("# Date: ").append(new java.util.Date().toString()).append("\r\n\r\n");
1013    
1014     Client lscpClient = new Client(true);
1015     ByteArrayOutputStream out = new ByteArrayOutputStream();
1016     lscpClient.setPrintOnlyModeOutputStream(out);
1017    
1018     exportInstrMapsToLscpScript(lscpClient);
1019     sb.append(out.toString());
1020     out.reset();
1021    
1022     return sb.toString();
1023     }
1024    
1025     private static void
1026     exportInstrMapsToLscpScript(Client lscpClient) {
1027     try {
1028     lscpClient.removeAllMidiInstrumentMaps();
1029 iliev 1767 MidiInstrumentMap[] maps = getSamplerModel().getMidiInstrumentMaps();
1030 iliev 1143 for(int i = 0; i < maps.length; i++) {
1031     lscpClient.addMidiInstrumentMap(maps[i].getName());
1032     exportInstrumentsToLscpScript(i, maps[i], lscpClient);
1033     }
1034     } catch(Exception e) {
1035 iliev 1767 getLogger().log(Level.FINE, HF.getErrorMessage(e), e);
1036 iliev 1143 HF.showErrorMessage(e);
1037     }
1038     }
1039    
1040     private static void
1041     exportInstrumentsToLscpScript(int mapId, MidiInstrumentMap map, Client lscpClient)
1042     throws Exception {
1043    
1044 iliev 1767 boolean b = preferences().getBoolProperty(JSPrefs.LOAD_MIDI_INSTRUMENTS_IN_BACKGROUND);
1045    
1046 iliev 1143 for(MidiInstrument i : map.getAllMidiInstruments()) {
1047 iliev 1767 lscpClient.mapMidiInstrument(mapId, i.getInfo().getEntry(), i.getInfo(), b);
1048 iliev 1143 }
1049     }
1050    
1051     public static String
1052     exportSessionToLscpScript() {
1053 iliev 1767 getSamplerModel().setModified(false);
1054 iliev 1567
1055 iliev 1143 StringBuffer sb = new StringBuffer("# Exported by: ");
1056     sb.append("JSampler - a java front-end for LinuxSampler\r\n# Version: ");
1057     sb.append(JSampler.VERSION).append("\r\n");
1058     sb.append("# Date: ").append(new java.util.Date().toString()).append("\r\n\r\n");
1059    
1060     Client lscpClient = new Client(true);
1061     ByteArrayOutputStream out = new ByteArrayOutputStream();
1062     lscpClient.setPrintOnlyModeOutputStream(out);
1063    
1064     try {
1065     lscpClient.resetSampler();
1066     sb.append(out.toString());
1067     out.reset();
1068     sb.append("\r\n");
1069 iliev 1767 lscpClient.setVolume(getSamplerModel().getVolume());
1070 iliev 1143 sb.append(out.toString());
1071     out.reset();
1072     sb.append("\r\n");
1073 iliev 1767 } catch(Exception e) { getLogger().log(Level.FINE, HF.getErrorMessage(e), e); }
1074 iliev 1143
1075 iliev 1204 MidiDeviceModel[] mDevs = getSamplerModel().getMidiDevices();
1076 iliev 1143 for(int i = 0; i < mDevs.length; i++) {
1077     exportMidiDeviceToLscpScript(mDevs[i].getDeviceInfo(), i, lscpClient);
1078     sb.append(out.toString());
1079     out.reset();
1080     sb.append("\r\n");
1081     }
1082    
1083 iliev 1204 AudioDeviceModel[] aDevs = getSamplerModel().getAudioDevices();
1084 iliev 1143 for(int i = 0; i < aDevs.length; i++) {
1085     exportAudioDeviceToLscpScript(aDevs[i].getDeviceInfo(), i, lscpClient);
1086     sb.append(out.toString());
1087     out.reset();
1088     sb.append("\r\n");
1089     }
1090    
1091 iliev 1767 boolean b = preferences().getBoolProperty(JSPrefs.EXPORT_MIDI_MAPS_TO_SESSION_SCRIPT);
1092     if(b) {
1093     exportInstrMapsToLscpScript(lscpClient);
1094     sb.append(out.toString());
1095     out.reset();
1096     sb.append("\r\n");
1097     }
1098 iliev 1708
1099 iliev 1204 SamplerChannelModel[] channels = getSamplerModel().getChannels();
1100 iliev 1143
1101     for(int i = 0; i < channels.length; i++) {
1102 iliev 1467 SamplerChannelModel scm = channels[i];
1103 iliev 1143 exportChannelToLscpScript(scm.getChannelInfo(), i, lscpClient);
1104     sb.append(out.toString());
1105     out.reset();
1106    
1107     sb.append("\r\n");
1108    
1109     exportFxSendsToLscpScript(scm, i, lscpClient);
1110     sb.append(out.toString());
1111     out.reset();
1112    
1113     sb.append("\r\n");
1114     }
1115    
1116 iliev 1818 sb.append(getViewConfig().exportSessionViewConfig());
1117 iliev 1767
1118 iliev 1143 return sb.toString();
1119     }
1120    
1121     private static void
1122     exportMidiDeviceToLscpScript(MidiInputDevice mid, int devId, Client lscpCLient) {
1123     try {
1124     String s = mid.getDriverName();
1125     lscpCLient.createMidiInputDevice(s, mid.getAdditionalParameters());
1126    
1127     MidiPort[] mPorts = mid.getMidiPorts();
1128     int l = mPorts.length;
1129     if(l != 1) lscpCLient.setMidiInputPortCount(devId, l);
1130    
1131     for(int i = 0; i < l; i++) {
1132     Parameter[] prms = mPorts[i].getAllParameters();
1133     for(Parameter p : prms) {
1134     if(!p.isFixed() && p.getStringValue().length() > 0)
1135     lscpCLient.setMidiInputPortParameter(devId, i, p);
1136     }
1137     }
1138     } catch(Exception e) {
1139 iliev 1767 getLogger().log(Level.FINE, HF.getErrorMessage(e), e);
1140 iliev 1143 }
1141     }
1142    
1143     private static void
1144     exportAudioDeviceToLscpScript(AudioOutputDevice aod, int devId, Client lscpCLient) {
1145     try {
1146     String s = aod.getDriverName();
1147     lscpCLient.createAudioOutputDevice(s, aod.getAllParameters());
1148    
1149     AudioOutputChannel[] chns = aod.getAudioChannels();
1150    
1151     for(int i = 0; i < chns.length; i++) {
1152     Parameter[] prms = chns[i].getAllParameters();
1153     for(Parameter p : prms) {
1154     if(p.isFixed() || p.getStringValue().length() == 0);
1155     else lscpCLient.setAudioOutputChannelParameter(devId, i, p);
1156     }
1157     }
1158     } catch(Exception e) {
1159 iliev 1767 getLogger().log(Level.FINE, HF.getErrorMessage(e), e);
1160 iliev 1143 }
1161     }
1162    
1163     private static void
1164     exportChannelToLscpScript(SamplerChannel chn, int chnId, Client lscpCLient) {
1165     try {
1166     lscpCLient.addSamplerChannel();
1167    
1168 iliev 1767 SamplerModel sm = getSamplerModel();
1169 iliev 1467 int id = chn.getMidiInputDevice();
1170     if(id != -1) {
1171     for(int i = 0; i < sm.getMidiDeviceCount(); i++) {
1172     if(sm.getMidiDevice(i).getDeviceId() == id) {
1173     lscpCLient.setChannelMidiInputDevice(chnId, i);
1174     break;
1175     }
1176     }
1177 iliev 1540 lscpCLient.setChannelMidiInputPort(chnId, chn.getMidiInputPort());
1178     lscpCLient.setChannelMidiInputChannel(chnId, chn.getMidiInputChannel());
1179 iliev 1467 }
1180 iliev 1143
1181 iliev 1670 if(chn.getEngine() != null) {
1182     lscpCLient.loadSamplerEngine(chn.getEngine().getName(), chnId);
1183     lscpCLient.setChannelVolume(chnId, chn.getVolume());
1184 iliev 1708 int mapId = chn.getMidiInstrumentMapId();
1185     lscpCLient.setChannelMidiInstrumentMap(chnId, mapId);
1186 iliev 1670 }
1187    
1188 iliev 1467 id = chn.getAudioOutputDevice();
1189     if(id != -1) {
1190     for(int i = 0; i < sm.getAudioDeviceCount(); i++) {
1191     if(sm.getAudioDevice(i).getDeviceId() == id) {
1192     lscpCLient.setChannelAudioOutputDevice(chnId, i);
1193     break;
1194     }
1195     }
1196    
1197 iliev 1143 Integer[] routing = chn.getAudioOutputRouting();
1198    
1199     for(int j = 0; j < routing.length; j++) {
1200     int k = routing[j];
1201     if(k == j) continue;
1202    
1203     lscpCLient.setChannelAudioOutputChannel(chnId, j, k);
1204     }
1205     }
1206    
1207     String s = chn.getInstrumentFile();
1208 iliev 1467 int i = chn.getInstrumentIndex();
1209 iliev 1143 if(s != null) lscpCLient.loadInstrument(s, i, chnId, true);
1210    
1211     if(chn.isMuted()) lscpCLient.setChannelMute(chnId, true);
1212     if(chn.isSoloChannel()) lscpCLient.setChannelSolo(chnId, true);
1213     } catch(Exception e) {
1214 iliev 1767 getLogger().log(Level.FINE, HF.getErrorMessage(e), e);
1215 iliev 1143 }
1216     }
1217    
1218     private static void
1219     exportFxSendsToLscpScript(SamplerChannelModel scm, int chnId, Client lscpClient) {
1220     try {
1221     FxSend[] fxSends = scm.getFxSends();
1222    
1223     for(int i = 0; i < fxSends.length; i++) {
1224     FxSend f = fxSends[i];
1225     lscpClient.createFxSend(chnId, f.getMidiController(), f.getName());
1226 iliev 1866 lscpClient.setFxSendLevel(chnId, i, f.getLevel());
1227 iliev 1143
1228     Integer[] r = f.getAudioOutputRouting();
1229     for(int j = 0; j < r.length; j++) {
1230     lscpClient.setFxSendAudioOutputChannel(chnId, i, j, r[j]);
1231     }
1232     }
1233     } catch(Exception e) {
1234 iliev 1767 getLogger().log(Level.FINE, HF.getErrorMessage(e), e);
1235 iliev 1143 }
1236     }
1237    
1238 iliev 1688 public static void
1239     scheduleInTaskQueue(final Runnable r) {
1240     Task dummy = new Global.DummyTask();
1241     dummy.addTaskListener(new TaskListener() {
1242     public void
1243     taskPerformed(TaskEvent e) {
1244     javax.swing.SwingUtilities.invokeLater(r);
1245     }
1246     });
1247    
1248 iliev 1767 getTaskQueue().add(dummy);
1249 iliev 1688 }
1250 iliev 1143
1251 iliev 1688 public static boolean
1252     verifyConnection() {
1253     if(getCurrentServer() == null) {
1254     HF.showErrorMessage(i18n.getError("CC.notConnected"));
1255     return false;
1256     }
1257    
1258     return true;
1259     }
1260 iliev 1864
1261     public static boolean
1262     isMacOS() {
1263     return System.getProperty("os.name").toLowerCase().startsWith("mac os x");
1264     }
1265 iliev 1688
1266    
1267 iliev 911 private final static EventHandler eventHandler = new EventHandler();
1268    
1269     private static EventHandler
1270     getHandler() { return eventHandler; }
1271    
1272 iliev 787 private static class EventHandler implements ChannelCountListener, ChannelInfoListener,
1273 iliev 1143 FxSendCountListener, FxSendInfoListener, StreamCountListener, VoiceCountListener,
1274 iliev 1545 TotalStreamCountListener, TotalVoiceCountListener, TaskQueueListener,
1275     OrchestraListener, ListListener<OrchestraModel>, MidiInstrumentCountListener,
1276 iliev 1776 MidiInstrumentInfoListener, GlobalInfoListener, ChannelMidiDataListener {
1277 iliev 787
1278     /** Invoked when the number of channels has changed. */
1279 iliev 1786 @Override
1280 iliev 787 public void
1281     channelCountChanged( ChannelCountEvent e) {
1282 iliev 1818 if(e.getChannelCount() == 0) {
1283     /*
1284     * This special case is handled because this might be due to
1285     * loading a lscp script containing sampler view configuration.
1286     */
1287     CC.getSamplerModel().removeAllChannels();
1288     return;
1289     }
1290 iliev 1734 addTask(new UpdateChannels());
1291 iliev 787 }
1292    
1293     /** Invoked when changes to the sampler channel has occured. */
1294 iliev 1786 @Override
1295 iliev 787 public void
1296     channelInfoChanged(ChannelInfoEvent e) {
1297     /*
1298     * Because of the rapid notification flow when instrument is loaded
1299     * we need to do some optimization to decrease the traffic.
1300     */
1301     boolean b = true;
1302     Task[] tS = getTaskQueue().getPendingTasks();
1303    
1304     for(int i = tS.length - 1; i >= 0; i--) {
1305     Task t = tS[i];
1306    
1307 iliev 1143 if(t instanceof Channel.UpdateInfo) {
1308     Channel.UpdateInfo cui = (Channel.UpdateInfo)t;
1309     if(cui.getChannelId() == e.getSamplerChannel()) return;
1310 iliev 787 } else {
1311     b = false;
1312     break;
1313     }
1314     }
1315    
1316     if(b) {
1317     Task t = getTaskQueue().getRunningTask();
1318 iliev 1143 if(t instanceof Channel.UpdateInfo) {
1319     Channel.UpdateInfo cui = (Channel.UpdateInfo)t;
1320     if(cui.getChannelId() == e.getSamplerChannel()) return;
1321 iliev 787 }
1322     }
1323    
1324    
1325 iliev 1143 getTaskQueue().add(new Channel.UpdateInfo(e.getSamplerChannel()));
1326 iliev 787 }
1327    
1328     /**
1329 iliev 1143 * Invoked when the number of effect sends
1330     * on a particular sampler channel has changed.
1331     */
1332 iliev 1786 @Override
1333 iliev 1143 public void
1334     fxSendCountChanged(FxSendCountEvent e) {
1335     getTaskQueue().add(new Channel.UpdateFxSends(e.getChannel()));
1336     }
1337    
1338     /**
1339     * Invoked when the settings of an effect sends are changed.
1340     */
1341 iliev 1786 @Override
1342 iliev 1143 public void
1343     fxSendInfoChanged(FxSendInfoEvent e) {
1344     Task t = new Channel.UpdateFxSendInfo(e.getChannel(), e.getFxSend());
1345     getTaskQueue().add(t);
1346     }
1347    
1348     /**
1349 iliev 787 * Invoked when the number of active disk
1350     * streams in a specific sampler channel has changed.
1351     */
1352 iliev 1786 @Override
1353 iliev 787 public void
1354     streamCountChanged(StreamCountEvent e) {
1355     SamplerChannelModel scm =
1356 iliev 1204 getSamplerModel().getChannelById(e.getSamplerChannel());
1357 iliev 787
1358     if(scm == null) {
1359     CC.getLogger().log (
1360     Level.WARNING,
1361     "CC.unknownChannel!",
1362     e.getSamplerChannel()
1363     );
1364    
1365     return;
1366     }
1367    
1368     scm.setStreamCount(e.getStreamCount());
1369     }
1370    
1371     /**
1372     * Invoked when the number of active voices
1373     * in a specific sampler channel has changed.
1374     */
1375 iliev 1786 @Override
1376 iliev 787 public void
1377     voiceCountChanged(VoiceCountEvent e) {
1378     SamplerChannelModel scm =
1379 iliev 1204 getSamplerModel().getChannelById(e.getSamplerChannel());
1380 iliev 787
1381     if(scm == null) {
1382     CC.getLogger().log (
1383     Level.WARNING,
1384     "CC.unknownChannel!",
1385     e.getSamplerChannel()
1386     );
1387    
1388     return;
1389     }
1390    
1391     scm.setVoiceCount(e.getVoiceCount());
1392     }
1393    
1394 iliev 1545 /** Invoked when the total number of active streams has changed. */
1395 iliev 1786 @Override
1396 iliev 1545 public void
1397     totalStreamCountChanged(TotalStreamCountEvent e) {
1398     getSamplerModel().updateActiveStreamsInfo(e.getTotalStreamCount());
1399     }
1400    
1401 iliev 787 /** Invoked when the total number of active voices has changed. */
1402 iliev 1786 @Override
1403 iliev 787 public void
1404     totalVoiceCountChanged(TotalVoiceCountEvent e) {
1405 iliev 1818 scheduleTask(new UpdateTotalVoiceCount());
1406 iliev 787 }
1407 iliev 911
1408 iliev 1143 /** Invoked when the number of MIDI instruments in a MIDI instrument map is changed. */
1409 iliev 1786 @Override
1410 iliev 1143 public void
1411     instrumentCountChanged(MidiInstrumentCountEvent e) {
1412 iliev 1719 scheduleTask(new Midi.UpdateInstruments(e.getMapId()));
1413 iliev 1143 }
1414    
1415     /** Invoked when a MIDI instrument in a MIDI instrument map is changed. */
1416 iliev 1786 @Override
1417 iliev 1143 public void
1418     instrumentInfoChanged(MidiInstrumentInfoEvent e) {
1419     Task t = new Midi.UpdateInstrumentInfo (
1420     e.getMapId(), e.getMidiBank(), e.getMidiProgram()
1421     );
1422     getTaskQueue().add(t);
1423    
1424     }
1425    
1426     /** Invoked when the global volume of the sampler is changed. */
1427 iliev 1786 @Override
1428 iliev 1143 public void
1429     volumeChanged(GlobalInfoEvent e) {
1430     getSamplerModel().setVolume(e.getVolume());
1431     }
1432    
1433 iliev 1818 @Override
1434     public void
1435     voiceLimitChanged(GlobalInfoEvent e) { }
1436    
1437     @Override
1438     public void
1439     streamLimitChanged(GlobalInfoEvent e) { }
1440    
1441 iliev 911 /**
1442     * Invoked to indicate that the state of a task queue is changed.
1443     * This method is invoked only from the event-dispatching thread.
1444     */
1445 iliev 1786 @Override
1446 iliev 911 public void
1447     stateChanged(TaskQueueEvent e) {
1448     switch(e.getEventID()) {
1449     case TASK_FETCHED:
1450     getProgressIndicator().setString (
1451     ((Task)e.getSource()).getDescription()
1452     );
1453     break;
1454     case TASK_DONE:
1455     EnhancedTask t = (EnhancedTask)e.getSource();
1456 iliev 1786 if(t.doneWithErrors() && !t.isStopped() && !t.isSilent()) {
1457 iliev 1285 showError(t);
1458 iliev 1204 }
1459 iliev 911 break;
1460     case NOT_IDLE:
1461     timer.start();
1462     break;
1463     case IDLE:
1464     timer.stop();
1465     getProgressIndicator().stop();
1466     break;
1467     }
1468     }
1469    
1470 iliev 1285 private void
1471     showError(final Task t) {
1472     javax.swing.SwingUtilities.invokeLater(new Runnable() {
1473     public void
1474     run() {
1475     if(t.getErrorDetails() == null) {
1476     HF.showErrorMessage(t.getErrorMessage());
1477     } else {
1478     getMainFrame().showDetailedErrorMessage (
1479     getMainFrame(),
1480     t.getErrorMessage(),
1481     t.getErrorDetails()
1482     );
1483     }
1484     }
1485     });
1486     }
1487    
1488 iliev 911 /** Invoked when the name of orchestra is changed. */
1489 iliev 1786 @Override
1490 iliev 911 public void
1491     nameChanged(OrchestraEvent e) { saveOrchestras(); }
1492    
1493     /** Invoked when the description of orchestra is changed. */
1494 iliev 1786 @Override
1495 iliev 911 public void
1496     descriptionChanged(OrchestraEvent e) { saveOrchestras(); }
1497    
1498     /** Invoked when an instrument is added to the orchestra. */
1499 iliev 1786 @Override
1500 iliev 911 public void
1501     instrumentAdded(OrchestraEvent e) { saveOrchestras(); }
1502    
1503     /** Invoked when an instrument is removed from the orchestra. */
1504 iliev 1786 @Override
1505 iliev 911 public void
1506     instrumentRemoved(OrchestraEvent e) { saveOrchestras(); }
1507    
1508     /** Invoked when the settings of an instrument are changed. */
1509 iliev 1786 @Override
1510 iliev 911 public void
1511     instrumentChanged(OrchestraEvent e) { saveOrchestras(); }
1512    
1513     /** Invoked when an orchestra is added to the orchestra list. */
1514 iliev 1786 @Override
1515 iliev 911 public void
1516 iliev 1143 entryAdded(ListEvent<OrchestraModel> e) {
1517     e.getEntry().addOrchestraListener(getHandler());
1518 iliev 911 saveOrchestras();
1519     }
1520    
1521     /** Invoked when an orchestra is removed from the orchestra list. */
1522 iliev 1786 @Override
1523 iliev 911 public void
1524 iliev 1143 entryRemoved(ListEvent<OrchestraModel> e) {
1525     e.getEntry().removeOrchestraListener(getHandler());
1526 iliev 911 saveOrchestras();
1527     }
1528 iliev 1776
1529     /**
1530     * Invoked when MIDI data arrives.
1531     */
1532 iliev 1786 @Override
1533 iliev 1776 public void
1534     midiDataArrived(final ChannelMidiDataEvent e) {
1535     try {
1536     javax.swing.SwingUtilities.invokeAndWait(new Runnable() {
1537     public void
1538     run() { fireChannelMidiDataEvent(e); }
1539     });
1540     } catch(Exception x) {
1541     CC.getLogger().log(Level.INFO, "Failed!", x);
1542     }
1543     }
1544 iliev 787 }
1545 iliev 1143
1546 iliev 1776 private static void
1547     fireChannelMidiDataEvent(ChannelMidiDataEvent e) {
1548     SamplerChannelModel chn;
1549     chn = CC.getSamplerModel().getChannelById(e.getChannelId());
1550     if(chn == null) {
1551     CC.getLogger().info("Unknown channel ID: " + e.getChannelId());
1552     }
1553    
1554     ((DefaultSamplerChannelModel)chn).fireMidiDataEvent(e);
1555     }
1556    
1557 iliev 1143 private static final AudioDeviceCountListener audioDeviceCountListener =
1558     new AudioDeviceCountListener();
1559    
1560     private static class AudioDeviceCountListener implements ItemCountListener {
1561     /** Invoked when the number of audio output devices has changed. */
1562 iliev 1786 @Override
1563 iliev 1143 public void
1564     itemCountChanged(ItemCountEvent e) {
1565     getTaskQueue().add(new Audio.UpdateDevices());
1566     }
1567     }
1568    
1569     private static final AudioDeviceInfoListener audioDeviceInfoListener =
1570     new AudioDeviceInfoListener();
1571    
1572     private static class AudioDeviceInfoListener implements ItemInfoListener {
1573     /** Invoked when the audio output device's settings are changed. */
1574 iliev 1786 @Override
1575 iliev 1143 public void
1576     itemInfoChanged(ItemInfoEvent e) {
1577     getTaskQueue().add(new Audio.UpdateDeviceInfo(e.getItemID()));
1578     }
1579     }
1580    
1581     private static final MidiDeviceCountListener midiDeviceCountListener =
1582     new MidiDeviceCountListener();
1583    
1584     private static class MidiDeviceCountListener implements ItemCountListener {
1585     /** Invoked when the number of MIDI input devices has changed. */
1586 iliev 1786 @Override
1587 iliev 1143 public void
1588     itemCountChanged(ItemCountEvent e) {
1589     getTaskQueue().add(new Midi.UpdateDevices());
1590     }
1591     }
1592    
1593     private static final MidiDeviceInfoListener midiDeviceInfoListener =
1594     new MidiDeviceInfoListener();
1595    
1596     private static class MidiDeviceInfoListener implements ItemInfoListener {
1597     /** Invoked when the MIDI input device's settings are changed. */
1598 iliev 1786 @Override
1599 iliev 1143 public void
1600     itemInfoChanged(ItemInfoEvent e) {
1601     getTaskQueue().add(new Midi.UpdateDeviceInfo(e.getItemID()));
1602     }
1603     }
1604    
1605     private static final MidiInstrMapCountListener midiInstrMapCountListener =
1606     new MidiInstrMapCountListener();
1607    
1608     private static class MidiInstrMapCountListener implements ItemCountListener {
1609     /** Invoked when the number of MIDI instrument maps is changed. */
1610 iliev 1786 @Override
1611 iliev 1143 public void
1612     itemCountChanged(ItemCountEvent e) {
1613     getTaskQueue().add(new Midi.UpdateInstrumentMaps());
1614     }
1615     }
1616    
1617     private static final MidiInstrMapInfoListener midiInstrMapInfoListener =
1618     new MidiInstrMapInfoListener();
1619    
1620     private static class MidiInstrMapInfoListener implements ItemInfoListener {
1621     /** Invoked when the MIDI instrument map's settings are changed. */
1622 iliev 1786 @Override
1623 iliev 1143 public void
1624     itemInfoChanged(ItemInfoEvent e) {
1625     getTaskQueue().add(new Midi.UpdateInstrumentMapInfo(e.getItemID()));
1626     }
1627     }
1628 iliev 787 }

  ViewVC Help
Powered by ViewVC