/[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 1734 - (show annotations) (download)
Sun May 4 18:40:13 2008 UTC (15 years, 11 months ago) by iliev
File size: 39885 byte(s)
* bugfix: JSampler took forever to load a configuration with
  too many sampler channels
* Implemented option to show different channel view when
  the mouse pointer is over sampler channel
  (choose Edit/Preferences, then click the `Defaults' tab)

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

  ViewVC Help
Powered by ViewVC