/[svn]/jsampler/trunk/src/org/jsampler/view/classic/Channel.java
ViewVC logotype

Annotation of /jsampler/trunk/src/org/jsampler/view/classic/Channel.java

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1343 - (hide annotations) (download)
Tue Sep 11 15:38:28 2007 UTC (16 years, 7 months ago) by iliev
File size: 46527 byte(s)
* JS Classic: Added new button to sampler channels
  for starting an instrument editor
* The last used instrument selection method is now
  saved for the next session
* Fantasia: Removed the lock border from non-editable
  text fields in properties panes and LS Console

1 iliev 787 /*
2     * JSampler - a java front-end for LinuxSampler
3     *
4 iliev 1143 * Copyright (C) 2005-2007 Grigor Iliev <grigor@grigoriliev.com>
5 iliev 787 *
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.view.classic;
24    
25 iliev 1143 import java.awt.BorderLayout;
26 iliev 787 import java.awt.Color;
27 iliev 842 import java.awt.Cursor;
28 iliev 787 import java.awt.Dimension;
29     import java.awt.GridBagConstraints;
30     import java.awt.GridBagLayout;
31     import java.awt.Insets;
32    
33 iliev 911 import java.awt.datatransfer.Transferable;
34    
35 iliev 787 import java.awt.event.ActionEvent;
36     import java.awt.event.ActionListener;
37 iliev 1143 import java.awt.event.HierarchyEvent;
38     import java.awt.event.HierarchyListener;
39 iliev 911 import java.awt.event.MouseAdapter;
40     import java.awt.event.MouseEvent;
41     import java.awt.event.MouseMotionAdapter;
42 iliev 787
43 iliev 842 import java.beans.PropertyChangeEvent;
44     import java.beans.PropertyChangeListener;
45    
46 iliev 787 import java.net.URL;
47    
48 iliev 842 import java.util.Vector;
49    
50 iliev 787 import java.util.logging.Level;
51    
52 iliev 911 import javax.swing.Action;
53     import javax.swing.AbstractAction;
54 iliev 787 import javax.swing.BorderFactory;
55     import javax.swing.Box;
56     import javax.swing.BoxLayout;
57 iliev 911 import javax.swing.JComponent;
58 iliev 787 import javax.swing.ImageIcon;
59     import javax.swing.JButton;
60     import javax.swing.JComboBox;
61     import javax.swing.JLabel;
62     import javax.swing.JPanel;
63     import javax.swing.JSeparator;
64     import javax.swing.JSlider;
65     import javax.swing.JToggleButton;
66 iliev 1285 import javax.swing.JToolBar;
67 iliev 911 import javax.swing.TransferHandler;
68 iliev 787
69 iliev 842 import javax.swing.border.Border;
70     import javax.swing.border.LineBorder;
71 iliev 1143 import javax.swing.border.TitledBorder;
72 iliev 842
73 iliev 787 import javax.swing.event.ChangeEvent;
74     import javax.swing.event.ChangeListener;
75    
76 iliev 1143 import net.sf.juife.InformationDialog;
77 iliev 787 import net.sf.juife.JuifeUtils;
78    
79 iliev 911 import org.jsampler.AudioDeviceModel;
80 iliev 787 import org.jsampler.CC;
81 iliev 911 import org.jsampler.HF;
82     import org.jsampler.Instrument;
83 iliev 787 import org.jsampler.MidiDeviceModel;
84 iliev 1143 import org.jsampler.MidiInstrumentMap;
85 iliev 787 import org.jsampler.SamplerChannelModel;
86     import org.jsampler.SamplerModel;
87    
88 iliev 1143 import org.jsampler.event.ListEvent;
89     import org.jsampler.event.ListListener;
90 iliev 1285 import org.jsampler.event.MidiDeviceEvent;
91 iliev 787 import org.jsampler.event.MidiDeviceListEvent;
92     import org.jsampler.event.MidiDeviceListListener;
93 iliev 1285 import org.jsampler.event.MidiDeviceListener;
94 iliev 1143 import org.jsampler.event.SamplerAdapter;
95 iliev 787 import org.jsampler.event.SamplerChannelAdapter;
96     import org.jsampler.event.SamplerChannelEvent;
97 iliev 911 import org.jsampler.event.SamplerChannelListEvent;
98     import org.jsampler.event.SamplerChannelListListener;
99 iliev 787 import org.jsampler.event.SamplerChannelListener;
100 iliev 1143 import org.jsampler.event.SamplerEvent;
101 iliev 1285 import org.jsampler.event.SamplerListener;
102 iliev 787
103 iliev 1285 import org.jsampler.view.std.JSChannelOutputRoutingDlg;
104     import org.jsampler.view.std.JSFxSendsPane;
105     import org.jsampler.view.std.JSInstrumentChooser;
106    
107 iliev 787 import org.linuxsampler.lscp.AudioOutputDevice;
108     import org.linuxsampler.lscp.MidiInputDevice;
109     import org.linuxsampler.lscp.MidiPort;
110     import org.linuxsampler.lscp.SamplerChannel;
111     import org.linuxsampler.lscp.SamplerEngine;
112    
113     import static org.jsampler.view.classic.ClassicI18n.i18n;
114    
115    
116     /**
117     *
118     * @author Grigor Iliev
119     */
120     public class Channel extends org.jsampler.view.JSChannel {
121 iliev 1343 private final static ImageIcon iconEdit;
122    
123 iliev 787 private final static ImageIcon iconMuteOn;
124     private final static ImageIcon iconMuteOff;
125     private final static ImageIcon iconMutedBySolo;
126    
127     private final static ImageIcon iconSoloOn;
128     private final static ImageIcon iconSoloOff;
129    
130     private final static ImageIcon iconShowProperties;
131     private final static ImageIcon iconHideProperties;
132    
133 iliev 842 private static Border borderSelected;
134 iliev 1143 private static Border borderHighlighted;
135 iliev 842 private static Border borderDeselected;
136    
137 iliev 1143 private static Color chnColor;
138 iliev 842 private static Color borderColor;
139 iliev 1143 private static Color borderHighlightedColor;
140     private static Color chnSelectedColor;
141     private static Color chnHighlightedColor;
142 iliev 842
143     private final static Vector<PropertyChangeListener> propertyChangeListeners
144     = new Vector<PropertyChangeListener>();
145    
146 iliev 787 static {
147 iliev 1343 iconEdit = new ImageIcon(Channel.class.getResource("res/icons/edit.png"));
148    
149 iliev 787 String path = "org/jsampler/view/classic/res/icons/";
150     URL url = ClassLoader.getSystemClassLoader().getResource(path + "mute_on.png");
151     iconMuteOn = new ImageIcon(url);
152    
153     url = ClassLoader.getSystemClassLoader().getResource(path + "mute_off.png");
154     iconMuteOff = new ImageIcon(url);
155    
156     url = ClassLoader.getSystemClassLoader().getResource(path + "muted_by_solo.png");
157     iconMutedBySolo = new ImageIcon(url);
158    
159     url = ClassLoader.getSystemClassLoader().getResource(path + "solo_on.png");
160     iconSoloOn = new ImageIcon(url);
161    
162     url = ClassLoader.getSystemClassLoader().getResource(path + "solo_off.png");
163     iconSoloOff = new ImageIcon(url);
164    
165     url = ClassLoader.getSystemClassLoader().getResource(path + "Back16.gif");
166     iconShowProperties = new ImageIcon(url);
167    
168 iliev 911 iconHideProperties = Res.iconDown16;
169 iliev 842
170     if(ClassicPrefs.getCustomChannelBorderColor())
171     setBorderColor(ClassicPrefs.getChannelBorderColor());
172     else setBorderColor(ClassicPrefs.getDefaultChannelBorderColor());
173    
174 iliev 1143 if(ClassicPrefs.getCustomChannelBorderHlColor())
175     setBorderHighlightedColor(ClassicPrefs.getChannelBorderHlColor());
176     else setBorderHighlightedColor(ClassicPrefs.getDefaultChannelBorderHlColor());
177    
178 iliev 842 borderSelected = new LineBorder(getBorderColor(), 2, true);
179 iliev 1143 borderHighlighted = new LineBorder(getBorderHighlightedColor(), 2, true);
180 iliev 842 borderDeselected = BorderFactory.createEmptyBorder(2, 2, 2, 2);
181 iliev 1143
182     chnColor = new JPanel().getBackground();
183    
184     if(ClassicPrefs.getCustomSelectedChannelBgColor()) {
185     chnSelectedColor = ClassicPrefs.getSelectedChannelBgColor();
186     } else {
187     int r = chnColor.getRed() - 14 < 0 ? 0 : chnColor.getRed() - 14;
188     int g = chnColor.getGreen() - 8 < 0 ? 0 : chnColor.getGreen() - 8;
189     int b = chnColor.getBlue() - 3 < 0 ? 0 : chnColor.getBlue() - 3;
190    
191     chnSelectedColor = new Color(r, g, b);
192     }
193    
194     /*r = r + 5 > 255 ? 255 : r + 5;
195     g = g + 4 > 255 ? 255 : g + 4;
196     b = b + 1 > 255 ? 255 : b + 1;*/
197    
198     chnHighlightedColor = new Color(chnColor.getRGB());
199 iliev 787 }
200    
201 iliev 842 /**
202     * Registers the specified listener for receiving property change events.
203     * @param l The <code>PropertyChangeListener</code> to register.
204     */
205     public void
206     addPropertyChangeListener(PropertyChangeListener l) {
207     propertyChangeListeners.add(l);
208     }
209 iliev 787
210 iliev 842 /**
211     * Removes the specified listener.
212     * @param l The <code>PropertyChangeListener</code> to remove.
213     */
214     public void
215     removePropertyChangeListener(PropertyChangeListener l) {
216     propertyChangeListeners.remove(l);
217     }
218    
219     /**
220     * Gets the border color that is used when the channel is selected.
221     * @return The border color that is used when the channel is selected.
222     */
223     public static Color
224     getBorderColor() { return borderColor; }
225    
226     /**
227     * Sets the border color to be used when the channel is selected.
228     * @param c The border color to be used when the channel is selected.
229     */
230     public static void
231     setBorderColor(Color c) {
232     if(borderColor != null && borderColor.getRGB() == c.getRGB()) return;
233    
234     Color oldColor = borderColor;
235     borderColor = c;
236     borderSelected = new LineBorder(getBorderColor(), 2, true);
237     firePropertyChanged("borderColor", oldColor, borderColor);
238     }
239    
240 iliev 1143 /**
241     * Gets the border color that is used when the mouse pointer is over a channel.
242     * @return The border color that is used when the mouse pointer is over a channel.
243     */
244     public static Color
245     getBorderHighlightedColor() { return borderHighlightedColor; }
246    
247     /**
248     * Sets the border color to be used when the mouse pointer is over a channel.
249     * @param c The border color to be used when the mouse pointer is over a channel.
250     */
251     public static void
252     setBorderHighlightedColor(Color c) {
253     Color oldColor = borderHighlightedColor;
254     if(oldColor != null && oldColor.getRGB() == c.getRGB()) return;
255    
256     borderHighlightedColor = c;
257     borderHighlighted = new LineBorder(getBorderHighlightedColor(), 2, true);
258     firePropertyChanged("borderHighlightedColor", oldColor, borderHighlightedColor);
259     }
260    
261     /**
262     * Gets the background color that is used when a channel is selected.
263     * @return The background color that is used when a channel is selected.
264     */
265     public static Color
266     getSelectedChannelBgColor() { return chnSelectedColor; }
267    
268     /**
269     * Sets the background color that is used when a channel is selected.
270     * @param c The background color to be used when a channel is selected.
271     */
272     public static void
273     setSelectedChannelBgColor(Color c) {
274     Color oldColor = chnSelectedColor;
275     if(oldColor != null && oldColor.getRGB() == c.getRGB()) return;
276    
277     chnSelectedColor = c;
278     firePropertyChanged("selectedChannelBgColor", oldColor, chnSelectedColor);
279     }
280    
281     /**
282     * Gets the background color that is used when the mouse pointer is over a channel.
283     * @return The background color that is used when the mouse pointer is over a channel.
284     */
285     public static Color
286     getHighlightedChannelBgColor() { return chnHighlightedColor; }
287    
288     /**
289     * Sets the background color to be used when the mouse pointer is over a channel.
290     * @param c The background color to be used when the mouse pointer is over a channel.
291     */
292     public static void
293     setHighlightedChannelBgColor(Color c) {
294     Color oldColor = chnHighlightedColor;
295     if(oldColor != null && oldColor.getRGB() == c.getRGB()) return;
296    
297     chnHighlightedColor = c;
298     firePropertyChanged("highlightedChannelBgColor", oldColor, chnHighlightedColor);
299     }
300    
301 iliev 842 private static void
302     firePropertyChanged(String propertyName, Object oldValue, Object newValue) {
303     PropertyChangeEvent e =
304     new PropertyChangeEvent(Channel.class, propertyName, oldValue, newValue);
305    
306     for(PropertyChangeListener l : propertyChangeListeners) l.propertyChange(e);
307     }
308    
309    
310 iliev 787 private final JPanel mainPane = new JPanel();
311     private final ChannelProperties propertiesPane;
312 iliev 911 private final JButton btnInstr = new InstrumentButton(i18n.getLabel("Channel.btnInstr"));
313     private final Action actInstr;
314 iliev 1343 private final JButton btnEdit = new JButton(iconEdit);
315 iliev 787 private final JButton btnMute = new JButton();
316     private final JButton btnSolo = new JButton();
317     private final JSlider slVolume = new JSlider(0, 100);
318     private final JLabel lVolume = new JLabel();
319 iliev 1143 private final JLabel lVolImg = new JLabel(Res.iconVolume16);
320 iliev 787 private final JLabel lStreams = new JLabel("--");
321     private final JLabel lVoices = new JLabel("--");
322     private final JToggleButton btnProperties = new JToggleButton();
323    
324     private static int count = 2;
325    
326     private boolean selected = false;
327 iliev 1143 private boolean mouseOver = false;
328 iliev 787
329    
330     /**
331     * Creates a new instance of <code>Channel</code> using the specified
332     * non-<code>null</code> channel model.
333     * @param model The model to be used by this channel.
334     * @throws IllegalArgumentException If the model is <code>null</code>.
335     */
336     public
337     Channel(SamplerChannelModel model) {
338     super(model);
339    
340     setBorder(BorderFactory.createEmptyBorder(1, 1, 1, 1));
341    
342     mainPane.setLayout(new BoxLayout(mainPane, BoxLayout.Y_AXIS));
343 iliev 1143 addMouseListener(getHandler());
344 iliev 1341 addHierarchyListener(getHandler());
345 iliev 787
346     JPanel p = new JPanel();
347 iliev 1143 p.setOpaque(false);
348 iliev 787 p.setLayout(new BoxLayout(p, BoxLayout.X_AXIS));
349     p.setBorder(BorderFactory.createEmptyBorder(3, 3, 3, 3));
350    
351 iliev 1143 setToolTipText(i18n.getLabel("Channel.tt", getModel().getChannelId()));
352 iliev 787
353     Dimension d = btnInstr.getPreferredSize();
354     btnInstr.setMaximumSize(new Dimension(Short.MAX_VALUE, d.height));
355     p.add(btnInstr);
356     p.add(Box.createRigidArea(new Dimension(6, 0)));
357    
358 iliev 1343 btnEdit.setToolTipText(i18n.getLabel("Channel.btnEdit.tt"));
359     btnEdit.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
360     p.add(btnEdit);
361     p.add(Box.createRigidArea(new Dimension(6, 0)));
362    
363 iliev 787 lStreams.setHorizontalAlignment(JLabel.CENTER);
364     lVoices.setHorizontalAlignment(JLabel.CENTER);
365    
366     JPanel statPane = new JPanel();
367 iliev 1143 statPane.setOpaque(false);
368 iliev 787 statPane.setBorder(BorderFactory.createLoweredBevelBorder());
369     statPane.setLayout(new BoxLayout(statPane, BoxLayout.X_AXIS));
370     statPane.add(Box.createRigidArea(new Dimension(6, 0)));
371     statPane.add(lStreams);
372     statPane.add(new JLabel("/"));
373     statPane.add(lVoices);
374     statPane.add(Box.createRigidArea(new Dimension(6, 0)));
375    
376     p.add(statPane);
377    
378     p.add(Box.createRigidArea(new Dimension(6, 0)));
379    
380     btnMute.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
381     p.add(btnMute);
382     p.add(Box.createRigidArea(new Dimension(6, 0)));
383    
384     btnSolo.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
385     p.add(btnSolo);
386     p.add(Box.createRigidArea(new Dimension(6, 0)));
387    
388     JPanel volumePane = new JPanel();
389 iliev 1143 volumePane.setOpaque(false);
390 iliev 787 volumePane.setBorder(BorderFactory.createLoweredBevelBorder());
391     volumePane.setLayout(new BoxLayout(volumePane, BoxLayout.X_AXIS));
392     volumePane.add(Box.createRigidArea(new Dimension(6, 0)));
393    
394 iliev 1143 volumePane.add(lVolImg);
395     volumePane.add(Box.createRigidArea(new Dimension(1, 0)));
396    
397 iliev 787 d = slVolume.getPreferredSize();
398     slVolume.setMaximumSize(new Dimension(d.width > 300 ? d.width : 300, d.height));
399 iliev 1143 slVolume.setOpaque(false);
400 iliev 787 volumePane.add(slVolume);
401    
402     lVolume.setBorder(BorderFactory.createEmptyBorder(3, 6, 3, 6));
403     lVolume.setHorizontalAlignment(lVolume.RIGHT);
404    
405     // We use this to set the size of the lVolume that will be used in setVolume()
406     // to prevent the frequent resizing of lVolume
407     lVolume.setText("100%");
408    
409     volumePane.add(lVolume);
410    
411     p.add(volumePane);
412     p.add(Box.createRigidArea(new Dimension(6, 0)));
413    
414     btnProperties.setContentAreaFilled(false);
415     btnProperties.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
416     btnProperties.setIcon(iconShowProperties);
417     btnProperties.setSelectedIcon(iconHideProperties);
418     p.add(btnProperties);
419    
420     mainPane.add(p);
421    
422     propertiesPane = new ChannelProperties(model);
423     propertiesPane.setBorder(BorderFactory.createEmptyBorder(0, 3, 3, 3));
424     propertiesPane.setVisible(false);
425     mainPane.add(propertiesPane);
426     add(mainPane);
427    
428     d = getPreferredSize();
429     setMaximumSize(new Dimension(getMaximumSize().width, d.height));
430    
431 iliev 842 getModel().addSamplerChannelListener(getHandler());
432 iliev 787
433 iliev 911 actInstr = new AbstractAction() {
434 iliev 787 public void
435 iliev 911 actionPerformed(ActionEvent e) {
436     if(actInstr.isEnabled()) loadInstrument();
437     }
438     };
439 iliev 787
440 iliev 911 btnInstr.addActionListener(actInstr);
441    
442 iliev 1343 btnEdit.addActionListener(new ActionListener() {
443     public void
444     actionPerformed(ActionEvent e) {
445     CC.getSamplerModel().editBackendInstrument(getChannelId());
446     }
447     });
448    
449 iliev 787 btnMute.addActionListener(new ActionListener() {
450     public void
451     actionPerformed(ActionEvent e) { changeMute(); }
452     });
453    
454     btnSolo.addActionListener(new ActionListener() {
455     public void
456     actionPerformed(ActionEvent e) { changeSolo(); }
457     });
458    
459     slVolume.addChangeListener(new ChangeListener() {
460     public void
461     stateChanged(ChangeEvent e) { setVolume(); }
462     });
463    
464     btnProperties.addActionListener(new ActionListener() {
465     public void
466     actionPerformed(ActionEvent e) {
467     showProperties(btnProperties.isSelected());
468 iliev 842
469     String s;
470     if(btnProperties.isSelected()) {
471     s = i18n.getButtonLabel("Channel.ttHideProps");
472     } else {
473     s = i18n.getButtonLabel("Channel.ttShowProps");
474     }
475    
476     btnProperties.setToolTipText(s);
477 iliev 787 }
478     });
479    
480 iliev 842 btnProperties.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
481    
482     String s;
483     if(btnProperties.isSelected()) s = i18n.getButtonLabel("Channel.ttHideProps");
484     else s = i18n.getButtonLabel("Channel.ttShowProps");
485    
486     btnProperties.setToolTipText(s);
487    
488     addPropertyChangeListener(getHandler());
489    
490 iliev 787 updateChannelInfo();
491     }
492    
493 iliev 911 public class InstrumentButton extends JButton {
494     private boolean dragging = false;
495    
496     InstrumentButton(String s) {
497     super(s);
498    
499     setTransferHandler(new TransferHandler("instrument"));
500    
501     addMouseListener(new MouseAdapter() {
502     public void
503     mouseExited(MouseEvent e) {
504     if(!dragging) return;
505    
506     int b1 = e.BUTTON1_DOWN_MASK;
507     if((e.getModifiersEx() & b1) != b1) return;
508    
509     actInstr.setEnabled(false);
510     doClick(0);
511     actInstr.setEnabled(true);
512    
513     JComponent c = (JComponent)e.getSource();
514     TransferHandler handler = c.getTransferHandler();
515     handler.exportAsDrag(c, e, TransferHandler.COPY);
516     }
517    
518     public void
519     mouseReleased(MouseEvent e) { dragging = false; }
520     });
521    
522     addMouseMotionListener(new MouseMotionAdapter() {
523     public void
524     mouseDragged(MouseEvent e) { dragging = true; }
525     });
526     }
527    
528     public String
529     getInstrument() {
530     SamplerChannel sc = Channel.this.getChannelInfo();
531    
532     if(sc.getInstrumentName() == null || sc.getInstrumentStatus() < 0)
533     return null;
534    
535     Instrument instr = new Instrument();
536     instr.setName(sc.getInstrumentName());
537     instr.setInstrumentIndex(sc.getInstrumentIndex());
538     instr.setPath(sc.getInstrumentFile());
539     return instr.getDnDString();
540     }
541    
542     public void setInstrument(String instr) {
543     if(!Instrument.isDnDString(instr)) return;
544    
545     String[] args = instr.split("\n");
546     if(args.length < 6) return;
547    
548     try {
549     int idx = Integer.parseInt(args[5]);
550 iliev 1143 Channel.this.getModel().loadBackendInstrument(args[4], idx);
551 iliev 911 } catch(Exception x) {
552     CC.getLogger().log(Level.INFO, HF.getErrorMessage(x), x);
553     }
554     }
555     }
556    
557     private final EventHandler eventHandler = new EventHandler();
558    
559 iliev 842 private EventHandler
560     getHandler() { return eventHandler; }
561    
562 iliev 1143 private class EventHandler extends MouseAdapter implements SamplerChannelListener,
563     PropertyChangeListener, HierarchyListener {
564 iliev 787 /**
565     * Invoked when changes are made to a sampler channel.
566     * @param e A <code>SamplerChannelEvent</code> instance
567     * containing event information.
568     */
569     public void
570     channelChanged(SamplerChannelEvent e) { updateChannelInfo(); }
571    
572     /**
573     * Invoked when the number of active disk streams has changed.
574     * @param e A <code>SamplerChannelEvent</code> instance
575     * containing event information.
576     */
577     public void
578     streamCountChanged(SamplerChannelEvent e) {
579     updateStreamCount(getModel().getStreamCount());
580     }
581    
582     /**
583     * Invoked when the number of active voices has changed.
584     * @param e A <code>SamplerChannelEvent</code> instance
585     * containing event information.
586     */
587     public void
588     voiceCountChanged(SamplerChannelEvent e) {
589     updateVoiceCount(getModel().getVoiceCount());
590     }
591 iliev 842
592     public void
593     propertyChange(PropertyChangeEvent e) {
594 iliev 1143 if (
595     e.getPropertyName() == "borderColor" ||
596     e.getPropertyName() == "borderHighlightedColor" ||
597     e.getPropertyName() == "selectedChannelBgColor" ||
598     e.getPropertyName() == "highlightedChannelBgColor"
599     ) {
600     updateColors(isSelected());
601     }
602 iliev 842 }
603 iliev 1143
604     public void
605     mouseEntered(MouseEvent e) {
606     mouseOver = true;
607     updateColors(isSelected());
608     }
609    
610     public void
611     mouseExited(MouseEvent e) {
612     if(getMousePosition(true) != null) return;
613    
614     mouseOver = false;
615     updateColors(isSelected());
616     }
617    
618    
619    
620     /** Called when the hierarchy has been changed. */
621     public void
622     hierarchyChanged(HierarchyEvent e) {
623     if((e.getChangeFlags() & e.SHOWING_CHANGED) == e.SHOWING_CHANGED) {
624     if(getMousePosition() == null) mouseExited(null);
625     else mouseEntered(null);
626     }
627     }
628 iliev 787 }
629    
630     /**
631     * Determines whether the channel is selected.
632     * @return <code>true</code> if the channel is selected, <code>false</code> otherwise.
633     */
634     public boolean isSelected() { return selected; }
635    
636     /**
637     * Sets the selection state of this channel.
638     * This method is invoked when the selection state of the channel has changed.
639     * @param select Specifies the new selection state of this channel;
640     * <code>true</code> to select the channel, <code>false</code> otherwise.
641     */
642     public void
643     setSelected(boolean select) {
644 iliev 1143 updateColors(select);
645 iliev 787
646     selected = select;
647     }
648    
649 iliev 1143 /**
650     * Updates the channel background and border colors.
651     * @param selected Specifies the selection state of this channel.
652     */
653     private void
654     updateColors(boolean selected) {
655     if(selected) {
656     mainPane.setBorder(borderSelected);
657     mainPane.setBackground(chnSelectedColor);
658     } else {
659     if(mouseOver) {
660     mainPane.setBorder(borderHighlighted);
661     mainPane.setBackground(chnHighlightedColor);
662     } else {
663     mainPane.setBorder(borderDeselected);
664     mainPane.setBackground(chnColor);
665     }
666     }
667     }
668    
669 iliev 787 /** Hides the channel properties. */
670     public void
671     collapseChannel() { if(btnProperties.isSelected()) btnProperties.doClick(); }
672    
673     /** Shows the channel properties. */
674     public void
675     expandChannel() { if(!btnProperties.isSelected()) btnProperties.doClick(); }
676    
677     /**
678     * Updates the channel settings. This method is invoked when changes to the
679     * channel were made.
680     */
681     private void
682     updateChannelInfo() {
683     SamplerChannel sc = getChannelInfo();
684    
685     int status = sc.getInstrumentStatus();
686     if(status >= 0 && status < 100) {
687     btnInstr.setText(i18n.getLabel("Channel.loadingInstrument", status));
688 iliev 911 } else if(status == -1) {
689     btnInstr.setText(i18n.getLabel("Channel.btnInstr"));
690     } else if(status < -1) {
691     btnInstr.setText(i18n.getLabel("Channel.errorLoadingInstrument"));
692 iliev 787 } else {
693     if(sc.getInstrumentName() != null) btnInstr.setText(sc.getInstrumentName());
694     else btnInstr.setText(i18n.getLabel("Channel.btnInstr"));
695     }
696    
697 iliev 911 updateMuteIcon(sc);
698 iliev 787
699     if(sc.isSoloChannel()) btnSolo.setIcon(iconSoloOn);
700     else btnSolo.setIcon(iconSoloOff);
701    
702     slVolume.setValue((int)(sc.getVolume() * 100));
703    
704     boolean b = sc.getEngine() != null;
705     slVolume.setEnabled(b);
706     btnSolo.setEnabled(b);
707     btnMute.setEnabled(b);
708     }
709    
710     /** Invoked when the user clicks the mute button. */
711     private void
712     changeMute() {
713     SamplerChannel sc = getChannelInfo();
714     boolean b = true;
715    
716     /*
717     * Changing the mute button icon now instead of
718     * leaving the work to the notification mechanism of the LinuxSampler.
719     */
720     if(sc.isMuted() && !sc.isMutedBySolo()) {
721     b = false;
722     boolean hasSolo = CC.getSamplerModel().hasSoloChannel();
723    
724     if(sc.isSoloChannel() || !hasSolo) btnMute.setIcon(iconMuteOff);
725     else btnMute.setIcon(iconMutedBySolo);
726     } else btnMute.setIcon(iconMuteOn);
727    
728 iliev 1143 getModel().setBackendMute(b);
729 iliev 787 }
730    
731     /** Invoked when the user clicks the solo button. */
732     private void
733     changeSolo() {
734     SamplerChannel sc = getChannelInfo();
735     boolean b = !sc.isSoloChannel();
736    
737     /*
738     * Changing the solo button icon (and related) now instead of
739     * leaving the work to the notification mechanism of the LinuxSampler.
740     */
741     if(b) {
742     btnSolo.setIcon(iconSoloOn);
743     if(sc.isMutedBySolo()) btnMute.setIcon(iconMuteOff);
744     } else {
745     btnSolo.setIcon(iconSoloOff);
746     if(!sc.isMuted() && CC.getSamplerModel().getSoloChannelCount() > 1)
747     btnMute.setIcon(iconMutedBySolo);
748     }
749    
750 iliev 1143 getModel().setBackendSolo(b);
751 iliev 787 }
752    
753     /** Invoked when the user changes the volume */
754     private void
755     setVolume() {
756     updateVolume();
757    
758     if(slVolume.getValueIsAdjusting()) return;
759    
760     int vol = (int)(getChannelInfo().getVolume() * 100);
761    
762     if(vol == slVolume.getValue()) return;
763    
764     /*
765     * If the model's volume is not equal to the slider
766     * value we assume that the change is due to user input.
767     * So we must update the volume at the backend too.
768     */
769     float volume = slVolume.getValue();
770     volume /= 100;
771 iliev 1143 getModel().setBackendVolume(volume);
772 iliev 787 }
773    
774     private void
775     updateVolume() {
776     int volume = slVolume.getValue();
777     slVolume.setToolTipText(i18n.getLabel("Channel.volume", volume));
778 iliev 1143 lVolImg.setToolTipText(i18n.getLabel("Channel.volume", volume));
779 iliev 787
780     setVolumeLabel(volume);
781    
782    
783     }
784    
785     private void
786     setVolumeLabel(int volume) {
787     Dimension d = lVolume.getPreferredSize();
788     lVolume.setText(String.valueOf(volume) + '%');
789     d = JuifeUtils.getUnionSize(d, lVolume.getPreferredSize());
790     lVolume.setMinimumSize(d);
791     lVolume.setPreferredSize(d);
792     lVolume.setMaximumSize(d);
793     }
794    
795     /**
796     * Updates the mute button with the proper icon regarding to information obtained
797     * from <code>channel</code>.
798     * @param channel A <code>SamplerChannel</code> instance containing the new settings
799     * for this channel.
800     */
801     private void
802 iliev 911 updateMuteIcon(SamplerChannel channel) {
803 iliev 787 if(channel.isMutedBySolo()) btnMute.setIcon(iconMutedBySolo);
804     else if(channel.isMuted()) btnMute.setIcon(iconMuteOn);
805     else btnMute.setIcon(iconMuteOff);
806     }
807    
808     /**
809     * Updates the number of active disk streams.
810     * @param count The new number of active disk streams.
811     */
812     private void
813     updateStreamCount(int count) {
814     Dimension d = lStreams.getPreferredSize();
815     lStreams.setText(count == 0 ? "--" : String.valueOf(count));
816     d = JuifeUtils.getUnionSize(d, lStreams.getPreferredSize());
817     lStreams.setMinimumSize(d);
818     lStreams.setPreferredSize(d);
819     lStreams.setMaximumSize(d);
820     }
821    
822     /**
823     * Updates the number of active voices.
824     * @param count The new number of active voices.
825     */
826     private void
827     updateVoiceCount(int count) {
828     Dimension d = lVoices.getPreferredSize();
829     lVoices.setText(count == 0 ? "--" : String.valueOf(count));
830     d = JuifeUtils.getUnionSize(d, lVoices.getPreferredSize());
831     lVoices.setMinimumSize(d);
832     lVoices.setPreferredSize(d);
833     lVoices.setMaximumSize(d);
834     }
835    
836     private void
837     showProperties(boolean show) {propertiesPane.setVisible(show); }
838    
839     private void
840     loadInstrument() {
841 iliev 1285 JSInstrumentChooser dlg = new JSInstrumentChooser(CC.getMainFrame());
842 iliev 787 dlg.setVisible(true);
843    
844 iliev 1204 if(dlg.isCancelled()) return;
845    
846     SamplerEngine engine = getChannelInfo().getEngine();
847     if(dlg.getEngine() != null) {
848     if(engine == null || !dlg.getEngine().equals(engine.getName()));
849     getModel().setBackendEngineType(dlg.getEngine());
850 iliev 787 }
851 iliev 1204
852     int idx = dlg.getInstrumentIndex();
853     getModel().loadBackendInstrument(dlg.getInstrumentFile(), idx);
854    
855 iliev 787 }
856     }
857    
858     class ChannelProperties extends JPanel {
859     private final JLabel lMidiDevice =
860     new JLabel(i18n.getLabel("ChannelProperties.lMidiDevice"));
861     private final JLabel lMidiPort =
862     new JLabel(i18n.getLabel("ChannelProperties.lMidiPort"));
863     private final JLabel lMidiChannel =
864     new JLabel(i18n.getLabel("ChannelProperties.lMidiChannel"));
865    
866 iliev 1143 private final JLabel lInstrumentMap =
867     new JLabel(i18n.getLabel("ChannelProperties.lInstrumentMap"));
868    
869 iliev 787 private final JLabel lAudioDevice =
870     new JLabel(i18n.getLabel("ChannelProperties.lAudioDevice"));
871    
872     private final JComboBox cbEngines = new JComboBox();
873    
874 iliev 1143 private final JComboBox cbInstrumentMap = new JComboBox();
875 iliev 787 private final JComboBox cbMidiDevice = new JComboBox();
876     private final JComboBox cbMidiPort = new JComboBox();
877     private final JComboBox cbMidiChannel = new JComboBox();
878     private final JComboBox cbAudioDevice = new JComboBox();
879    
880 iliev 1143 private final JButton btnFxSends = new JButton(Res.iconFxSends22);
881     private final JButton btnAudioProps = new JButton(Res.iconAudioProps16);
882     private InformationDialog fxSendsDlg = null;
883 iliev 787
884     private SamplerChannelModel channelModel = null;
885 iliev 1285 private MidiDeviceModel midiDevice = null;
886 iliev 787
887     private boolean update = false;
888    
889 iliev 1285 private final SamplerListener samplerListener;
890     private final MapListListener mapListListener = new MapListListener();
891    
892 iliev 1143 private class NoMap {
893     public String
894     toString() { return "[None]"; }
895     }
896    
897     private NoMap noMap = new NoMap();
898    
899     private class DefaultMap {
900     public String
901     toString() { return "[Default]"; }
902     }
903    
904     private DefaultMap defaultMap = new DefaultMap();
905    
906 iliev 787 /**
907     * Creates a new instance of <code>ChannelProperties</code> using the specified non-null
908     * channel model.
909     * @param model The model to be used by this channel properties pane.
910     */
911     ChannelProperties(SamplerChannelModel model) {
912     channelModel = model;
913    
914     setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
915 iliev 1143 setOpaque(false);
916 iliev 787
917     add(new JSeparator());
918    
919 iliev 1143 JPanel enginesPane = createEnginePane();
920 iliev 787
921     JPanel devicesPane = new JPanel();
922 iliev 1143 devicesPane.setOpaque(false);
923 iliev 787 devicesPane.setLayout(new BoxLayout(devicesPane, BoxLayout.X_AXIS));
924    
925     devicesPane.add(Box.createRigidArea(new Dimension(3, 0)));
926    
927     devicesPane.add(createMidiPane());
928    
929     devicesPane.add(Box.createRigidArea(new Dimension(3, 0)));
930    
931     devicesPane.add(enginesPane);
932    
933     devicesPane.add(Box.createRigidArea(new Dimension(3, 0)));
934    
935     JPanel audioPane = createAudioPane();
936     Dimension d = audioPane.getPreferredSize();
937     d.height = Short.MAX_VALUE;
938    
939     audioPane.setMaximumSize(d);
940     devicesPane.add(audioPane);
941    
942     add(devicesPane);
943     add(Box.createRigidArea(new Dimension(0, 6)));
944    
945     add(new JSeparator());
946    
947     cbMidiChannel.addItem("All");
948     for(int i = 1; i <= 16; i++) cbMidiChannel.addItem(String.valueOf(i));
949    
950     cbMidiDevice.addActionListener(new ActionListener() {
951     public void
952     actionPerformed(ActionEvent e) { setMidiDevice(); }
953     });
954    
955     cbMidiPort.addActionListener(new ActionListener() {
956     public void
957     actionPerformed(ActionEvent e) { setMidiPort(); }
958     });
959    
960     cbMidiChannel.addActionListener(new ActionListener() {
961     public void
962     actionPerformed(ActionEvent e) { setMidiChannel(); }
963     });
964    
965     cbEngines.addActionListener(new ActionListener() {
966     public void
967     actionPerformed(ActionEvent e) { setEngineType(); }
968     });
969    
970     cbAudioDevice.addActionListener(new ActionListener() {
971     public void
972     actionPerformed(ActionEvent e) { setAudioDevice(); }
973     });
974    
975     getModel().addSamplerChannelListener(new SamplerChannelAdapter() {
976     public void
977     channelChanged(SamplerChannelEvent e) { updateChannelProperties(); }
978     });
979    
980 iliev 1285 samplerListener = new SamplerAdapter() {
981 iliev 1143 /** Invoked when the default MIDI instrument map is changed. */
982     public void
983     defaultMapChanged(SamplerEvent e) {
984     updateCbInstrumentMapToolTipText();
985     }
986 iliev 1285 };
987 iliev 1143
988 iliev 1285 CC.getSamplerModel().addSamplerListener(samplerListener);
989    
990 iliev 1143 cbInstrumentMap.addItem(noMap);
991     cbInstrumentMap.addItem(defaultMap);
992     for(MidiInstrumentMap map : CC.getSamplerModel().getMidiInstrumentMaps()) {
993     cbInstrumentMap.addItem(map);
994     }
995    
996     int map = getModel().getChannelInfo().getMidiInstrumentMapId();
997     cbInstrumentMap.setSelectedItem(CC.getSamplerModel().getMidiInstrumentMapById(map));
998     if(cbInstrumentMap.getSelectedItem() == null) {
999     if(map == -1) cbInstrumentMap.setSelectedItem(noMap);
1000     else if(map == -2) {
1001     cbInstrumentMap.setSelectedItem(defaultMap);
1002     }
1003     }
1004    
1005     updateCbInstrumentMapToolTipText();
1006    
1007     if(getModel().getChannelInfo().getEngine() == null) {
1008     cbInstrumentMap.setEnabled(false);
1009     }
1010    
1011     cbInstrumentMap.addActionListener(new ActionListener() {
1012     public void
1013     actionPerformed(ActionEvent e) { updateInstrumentMap(); }
1014     });
1015    
1016 iliev 787 CC.getSamplerModel().addMidiDeviceListListener(getHandler());
1017     CC.getSamplerModel().addAudioDeviceListListener(getHandler());
1018 iliev 911 CC.getSamplerModel().addSamplerChannelListListener(getHandler());
1019 iliev 1285 CC.getSamplerModel().addMidiInstrumentMapListListener(mapListListener);
1020 iliev 787
1021     btnAudioProps.setToolTipText(i18n.getLabel("ChannelProperties.routing"));
1022 iliev 1285 btnAudioProps.setEnabled(false);
1023 iliev 787 btnAudioProps.addActionListener(new ActionListener() {
1024     public void
1025     actionPerformed(ActionEvent e) {
1026     SamplerChannel c = getModel().getChannelInfo();
1027 iliev 1285 new JSChannelOutputRoutingDlg(CC.getMainFrame(), c).setVisible(true);
1028 iliev 787
1029     }
1030     });
1031    
1032 iliev 1143 btnFxSends.setToolTipText(i18n.getButtonLabel("ChannelProperties.btnFxSends"));
1033     btnFxSends.addActionListener(new ActionListener() {
1034     public void
1035     actionPerformed(ActionEvent e) {
1036     if(fxSendsDlg != null && fxSendsDlg.isVisible()) {
1037     fxSendsDlg.toFront();
1038     return;
1039     }
1040    
1041     FxSendsPane p = new FxSendsPane(getModel());
1042     int id = getModel().getChannelId();
1043     fxSendsDlg = new InformationDialog(CC.getMainFrame(), p);
1044 iliev 1285 fxSendsDlg.setTitle(i18n.getLabel("FxSendsDlg.title", id));
1045 iliev 1143 fxSendsDlg.setModal(false);
1046     fxSendsDlg.showCloseButton(false);
1047     fxSendsDlg.setVisible(true);
1048     }
1049     });
1050    
1051 iliev 787 updateMidiDevices();
1052     updateAudioDevices();
1053     updateChannelProperties();
1054     }
1055 iliev 1143
1056 iliev 1285 class FxSendsPane extends JSFxSendsPane {
1057     FxSendsPane(SamplerChannelModel model) {
1058     super(model);
1059    
1060     actionAddFxSend.putValue(Action.SMALL_ICON, Res.iconNew16);
1061     actionRemoveFxSend.putValue(Action.SMALL_ICON, Res.iconDelete16);
1062     }
1063    
1064     protected JToolBar
1065     createToolBar() {
1066     JToolBar tb = new JToolBar();
1067     Dimension d = new Dimension(Short.MAX_VALUE, tb.getPreferredSize().height);
1068     tb.setMaximumSize(d);
1069     tb.setFloatable(false);
1070     tb.setAlignmentX(JPanel.RIGHT_ALIGNMENT);
1071    
1072     tb.add(new ToolbarButton(actionAddFxSend));
1073     tb.add(new ToolbarButton(actionRemoveFxSend));
1074    
1075     return tb;
1076     }
1077     }
1078    
1079 iliev 787 private JPanel
1080 iliev 1143 createEnginePane() {
1081     for(SamplerEngine e : CC.getSamplerModel().getEngines()) cbEngines.addItem(e);
1082    
1083     cbEngines.setMaximumSize(cbEngines.getPreferredSize());
1084    
1085     JPanel p = new JPanel();
1086     p.setOpaque(false);
1087     p.setLayout(new BoxLayout(p, BoxLayout.Y_AXIS));
1088     p.add(cbEngines);
1089     p.setBorder(BorderFactory.createEmptyBorder(3, 3, 3, 3));
1090    
1091     //enginesPane.add(Box.createGlue());
1092     JPanel enginesPane = new JPanel();
1093     enginesPane.setOpaque(false);
1094     enginesPane.setLayout(new BorderLayout());
1095     enginesPane.add(p, BorderLayout.SOUTH);
1096     //enginesPane.add(Box.createRigidArea(new Dimension(0, 3)));
1097    
1098     String s = i18n.getLabel("ChannelProperties.enginesPane");
1099     enginesPane.setBorder(BorderFactory.createTitledBorder(s));
1100     Dimension d = new Dimension(enginesPane.getPreferredSize().width, Short.MAX_VALUE);
1101     enginesPane.setMaximumSize(d);
1102     return enginesPane;
1103     }
1104    
1105     private JPanel
1106 iliev 787 createMidiPane() {
1107     JPanel midiPane = new JPanel();
1108 iliev 1143 midiPane.setOpaque(false);
1109 iliev 787
1110     GridBagLayout gridbag = new GridBagLayout();
1111     GridBagConstraints c = new GridBagConstraints();
1112    
1113     midiPane.setLayout(gridbag);
1114    
1115 iliev 1143 c.gridx = 1;
1116 iliev 787 c.gridy = 0;
1117 iliev 1143 c.insets = new Insets(0, 3, 3, 3);
1118 iliev 787 gridbag.setConstraints(lMidiDevice, c);
1119     midiPane.add(lMidiDevice);
1120    
1121     c.gridx = 2;
1122     c.gridy = 0;
1123     gridbag.setConstraints(lMidiPort, c);
1124     midiPane.add(lMidiPort);
1125    
1126 iliev 1143 c.gridx = 3;
1127 iliev 787 c.gridy = 0;
1128     gridbag.setConstraints(lMidiChannel, c);
1129     midiPane.add(lMidiChannel);
1130    
1131 iliev 1143 c.gridx = 4;
1132 iliev 787 c.gridy = 0;
1133 iliev 1143 c.insets = new Insets(0, 10, 3, 3);
1134     gridbag.setConstraints(lInstrumentMap, c);
1135     midiPane.add(lInstrumentMap);
1136    
1137     btnFxSends.setMargin(new Insets(0, 0, 0, 0));
1138     c.gridx = 0;
1139     c.gridy = 0;
1140     c.gridheight = 2;
1141     c.insets = new Insets(0, 5, 0, 8);
1142     gridbag.setConstraints(btnFxSends, c);
1143     midiPane.add(btnFxSends);
1144    
1145     c.gridx = 1;
1146     c.gridy = 1;
1147     c.gridheight = 1;
1148     c.insets = new Insets(0, 4, 4, 3);
1149     c.fill = GridBagConstraints.HORIZONTAL;
1150     gridbag.setConstraints(cbMidiDevice, c);
1151     midiPane.add(cbMidiDevice);
1152    
1153     c.gridx = 3;
1154     c.gridy = 1;
1155 iliev 787 gridbag.setConstraints(cbMidiChannel, c);
1156     midiPane.add(cbMidiChannel);
1157    
1158 iliev 1143 c.gridx = 2;
1159     c.gridy = 1;
1160 iliev 787 gridbag.setConstraints(cbMidiPort, c);
1161     midiPane.add(cbMidiPort);
1162    
1163 iliev 1143 c.gridx = 4;
1164     c.gridy = 1;
1165     c.weightx = 1.0;
1166     c.insets = new Insets(0, 10, 3, 3);
1167     gridbag.setConstraints(cbInstrumentMap, c);
1168     midiPane.add(cbInstrumentMap);
1169    
1170 iliev 787 String s = i18n.getLabel("ChannelProperties.midiPane");
1171 iliev 1143 TitledBorder border = BorderFactory.createTitledBorder(s);
1172     //border.setTitlePosition(border.TOP);
1173     midiPane.setBorder(border);
1174 iliev 787 return midiPane;
1175     }
1176    
1177     private JPanel
1178     createAudioPane() {
1179     JPanel audioPane = new JPanel();
1180 iliev 1143 audioPane.setOpaque(false);
1181 iliev 787
1182     GridBagLayout gridbag = new GridBagLayout();
1183     GridBagConstraints c = new GridBagConstraints();
1184    
1185     audioPane.setLayout(gridbag);
1186    
1187     c.gridx = 0;
1188     c.gridy = 0;
1189 iliev 1143 c.insets = new Insets(0, 3, 3, 3);
1190 iliev 787 gridbag.setConstraints(lAudioDevice, c);
1191     audioPane.add(lAudioDevice);
1192    
1193 iliev 1143 c.gridx = 0;
1194     c.gridy = 1;
1195     c.fill = GridBagConstraints.HORIZONTAL;
1196 iliev 787 gridbag.setConstraints(cbAudioDevice, c);
1197     audioPane.add(cbAudioDevice);
1198    
1199     btnAudioProps.setMargin(new Insets(0, 0, 0, 0));
1200 iliev 1143 c.gridx = 1;
1201     c.gridy = 1;
1202     c.fill = GridBagConstraints.NONE;
1203 iliev 787 gridbag.setConstraints(btnAudioProps, c);
1204     audioPane.add(btnAudioProps);
1205    
1206     String s = i18n.getLabel("ChannelProperties.audioPane");
1207     audioPane.setBorder(BorderFactory.createTitledBorder(s));
1208    
1209     return audioPane;
1210     }
1211    
1212     /**
1213     * Gets the model that is currently used by this channel properties pane.
1214     * @return model The <code>SamplerChannelModel</code> instance
1215     * that provides information about the channel whose settings are
1216     * represented by this channel properties pane.
1217     */
1218     public SamplerChannelModel
1219     getModel() { return channelModel; }
1220    
1221 iliev 1143
1222     private void
1223     updateInstrumentMap() {
1224     updateCbInstrumentMapToolTipText();
1225    
1226     int id = getModel().getChannelInfo().getMidiInstrumentMapId();
1227     Object o = cbInstrumentMap.getSelectedItem();
1228     if(o == null && id == -1) return;
1229    
1230     int cbId;
1231     if(o == null || o == noMap) cbId = -1;
1232     else if(o == defaultMap) cbId = -2;
1233     else cbId = ((MidiInstrumentMap)o).getMapId();
1234    
1235     if(cbId == id) return;
1236    
1237     channelModel.setBackendMidiInstrumentMap(cbId);
1238     }
1239    
1240     private void
1241     updateCbInstrumentMapToolTipText() {
1242     if(cbInstrumentMap.getSelectedItem() != defaultMap) {
1243     cbInstrumentMap.setToolTipText(null);
1244     return;
1245     }
1246    
1247     MidiInstrumentMap m = CC.getSamplerModel().getDefaultMidiInstrumentMap();
1248     if(m != null) {
1249     String s = i18n.getLabel("Channel.ttDefault", m.getName());
1250     cbInstrumentMap.setToolTipText(s);
1251     } else {
1252     cbInstrumentMap.setToolTipText(null);
1253     }
1254     }
1255    
1256 iliev 787 /**
1257     * Updates the channel settings. This method is invoked when changes to the
1258     * channel were made.
1259     */
1260     private void
1261     updateChannelProperties() {
1262     SamplerModel sm = CC.getSamplerModel();
1263     SamplerChannel sc = getModel().getChannelInfo();
1264    
1265 iliev 1204 MidiDeviceModel mm = sm.getMidiDeviceById(sc.getMidiInputDevice());
1266     AudioDeviceModel am = sm.getAudioDeviceById(sc.getAudioOutputDevice());
1267 iliev 787
1268     if(isUpdate()) CC.getLogger().warning("Unexpected update state!");
1269    
1270     setUpdate(true);
1271    
1272     try {
1273     cbMidiDevice.setSelectedItem(mm == null ? null : mm.getDeviceInfo());
1274    
1275     cbEngines.setSelectedItem(sc.getEngine());
1276    
1277     cbAudioDevice.setSelectedItem(am == null ? null : am.getDeviceInfo());
1278 iliev 1285 btnAudioProps.setEnabled(am != null);
1279 iliev 787 } catch(Exception x) {
1280     CC.getLogger().log(Level.WARNING, "Unkown error", x);
1281     }
1282    
1283 iliev 1143 if(sc.getEngine() != null) {
1284 iliev 1285 cbInstrumentMap.setEnabled(true);
1285     int id = sc.getMidiInstrumentMapId();
1286     Object o;
1287     if(id == -2) o = defaultMap;
1288     else if(id == -1) o = noMap;
1289     else o = CC.getSamplerModel().getMidiInstrumentMapById(id);
1290    
1291     if(cbInstrumentMap.getSelectedItem() != o) {
1292     cbInstrumentMap.setSelectedItem(o);
1293     }
1294 iliev 1143 } else {
1295     cbInstrumentMap.setSelectedItem(noMap);
1296     cbInstrumentMap.setEnabled(false);
1297     }
1298    
1299 iliev 787 setUpdate(false);
1300     }
1301    
1302     /**
1303     * Updates the MIDI device list.
1304     */
1305     private void
1306     updateMidiDevices() {
1307     SamplerModel sm = CC.getSamplerModel();
1308     SamplerChannel sc = getModel().getChannelInfo();
1309    
1310     setUpdate(true);
1311    
1312     try {
1313     cbMidiDevice.removeAllItems();
1314    
1315 iliev 1204 for(MidiDeviceModel m : sm.getMidiDevices())
1316 iliev 787 cbMidiDevice.addItem(m.getDeviceInfo());
1317    
1318 iliev 1204 MidiDeviceModel mm = sm.getMidiDeviceById(sc.getMidiInputDevice());
1319 iliev 787 cbMidiDevice.setSelectedItem(mm == null ? null : mm.getDeviceInfo());
1320     } catch(Exception x) {
1321     CC.getLogger().log(Level.WARNING, "Unkown error", x);
1322     }
1323    
1324     setUpdate(false);
1325     }
1326    
1327     /**
1328     * Updates the audio device list.
1329     */
1330     private void
1331     updateAudioDevices() {
1332     SamplerModel sm = CC.getSamplerModel();
1333     SamplerChannel sc = getModel().getChannelInfo();
1334    
1335     setUpdate(true);
1336    
1337     try {
1338     cbAudioDevice.removeAllItems();
1339    
1340 iliev 1204 for(AudioDeviceModel m : sm.getAudioDevices())
1341 iliev 787 cbAudioDevice.addItem(m.getDeviceInfo());
1342    
1343 iliev 1204 AudioDeviceModel am = sm.getAudioDeviceById(sc.getAudioOutputDevice());
1344 iliev 787 cbAudioDevice.setSelectedItem(am == null ? null : am.getDeviceInfo());
1345     } catch(Exception x) {
1346     CC.getLogger().log(Level.WARNING, "Unkown error", x);
1347     }
1348    
1349     setUpdate(false);
1350     }
1351    
1352     private void
1353     setMidiDevice() {
1354     MidiInputDevice mid = (MidiInputDevice)cbMidiDevice.getSelectedItem();
1355    
1356     if(!isUpdate()) {
1357 iliev 1143 if(mid != null) getModel().setBackendMidiInputDevice(mid.getDeviceId());
1358 iliev 787 return;
1359     }
1360    
1361 iliev 1285 if(midiDevice != null) midiDevice.removeMidiDeviceListener(getHandler());
1362    
1363 iliev 787 cbMidiPort.removeAllItems();
1364    
1365     if(mid == null) {
1366 iliev 1285 midiDevice = null;
1367 iliev 787 cbMidiPort.setEnabled(false);
1368    
1369     cbMidiChannel.setSelectedItem(null);
1370     cbMidiChannel.setEnabled(false);
1371     } else {
1372 iliev 1285 midiDevice = CC.getSamplerModel().getMidiDeviceById(mid.getDeviceId());
1373     if(midiDevice != null) midiDevice.addMidiDeviceListener(getHandler());
1374    
1375 iliev 787 cbMidiPort.setEnabled(true);
1376    
1377     MidiPort[] ports = mid.getMidiPorts();
1378     for(MidiPort port : ports) cbMidiPort.addItem(port);
1379    
1380     int p = getModel().getChannelInfo().getMidiInputPort();
1381     cbMidiPort.setSelectedItem(p >= 0 && p < ports.length ? ports[p] : null);
1382    
1383     cbMidiChannel.setEnabled(true);
1384     int c = getModel().getChannelInfo().getMidiInputChannel();
1385     cbMidiChannel.setSelectedItem(c == -1 ? "All" : String.valueOf(c + 1));
1386     }
1387    
1388    
1389     }
1390    
1391     private void
1392     setMidiPort() {
1393     if(isUpdate()) return;
1394    
1395 iliev 1143 getModel().setBackendMidiInputPort(cbMidiPort.getSelectedIndex());
1396 iliev 787 }
1397    
1398     private void
1399     setMidiChannel() {
1400     if(isUpdate()) return;
1401    
1402     Object o = cbMidiChannel.getSelectedItem();
1403     if(o == null) return;
1404    
1405     int c = o.toString().equals("All") ? -1 : Integer.parseInt(o.toString()) - 1;
1406    
1407 iliev 1143 getModel().setBackendMidiInputChannel(c);
1408 iliev 787 }
1409    
1410     /** Invoked when the user selects an engine. */
1411     private void
1412     setEngineType() {
1413     Object oldEngine = getModel().getChannelInfo().getEngine();
1414     SamplerEngine newEngine = (SamplerEngine)cbEngines.getSelectedItem();
1415    
1416     if(oldEngine != null) { if(oldEngine.equals(newEngine)) return; }
1417     else if(newEngine == null) return;
1418    
1419 iliev 1143 getModel().setBackendEngineType(newEngine.getName());
1420 iliev 787
1421     }
1422    
1423     private void
1424     setAudioDevice() {
1425     if(isUpdate()) return;
1426     AudioOutputDevice dev = (AudioOutputDevice)cbAudioDevice.getSelectedItem();
1427 iliev 1143 if(dev != null) getModel().setBackendAudioOutputDevice(dev.getDeviceId());
1428 iliev 787 }
1429    
1430     /**
1431     * Determines whether the currently processed changes are due to update.
1432     * @return <code>true</code> if the currently processed changes are due to update and
1433     * <code>false</code> if the currently processed changes are due to user input.
1434     */
1435     private boolean
1436     isUpdate() { return update; }
1437    
1438     /**
1439     * Sets whether the currently processed changes are due to update.
1440     * @param b Specify <code>true</code> to indicate that the currently
1441     * processed changes are due to update; <code>false</code>
1442     * indicates that the currently processed changes are due to user input.
1443     */
1444     private void
1445     setUpdate(boolean b) { update = b; }
1446    
1447     private final Handler handler = new Handler();
1448    
1449     private Handler
1450     getHandler() { return handler; }
1451    
1452 iliev 1285 private class Handler implements MidiDeviceListListener, ListListener<AudioDeviceModel>,
1453     SamplerChannelListListener, MidiDeviceListener {
1454 iliev 911
1455 iliev 787 /**
1456     * Invoked when a new MIDI device is created.
1457     * @param e A <code>MidiDeviceListEvent</code>
1458     * instance providing the event information.
1459     */
1460     public void
1461     deviceAdded(MidiDeviceListEvent e) {
1462     cbMidiDevice.addItem(e.getMidiDeviceModel().getDeviceInfo());
1463     }
1464    
1465     /**
1466     * Invoked when a MIDI device is removed.
1467     * @param e A <code>MidiDeviceListEvent</code>
1468     * instance providing the event information.
1469     */
1470     public void
1471     deviceRemoved(MidiDeviceListEvent e) {
1472     cbMidiDevice.removeItem(e.getMidiDeviceModel().getDeviceInfo());
1473     }
1474    
1475     /**
1476     * Invoked when a new audio device is created.
1477     * @param e An <code>AudioDeviceListEvent</code>
1478     * instance providing the event information.
1479     */
1480     public void
1481 iliev 1143 entryAdded(ListEvent<AudioDeviceModel> e) {
1482     cbAudioDevice.addItem(e.getEntry().getDeviceInfo());
1483 iliev 787 }
1484    
1485     /**
1486     * Invoked when an audio device is removed.
1487     * @param e An <code>AudioDeviceListEvent</code>
1488     * instance providing the event information.
1489     */
1490     public void
1491 iliev 1143 entryRemoved(ListEvent<AudioDeviceModel> e) {
1492     cbAudioDevice.removeItem(e.getEntry().getDeviceInfo());
1493 iliev 787 }
1494 iliev 911
1495     /**
1496     * Invoked when a new sampler channel is created.
1497     * @param e A <code>SamplerChannelListEvent</code>
1498     * instance providing the event information.
1499     */
1500     public void
1501     channelAdded(SamplerChannelListEvent e) { }
1502    
1503     /**
1504     * Invoked when a sampler channel is removed.
1505     * @param e A <code>SamplerChannelListEvent</code>
1506     * instance providing the event information.
1507     */
1508     public void
1509     channelRemoved(SamplerChannelListEvent e) {
1510     // Some cleanup when the channel is removed.
1511 iliev 1143 if(e.getChannelModel().getChannelId() == channelModel.getChannelId()) {
1512 iliev 1285 SamplerModel sm = CC.getSamplerModel();
1513    
1514     sm.removeMidiDeviceListListener(getHandler());
1515     sm.removeAudioDeviceListListener(getHandler());
1516     sm.removeMidiInstrumentMapListListener(mapListListener);
1517     sm.removeSamplerListener(samplerListener);
1518     sm.removeSamplerChannelListListener(getHandler());
1519    
1520     if(midiDevice != null) {
1521     midiDevice.removeMidiDeviceListener(getHandler());
1522     }
1523 iliev 911 }
1524     }
1525 iliev 1285
1526     public void
1527     settingsChanged(MidiDeviceEvent e) {
1528     if(isUpdate()) {
1529     CC.getLogger().warning("Invalid update state");
1530     return;
1531     }
1532    
1533     setUpdate(true);
1534     int idx = cbMidiPort.getSelectedIndex();
1535     MidiInputDevice d = e.getMidiDeviceModel().getDeviceInfo();
1536    
1537     cbMidiPort.removeAllItems();
1538     for(MidiPort port : d.getMidiPorts()) cbMidiPort.addItem(port);
1539    
1540     if(idx >= cbMidiPort.getModel().getSize()) idx = 0;
1541    
1542     setUpdate(false);
1543    
1544     if(cbMidiPort.getModel().getSize() > 0) cbMidiPort.setSelectedIndex(idx);
1545     }
1546 iliev 787 }
1547 iliev 1143
1548     private class MapListListener implements ListListener<MidiInstrumentMap> {
1549     /** Invoked when a new MIDI instrument map is added to a list. */
1550     public void
1551     entryAdded(ListEvent<MidiInstrumentMap> e) {
1552     cbInstrumentMap.insertItemAt(e.getEntry(), cbInstrumentMap.getItemCount());
1553     boolean b = getModel().getChannelInfo().getEngine() != null;
1554     if(b && !cbInstrumentMap.isEnabled()) cbInstrumentMap.setEnabled(true);
1555     }
1556    
1557     /** Invoked when a new MIDI instrument map is removed from a list. */
1558     public void
1559     entryRemoved(ListEvent<MidiInstrumentMap> e) {
1560     cbInstrumentMap.removeItem(e.getEntry());
1561     if(cbInstrumentMap.getItemCount() == 0) {
1562     cbInstrumentMap.setSelectedItem(noMap);
1563     cbInstrumentMap.setEnabled(false);
1564     }
1565     }
1566     }
1567 iliev 787 }

  ViewVC Help
Powered by ViewVC