/[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 1357 - (hide annotations) (download)
Sat Sep 22 17:27:06 2007 UTC (16 years, 7 months ago) by iliev
File size: 47092 byte(s)
* Added options for setting the maximum master and channel volume
  (choose Edit/Preferences)
* Fantasia: Edit instrument button is now shown on the channel
  screen only when there is loaded instrument on that channel
* Fantasia: Added options for showing additional device parameters in
  audio/MIDI device panes (Edit/Preferences, then click the `View' tab)
* Fantasia: Master volume is now fully implemented

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

  ViewVC Help
Powered by ViewVC