/[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 1776 - (show annotations) (download)
Thu Sep 11 18:48:36 2008 UTC (15 years, 7 months ago) by iliev
File size: 41141 byte(s)
* Implemented virtual MIDI keyboard

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

  ViewVC Help
Powered by ViewVC