/[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 1729 - (show annotations) (download)
Tue Apr 29 22:22:40 2008 UTC (16 years ago) by iliev
File size: 39597 byte(s)
* Added support for handling lost files in the Instruments Database
  (In the Instruments Database window choose Actions/Check For Lost Files)
* Fantasia: Added option to show the Instruments Database
  on the Right-Side Pane of the Fantasia's main window
  (choose Edit/Preferences, then click the `View' tab)
* Added new menu item in the Instruments Database window: Edit/Find
* Some minor bugfixes and enhancements

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

  ViewVC Help
Powered by ViewVC