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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1883 - (show annotations) (download)
Sun Apr 5 09:15:35 2009 UTC (15 years ago) by iliev
File size: 46829 byte(s)
* fixed the channel order when exporting sampler configuration
* don't mute channels muted by solo channel when exporting
   sampler configuration
* don't ask whether to replace a file on Mac OS when using
  native file choosers

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

  ViewVC Help
Powered by ViewVC