23 |
package org.jsampler.view.classic; |
package org.jsampler.view.classic; |
24 |
|
|
25 |
import java.awt.Color; |
import java.awt.Color; |
26 |
|
import java.awt.Cursor; |
27 |
import java.awt.Dimension; |
import java.awt.Dimension; |
28 |
import java.awt.GridBagConstraints; |
import java.awt.GridBagConstraints; |
29 |
import java.awt.GridBagLayout; |
import java.awt.GridBagLayout; |
30 |
import java.awt.Insets; |
import java.awt.Insets; |
31 |
|
|
32 |
|
import java.awt.datatransfer.Transferable; |
33 |
|
|
34 |
import java.awt.event.ActionEvent; |
import java.awt.event.ActionEvent; |
35 |
import java.awt.event.ActionListener; |
import java.awt.event.ActionListener; |
36 |
|
import java.awt.event.MouseAdapter; |
37 |
|
import java.awt.event.MouseEvent; |
38 |
|
import java.awt.event.MouseMotionAdapter; |
39 |
|
|
40 |
|
import java.beans.PropertyChangeEvent; |
41 |
|
import java.beans.PropertyChangeListener; |
42 |
|
|
43 |
import java.net.URL; |
import java.net.URL; |
44 |
|
|
45 |
|
import java.util.Vector; |
46 |
|
|
47 |
import java.util.logging.Level; |
import java.util.logging.Level; |
48 |
|
|
49 |
|
import javax.swing.Action; |
50 |
|
import javax.swing.AbstractAction; |
51 |
import javax.swing.BorderFactory; |
import javax.swing.BorderFactory; |
52 |
import javax.swing.Box; |
import javax.swing.Box; |
53 |
import javax.swing.BoxLayout; |
import javax.swing.BoxLayout; |
54 |
|
import javax.swing.JComponent; |
55 |
import javax.swing.ImageIcon; |
import javax.swing.ImageIcon; |
56 |
import javax.swing.JButton; |
import javax.swing.JButton; |
57 |
import javax.swing.JComboBox; |
import javax.swing.JComboBox; |
60 |
import javax.swing.JSeparator; |
import javax.swing.JSeparator; |
61 |
import javax.swing.JSlider; |
import javax.swing.JSlider; |
62 |
import javax.swing.JToggleButton; |
import javax.swing.JToggleButton; |
63 |
|
import javax.swing.TransferHandler; |
64 |
|
|
65 |
|
import javax.swing.border.Border; |
66 |
|
import javax.swing.border.LineBorder; |
67 |
|
|
68 |
import javax.swing.event.ChangeEvent; |
import javax.swing.event.ChangeEvent; |
69 |
import javax.swing.event.ChangeListener; |
import javax.swing.event.ChangeListener; |
70 |
|
|
71 |
import net.sf.juife.JuifeUtils; |
import net.sf.juife.JuifeUtils; |
72 |
|
|
|
import org.jsampler.CC; |
|
73 |
import org.jsampler.AudioDeviceModel; |
import org.jsampler.AudioDeviceModel; |
74 |
|
import org.jsampler.CC; |
75 |
|
import org.jsampler.HF; |
76 |
|
import org.jsampler.Instrument; |
77 |
import org.jsampler.MidiDeviceModel; |
import org.jsampler.MidiDeviceModel; |
78 |
import org.jsampler.SamplerChannelModel; |
import org.jsampler.SamplerChannelModel; |
79 |
import org.jsampler.SamplerModel; |
import org.jsampler.SamplerModel; |
84 |
import org.jsampler.event.MidiDeviceListListener; |
import org.jsampler.event.MidiDeviceListListener; |
85 |
import org.jsampler.event.SamplerChannelAdapter; |
import org.jsampler.event.SamplerChannelAdapter; |
86 |
import org.jsampler.event.SamplerChannelEvent; |
import org.jsampler.event.SamplerChannelEvent; |
87 |
|
import org.jsampler.event.SamplerChannelListEvent; |
88 |
|
import org.jsampler.event.SamplerChannelListListener; |
89 |
import org.jsampler.event.SamplerChannelListener; |
import org.jsampler.event.SamplerChannelListener; |
90 |
|
|
91 |
import org.linuxsampler.lscp.AudioOutputDevice; |
import org.linuxsampler.lscp.AudioOutputDevice; |
112 |
private final static ImageIcon iconShowProperties; |
private final static ImageIcon iconShowProperties; |
113 |
private final static ImageIcon iconHideProperties; |
private final static ImageIcon iconHideProperties; |
114 |
|
|
115 |
|
private static Border borderSelected; |
116 |
|
private static Border borderDeselected; |
117 |
|
|
118 |
|
private static Color borderColor; |
119 |
|
|
120 |
|
private final static Vector<PropertyChangeListener> propertyChangeListeners |
121 |
|
= new Vector<PropertyChangeListener>(); |
122 |
|
|
123 |
static { |
static { |
124 |
String path = "org/jsampler/view/classic/res/icons/"; |
String path = "org/jsampler/view/classic/res/icons/"; |
125 |
URL url = ClassLoader.getSystemClassLoader().getResource(path + "mute_on.png"); |
URL url = ClassLoader.getSystemClassLoader().getResource(path + "mute_on.png"); |
140 |
url = ClassLoader.getSystemClassLoader().getResource(path + "Back16.gif"); |
url = ClassLoader.getSystemClassLoader().getResource(path + "Back16.gif"); |
141 |
iconShowProperties = new ImageIcon(url); |
iconShowProperties = new ImageIcon(url); |
142 |
|
|
143 |
url = ClassLoader.getSystemClassLoader().getResource(path + "Down16.gif"); |
iconHideProperties = Res.iconDown16; |
144 |
iconHideProperties = new ImageIcon(url); |
|
145 |
|
if(ClassicPrefs.getCustomChannelBorderColor()) |
146 |
|
setBorderColor(ClassicPrefs.getChannelBorderColor()); |
147 |
|
else setBorderColor(ClassicPrefs.getDefaultChannelBorderColor()); |
148 |
|
|
149 |
|
borderSelected = new LineBorder(getBorderColor(), 2, true); |
150 |
|
borderDeselected = BorderFactory.createEmptyBorder(2, 2, 2, 2); |
151 |
|
} |
152 |
|
|
153 |
|
/** |
154 |
|
* Registers the specified listener for receiving property change events. |
155 |
|
* @param l The <code>PropertyChangeListener</code> to register. |
156 |
|
*/ |
157 |
|
public void |
158 |
|
addPropertyChangeListener(PropertyChangeListener l) { |
159 |
|
propertyChangeListeners.add(l); |
160 |
|
} |
161 |
|
|
162 |
|
/** |
163 |
|
* Removes the specified listener. |
164 |
|
* @param l The <code>PropertyChangeListener</code> to remove. |
165 |
|
*/ |
166 |
|
public void |
167 |
|
removePropertyChangeListener(PropertyChangeListener l) { |
168 |
|
propertyChangeListeners.remove(l); |
169 |
|
} |
170 |
|
|
171 |
|
/** |
172 |
|
* Gets the border color that is used when the channel is selected. |
173 |
|
* @return The border color that is used when the channel is selected. |
174 |
|
*/ |
175 |
|
public static Color |
176 |
|
getBorderColor() { return borderColor; } |
177 |
|
|
178 |
|
/** |
179 |
|
* Sets the border color to be used when the channel is selected. |
180 |
|
* @param c The border color to be used when the channel is selected. |
181 |
|
*/ |
182 |
|
public static void |
183 |
|
setBorderColor(Color c) { |
184 |
|
if(borderColor != null && borderColor.getRGB() == c.getRGB()) return; |
185 |
|
|
186 |
|
Color oldColor = borderColor; |
187 |
|
borderColor = c; |
188 |
|
borderSelected = new LineBorder(getBorderColor(), 2, true); |
189 |
|
firePropertyChanged("borderColor", oldColor, borderColor); |
190 |
|
} |
191 |
|
|
192 |
|
private static void |
193 |
|
firePropertyChanged(String propertyName, Object oldValue, Object newValue) { |
194 |
|
PropertyChangeEvent e = |
195 |
|
new PropertyChangeEvent(Channel.class, propertyName, oldValue, newValue); |
196 |
|
|
197 |
|
for(PropertyChangeListener l : propertyChangeListeners) l.propertyChange(e); |
198 |
} |
} |
199 |
|
|
200 |
|
|
201 |
private final JPanel mainPane = new JPanel(); |
private final JPanel mainPane = new JPanel(); |
202 |
private final ChannelProperties propertiesPane; |
private final ChannelProperties propertiesPane; |
203 |
private final JButton btnInstr = new JButton(i18n.getLabel("Channel.btnInstr")); |
private final JButton btnInstr = new InstrumentButton(i18n.getLabel("Channel.btnInstr")); |
204 |
|
private final Action actInstr; |
205 |
private final JButton btnMute = new JButton(); |
private final JButton btnMute = new JButton(); |
206 |
private final JButton btnSolo = new JButton(); |
private final JButton btnSolo = new JButton(); |
207 |
private final JSlider slVolume = new JSlider(0, 100); |
private final JSlider slVolume = new JSlider(0, 100); |
210 |
private final JLabel lVoices = new JLabel("--"); |
private final JLabel lVoices = new JLabel("--"); |
211 |
private final JToggleButton btnProperties = new JToggleButton(); |
private final JToggleButton btnProperties = new JToggleButton(); |
212 |
|
|
|
private final EventHandler eventHandler = new EventHandler(); |
|
|
|
|
213 |
private static int count = 2; |
private static int count = 2; |
214 |
|
|
215 |
private boolean selected = false; |
private boolean selected = false; |
302 |
d = getPreferredSize(); |
d = getPreferredSize(); |
303 |
setMaximumSize(new Dimension(getMaximumSize().width, d.height)); |
setMaximumSize(new Dimension(getMaximumSize().width, d.height)); |
304 |
|
|
305 |
getModel().addSamplerChannelListener(eventHandler); |
getModel().addSamplerChannelListener(getHandler()); |
306 |
|
|
307 |
btnInstr.addActionListener(new ActionListener() { |
actInstr = new AbstractAction() { |
308 |
public void |
public void |
309 |
actionPerformed(ActionEvent e) { loadInstrument(); } |
actionPerformed(ActionEvent e) { |
310 |
}); |
if(actInstr.isEnabled()) loadInstrument(); |
311 |
|
} |
312 |
|
}; |
313 |
|
|
314 |
|
btnInstr.addActionListener(actInstr); |
315 |
|
|
316 |
btnMute.addActionListener(new ActionListener() { |
btnMute.addActionListener(new ActionListener() { |
317 |
public void |
public void |
332 |
public void |
public void |
333 |
actionPerformed(ActionEvent e) { |
actionPerformed(ActionEvent e) { |
334 |
showProperties(btnProperties.isSelected()); |
showProperties(btnProperties.isSelected()); |
335 |
|
|
336 |
|
String s; |
337 |
|
if(btnProperties.isSelected()) { |
338 |
|
s = i18n.getButtonLabel("Channel.ttHideProps"); |
339 |
|
} else { |
340 |
|
s = i18n.getButtonLabel("Channel.ttShowProps"); |
341 |
|
} |
342 |
|
|
343 |
|
btnProperties.setToolTipText(s); |
344 |
} |
} |
345 |
}); |
}); |
346 |
|
|
347 |
|
btnProperties.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR)); |
348 |
|
|
349 |
|
String s; |
350 |
|
if(btnProperties.isSelected()) s = i18n.getButtonLabel("Channel.ttHideProps"); |
351 |
|
else s = i18n.getButtonLabel("Channel.ttShowProps"); |
352 |
|
|
353 |
|
btnProperties.setToolTipText(s); |
354 |
|
|
355 |
|
addPropertyChangeListener(getHandler()); |
356 |
|
|
357 |
updateChannelInfo(); |
updateChannelInfo(); |
358 |
} |
} |
359 |
|
|
360 |
private class EventHandler implements SamplerChannelListener { |
public class InstrumentButton extends JButton { |
361 |
|
private boolean dragging = false; |
362 |
|
|
363 |
|
InstrumentButton(String s) { |
364 |
|
super(s); |
365 |
|
|
366 |
|
setTransferHandler(new TransferHandler("instrument")); |
367 |
|
|
368 |
|
addMouseListener(new MouseAdapter() { |
369 |
|
public void |
370 |
|
mouseExited(MouseEvent e) { |
371 |
|
if(!dragging) return; |
372 |
|
|
373 |
|
int b1 = e.BUTTON1_DOWN_MASK; |
374 |
|
if((e.getModifiersEx() & b1) != b1) return; |
375 |
|
|
376 |
|
actInstr.setEnabled(false); |
377 |
|
doClick(0); |
378 |
|
actInstr.setEnabled(true); |
379 |
|
|
380 |
|
JComponent c = (JComponent)e.getSource(); |
381 |
|
TransferHandler handler = c.getTransferHandler(); |
382 |
|
handler.exportAsDrag(c, e, TransferHandler.COPY); |
383 |
|
} |
384 |
|
|
385 |
|
public void |
386 |
|
mouseReleased(MouseEvent e) { dragging = false; } |
387 |
|
}); |
388 |
|
|
389 |
|
addMouseMotionListener(new MouseMotionAdapter() { |
390 |
|
public void |
391 |
|
mouseDragged(MouseEvent e) { dragging = true; } |
392 |
|
}); |
393 |
|
} |
394 |
|
|
395 |
|
public String |
396 |
|
getInstrument() { |
397 |
|
SamplerChannel sc = Channel.this.getChannelInfo(); |
398 |
|
|
399 |
|
if(sc.getInstrumentName() == null || sc.getInstrumentStatus() < 0) |
400 |
|
return null; |
401 |
|
|
402 |
|
Instrument instr = new Instrument(); |
403 |
|
instr.setName(sc.getInstrumentName()); |
404 |
|
instr.setInstrumentIndex(sc.getInstrumentIndex()); |
405 |
|
instr.setPath(sc.getInstrumentFile()); |
406 |
|
return instr.getDnDString(); |
407 |
|
} |
408 |
|
|
409 |
|
public void setInstrument(String instr) { |
410 |
|
if(!Instrument.isDnDString(instr)) return; |
411 |
|
|
412 |
|
String[] args = instr.split("\n"); |
413 |
|
if(args.length < 6) return; |
414 |
|
|
415 |
|
try { |
416 |
|
int idx = Integer.parseInt(args[5]); |
417 |
|
Channel.this.getModel().loadInstrument(args[4], idx); |
418 |
|
} catch(Exception x) { |
419 |
|
CC.getLogger().log(Level.INFO, HF.getErrorMessage(x), x); |
420 |
|
} |
421 |
|
} |
422 |
|
} |
423 |
|
|
424 |
|
private final EventHandler eventHandler = new EventHandler(); |
425 |
|
|
426 |
|
private EventHandler |
427 |
|
getHandler() { return eventHandler; } |
428 |
|
|
429 |
|
private class EventHandler implements SamplerChannelListener, PropertyChangeListener { |
430 |
/** |
/** |
431 |
* Invoked when changes are made to a sampler channel. |
* Invoked when changes are made to a sampler channel. |
432 |
* @param e A <code>SamplerChannelEvent</code> instance |
* @param e A <code>SamplerChannelEvent</code> instance |
454 |
voiceCountChanged(SamplerChannelEvent e) { |
voiceCountChanged(SamplerChannelEvent e) { |
455 |
updateVoiceCount(getModel().getVoiceCount()); |
updateVoiceCount(getModel().getVoiceCount()); |
456 |
} |
} |
457 |
|
|
458 |
|
public void |
459 |
|
propertyChange(PropertyChangeEvent e) { |
460 |
|
if(e.getPropertyName() == "borderColor") setSelected(isSelected()); |
461 |
|
} |
462 |
} |
} |
463 |
|
|
464 |
/** |
/** |
475 |
*/ |
*/ |
476 |
public void |
public void |
477 |
setSelected(boolean select) { |
setSelected(boolean select) { |
478 |
if(select) |
if(select) mainPane.setBorder(borderSelected); |
479 |
mainPane.setBorder(BorderFactory.createLineBorder(java.awt.Color.WHITE, 3)); |
else mainPane.setBorder(borderDeselected); |
|
else mainPane.setBorder(BorderFactory.createEmptyBorder(3, 3, 3, 3)); |
|
480 |
|
|
481 |
selected = select; |
selected = select; |
482 |
} |
} |
500 |
int status = sc.getInstrumentStatus(); |
int status = sc.getInstrumentStatus(); |
501 |
if(status >= 0 && status < 100) { |
if(status >= 0 && status < 100) { |
502 |
btnInstr.setText(i18n.getLabel("Channel.loadingInstrument", status)); |
btnInstr.setText(i18n.getLabel("Channel.loadingInstrument", status)); |
503 |
|
} else if(status == -1) { |
504 |
|
btnInstr.setText(i18n.getLabel("Channel.btnInstr")); |
505 |
|
} else if(status < -1) { |
506 |
|
btnInstr.setText(i18n.getLabel("Channel.errorLoadingInstrument")); |
507 |
} else { |
} else { |
508 |
if(sc.getInstrumentName() != null) btnInstr.setText(sc.getInstrumentName()); |
if(sc.getInstrumentName() != null) btnInstr.setText(sc.getInstrumentName()); |
509 |
else btnInstr.setText(i18n.getLabel("Channel.btnInstr")); |
else btnInstr.setText(i18n.getLabel("Channel.btnInstr")); |
510 |
} |
} |
511 |
|
|
512 |
updateMute(sc); |
updateMuteIcon(sc); |
513 |
|
|
514 |
if(sc.isSoloChannel()) btnSolo.setIcon(iconSoloOn); |
if(sc.isSoloChannel()) btnSolo.setIcon(iconSoloOn); |
515 |
else btnSolo.setIcon(iconSoloOff); |
else btnSolo.setIcon(iconSoloOff); |
613 |
* for this channel. |
* for this channel. |
614 |
*/ |
*/ |
615 |
private void |
private void |
616 |
updateMute(SamplerChannel channel) { |
updateMuteIcon(SamplerChannel channel) { |
617 |
if(channel.isMutedBySolo()) btnMute.setIcon(iconMutedBySolo); |
if(channel.isMutedBySolo()) btnMute.setIcon(iconMutedBySolo); |
618 |
else if(channel.isMuted()) btnMute.setIcon(iconMuteOn); |
else if(channel.isMuted()) btnMute.setIcon(iconMuteOn); |
619 |
else btnMute.setIcon(iconMuteOff); |
else btnMute.setIcon(iconMuteOff); |
775 |
|
|
776 |
CC.getSamplerModel().addMidiDeviceListListener(getHandler()); |
CC.getSamplerModel().addMidiDeviceListListener(getHandler()); |
777 |
CC.getSamplerModel().addAudioDeviceListListener(getHandler()); |
CC.getSamplerModel().addAudioDeviceListListener(getHandler()); |
778 |
|
CC.getSamplerModel().addSamplerChannelListListener(getHandler()); |
779 |
|
|
780 |
btnAudioProps.setToolTipText(i18n.getLabel("ChannelProperties.routing")); |
btnAudioProps.setToolTipText(i18n.getLabel("ChannelProperties.routing")); |
781 |
btnAudioProps.addActionListener(new ActionListener() { |
btnAudioProps.addActionListener(new ActionListener() { |
787 |
} |
} |
788 |
}); |
}); |
789 |
|
|
|
|
|
|
|
|
790 |
updateMidiDevices(); |
updateMidiDevices(); |
791 |
updateAudioDevices(); |
updateAudioDevices(); |
792 |
updateChannelProperties(); |
updateChannelProperties(); |
1056 |
private Handler |
private Handler |
1057 |
getHandler() { return handler; } |
getHandler() { return handler; } |
1058 |
|
|
1059 |
private class Handler implements MidiDeviceListListener, AudioDeviceListListener { |
private class Handler implements MidiDeviceListListener, |
1060 |
|
AudioDeviceListListener, SamplerChannelListListener { |
1061 |
|
|
1062 |
/** |
/** |
1063 |
* Invoked when a new MIDI device is created. |
* Invoked when a new MIDI device is created. |
1064 |
* @param e A <code>MidiDeviceListEvent</code> |
* @param e A <code>MidiDeviceListEvent</code> |
1098 |
deviceRemoved(AudioDeviceListEvent e) { |
deviceRemoved(AudioDeviceListEvent e) { |
1099 |
cbAudioDevice.removeItem(e.getAudioDeviceModel().getDeviceInfo()); |
cbAudioDevice.removeItem(e.getAudioDeviceModel().getDeviceInfo()); |
1100 |
} |
} |
1101 |
|
|
1102 |
|
/** |
1103 |
|
* Invoked when a new sampler channel is created. |
1104 |
|
* @param e A <code>SamplerChannelListEvent</code> |
1105 |
|
* instance providing the event information. |
1106 |
|
*/ |
1107 |
|
public void |
1108 |
|
channelAdded(SamplerChannelListEvent e) { } |
1109 |
|
|
1110 |
|
/** |
1111 |
|
* Invoked when a sampler channel is removed. |
1112 |
|
* @param e A <code>SamplerChannelListEvent</code> |
1113 |
|
* instance providing the event information. |
1114 |
|
*/ |
1115 |
|
public void |
1116 |
|
channelRemoved(SamplerChannelListEvent e) { |
1117 |
|
// Some cleanup when the channel is removed. |
1118 |
|
if(e.getChannelModel().getChannelID() == channelModel.getChannelID()) { |
1119 |
|
CC.getSamplerModel().removeMidiDeviceListListener(getHandler()); |
1120 |
|
CC.getSamplerModel().removeAudioDeviceListListener(getHandler()); |
1121 |
|
} |
1122 |
|
} |
1123 |
} |
} |
1124 |
} |
} |