22 |
|
|
23 |
package org.jsampler; |
package org.jsampler; |
24 |
|
|
|
import java.awt.event.ActionEvent; |
|
|
import java.awt.event.ActionListener; |
|
|
|
|
25 |
import java.io.File; |
import java.io.File; |
26 |
import java.io.FileInputStream; |
import java.io.FileInputStream; |
27 |
import java.io.FileOutputStream; |
import java.io.FileOutputStream; |
28 |
import java.io.InputStream; |
import java.io.InputStream; |
29 |
|
|
30 |
|
import java.util.Timer; |
31 |
|
import java.util.TimerTask; |
32 |
import java.util.Vector; |
import java.util.Vector; |
33 |
|
|
34 |
import java.util.logging.Handler; |
import java.util.logging.Handler; |
37 |
import java.util.logging.SimpleFormatter; |
import java.util.logging.SimpleFormatter; |
38 |
import java.util.logging.StreamHandler; |
import java.util.logging.StreamHandler; |
39 |
|
|
40 |
import javax.swing.SwingUtilities; |
import net.sf.juife.PDUtils; |
|
import javax.swing.Timer; |
|
|
|
|
|
import javax.swing.event.ChangeEvent; |
|
|
import javax.swing.event.ChangeListener; |
|
|
|
|
41 |
import net.sf.juife.Task; |
import net.sf.juife.Task; |
42 |
import net.sf.juife.TaskQueue; |
import net.sf.juife.TaskQueue; |
43 |
|
|
44 |
|
import net.sf.juife.event.GenericEvent; |
45 |
|
import net.sf.juife.event.GenericListener; |
46 |
import net.sf.juife.event.TaskEvent; |
import net.sf.juife.event.TaskEvent; |
47 |
import net.sf.juife.event.TaskListener; |
import net.sf.juife.event.TaskListener; |
48 |
import net.sf.juife.event.TaskQueueEvent; |
import net.sf.juife.event.TaskQueueEvent; |
55 |
|
|
56 |
import org.jsampler.task.*; |
import org.jsampler.task.*; |
57 |
|
|
58 |
import org.jsampler.view.InstrumentsDbTreeModel; |
import org.jsampler.view.JSChannelsPane; |
59 |
import org.jsampler.view.JSMainFrame; |
import org.jsampler.view.JSMainFrame; |
60 |
import org.jsampler.view.JSProgress; |
import org.jsampler.view.JSProgress; |
61 |
import org.jsampler.view.JSViewConfig; |
import org.jsampler.view.JSViewConfig; |
89 |
private static String jSamplerHome = null; |
private static String jSamplerHome = null; |
90 |
|
|
91 |
private final static TaskQueue taskQueue = new TaskQueue(); |
private final static TaskQueue taskQueue = new TaskQueue(); |
92 |
private final static Timer timer = new Timer(2000, null); |
private final static Timer timer = new Timer(); |
93 |
|
private static TimerTask progressTimerTask = null; |
94 |
|
|
95 |
private static int connectionFailureCount = 0; |
private static int connectionFailureCount = 0; |
96 |
|
|
97 |
/** Forbits the instantiation of this class. */ |
static class ProgressTimerTask extends TimerTask { |
98 |
|
public void run() { |
99 |
|
PDUtils.runOnUiThread(new Runnable() { public void run() { run0(); } }); |
100 |
|
} |
101 |
|
|
102 |
|
private void |
103 |
|
run0() { CC.getProgressIndicator().start(); } |
104 |
|
} |
105 |
|
|
106 |
|
public static interface Run<A> { |
107 |
|
public void run(A arg); |
108 |
|
} |
109 |
|
|
110 |
|
/** Forbids the instantiation of this class. */ |
111 |
private |
private |
112 |
CC() { } |
CC() { } |
113 |
|
|
173 |
* Returns the main window of this application. |
* Returns the main window of this application. |
174 |
* @return The main window of this application. |
* @return The main window of this application. |
175 |
*/ |
*/ |
176 |
public static JSMainFrame |
public static JSMainFrame<JSChannelsPane> |
177 |
getMainFrame() { return mainFrame; } |
getMainFrame() { return mainFrame; } |
178 |
|
|
179 |
/** |
/** |
242 |
Logger.getLogger("org.linuxsampler.lscp").addHandler(handler); |
Logger.getLogger("org.linuxsampler.lscp").addHandler(handler); |
243 |
|
|
244 |
// Flushing logs on every second |
// Flushing logs on every second |
245 |
new java.util.Timer().schedule(new java.util.TimerTask() { |
timer.schedule(new java.util.TimerTask() { |
246 |
public void |
public void |
247 |
run() { if(handler != null) handler.flush(); } |
run() { if(handler != null) handler.flush(); } |
248 |
}, 1000, 1000); |
}, 1000, 1000); |
249 |
|
|
250 |
getLogger().fine("CC.jsStarted"); |
getLogger().fine("CC.jsStarted"); |
251 |
|
|
|
HF.setUIDefaultFont(Prefs.getInterfaceFont()); |
|
|
|
|
|
timer.setRepeats(false); |
|
|
|
|
|
timer.addActionListener(new ActionListener() { |
|
|
public void |
|
|
actionPerformed(ActionEvent e) { CC.getProgressIndicator().start(); } |
|
|
}); |
|
|
|
|
252 |
getTaskQueue().addTaskQueueListener(getHandler()); |
getTaskQueue().addTaskQueueListener(getHandler()); |
253 |
|
|
254 |
getTaskQueue().start(); |
getTaskQueue().start(); |
316 |
getClient().removeEffectInstanceInfoListener(getHandler()); |
getClient().removeEffectInstanceInfoListener(getHandler()); |
317 |
getClient().addEffectInstanceInfoListener(getHandler()); |
getClient().addEffectInstanceInfoListener(getHandler()); |
318 |
|
|
319 |
CC.addConnectionEstablishedListener(new ActionListener() { |
CC.addConnectionEstablishedListener(new GenericListener() { |
320 |
public void |
public void |
321 |
actionPerformed(ActionEvent e) { |
jobDone(GenericEvent e) { |
322 |
connectionFailureCount = 0; |
connectionFailureCount = 0; |
323 |
} |
} |
324 |
}); |
}); |
341 |
|
|
342 |
private static ServerListListener serverListListener = new ServerListListener(); |
private static ServerListListener serverListListener = new ServerListListener(); |
343 |
|
|
344 |
private static class ServerListListener implements ChangeListener { |
private static class ServerListListener implements GenericListener { |
|
@Override |
|
345 |
public void |
public void |
346 |
stateChanged(ChangeEvent e) { |
jobDone(GenericEvent e) { saveServerList(); } |
|
saveServerList(); |
|
|
} |
|
|
} |
|
|
|
|
|
private static final Vector<ChangeListener> idtmListeners = new Vector<ChangeListener>(); |
|
|
private static InstrumentsDbTreeModel instrumentsDbTreeModel = null; |
|
|
|
|
|
/** |
|
|
* Gets the tree model of the instruments database. |
|
|
* If the currently used view doesn't have instruments |
|
|
* database support the tree model is initialized on first use. |
|
|
* @return The tree model of the instruments database or |
|
|
* <code>null</code> if the backend doesn't have instruments database support. |
|
|
* @see org.jsampler.view.JSViewConfig#getInstrumentsDbSupport |
|
|
*/ |
|
|
public static InstrumentsDbTreeModel |
|
|
getInstrumentsDbTreeModel() { |
|
|
if(getSamplerModel().getServerInfo() == null) return null; |
|
|
if(!getSamplerModel().getServerInfo().hasInstrumentsDbSupport()) return null; |
|
|
|
|
|
if(instrumentsDbTreeModel == null) { |
|
|
instrumentsDbTreeModel = new InstrumentsDbTreeModel(); |
|
|
for(ChangeListener l : idtmListeners) l.stateChanged(null); |
|
|
} |
|
|
|
|
|
return instrumentsDbTreeModel; |
|
|
} |
|
|
|
|
|
public static void |
|
|
addInstrumentsDbChangeListener(ChangeListener l) { |
|
|
idtmListeners.add(l); |
|
347 |
} |
} |
348 |
|
|
349 |
public static void |
private static final |
|
removeInstrumentsDbChangeListener(ChangeListener l) { |
|
|
idtmListeners.remove(l); |
|
|
} |
|
350 |
|
|
351 |
private static final LostFilesModel lostFilesModel = new LostFilesModel(); |
LostFilesModel lostFilesModel = new LostFilesModel(); |
352 |
|
|
353 |
public static LostFilesModel |
public static LostFilesModel |
354 |
getLostFilesModel() { return lostFilesModel; } |
getLostFilesModel() { return lostFilesModel; } |
389 |
|
|
390 |
try { getOrchestras().readObject(doc.getDocumentElement()); } |
try { getOrchestras().readObject(doc.getDocumentElement()); } |
391 |
catch(Exception x) { |
catch(Exception x) { |
392 |
HF.showErrorMessage(x, "Loading orchestras: "); |
getViewConfig().showErrorMessage(x, "Loading orchestras: "); |
393 |
return; |
return; |
394 |
} |
} |
395 |
|
|
424 |
|
|
425 |
HF.deleteFile("orchestras.xml.bkp"); |
HF.deleteFile("orchestras.xml.bkp"); |
426 |
} catch(Exception x) { |
} catch(Exception x) { |
427 |
HF.showErrorMessage(x, "Saving orchestras: "); |
getViewConfig().showErrorMessage(x, "Saving orchestras: "); |
428 |
return; |
return; |
429 |
} |
} |
430 |
} |
} |
474 |
|
|
475 |
try { getServerList().readObject(doc.getDocumentElement()); } |
try { getServerList().readObject(doc.getDocumentElement()); } |
476 |
catch(Exception x) { |
catch(Exception x) { |
477 |
HF.showErrorMessage(x, "Loading server list: "); |
getViewConfig().showErrorMessage(x, "Loading server list: "); |
478 |
return; |
return; |
479 |
} |
} |
480 |
} |
} |
505 |
|
|
506 |
HF.deleteFile("servers.xml.bkp"); |
HF.deleteFile("servers.xml.bkp"); |
507 |
} catch(Exception x) { |
} catch(Exception x) { |
508 |
HF.showErrorMessage(x, "Saving server list: "); |
getViewConfig().showErrorMessage(x, "Saving server list: "); |
509 |
return; |
return; |
510 |
} |
} |
511 |
} |
} |
539 |
public static Client |
public static Client |
540 |
getClient() { return lsClient; } |
getClient() { return lsClient; } |
541 |
|
|
542 |
private static final Vector<ActionListener> listeners = new Vector<ActionListener>(); |
private static final Vector<GenericListener> listeners = new Vector<GenericListener>(); |
543 |
|
|
544 |
/** |
/** |
545 |
* Registers the specified listener to be notified when reconnecting to LinuxSampler. |
* Registers the specified listener to be notified (outside the UI thread) |
546 |
|
* when reconnecting to LinuxSampler. |
547 |
* @param l The <code>ActionListener</code> to register. |
* @param l The <code>ActionListener</code> to register. |
548 |
*/ |
*/ |
549 |
public static void |
public static void |
550 |
addReconnectListener(ActionListener l) { listeners.add(l); } |
addReconnectListener(GenericListener l) { listeners.add(l); } |
551 |
|
|
552 |
/** |
/** |
553 |
* Removes the specified listener. |
* Removes the specified listener. |
554 |
* @param l The <code>ActionListener</code> to remove. |
* @param l The <code>ActionListener</code> to remove. |
555 |
*/ |
*/ |
556 |
public static void |
public static void |
557 |
removeReconnectListener(ActionListener l) { listeners.remove(l); } |
removeReconnectListener(GenericListener l) { listeners.remove(l); } |
558 |
|
|
559 |
private static void |
private static void |
560 |
fireReconnectEvent() { |
fireReconnectEvent() { |
561 |
ActionEvent e = new ActionEvent(CC.class, ActionEvent.ACTION_PERFORMED, null); |
GenericEvent e = new GenericEvent(CC.class); |
562 |
for(ActionListener l : listeners) l.actionPerformed(e); |
for(GenericListener l : listeners) l.jobDone(e); |
563 |
} |
} |
564 |
|
|
565 |
private static final Vector<ActionListener> ceListeners = new Vector<ActionListener>(); |
private static final Vector<GenericListener> ceListeners = new Vector<GenericListener>(); |
566 |
|
|
567 |
/** |
/** |
568 |
* Registers the specified listener to be notified when |
* Registers the specified listener to be notified (from the UI thread) when |
569 |
* jsampler is connected successfully to LinuxSampler. |
* jsampler is connected successfully to LinuxSampler. |
570 |
* @param l The <code>ActionListener</code> to register. |
* @param l The <code>GenericListener</code> to register. |
571 |
*/ |
*/ |
572 |
public static void |
public static void |
573 |
addConnectionEstablishedListener(ActionListener l) { ceListeners.add(l); } |
addConnectionEstablishedListener(GenericListener l) { ceListeners.add(l); } |
574 |
|
|
575 |
/** |
/** |
576 |
* Removes the specified listener. |
* Removes the specified listener. |
577 |
* @param l The <code>ActionListener</code> to remove. |
* @param l The <code>GenericListener</code> to remove. |
578 |
*/ |
*/ |
579 |
public static void |
public static void |
580 |
removeConnectionEstablishedListener(ActionListener l) { ceListeners.remove(l); } |
removeConnectionEstablishedListener(GenericListener l) { ceListeners.remove(l); } |
581 |
|
|
582 |
private static void |
private static void |
583 |
fireConnectionEstablishedEvent() { |
fireConnectionEstablishedEvent() { |
584 |
ActionEvent e = new ActionEvent(CC.class, ActionEvent.ACTION_PERFORMED, null); |
GenericEvent e = new GenericEvent(CC.class); |
585 |
for(ActionListener l : ceListeners) l.actionPerformed(e); |
for(GenericListener l : ceListeners) l.jobDone(e); |
586 |
} |
} |
587 |
|
|
588 |
private static final SamplerModel samplerModel = new DefaultSamplerModel(); |
private static final SamplerModel samplerModel = new DefaultSamplerModel(); |
596 |
|
|
597 |
/** |
/** |
598 |
* Connects to LinuxSampler. |
* Connects to LinuxSampler. |
599 |
|
* The connection can be done asynchronously. |
600 |
*/ |
*/ |
601 |
public static void |
public static void |
602 |
connect() { initSamplerModel(); } |
connect() { initSamplerModel(); } |
637 |
|
|
638 |
/** |
/** |
639 |
* This method updates the information about the backend state. |
* This method updates the information about the backend state. |
640 |
|
* The update can be done asynchronously. |
641 |
*/ |
*/ |
642 |
private static void |
private static void |
643 |
initSamplerModel() { |
initSamplerModel() { |
644 |
Server srv = getMainFrame().getServer(); |
getMainFrame().getServer(new Run<Server>() { |
645 |
if(srv == null) return; |
public void |
646 |
initSamplerModel(srv); |
run(Server srv) { |
647 |
|
if(srv == null) return; |
648 |
|
initSamplerModel(srv); |
649 |
|
} |
650 |
|
}); |
651 |
} |
} |
652 |
|
|
653 |
/** |
/** |
669 |
model.setServerInfo(gsi.getResult()); |
model.setServerInfo(gsi.getResult()); |
670 |
|
|
671 |
if(CC.getViewConfig().getInstrumentsDbSupport()) { |
if(CC.getViewConfig().getInstrumentsDbSupport()) { |
672 |
getInstrumentsDbTreeModel(); |
CC.getViewConfig().initInstrumentsDbTreeModel(); |
673 |
} |
} |
674 |
} |
} |
675 |
}); |
}); |
792 |
}); |
}); |
793 |
|
|
794 |
getSamplerModel().reset(); |
getSamplerModel().reset(); |
795 |
if(instrumentsDbTreeModel != null) { |
getViewConfig().resetInstrumentsDbTreeModel(); |
|
instrumentsDbTreeModel.reset(); |
|
|
instrumentsDbTreeModel = null; |
|
|
} |
|
796 |
|
|
797 |
getTaskQueue().removePendingTasks(); |
getTaskQueue().removePendingTasks(); |
798 |
getTaskQueue().add(ssa); |
getTaskQueue().add(ssa); |
825 |
final String s = JSI18n.i18n.getError("CC.failedToLaunchBackend"); |
final String s = JSI18n.i18n.getError("CC.failedToLaunchBackend"); |
826 |
CC.getLogger().log(Level.INFO, s, x); |
CC.getLogger().log(Level.INFO, s, x); |
827 |
|
|
828 |
SwingUtilities.invokeLater(new Runnable() { |
PDUtils.runOnUiThread(new Runnable() { |
829 |
public void |
public void |
830 |
run() { HF.showErrorMessage(s); } |
run() { getViewConfig().showErrorMessage(s); } |
831 |
}); |
}); |
832 |
return; |
return; |
833 |
} |
} |
837 |
|
|
838 |
private static void |
private static void |
839 |
retryToConnect() { |
retryToConnect() { |
840 |
javax.swing.SwingUtilities.invokeLater(new Runnable() { |
PDUtils.runOnUiThread(new Runnable() { |
841 |
public void |
public void |
842 |
run() { changeBackend(); } |
run() { changeBackend(); } |
843 |
}); |
}); |
845 |
|
|
846 |
public static void |
public static void |
847 |
changeBackend() { |
changeBackend() { |
848 |
Server s = getMainFrame().getServer(true); |
getMainFrame().getServer(new Run<Server>() { |
849 |
if(s != null) { |
public void |
850 |
connectionFailureCount = 0; // cleared because this change due to user interaction |
run(Server srv) { |
851 |
initSamplerModel(s); |
if(srv == null) return; |
852 |
} |
connectionFailureCount = 0; // cleared because this change is due to user interaction |
853 |
|
initSamplerModel(srv); |
854 |
|
} |
855 |
|
}, true); |
856 |
} |
} |
857 |
|
|
858 |
private static final Vector<ActionListener> pListeners = new Vector<ActionListener>(); |
private static final Vector<GenericListener> pListeners = new Vector<GenericListener>(); |
859 |
|
|
860 |
/** |
/** |
861 |
* Registers the specified listener to be notified when |
* Registers the specified listener to be notified (from UI thread) when |
862 |
* backend process is created/terminated. |
* backend process is created/terminated. |
863 |
* @param l The <code>ActionListener</code> to register. |
* @param l The <code>ActionListener</code> to register. |
864 |
*/ |
*/ |
865 |
public static void |
public static void |
866 |
addBackendProcessListener(ActionListener l) { pListeners.add(l); } |
addBackendProcessListener(GenericListener l) { pListeners.add(l); } |
867 |
|
|
868 |
/** |
/** |
869 |
* Removes the specified listener. |
* Removes the specified listener. |
870 |
* @param l The <code>ActionListener</code> to remove. |
* @param l The <code>ActionListener</code> to remove. |
871 |
*/ |
*/ |
872 |
public static void |
public static void |
873 |
removeBackendProcessListener(ActionListener l) { pListeners.remove(l); } |
removeBackendProcessListener(GenericListener l) { pListeners.remove(l); } |
874 |
|
|
875 |
private static void |
private static void |
876 |
fireBackendProcessEvent() { |
fireBackendProcessEvent() { |
877 |
ActionEvent e = new ActionEvent(CC.class, ActionEvent.ACTION_PERFORMED, null); |
GenericEvent e = new GenericEvent(CC.class); |
878 |
for(ActionListener l : pListeners) l.actionPerformed(e); |
for(GenericListener l : pListeners) l.jobDone(e); |
879 |
} |
} |
880 |
|
|
881 |
private static Process backendProcess = null; |
private static Process backendProcess = null; |
914 |
} |
} |
915 |
|
|
916 |
private static class GetFxSendsListener implements TaskListener { |
private static class GetFxSendsListener implements TaskListener { |
|
@Override |
|
917 |
public void |
public void |
918 |
taskPerformed(TaskEvent e) { |
taskPerformed(TaskEvent e) { |
919 |
Channel.GetFxSends gfs = (Channel.GetFxSends)e.getSource(); |
Channel.GetFxSends gfs = (Channel.GetFxSends)e.getSource(); |
931 |
dummy.addTaskListener(new TaskListener() { |
dummy.addTaskListener(new TaskListener() { |
932 |
public void |
public void |
933 |
taskPerformed(TaskEvent e) { |
taskPerformed(TaskEvent e) { |
934 |
javax.swing.SwingUtilities.invokeLater(r); |
PDUtils.runOnUiThread(r); |
935 |
} |
} |
936 |
}); |
}); |
937 |
|
|
941 |
public static boolean |
public static boolean |
942 |
verifyConnection() { |
verifyConnection() { |
943 |
if(getCurrentServer() == null) { |
if(getCurrentServer() == null) { |
944 |
HF.showErrorMessage(i18n.getError("CC.notConnected")); |
getViewConfig().showErrorMessage(i18n.getError("CC.notConnected")); |
945 |
return false; |
return false; |
946 |
} |
} |
947 |
|
|
1131 |
|
|
1132 |
/** |
/** |
1133 |
* Invoked to indicate that the state of a task queue is changed. |
* Invoked to indicate that the state of a task queue is changed. |
1134 |
* This method is invoked only from the event-dispatching thread. |
* This method is invoked only from the UI thread. |
1135 |
*/ |
*/ |
1136 |
@Override |
@Override |
1137 |
public void |
public void |
1153 |
} |
} |
1154 |
break; |
break; |
1155 |
case NOT_IDLE: |
case NOT_IDLE: |
1156 |
timer.start(); |
if(progressTimerTask != null) { |
1157 |
|
getLogger().warning("progressTimerTask != null - this is a bug!"); |
1158 |
|
} |
1159 |
|
progressTimerTask = new ProgressTimerTask(); |
1160 |
|
timer.schedule(progressTimerTask, 2000); |
1161 |
break; |
break; |
1162 |
case IDLE: |
case IDLE: |
1163 |
timer.stop(); |
if(progressTimerTask != null) { |
1164 |
|
progressTimerTask.cancel(); |
1165 |
|
progressTimerTask = null; |
1166 |
|
} |
1167 |
getProgressIndicator().stop(); |
getProgressIndicator().stop(); |
1168 |
break; |
break; |
1169 |
} |
} |
1171 |
|
|
1172 |
private void |
private void |
1173 |
showError(final Task t) { |
showError(final Task t) { |
1174 |
javax.swing.SwingUtilities.invokeLater(new Runnable() { |
PDUtils.runOnUiThread(new Runnable() { |
1175 |
public void |
public void |
1176 |
run() { |
run() { |
1177 |
if(t.getErrorDetails() == null) { |
if(t.getErrorDetails() == null) { |
1178 |
HF.showErrorMessage(t.getErrorMessage()); |
getViewConfig().showErrorMessage(t.getErrorMessage()); |
1179 |
} else { |
} else { |
1180 |
getMainFrame().showDetailedErrorMessage ( |
getMainFrame().showDetailedErrorMessage ( |
|
getMainFrame(), |
|
1181 |
t.getErrorMessage(), |
t.getErrorMessage(), |
1182 |
t.getErrorDetails() |
t.getErrorDetails() |
1183 |
); |
); |
1234 |
public void |
public void |
1235 |
midiDataArrived(final ChannelMidiDataEvent e) { |
midiDataArrived(final ChannelMidiDataEvent e) { |
1236 |
try { |
try { |
1237 |
javax.swing.SwingUtilities.invokeAndWait(new Runnable() { |
PDUtils.runOnUiThreadAndWait(new Runnable() { |
1238 |
public void |
public void |
1239 |
run() { fireChannelMidiDataEvent(e); } |
run() { fireChannelMidiDataEvent(e); } |
1240 |
}); |
}); |
1249 |
getTaskQueue().add(new Audio.UpdateSendEffectChains(e.getAudioDeviceId())); |
getTaskQueue().add(new Audio.UpdateSendEffectChains(e.getAudioDeviceId())); |
1250 |
} |
} |
1251 |
|
|
1252 |
public void sendEffectChainInfoChanged(SendEffectChainInfoEvent e) { |
@Override |
1253 |
|
public void |
1254 |
|
sendEffectChainInfoChanged(SendEffectChainInfoEvent e) { |
1255 |
if(e.getInstanceCount() == -1) return; |
if(e.getInstanceCount() == -1) return; |
1256 |
|
|
1257 |
getTaskQueue().add ( |
getTaskQueue().add ( |
1259 |
); |
); |
1260 |
} |
} |
1261 |
|
|
1262 |
|
@Override |
1263 |
public void |
public void |
1264 |
effectInstanceInfoChanged(EffectInstanceInfoEvent e) { |
effectInstanceInfoChanged(EffectInstanceInfoEvent e) { |
1265 |
getTaskQueue().add(new Audio.UpdateEffectInstanceInfo(e.getEffectInstanceId())); |
getTaskQueue().add(new Audio.UpdateEffectInstanceInfo(e.getEffectInstanceId())); |
1306 |
|
|
1307 |
private static class MidiDeviceCountListener implements ItemCountListener { |
private static class MidiDeviceCountListener implements ItemCountListener { |
1308 |
/** Invoked when the number of MIDI input devices has changed. */ |
/** Invoked when the number of MIDI input devices has changed. */ |
|
@Override |
|
1309 |
public void |
public void |
1310 |
itemCountChanged(ItemCountEvent e) { |
itemCountChanged(ItemCountEvent e) { |
1311 |
getTaskQueue().add(new Midi.UpdateDevices()); |
getTaskQueue().add(new Midi.UpdateDevices()); |