/[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 2288 - (hide annotations) (download)
Wed Nov 23 21:19:44 2011 UTC (12 years, 5 months ago) by iliev
File size: 48269 byte(s)
* Added option to select a sampler engine in Add/Edit Instrument dialog
* Moved all Swing dependent code outside the JSampler core

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

  ViewVC Help
Powered by ViewVC