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

Diff of /jsampler/trunk/src/org/jsampler/view/fantasia/Channel.java

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1545 by iliev, Tue Dec 4 18:28:29 2007 UTC revision 1975 by iliev, Mon Aug 3 14:54:18 2009 UTC
# Line 1  Line 1 
1  /*  /*
2   *   JSampler - a java front-end for LinuxSampler   *   JSampler - a java front-end for LinuxSampler
3   *   *
4   *   Copyright (C) 2005-2007 Grigor Iliev <grigor@grigoriliev.com>   *   Copyright (C) 2005-2008 Grigor Iliev <grigor@grigoriliev.com>
5   *   *
6   *   This file is part of JSampler.   *   This file is part of JSampler.
7   *   *
# Line 24  package org.jsampler.view.fantasia; Line 24  package org.jsampler.view.fantasia;
24    
25  import java.awt.Container;  import java.awt.Container;
26  import java.awt.Dimension;  import java.awt.Dimension;
 import java.awt.Graphics;  
 import java.awt.Graphics2D;  
 import java.awt.Insets;  
27  import java.awt.Rectangle;  import java.awt.Rectangle;
28    
29  import java.awt.event.ActionEvent;  import java.awt.event.ActionEvent;
30  import java.awt.event.ActionListener;  import java.awt.event.ActionListener;
 import java.awt.event.HierarchyEvent;  
 import java.awt.event.HierarchyListener;  
31  import java.awt.event.MouseAdapter;  import java.awt.event.MouseAdapter;
32  import java.awt.event.MouseEvent;  import java.awt.event.MouseEvent;
33    
# Line 41  import java.beans.PropertyChangeListener Line 36  import java.beans.PropertyChangeListener
36    
37  import java.text.NumberFormat;  import java.text.NumberFormat;
38    
39  import java.util.logging.Level;  import javax.swing.AbstractAction;
   
40  import javax.swing.Action;  import javax.swing.Action;
 import javax.swing.BorderFactory;  
 import javax.swing.Box;  
41  import javax.swing.BoxLayout;  import javax.swing.BoxLayout;
42  import javax.swing.DefaultListCellRenderer;  import javax.swing.ImageIcon;
43  import javax.swing.JButton;  import javax.swing.JButton;
 import javax.swing.JComboBox;  
44  import javax.swing.JComponent;  import javax.swing.JComponent;
45  import javax.swing.JLabel;  import javax.swing.JLabel;
46  import javax.swing.JMenuItem;  import javax.swing.JMenuItem;
47  import javax.swing.JPanel;  import javax.swing.JPanel;
48  import javax.swing.JPopupMenu;  import javax.swing.JPopupMenu;
49  import javax.swing.JScrollPane;  import javax.swing.JScrollPane;
 import javax.swing.JToggleButton;  
50  import javax.swing.JToolBar;  import javax.swing.JToolBar;
 import javax.swing.SwingConstants;  
 import javax.swing.Timer;  
   
 import javax.swing.event.ChangeEvent;  
 import javax.swing.event.ChangeListener;  
   
 import net.sf.juife.Dial;  
 import net.sf.juife.InformationDialog;  
 import net.sf.juife.JuifeUtils;  
 import net.sf.juife.TitleBar;  
51    
52  import org.jdesktop.swingx.JXCollapsiblePane;  import org.jdesktop.swingx.JXCollapsiblePane;
53    
 import org.jsampler.AudioDeviceModel;  
54  import org.jsampler.CC;  import org.jsampler.CC;
55  import org.jsampler.HF;  import org.jsampler.HF;
 import org.jsampler.MidiDeviceModel;  
 import org.jsampler.MidiInstrumentMap;  
56  import org.jsampler.SamplerChannelModel;  import org.jsampler.SamplerChannelModel;
 import org.jsampler.SamplerModel;  
57    
 import org.jsampler.event.ListEvent;  
 import org.jsampler.event.ListListener;  
 import org.jsampler.event.MidiDeviceEvent;  
 import org.jsampler.event.MidiDeviceListEvent;  
 import org.jsampler.event.MidiDeviceListListener;  
 import org.jsampler.event.MidiDeviceListener;  
 import org.jsampler.event.SamplerAdapter;  
 import org.jsampler.event.SamplerChannelAdapter;  
58  import org.jsampler.event.SamplerChannelEvent;  import org.jsampler.event.SamplerChannelEvent;
59  import org.jsampler.event.SamplerChannelListEvent;  import org.jsampler.event.SamplerChannelListEvent;
60  import org.jsampler.event.SamplerChannelListListener;  import org.jsampler.event.SamplerChannelListListener;
61  import org.jsampler.event.SamplerChannelListener;  import org.jsampler.event.SamplerChannelListener;
62  import org.jsampler.event.SamplerEvent;  
63  import org.jsampler.event.SamplerListener;  import org.jsampler.view.JSChannel;
64    import org.jsampler.view.JSChannelsPane;
65    
66    import org.jsampler.view.fantasia.basic.PixmapToggleButton;
67    
68  import org.jsampler.view.std.JSChannelOutputRoutingDlg;  import org.jsampler.view.std.JSChannelOutputRoutingDlg;
69    import org.jsampler.view.std.JSFxSendsDlg;
70  import org.jsampler.view.std.JSFxSendsPane;  import org.jsampler.view.std.JSFxSendsPane;
71  import org.jsampler.view.std.JSInstrumentChooser;  import org.jsampler.view.std.JSInstrumentChooser;
72  import org.jsampler.view.std.JSVolumeEditorPopup;  import org.jsampler.view.std.JSVolumeEditorPopup;
73    
 import org.jvnet.substance.SubstanceImageCreator;  
   
 import org.linuxsampler.lscp.AudioOutputDevice;  
 import org.linuxsampler.lscp.MidiInputDevice;  
 import org.linuxsampler.lscp.MidiPort;  
74  import org.linuxsampler.lscp.SamplerChannel;  import org.linuxsampler.lscp.SamplerChannel;
 import org.linuxsampler.lscp.SamplerEngine;  
75    
76    import static org.jsampler.view.fantasia.A4n.a4n;
77  import static org.jsampler.view.fantasia.FantasiaI18n.i18n;  import static org.jsampler.view.fantasia.FantasiaI18n.i18n;
78  import static org.jsampler.view.fantasia.FantasiaPrefs.*;  import static org.jsampler.view.fantasia.FantasiaPrefs.*;
79  import static org.jsampler.view.fantasia.FantasiaUtils.*;  import static org.jsampler.view.fantasia.FantasiaUtils.*;
# Line 117  import static org.jsampler.view.std.JSVo Line 84  import static org.jsampler.view.std.JSVo
84   *   *
85   * @author Grigor Iliev   * @author Grigor Iliev
86   */   */
87  public class Channel extends org.jsampler.view.JSChannel {  public class Channel extends JSChannel {
88          private final JXCollapsiblePane mainPane;          private final JXCollapsiblePane mainPane;
89          private final ChannelScreen screen = new ChannelScreen(this);          private final ChannelOptionsPane optionsPane = new ChannelOptionsPane();
90          private final ChannelOptions optionsPane = new ChannelOptions(this);          
91            private final ViewTracker viewTracker;
92                    
93          private final PowerButton btnPower = new PowerButton();          private JSFxSendsDlg fxSendsDlg = null;
         private final MuteButton btnMute = new MuteButton();  
         private final SoloButton btnSolo = new SoloButton();  
         private final OptionsButton btnOptions = new OptionsButton();  
94                    
95          private final EnhancedDial dialVolume = new EnhancedDial();          private final ContextMenu contextMenu;
96                    
97          private boolean selected = false;          private boolean selected = false;
98                    
99            private AnimatedPorpetyListener animatedPorpetyListener = new AnimatedPorpetyListener();
100            
101            class AnimatedPorpetyListener implements PropertyChangeListener {
102                    public void
103                    propertyChange(PropertyChangeEvent e) {
104                            mainPane.setAnimated(preferences().getBoolProperty(ANIMATED));
105                    }
106            }
107            
108            ////////////////////////////////
109            // ******* Mouse tracker *******
110            ////////////////////////////////
111            private static int mouseOverChannelId = -1;
112            private static boolean mousePressed = false;
113            
114            private static ActionListener guiListener = null;
115            
116            private static Channel oldMouseOverChannel = null;
117            private static Channel newMouseOverChannel = null;
118            
119            
120            private static void
121            mouseMoved() {
122                    JSChannelsPane cp = CC.getMainFrame().getSelectedChannelsPane();
123                    for(int i = 0; i < cp.getChannelCount(); i++) {
124                            mouseMoved((Channel)cp.getChannel(i));
125                    }
126                    
127                    if(oldMouseOverChannel == newMouseOverChannel) return;
128                    
129                    if(oldMouseOverChannel != null) oldMouseOverChannel.mouseExited();
130                    
131                    if(newMouseOverChannel != null) {
132                            mouseOverChannelId = newMouseOverChannel.getChannelId();
133                            newMouseOverChannel.mouseEntered();
134                    }
135                    
136                    oldMouseOverChannel = newMouseOverChannel = null;
137            }
138            
139            private static void
140            mouseMoved(Channel c) {
141                    int id = c.getChannelId();
142                    if(c.mainPane.getMousePosition(true) != null) {
143                            newMouseOverChannel = c;
144                    } else if(id == mouseOverChannelId) {
145                            oldMouseOverChannel = c;
146                    }
147            }
148            
149            ////////////////////////////////
150            
151            
152          /**          /**
153           * Creates a new instance of <code>Channel</code> using the specified           * Creates a new instance of <code>Channel</code> using the specified
154           * non-<code>null</code> channel model.           * non-<code>null</code> channel model.
# Line 152  public class Channel extends org.jsample Line 170  public class Channel extends org.jsample
170           */           */
171          public          public
172          Channel(SamplerChannelModel model, final ActionListener listener) {          Channel(SamplerChannelModel model, final ActionListener listener) {
173                    this (
174                            model, listener,
175                            preferences().getIntProperty(DEFAULT_CHANNEL_VIEW) == 0 ?
176                                    ChannelView.Type.SMALL : ChannelView.Type.NORMAL
177                    );
178            }
179            
180            /**
181             * Creates a new instance of <code>Channel</code> using the specified
182             * non-<code>null</code> channel model.
183             * @param model The model to be used by this channel.
184             * @param listener A listener which is notified when the newly created
185             * channel is fully expanded on the screen.
186             * @param type Specifies the view type to be used.
187             * @throws IllegalArgumentException If the model is <code>null</code>.
188             */
189            public
190            Channel(SamplerChannelModel model, final ActionListener listener, ChannelView.Type type) {
191                  super(model);                  super(model);
192                                    
193                  setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));                  setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
                 ChannelPane p = new ChannelPane();  
                 p.setLayout(new BoxLayout(p, BoxLayout.X_AXIS));  
                   
                 //p.add(Box.createRigidArea(new Dimension(3, 0)));  
                   
                 btnPower.setAlignmentY(JPanel.TOP_ALIGNMENT);  
                   
                 JPanel tb = new JPanel();  
                 tb.setBorder(BorderFactory.createEmptyBorder(3, 3, 0, 4));  
                 tb.setLayout(new BoxLayout(tb, BoxLayout.X_AXIS));  
                 tb.setOpaque(false);  
                 tb.setAlignmentY(JPanel.TOP_ALIGNMENT);  
                 tb.add(btnPower);  
                 tb.setPreferredSize(new Dimension(tb.getPreferredSize().width, 58));  
                 tb.setMinimumSize(tb.getPreferredSize());  
                 tb.setMaximumSize(tb.getPreferredSize());  
                 p.add(tb);  
                   
                 //p.add(Box.createRigidArea(new Dimension(4, 0)));  
                   
                 p.add(createVSeparator());  
                   
                 //p.add(Box.createRigidArea(new Dimension(3, 0)));  
                   
                 JPanel p2 = new JPanel();  
                 p2.setOpaque(false);  
                 p2.setLayout(new BoxLayout(p2, BoxLayout.Y_AXIS));  
                 p2.setAlignmentY(JPanel.TOP_ALIGNMENT);  
                 p2.setBorder(BorderFactory.createEmptyBorder(5, 3, 0, 2));  
                 p2.add(screen);  
                 p.add(p2);  
                   
                 p.add(createVSeparator());  
                   
                 p2 = new JPanel();  
                 p2.setOpaque(false);  
                 p2.setLayout(new BoxLayout(p2, BoxLayout.Y_AXIS));  
                 p2.setAlignmentY(JPanel.TOP_ALIGNMENT);  
                 p2.setBorder(BorderFactory.createEmptyBorder(4, 0, 0, 0));  
                 p2.add(new JLabel(Res.gfxMuteTitle));  
                 p2.add(btnMute);  
                 p2.add(new JLabel(Res.gfxSoloTitle));  
                 p2.add(btnSolo);  
                   
                 p.add(p2);  
                   
                 p.add(createVSeparator());  
                   
                 p2 = new JPanel();  
                 p2.setOpaque(false);  
                 p2.setLayout(new BoxLayout(p2, BoxLayout.Y_AXIS));  
                 p2.setAlignmentY(JPanel.TOP_ALIGNMENT);  
                 p2.setBorder(BorderFactory.createEmptyBorder(4, 0, 0, 0));  
                 JLabel l = new JLabel(Res.gfxVolumeTitle);  
                 l.setAlignmentX(JPanel.CENTER_ALIGNMENT);  
                 l.setBorder(BorderFactory.createEmptyBorder(0, 0, 2, 0));  
                 p2.add(l);  
                 dialVolume.setDialPixmap(Res.gfxVolumeDial, 30, 330);  
                 dialVolume.setAlignmentX(JPanel.CENTER_ALIGNMENT);  
                 p2.add(dialVolume);  
                 p.add(p2);  
                   
                 p.add(createVSeparator());  
                   
                 p2 = new JPanel();  
                 p2.setOpaque(false);  
                 p2.setLayout(new BoxLayout(p2, BoxLayout.Y_AXIS));  
                 p2.setAlignmentY(JPanel.TOP_ALIGNMENT);  
                 p2.setBorder(BorderFactory.createEmptyBorder(27, 0, 0, 0));  
                 l = new JLabel(Res.gfxOptionsTitle);  
                 l.setAlignmentX(JPanel.CENTER_ALIGNMENT);  
                 l.setBorder(BorderFactory.createEmptyBorder(0, 0, 2, 0));  
                 p2.add(l);  
                   
                 p2.add(Box.createRigidArea(new Dimension(0, 3)));  
                   
                 btnOptions.setAlignmentX(JPanel.CENTER_ALIGNMENT);  
                 p2.add(btnOptions);  
                 p.add(p2);  
                   
                   
                 p.setPreferredSize(new Dimension(420, 60));  
                 p.setMinimumSize(p.getPreferredSize());  
                 p.setMaximumSize(p.getPreferredSize());  
                 //p.setBorder(BorderFactory.createEmptyBorder(1, 0, 1, 0));  
   
                 p.setAlignmentX(JPanel.CENTER_ALIGNMENT);  
194                  optionsPane.setAlignmentX(JPanel.CENTER_ALIGNMENT);                  optionsPane.setAlignmentX(JPanel.CENTER_ALIGNMENT);
195                                    
196                  mainPane = new JXCollapsiblePane();                  mainPane = new JXCollapsiblePane();
197                    viewTracker = new ViewTracker();
198                    contextMenu = new ContextMenu();
199                    
200                  mainPane.getContentPane().setLayout (                  mainPane.getContentPane().setLayout (
201                          new BoxLayout(mainPane.getContentPane(), BoxLayout.Y_AXIS)                          new BoxLayout(mainPane.getContentPane(), BoxLayout.Y_AXIS)
202                  );                  );
203                                    
204                  mainPane.add(p);                  switch(type) {
205                  mainPane.add(optionsPane);                          case SMALL: viewTracker.setView(new SmallChannelView(Channel.this)); break;
206                            case NORMAL: viewTracker.setView(new NormalChannelView(Channel.this)); break;
207                            default: viewTracker.setView(new NormalChannelView(Channel.this));
208                    }
209                                    
210                  setOpaque(false);                  setOpaque(false);
211                                    
                 String vmud = VOL_MEASUREMENT_UNIT_DECIBEL;  
                 preferences().addPropertyChangeListener(vmud, new PropertyChangeListener() {  
                         public void  
                         propertyChange(PropertyChangeEvent e) {  
                                 boolean b;  
                                 b = preferences().getBoolProperty(VOL_MEASUREMENT_UNIT_DECIBEL);  
                                 screen.updateVolumeInfo(dialVolume.getValue());  
                         }  
                 });  
                   
212                  getModel().addSamplerChannelListener(getHandler());                  getModel().addSamplerChannelListener(getHandler());
213                                    
214                  updateChannelInfo();                  updateChannelInfo();
# Line 293  public class Channel extends org.jsample Line 238  public class Channel extends org.jsample
238                  mainPane.setAnimated(preferences().getBoolProperty(ANIMATED));                  mainPane.setAnimated(preferences().getBoolProperty(ANIMATED));
239                  mainPane.setCollapsed(false);                  mainPane.setCollapsed(false);
240                                    
241                  preferences().addPropertyChangeListener(ANIMATED, new PropertyChangeListener() {                  preferences().addPropertyChangeListener(ANIMATED, animatedPorpetyListener);
                         public void  
                         propertyChange(PropertyChangeEvent e) {  
                                 mainPane.setAnimated(preferences().getBoolProperty(ANIMATED));  
                         }  
                 });  
242                                    
243                  if(listener != null) {                  if(listener != null) {
244                          javax.swing.SwingUtilities.invokeLater(new Runnable() {                          javax.swing.SwingUtilities.invokeLater(new Runnable() {
# Line 308  public class Channel extends org.jsample Line 248  public class Channel extends org.jsample
248                  }                  }
249                                    
250                  CC.getSamplerModel().addSamplerChannelListListener(getHandler());                  CC.getSamplerModel().addSamplerChannelListListener(getHandler());
251                    
252                    installGuiListener();
253            }
254            
255            private static void
256            installGuiListener() {
257                    if(guiListener != null) return;
258                    
259                    guiListener = new ActionListener() {
260                            public void
261                            actionPerformed(ActionEvent e) {
262                                    mouseMoved();
263                            }
264                    };
265                    
266                    ((MainFrame)CC.getMainFrame()).getGuiTimer().addActionListener(guiListener);
267            }
268            
269            private void
270            mouseEntered() {
271                    viewTracker.mouseEntered();
272            }
273            
274            private void
275            mouseExited() {
276                    viewTracker.mouseExited();
277          }          }
278                    
279          private void          private void
# Line 326  public class Channel extends org.jsample Line 292  public class Channel extends org.jsample
292                  sp.getViewport().scrollRectToVisible(new Rectangle(0, h - 2, 1, 1));                  sp.getViewport().scrollRectToVisible(new Rectangle(0, h - 2, 1, 1));
293          }          }
294                    
         private JPanel  
         createVSeparator() {  
                 PixmapPane p = new PixmapPane(Res.gfxVLine);  
                 p.setAlignmentY(JPanel.TOP_ALIGNMENT);  
                 p.setPreferredSize(new Dimension(2, 60));  
                 p.setMinimumSize(p.getPreferredSize());  
                 p.setMaximumSize(p.getPreferredSize());  
                 return p;  
         }  
           
295          /**          /**
296           * Determines whether the channel is selected.           * Determines whether the channel is selected.
297           * @return <code>true</code> if the channel is selected, <code>false</code> otherwise.           * @return <code>true</code> if the channel is selected, <code>false</code> otherwise.
298           */           */
299          public boolean isSelected() { return selected; }          @Override
300            public boolean
301            isSelected() { return selected; }
302                    
303          /**          /**
304           * Sets the selection state of this channel.           * Sets the selection state of this channel.
# Line 348  public class Channel extends org.jsample Line 306  public class Channel extends org.jsample
306           * @param select Specifies the new selection state of this channel;           * @param select Specifies the new selection state of this channel;
307           * <code>true</code> to select the channel, <code>false</code> otherwise.           * <code>true</code> to select the channel, <code>false</code> otherwise.
308           */           */
309            @Override
310          public void          public void
311          setSelected(boolean select) {          setSelected(boolean select) {
312                                    if(selected == select) return;
313                  selected = select;                  selected = select;
314                    repaint();
315          }          }
316                    
317          /** Shows the channel properties. */          /** Shows the channel properties. */
# Line 361  public class Channel extends org.jsample Line 321  public class Channel extends org.jsample
321          /** Shows the channel properties. */          /** Shows the channel properties. */
322          public void          public void
323          expandChannel(boolean animated) {          expandChannel(boolean animated) {
                 if(btnOptions.isSelected()) return;  
                   
324                  boolean b = optionsPane.isAnimated();                  boolean b = optionsPane.isAnimated();
325                  optionsPane.setAnimated(animated);                  optionsPane.setAnimated(animated);
326                  btnOptions.doClick();                  viewTracker.getCurrentView().expandChannel();
327                  optionsPane.setAnimated(b);                  optionsPane.setAnimated(b);
328          }          }
329                    
           
         /** Invoked when the user changes the volume */  
         private void  
         setVolume() {  
                 screen.updateVolumeInfo(dialVolume.getValue());  
                   
                 if(dialVolume.getValueIsAdjusting()) return;  
                   
                 int vol = (int)(getChannelInfo().getVolume() * 100);  
                   
                 if(vol == dialVolume.getValue()) return;  
                   
                 /*  
                  * If the model's volume is not equal to the dial knob  
                  * value we assume that the change is due to user input.  
                  * So we must update the volume at the backend too.  
                  */  
                 float volume = dialVolume.getValue();  
                 volume /= 100;  
                 getModel().setBackendVolume(volume);  
         }  
           
330          /**          /**
331           * Updates the channel settings. This method is invoked when changes to the           * Updates the channel settings. This method is invoked when changes to the
332           * channel were made.           * channel were made.
333           */           */
334          private void          private void
335          updateChannelInfo() {          updateChannelInfo() {
336                  SamplerChannel sc = getChannelInfo();                  viewTracker.getCurrentView().updateChannelInfo();
                   
                 screen.updateScreenInfo(sc);  
                 updateMuteIcon(sc);  
                   
                 if(sc.isSoloChannel()) btnSolo.setIcon(Res.gfxSoloOn);  
                 else btnSolo.setIcon(Res.gfxSoloOff);  
                 dialVolume.setValue((int)(sc.getVolume() * 100));  
                   
                 boolean b = sc.getEngine() != null;  
                 dialVolume.setEnabled(b);  
                 btnSolo.setEnabled(b);  
                 btnMute.setEnabled(b);  
337          }          }
338                    
339          /**          public void
340           * Updates the mute button with the proper icon regarding to information obtained          loadInstrument() {
341           * from <code>channel</code>.                  JSInstrumentChooser dlg = FantasiaUtils.createInstrumentChooser(CC.getMainFrame());
342           * @param channel A <code>SamplerChannel</code> instance containing the new settings                  dlg.setVisible(true);
343           * for this channel.                  
344           */                  if(!dlg.isCancelled()) {
345          private void                          SamplerChannelModel m = getModel();
346          updateMuteIcon(SamplerChannel channel) {                          m.loadBackendInstrument(dlg.getInstrumentFile(), dlg.getInstrumentIndex());
                 if(channel.isMutedBySolo()) btnMute.setIcon(Res.gfxMutedBySolo);  
                 else if(channel.isMuted()) btnMute.setIcon(Res.gfxMuteOn);  
                 else btnMute.setIcon(Res.gfxMuteOff);  
         }  
           
         private class EnhancedDial extends Dial {  
                 EnhancedDial() {  
                         super(0, 100, 0);  
                           
                         setMouseHandlerMode(MouseHandlerMode.LEFT_TO_RIGHT_AND_DOWN_TO_UP);  
                           
                         int i = preferences().getIntProperty(MAXIMUM_CHANNEL_VOLUME);  
                         setMaximum(i);  
                         String mcv = MAXIMUM_CHANNEL_VOLUME;  
                         preferences().addPropertyChangeListener(mcv, new PropertyChangeListener() {  
                                 public void  
                                 propertyChange(PropertyChangeEvent e) {  
                                         int j = preferences().getIntProperty(MAXIMUM_CHANNEL_VOLUME);  
                                         setMaximum(j);  
                                 }  
                         });  
                           
                         addMouseListener(new MouseAdapter() {  
                                 public void  
                                 mouseClicked(MouseEvent e) {  
                                         if(e.getButton() == e.BUTTON3) {  
                                                 setValue(getMaximum() / 2);  
                                                 return;  
                                         }  
                                           
                                         if(e.getButton() != e.BUTTON1) return;  
                                           
                                         if(e.getClickCount() < 2) return;  
                                         setValue(getValueByPoint(e.getPoint()));  
                                 }  
                         });  
                           
                         addChangeListener(new ChangeListener() {  
                                 public void  
                                 stateChanged(ChangeEvent e) { setVolume(); }  
                         });  
347                  }                  }
348          }          }
349                    
350            public void
351            fallbackToOriginalView() {
352                    viewTracker.fallbackToOriginalView();
353            }
354            
355            public boolean
356            isUsingOriginalView() {
357                    return viewTracker.isUsingOriginalView();
358            }
359            
360          protected void          protected void
361          onDestroy() {          onDestroy() {
362                  CC.getSamplerModel().removeSamplerChannelListListener(getHandler());                  CC.getSamplerModel().removeSamplerChannelListListener(getHandler());
363                    preferences().removePropertyChangeListener(ANIMATED, animatedPorpetyListener);
364                    if(fxSendsDlg != null) fxSendsDlg.dispose();
365                    viewTracker.onDestroy();
366            }
367                    
368            public void
369            remove() {
370                    if(!mainPane.isAnimated()) {
371                            CC.getSamplerModel().removeBackendChannel(getChannelId());
372                            return;
373                    }
374                    
375                    String s = JXCollapsiblePane.ANIMATION_STATE_KEY;
376                    mainPane.addPropertyChangeListener(s, getHandler());
377                    mainPane.setCollapsed(true);
378            }
379            
380            public void
381            showOptionsPane(boolean show) { optionsPane.showOptionsPane(show); }
382            
383            public void
384            showFxSendsDialog() {
385                    if(fxSendsDlg != null && fxSendsDlg.isVisible()) {
386                            fxSendsDlg.toFront();
387                            return;
388                    }
389                                    
390                  screen.onDestroy();                  fxSendsDlg = new JSFxSendsDlg(new FxSendsPane(getModel()));
391                  optionsPane.onDestroy();                  fxSendsDlg.setVisible(true);
392          }          }
393                    
394          private final EventHandler eventHandler = new EventHandler();          private final EventHandler eventHandler = new EventHandler();
# Line 477  public class Channel extends org.jsample Line 396  public class Channel extends org.jsample
396          private EventHandler          private EventHandler
397          getHandler() { return eventHandler; }          getHandler() { return eventHandler; }
398                    
399          private class EventHandler implements SamplerChannelListener, SamplerChannelListListener {          private class EventHandler implements SamplerChannelListener,
400                                            SamplerChannelListListener, PropertyChangeListener {
401                  /**                  /**
402                   * Invoked when changes are made to a sampler channel.                   * Invoked when changes are made to a sampler channel.
403                   * @param e A <code>SamplerChannelEvent</code> instance                   * @param e A <code>SamplerChannelEvent</code> instance
404                   * containing event information.                   * containing event information.
405                   */                   */
406                    @Override
407                  public void                  public void
408                  channelChanged(SamplerChannelEvent e) { updateChannelInfo(); }                  channelChanged(SamplerChannelEvent e) { updateChannelInfo(); }
409                    
# Line 491  public class Channel extends org.jsample Line 412  public class Channel extends org.jsample
412                   * @param e A <code>SamplerChannelEvent</code> instance                   * @param e A <code>SamplerChannelEvent</code> instance
413                   * containing event information.                   * containing event information.
414                   */                   */
415                    @Override
416                  public void                  public void
417                  streamCountChanged(SamplerChannelEvent e) {                  streamCountChanged(SamplerChannelEvent e) {
418                          screen.updateStreamCount(getModel().getStreamCount());                          viewTracker.getCurrentView().updateStreamCount(getModel().getStreamCount());
419                  }                  }
420                    
421                  /**                  /**
# Line 501  public class Channel extends org.jsample Line 423  public class Channel extends org.jsample
423                   * @param e A <code>SamplerChannelEvent</code> instance                   * @param e A <code>SamplerChannelEvent</code> instance
424                   * containing event information.                   * containing event information.
425                   */                   */
426                    @Override
427                  public void                  public void
428                  voiceCountChanged(SamplerChannelEvent e) {                  voiceCountChanged(SamplerChannelEvent e) {
429                          screen.updateVoiceCount(getModel().getVoiceCount());                          viewTracker.getCurrentView().updateVoiceCount(getModel().getVoiceCount());
430                  }                  }
431                                    
432                  /**                  /**
# Line 511  public class Channel extends org.jsample Line 434  public class Channel extends org.jsample
434                   * @param e A <code>SamplerChannelListEvent</code>                   * @param e A <code>SamplerChannelListEvent</code>
435                   * instance providing the event information.                   * instance providing the event information.
436                   */                   */
437                    @Override
438                  public void                  public void
439                  channelAdded(SamplerChannelListEvent e) { }                  channelAdded(SamplerChannelListEvent e) { }
440                    
# Line 519  public class Channel extends org.jsample Line 443  public class Channel extends org.jsample
443                   * @param e A <code>SamplerChannelListEvent</code>                   * @param e A <code>SamplerChannelListEvent</code>
444                   * instance providing the event information.                   * instance providing the event information.
445                   */                   */
446                    @Override
447                  public void                  public void
448                  channelRemoved(SamplerChannelListEvent e) {                  channelRemoved(SamplerChannelListEvent e) {
449                          // Some cleanup when the channel is removed.                          // Some cleanup when the channel is removed.
# Line 526  public class Channel extends org.jsample Line 451  public class Channel extends org.jsample
451                                  onDestroy();                                  onDestroy();
452                          }                          }
453                  }                  }
454                    
455                    @Override
456                    public void
457                    propertyChange(PropertyChangeEvent e) {
458                            if(e.getNewValue() == "collapsed") {
459                                    CC.getSamplerModel().removeBackendChannel(getChannelId());
460                            }
461                    }
462          }          }
463                    
464            public ViewTracker
465            getViewTracker() { return viewTracker; }
466                    
467          private class PowerButton extends PixmapToggleButton          class ViewTracker extends MouseAdapter implements PropertyChangeListener {
468                          implements ActionListener, PropertyChangeListener {                  private ChannelView originalView;
469                    private ChannelView mouseOverView;
470                    private ChannelView currentView;
471                                    
472                  PowerButton() {                  private ChannelView.Type mouseOverViewType = null;
                         super(Res.gfxPowerOff, Res.gfxPowerOn);  
473                                    
474                          setSelected(true);                  ViewTracker() {
                         addActionListener(this);  
                 }  
                   
                 public void  
                 actionPerformed(ActionEvent e) {  
                         if(!mainPane.isAnimated()) {  
                                 CC.getSamplerModel().removeBackendChannel(getChannelId());  
                                 return;  
                         }  
475                                                    
476                          String s = JXCollapsiblePane.ANIMATION_STATE_KEY;                          
477                          mainPane.addPropertyChangeListener(s, this);                          updateMouseOverViewType();
478                          mainPane.setCollapsed(true);                          
479                            String s = DIFFERENT_CHANNEL_VIEW_ON_MOUSE_OVER;
480                            preferences().addPropertyChangeListener(s, this);
481                            
482                            s = CHANNEL_VIEW_ON_MOUSE_OVER;
483                            preferences().addPropertyChangeListener(s, this);
484                  }                  }
485                                    
486                  public void                  public boolean
487                  propertyChange(PropertyChangeEvent e) {                  isUsingOriginalView() {
488                          if(e.getNewValue() == "collapsed") {                          return currentView == originalView;
                                 CC.getSamplerModel().removeBackendChannel(getChannelId());  
                         }  
489                  }                  }
490                                    
491                  public boolean                  private void
492                  contains(int x, int y) { return (x - 11)*(x - 11) + (y - 11)*(y - 11) < 71; }                  installListeners() {
493          }                          
           
         private class MuteButton extends PixmapButton implements ActionListener {  
                 MuteButton() {  
                         super(Res.gfxMuteOff);  
                         //setDisabledIcon(Res.gfxMuteSoloDisabled);  
                         setDisabledIcon (  
                                 SubstanceImageCreator.makeTransparent(this, Res.gfxMuteOff, 0.4)  
                         );  
                         addActionListener(this);  
494                  }                  }
495                                    
496                  public void                  private void
497                  actionPerformed(ActionEvent e) {                  uninstallListeners() {
498                          SamplerChannel sc = getChannelInfo();                          
499                          boolean b = true;                  }
500                                    
501                          /*                  private void
502                           * Changing the mute button icon now instead of                  updateMouseOverViewType() {
503                           * leaving the work to the notification mechanism of the LinuxSampler.                          if(mouseOverView != null) {
504                           */                                  mouseOverView.removeEnhancedMouseListener(this);
505                          if(sc.isMuted() && !sc.isMutedBySolo()) {                          }
506                                  b = false;                          
507                                  boolean hasSolo = CC.getSamplerModel().hasSoloChannel();                          mouseOverView = null;
508                                                    
509                                  if(sc.isSoloChannel() || !hasSolo) setIcon(Res.gfxMuteOff);                          boolean b;
510                                  else setIcon(Res.gfxMutedBySolo);                          b = preferences().getBoolProperty(DIFFERENT_CHANNEL_VIEW_ON_MOUSE_OVER);
511                          } else setIcon(Res.gfxMuteOn);                          if(!b) {
512                                    mouseOverViewType = null;
513                                    uninstallListeners();
514                                    return;
515                            }
516                                                    
517                          Channel.this.getModel().setBackendMute(b);                          int i = preferences().getIntProperty(CHANNEL_VIEW_ON_MOUSE_OVER);
518                            
519                            switch(i) {
520                                    case 0: mouseOverViewType = ChannelView.Type.SMALL; break;
521                                    case 1: mouseOverViewType = ChannelView.Type.NORMAL; break;
522                                    default:mouseOverViewType = null;
523                            }
524                            
525                            if(mouseOverViewType != null) {
526                                    installListeners();
527                            }
528                  }                  }
529                                    
530                  public boolean                  public ChannelView
531                  contains(int x, int y) { return (x > 5 && x < 23) && (y > 5 && y < 16); }                  getMouseOverView() {
532          }                          if(mouseOverViewType == null) return null;
533                                    
534          private class SoloButton extends PixmapButton implements ActionListener {                          if(mouseOverView == null) {
535                  SoloButton() {                                  Channel channel = Channel.this;
536                          super(Res.gfxSoloOff);                                  
537                          //setDisabledIcon(Res.gfxMuteSoloDisabled);                                  switch(mouseOverViewType) {
538                          setDisabledIcon (                                  case SMALL: mouseOverView = new SmallChannelView(channel); break;
539                                  SubstanceImageCreator.makeTransparent(this, Res.gfxSoloOff, 0.4)                                  case NORMAL: mouseOverView = new NormalChannelView(channel); break;
540                          );                                  default: mouseOverView = new NormalChannelView(channel);
541                          addActionListener(this);                                  }
542                                    
543                                    mouseOverView.addEnhancedMouseListener(this);
544                            }
545                            
546                            return mouseOverView;
547                  }                  }
548                                    
549                    public ChannelView
550                    getCurrentView() { return currentView; }
551                    
552                    public ChannelView
553                    getOriginalView() { return originalView; }
554                    
555                  public void                  public void
556                  actionPerformed(ActionEvent e) {                  setView(ChannelView view) {
557                          SamplerChannel sc = getChannelInfo();                          setView(view, true);
558                          boolean b = !sc.isSoloChannel();                  }
559                                    
560                          /*                  public void
561                           * Changing the solo button icon (and related) now instead of                  setView(ChannelView view, boolean manual) {
562                           * leaving the work to the notification mechanism of the LinuxSampler.                          boolean selected = false;
563                           */                          if(currentView != null) selected = currentView.isOptionsButtonSelected();
564                          if(b) {                          
565                                  setIcon(Res.gfxSoloOn);                          if(manual) {
566                                  if(sc.isMutedBySolo()) btnMute.setIcon(Res.gfxMuteOff);                                  if(originalView != null) {
567                                            originalView.removeEnhancedMouseListener(this);
568                                    }
569                                    
570                                    if(originalView != currentView) destroyOriginalView();
571                                    if(currentView != null && currentView.getType() == view.getType()) {
572                                            originalView = currentView;
573                                            originalView.addEnhancedMouseListener(this);
574                                            destroyView(view);
575                                            return;
576                                    }
577                                    
578                                    removeCurrentView();
579                                    
580                                    originalView = view;
581                                    originalView.addEnhancedMouseListener(this);
582                                    currentView = view;
583                          } else {                          } else {
584                                  setIcon(Res.gfxSoloOff);                                  if(view.getType() == getCurrentView().getType()) {
585                                  if(!sc.isMuted() && CC.getSamplerModel().getSoloChannelCount() > 1)                                          destroyView(view);
586                                          btnMute.setIcon(Res.gfxMutedBySolo);                                          return;
587                                    }
588                                    
589                                    removeCurrentView();
590                                    currentView = view;
591                          }                          }
592                                            
593                          Channel.this.getModel().setBackendSolo(b);                          currentView.setOptionsButtonSelected(selected);
594                            
595                            updateView();
596                  }                  }
597                                    
598                  public boolean                  private void
599                  contains(int x, int y) { return (x > 5 && x < 23) && (y > 5 && y < 16); }                  updateView() {
600          }                          ChannelOptionsView view = getCurrentView().getChannelOptionsView();
601                                    if(view != null) optionsPane.setContentPane(view.getComponent());
602          private class OptionsButton extends PixmapToggleButton implements ActionListener {                          
603                  OptionsButton() {                          updateChannelInfo();
604                          super(Res.gfxOptionsOff, Res.gfxOptionsOn);                  
605                          setRolloverIcon(Res.gfxOptionsOffRO);                          mainPane.add(getCurrentView().getComponent());
606                          this.setRolloverSelectedIcon(Res.gfxOptionsOnRO);                          mainPane.add(optionsPane);
607                          addActionListener(this);                          mainPane.validate();
608                            mainPane.revalidate();
609                            mainPane.repaint();
610                  }                  }
611                                    
612                  public void                  public void
613                  actionPerformed(ActionEvent e) {                  fallbackToOriginalView() {
614                          showOptionsPane(isSelected());                          if(currentView == originalView) return;
615                                                    
616                          String s;                          boolean selected = false;
617                          if(isSelected()) s = i18n.getButtonLabel("OptionsButton.ttHideOptions");                          if(currentView != null) selected = currentView.isOptionsButtonSelected();
                         else s = i18n.getButtonLabel("OptionsButton.ttShowOptions");  
618                                                    
619                          setToolTipText(s);                          removeCurrentView();
620                            currentView = originalView;
621                            currentView.setOptionsButtonSelected(selected);
622                            
623                            updateView();
624                  }                  }
625                                    
626                  private void                  private void
627                  showOptionsPane(boolean show) {                  removeCurrentView() { removeView(currentView); }
                         optionsPane.setCollapsed(!show);  
                 }  
628                                    
629                  public boolean                  private void
630                  contains(int x, int y) { return super.contains(x, y) & y < 13; }                  destroyCurrentView() { destroyView(currentView); }
         }  
 }  
   
 class ChannelPane extends PixmapPane {  
         ChannelPane() {  
                 super(Res.gfxChannel);  
                 setPixmapInsets(new Insets(3, 3, 3, 3));  
         }  
 }  
   
 class ChannelScreen extends PixmapPane {  
         private final Channel channel;  
           
         private final InstrumentPane instrumentPane;  
           
         private JButton btnInstr =  
                 createScreenButton(i18n.getButtonLabel("ChannelScreen.btnInstr"));  
           
         private final JButton btnEditInstr =  
                 createScreenButton(i18n.getButtonLabel("ChannelScreen.btnEditInstr"));  
         private final ScreenButtonBg sbbEditInstr = new ScreenButtonBg(btnEditInstr);  
           
         private final JButton btnFxSends =  
                 createScreenButton(i18n.getButtonLabel("ChannelScreen.btnFxSends"));  
           
         private final JButton btnEngine  
                 = createScreenButton(i18n.getButtonLabel("ChannelScreen.btnEngine"));  
           
         private final JPopupMenu menuEngines = new JPopupMenu();  
           
         private final JButton btnVolume = createScreenButton("");  
         private JSVolumeEditorPopup popupVolume;  
           
         private final JLabel lStreams = createScreenLabel(" --");  
         private final JLabel lVoices = createScreenLabel("-- ");  
           
         private InformationDialog fxSendsDlg = null;  
           
         private Timer timer;  
           
         private static NumberFormat numberFormat = NumberFormat.getInstance();  
         static {  
                 numberFormat.setMaximumFractionDigits(1);  
         }  
           
         ChannelScreen(final Channel channel) {  
                 super(Res.gfxChannelScreen);  
                 setPixmapInsets(new Insets(6, 6, 6, 6));  
                 setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));  
631                                    
632                  this.channel = channel;                  private void
633                  popupVolume = new JSVolumeEditorPopup(btnVolume, VolumeType.CHANNEL);                  removeOriginalView() { removeView(originalView); }
634                                    
635                  setOpaque(false);                  private void
636                    destroyOriginalView() { destroyView(originalView); }
637                                    
638                  setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));                  private void
639                    removeView(ChannelView view) {
640                            if(view == null) return;
641                            
642                            mainPane.remove(view.getComponent());
643                            mainPane.remove(optionsPane);
644                                    
645                            destroyView(view);
646                    }
647                                    
648                  btnInstr.setAlignmentX(CENTER_ALIGNMENT);                  private void
649                  btnInstr.setRolloverEnabled(false);                  destroyView(ChannelView view) {
650                  btnInstr.setBorder(BorderFactory.createEmptyBorder(3, 0, 0, 0));                          if(view == null) return;
651                                            
652                  instrumentPane = new InstrumentPane();                          view.uninstallView();
653                  add(instrumentPane);                          
654                                            view = null;
655                  JPanel p = new JPanel();                  }
                 p.setLayout(new BoxLayout(p, BoxLayout.X_AXIS));  
                 p.setAlignmentX(CENTER_ALIGNMENT);  
                 p.setBorder(BorderFactory.createEmptyBorder(5, 2, 0, 0));  
656                                    
657                  btnFxSends.setToolTipText(i18n.getButtonLabel("ChannelScreen.btnFxSends.tt"));                  public boolean
658                  btnFxSends.addActionListener(new ActionListener() {                  isMouseOverEnabled() { return mouseOverViewType != null; }
                         public void  
                         actionPerformed(ActionEvent e) {  
                                 if(fxSendsDlg != null && fxSendsDlg.isVisible()) {  
                                         fxSendsDlg.toFront();  
                                         return;  
                                 }  
                                 FxSendsPane p = new FxSendsPane(channel.getModel());  
                                 int id = channel.getModel().getChannelId();  
                                 fxSendsDlg = new InformationDialog(CC.getMainFrame(), p);  
                                 fxSendsDlg.setTitle(i18n.getLabel("FxSendsDlg.title", id));  
                                 fxSendsDlg.setModal(false);  
                                 fxSendsDlg.showCloseButton(false);  
                                 fxSendsDlg.setVisible(true);  
                         }  
                 });  
659                                    
660                  p.add(btnFxSends);                  private void
661                    mouseEntered() {
662                            if(!isMouseOverEnabled()) return;
663                            if(getCurrentView().getType() == getMouseOverView().getType()) return;
664                            
665                            JSChannel[] channels = CC.getMainFrame().getChannelsPane(0).getChannels();
666                            for(JSChannel c : channels) {
667                                    if(c == Channel.this) continue;
668                                    
669                                    Channel chn = (Channel)c;
670                                    if(!(chn).isUsingOriginalView()) chn.fallbackToOriginalView();
671                            }
672                            
673                            setView(getMouseOverView(), false);
674                    }
675                                    
676                  //p.add(Box.createRigidArea(new Dimension(6, 0)));                  private void
677                  p.add(Box.createGlue());                  mouseExited() {
678                            if(!isMouseOverEnabled()) return;
679                            if(getCurrentView().getType() == originalView.getType()) return;
680                            
681                            fallbackToOriginalView();
682                    }
683                                    
684                  btnEngine.setIcon(Res.iconEngine12);                  @Override
685                  btnEngine.setIconTextGap(1);                  public void
686                  p.add(btnEngine);                  mouseEntered(MouseEvent e) {
687                  //p.add(new Label("|"));                          guiListener.actionPerformed(null);
688                                    }
                 //p.add(Box.createRigidArea(new Dimension(6, 0)));  
                   
                 //p.add(btnReset);  
                   
                 p.add(Box.createGlue());  
                   
                 lStreams.setFont(Res.fontScreenMono);  
                 lStreams.setHorizontalAlignment(JLabel.RIGHT);  
                 lStreams.setToolTipText(i18n.getLabel("ChannelScreen.streamVoiceCount"));  
                 p.add(lStreams);  
                   
                 JLabel l = createScreenLabel("/");  
                 l.setFont(Res.fontScreenMono);  
                 l.setToolTipText(i18n.getLabel("ChannelScreen.streamVoiceCount"));  
                 p.add(l);  
                   
                 lVoices.setFont(Res.fontScreenMono);  
                 lVoices.setToolTipText(i18n.getLabel("ChannelScreen.streamVoiceCount"));  
                 p.add(lVoices);  
                   
                 btnVolume.setIcon(Res.iconVolume14);  
                 btnVolume.setIconTextGap(2);  
                 btnVolume.setAlignmentX(RIGHT_ALIGNMENT);  
                 btnVolume.setHorizontalAlignment(btnVolume.LEFT);  
                 updateVolumeInfo(100);  
                 Dimension d = btnVolume.getPreferredSize();  
                 d.width = 60;  
                 btnVolume.setPreferredSize(d);  
                 btnVolume.setMinimumSize(d);  
689                                    
690                  btnVolume.addActionListener(new ActionListener() {                  @Override
691                          public void                  public void
692                          actionPerformed(ActionEvent e) {                  mouseExited(MouseEvent e) {
693                                  if(popupVolume.isVisible()) {                          guiListener.actionPerformed(null);
694                                          popupVolume.commit();                  }
                                         popupVolume.hide();  
                                 } else {  
                                         float vol = channel.getModel().getChannelInfo().getVolume();  
                                         popupVolume.setCurrentVolume(vol);  
                                         popupVolume.show();  
                                 }  
                         }  
                 });  
695                                    
696                  popupVolume.addActionListener(new ActionListener() {                  @Override
697                          public void                  public void
698                          actionPerformed(ActionEvent e) {                  mousePressed(MouseEvent e) {
699                                  channel.getModel().setBackendVolume(popupVolume.getVolumeFactor());                          mousePressed = true;
700                          }                  }
                 });  
701                                    
702                  p.add(btnVolume);                  @Override
703                  p.setPreferredSize(new Dimension(260, p.getPreferredSize().height));                  public void
704                  p.setMinimumSize(p.getPreferredSize());                  mouseReleased(MouseEvent e) {
705                  p.setMaximumSize(p.getPreferredSize());                          mousePressed = false;
706                                    }
                 //btnInstr.setBorder(BorderFactory.createEmptyBorder(3, 3, 3, 3));  
                 p.setOpaque(false);  
                 add(p);  
                   
                   
                 setPreferredSize(new Dimension(270, 48));  
                 setMinimumSize(getPreferredSize());  
                 setMaximumSize(getPreferredSize());  
707                                    
708                  createEngineMenu();                  public void
709                  installListeners();                  onDestroy() {
710          }                          destroyCurrentView();
711                                    destroyOriginalView();
         protected void  
         onDestroy() { timer.stop(); }  
           
         private void  
         createEngineMenu() {  
                 for(final SamplerEngine engine : CC.getSamplerModel().getEngines()) {  
                         JMenuItem mi = new JMenuItem(engine.getName() + " engine");  
                         mi.setToolTipText(engine.getDescription());  
712                                                    
713                          mi.addActionListener(new ActionListener() {                          uninstallListeners();
714                                  public void                          
715                                  actionPerformed(ActionEvent e) {                          if(currentView != null) {
716                                          channel.getModel().setBackendEngineType(engine.getName());                                  currentView.removeEnhancedMouseListener(this);
717                                  }                          }
718                          });                          
719                            if(mouseOverView != null) {
720                                    mouseOverView.removeEnhancedMouseListener(this);
721                            }
722                                                    
723                          menuEngines.add(mi);                          String s = DIFFERENT_CHANNEL_VIEW_ON_MOUSE_OVER;
724                            preferences().removePropertyChangeListener(s, this);
725                            
726                            s = CHANNEL_VIEW_ON_MOUSE_OVER;
727                            preferences().removePropertyChangeListener(s, this);
728                    }
729                    
730                    @Override
731                    public void
732                    propertyChange(PropertyChangeEvent e) {
733                            updateMouseOverViewType();
734                  }                  }
735          }          }
736                    
737          private void          class EditInstrumentAction extends AbstractAction implements SamplerChannelListener {
738          installListeners() {                  EditInstrumentAction() {
739                  btnInstr.addActionListener(new ActionListener() {                          super(i18n.getMenuLabel("channels.editInstrument"));
740                          public void                          channelChanged(null);
741                          actionPerformed(ActionEvent e) { loadInstrument(); }                          getModel().addSamplerChannelListener(this);
742                  });                  }
743                                    
744                  btnEditInstr.addActionListener(new ActionListener() {                  @Override
745                          public void                  public void
746                          actionPerformed(ActionEvent e) {                  actionPerformed(ActionEvent e) {
747                                  CC.getSamplerModel().editBackendInstrument(channel.getChannelId());                          CC.getSamplerModel().editBackendInstrument(getChannelId());
748                          }                  }
                 });  
749                                    
750                  btnEngine.addActionListener(new ActionListener() {                  @Override
751                          public void                  public void
752                          actionPerformed(ActionEvent e) {                  channelChanged(SamplerChannelEvent e) {
753                                  int y = btnEngine.getHeight() + 1;                          boolean b = getChannelInfo().getInstrumentStatus() == 100;
754                                  menuEngines.show(btnEngine, 0, y);                          setEnabled(b);
755                          }                  }
                 });  
756                                    
757                  addMouseListener(getHandler());                  @Override
758                  addHierarchyListener(getHandler());                  public void
759                    streamCountChanged(SamplerChannelEvent e) { }
760                                    
761                  ActionListener l = new ActionListener() {                  @Override
762                          public void                  public void
763                          actionPerformed(ActionEvent e) {                  voiceCountChanged(SamplerChannelEvent e) { }
                                 if(getMousePosition(true) != null) {  
                                         getHandler().mouseEntered(null);  
                                 } else {  
                                         getHandler().mouseExited(null);  
                                 }  
                         }  
                 };  
                 timer = new Timer(1000, l);  
                 timer.start();  
764          }          }
765                    
766          private void          class FxSendsAction extends AbstractAction {
767          loadInstrument() {                  FxSendsAction() {
768                  JSInstrumentChooser dlg = FantasiaUtils.createInstrumentChooser(CC.getMainFrame());                          super(i18n.getMenuLabel("channels.fxSends"));
769                  dlg.setVisible(true);                  }
770                                    
771                  if(!dlg.isCancelled()) {                  @Override
772                          SamplerChannelModel m = channel.getModel();                  public void
773                          m.loadBackendInstrument(dlg.getInstrumentFile(), dlg.getInstrumentIndex());                  actionPerformed(ActionEvent e) {
774                            showFxSendsDialog();
775                  }                  }
776          }          }
777                    
778          protected void          class ChannelRoutingAction extends AbstractAction implements SamplerChannelListener {
779          updateScreenInfo(SamplerChannel sc) {                  ChannelRoutingAction() {
780                  int status = sc.getInstrumentStatus();                          super(i18n.getMenuLabel("channels.channelRouting"));
781                  if(status >= 0 && status < 100) {                          channelChanged(null);
782                          btnInstr.setText(i18n.getLabel("ChannelScreen.loadingInstrument", status));                          getModel().addSamplerChannelListener(this);
                 } else if(status == -1) {  
                         btnInstr.setText(i18n.getButtonLabel("ChannelScreen.btnInstr"));  
                 } else if(status < -1) {  
                          btnInstr.setText(i18n.getLabel("ChannelScreen.errorLoadingInstrument"));  
                 } else {  
                         if(sc.getInstrumentName() != null) btnInstr.setText(sc.getInstrumentName());  
                         else btnInstr.setText(i18n.getButtonLabel("ChannelScreen.btnInstr"));  
                 }  
                   
                 instrumentPane.update();  
           
                 if(sc.getEngine() != null) {  
                         String s = sc.getEngine().getName();  
                         s += " engine";  
                         if(!s.equals(btnEngine.getText())) {  
                                 btnEngine.setText(s);  
                                 btnEngine.setToolTipText(sc.getEngine().getDescription());  
                         }  
783                  }                  }
784                                    
785          }                  @Override
786                            public void
787          protected void                  actionPerformed(ActionEvent e) {
788          updateVolumeInfo(int volume) {                          SamplerChannel c = getChannelInfo();
789                  if(CC.getViewConfig().isMeasurementUnitDecibel()) {                          new JSChannelOutputRoutingDlg(CC.getMainFrame(), c).setVisible(true);
                         String s = numberFormat.format(HF.percentsToDecibels(volume));  
                         btnVolume.setText(s + "dB");  
                 } else {  
                         btnVolume.setText(String.valueOf(volume) + "%");  
790                  }                  }
791                    
792                    @Override
793                    public void
794                    channelChanged(SamplerChannelEvent e) {
795                            boolean b = getChannelInfo().getAudioOutputDevice() != -1;
796                            setEnabled(b);
797                    }
798                    
799                    @Override
800                    public void
801                    streamCountChanged(SamplerChannelEvent e) { }
802                    
803                    @Override
804                    public void
805                    voiceCountChanged(SamplerChannelEvent e) { }
806          }          }
807                    
808          /**          public ContextMenu
809           * Updates the number of active disk streams.          getContextMenu() { return contextMenu; }
          * @param count The new number of active disk streams.  
          */  
         protected void  
         updateStreamCount(int count) {  
                 Dimension d = lStreams.getPreferredSize();  
                 lStreams.setText(count == 0 ? "--" : String.valueOf(count));  
                 d = JuifeUtils.getUnionSize(d, lStreams.getPreferredSize());  
                 lStreams.setMinimumSize(d);  
                 lStreams.setPreferredSize(d);  
                 lStreams.setMaximumSize(d);  
         }  
           
         /**  
          * Updates the number of active voices.  
          * @param count The new number of active voices.  
          */  
         protected void  
         updateVoiceCount(int count) {  
                 Dimension d = lVoices.getPreferredSize();  
                 lVoices.setText(count == 0 ? "--" : String.valueOf(count));  
                 d = JuifeUtils.getUnionSize(d, lVoices.getPreferredSize());  
                 lVoices.setMinimumSize(d);  
                 lVoices.setPreferredSize(d);  
                 lVoices.setMaximumSize(d);  
         }  
810                    
811          class InstrumentPane extends JPanel {          class ContextMenu extends MouseAdapter {
812                  private final JPanel leftPane = new JPanel();                  private JPopupMenu menu = null;
                 private final JPanel rightPane = new JPanel();  
813                                    
814                  InstrumentPane() {                  ContextMenu() {
                         setOpaque(false);  
                         setLayout(new BoxLayout(this, BoxLayout.X_AXIS));  
                         add(leftPane);  
                         add(btnInstr);  
                         add(rightPane);  
                         add(sbbEditInstr);  
                         btnEditInstr.setToolTipText(i18n.getLabel("ChannelScreen.btnEditInstr.tt"));  
                         sbbEditInstr.setVisible(false);  
                         setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 6));  
815                                                    
                         update();  
816                  }                  }
817                                    
818                  public void                  private void
819                  update() {                  createMenu() {
820                          int a = btnInstr.getMinimumSize().width;                          menu = new JPopupMenu();
821                          int b = 0;                          menu.add(new JMenuItem(new EditInstrumentAction()));
822                          if(sbbEditInstr.isVisible()) b = sbbEditInstr.getPreferredSize().width;                          menu.addSeparator();
                           
                         int max = 254 - b;  
                         if(a > max) a = max;  
823                                                    
824                          int h = btnInstr.getPreferredSize().height;                          MenuManager.ChannelViewGroup group;
825                          btnInstr.setPreferredSize(new Dimension(a, h));                          group = new MenuManager.ChannelViewGroup(true, true);
826                          h = btnInstr.getMaximumSize().height;                          MenuManager.getMenuManager().registerChannelViewGroup(group);
                         btnInstr.setMaximumSize(new Dimension(a, h));  
827                                                    
828                            for(JMenuItem mi : group.getMenuItems()) menu.add(mi);
829                                                    
830                          int i = (254 - btnInstr.getPreferredSize().width) / 2;                          menu.addSeparator();
831                                                    
832                          int j = i;                          menu.add(new JMenuItem(a4n.moveChannelsOnTop));
833                          if(sbbEditInstr.isVisible()) j -= sbbEditInstr.getPreferredSize().width;                          menu.add(new JMenuItem(a4n.moveChannelsUp));
834                          if(i < 0 || j < 0) i = j = 0;                          menu.add(new JMenuItem(a4n.moveChannelsDown));
835                            menu.add(new JMenuItem(a4n.moveChannelsAtBottom));
836                                                    
837                          Dimension d = new Dimension(i, 1);                          menu.add(new MainFrame.ToPanelMenu());
                         leftPane.setMinimumSize(d);  
                         leftPane.setPreferredSize(d);  
                         leftPane.setMaximumSize(d);  
838                                                    
839                          d = new Dimension(j, 1);                          menu.addSeparator();
                         rightPane.setMinimumSize(d);  
                         rightPane.setPreferredSize(d);  
                         rightPane.setMaximumSize(d);  
840                                                    
841                          validate();                          menu.add(new JMenuItem(new FxSendsAction()));
842                            menu.add(new JMenuItem(new ChannelRoutingAction()));
843                    }
844                    
845                    private JPopupMenu
846                    getMenu() {
847                            if(menu == null) createMenu();
848                            return menu;
849                    }
850                    
851                    @Override
852                    public void
853                    mousePressed(MouseEvent e) {
854                            if(e.isPopupTrigger()) show(e);
855                    }
856            
857                    @Override
858                    public void
859                    mouseReleased(MouseEvent e) {
860                            if(e.isPopupTrigger()) show(e);
861                    }
862            
863                    void
864                    show(MouseEvent e) {
865                            getMenu().show(e.getComponent(), e.getX(), e.getY());
866                  }                  }
867          }          }
868                    
# Line 1019  class ChannelScreen extends PixmapPane { Line 874  class ChannelScreen extends PixmapPane {
874                          actionRemoveFxSend.putValue(Action.SMALL_ICON, Res.iconDelete16);                          actionRemoveFxSend.putValue(Action.SMALL_ICON, Res.iconDelete16);
875                  }                  }
876                                    
877                    @Override
878                  protected JToolBar                  protected JToolBar
879                  createToolBar() {                  createToolBar() {
880                          JToolBar tb = new JToolBar();                          JToolBar tb = new JToolBar();
# Line 1034  class ChannelScreen extends PixmapPane { Line 890  class ChannelScreen extends PixmapPane {
890                  }                  }
891          }          }
892                    
893          static class ScreenButtonBg extends PixmapPane {          public static class StreamVoiceCountPane extends JPanel {
894                  ScreenButtonBg(JButton btn) {                  private final Channel channel;
                         super(Res.gfxScreenBtnBg);  
                         setPixmapInsets(new Insets(4, 4, 4, 4));  
                         setLayout(new BoxLayout(this, BoxLayout.X_AXIS));  
                         setBorder(BorderFactory.createEmptyBorder(0, 7, 0, 7));  
                         add(btn);  
                         setPreferredSize(new Dimension(getPreferredSize().width, 13));  
                 }  
895                                    
896                  public Dimension                  private final JLabel lStreams = createScreenLabel(" --");
897                  getPreferredSize() {                  private final JLabel lSlash = createScreenLabel("/");
898                          return new Dimension(super.getPreferredSize().width, 13);                  private final JLabel lVoices = createScreenLabel("-- ");
899                  }                  
900          }                  public
901                            StreamVoiceCountPane(Channel channel) {
902                                    this.channel = channel;
         private final EventHandler eventHandler = new EventHandler();  
           
         private EventHandler  
         getHandler() { return eventHandler; }  
           
         private class EventHandler extends MouseAdapter implements HierarchyListener {  
                 public void  
                 mouseEntered(MouseEvent e)  {  
                         if(channel.getChannelInfo().getInstrumentStatus() != 100) return;  
903                                                    
904                          if(!sbbEditInstr.isVisible()) {                          setOpaque(false);
905                                  sbbEditInstr.setVisible(true);                          setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
906                                  instrumentPane.update();                          lStreams.setFont(Res.fontScreenMono);
907                          }                          lStreams.setHorizontalAlignment(JLabel.RIGHT);
908                            lStreams.setToolTipText(i18n.getLabel("Channel.streamVoiceCount"));
909                            
910                            Dimension d = lStreams.getPreferredSize();
911                            lStreams.setMinimumSize(d);
912                            lStreams.setPreferredSize(d);
913                            lStreams.setMaximumSize(d);
914                            add(lStreams);
915                            
916                            lSlash.setFont(Res.fontScreenMono);
917                            lSlash.setToolTipText(i18n.getLabel("Channel.streamVoiceCount"));
918                            add(lSlash);
919                            
920                            lVoices.setFont(Res.fontScreenMono);
921                            lVoices.setToolTipText(i18n.getLabel("Channel.streamVoiceCount"));
922                            
923                            d = lStreams.getPreferredSize();
924                            lVoices.setMinimumSize(d);
925                            lVoices.setPreferredSize(d);
926                            lVoices.setMaximumSize(d);
927                            add(lVoices);
928                            
929                            lStreams.addMouseListener(channel.getContextMenu());
930                            lSlash.addMouseListener(channel.getContextMenu());
931                            lVoices.addMouseListener(channel.getContextMenu());
932                  }                  }
933                                    
934                  public void                  public void
935                  mouseExited(MouseEvent e)  {                  updateStreamCount(int count) {
936                          if(getMousePosition(true) != null) return;                          lStreams.setText(count == 0 ? " --" : String.valueOf(count));
                         if(sbbEditInstr.isVisible()) {  
                                 sbbEditInstr.setVisible(false);  
                                 instrumentPane.update();  
                         }  
937                  }                  }
938                                    
                 /** Called when the hierarchy has been changed. */  
939                  public void                  public void
940                  hierarchyChanged(HierarchyEvent e) {                  updateVoiceCount(int count) {
941                          if((e.getChangeFlags() & e.SHOWING_CHANGED) == e.SHOWING_CHANGED) {                          lVoices.setText(count == 0 ? "-- " : String.valueOf(count));
                                 if(getMousePosition() == null) mouseExited(null);  
                                 else mouseEntered(null);  
                         }  
942                  }                  }
943          }          }
 }  
   
 class ChannelOptions extends JXCollapsiblePane {  
         private final Channel channel;  
         private MidiDeviceModel midiDevice = null;  
           
         private final JComboBox cbMidiDevice = new FantasiaComboBox();  
         private final JComboBox cbMidiPort = new FantasiaComboBox();  
         private final JComboBox cbMidiChannel = new FantasiaComboBox();  
         private final JComboBox cbInstrumentMap = new FantasiaComboBox();  
         private final JComboBox cbAudioDevice = new FantasiaComboBox();  
           
         private final PixmapButton btnChannelRouting;  
           
         private boolean update = false;  
           
         private final SamplerListener samplerListener;  
         private final MapListListener mapListListener = new MapListListener();  
           
         private class NoMap {  
                 public String  
                 toString() { return "[None]"; }  
         }  
           
         private NoMap noMap = new NoMap();  
           
         private class DefaultMap {  
                 public String  
                 toString() { return "[Default]"; }  
         }  
           
         private DefaultMap defaultMap = new DefaultMap();  
944                    
945          ChannelOptions(final Channel channel) {          public static class VolumePane extends JPanel {
946                  setAnimated(false);                  private final Channel channel;
947                  setCollapsed(true);                  private final JButton btnVolume = createScreenButton("");
948                  setAnimated(preferences().getBoolProperty(ANIMATED));                  private JSVolumeEditorPopup popupVolume;
949                                    
950                  preferences().addPropertyChangeListener(ANIMATED, new PropertyChangeListener() {                  private static NumberFormat numberFormat = NumberFormat.getInstance();
951                          public void                  static { numberFormat.setMaximumFractionDigits(1); }
                         propertyChange(PropertyChangeEvent e) {  
                                 setAnimated(preferences().getBoolProperty(ANIMATED));  
                         }  
                 });  
                   
                 PixmapPane bgp = new PixmapPane(Res.gfxChannelOptions);  
                 bgp.setPixmapInsets(new Insets(1, 1, 1, 1));  
                   
                 this.channel = channel;  
                   
                 bgp.setBorder(BorderFactory.createEmptyBorder(5, 4, 5, 4));  
                 bgp.setLayout(new BoxLayout(bgp, BoxLayout.X_AXIS));  
                   
                 bgp.setPreferredSize(new Dimension(420, 44));  
                 bgp.setMinimumSize(getPreferredSize());  
                 bgp.setMaximumSize(getPreferredSize());  
                   
                 JPanel p = new JPanel();  
                 p.setBorder(BorderFactory.createEmptyBorder(3, 4, 3, 4));  
                 p.setLayout(new BoxLayout(p, BoxLayout.Y_AXIS));  
                 JLabel l = new JLabel(Res.gfxMidiInputTitle);  
                 l.setAlignmentX(LEFT_ALIGNMENT);  
                 p.add(l);  
                   
                 JPanel p2 = new JPanel();  
                 p2.setBorder(BorderFactory.createEmptyBorder(3, 0, 0, 0));  
                 p2.setLayout(new BoxLayout(p2, BoxLayout.X_AXIS));  
                   
                 Object o = cbMidiDevice.getRenderer();  
                 if(o instanceof JLabel) ((JLabel )o).setHorizontalAlignment(SwingConstants.CENTER);  
                   
                 cbMidiDevice.setPreferredSize(new Dimension(40, 18));  
                 cbMidiDevice.setMinimumSize(cbMidiDevice.getPreferredSize());  
                 cbMidiDevice.setMaximumSize(cbMidiDevice.getPreferredSize());  
                 p2.add(cbMidiDevice);  
                   
                 p2.add(Box.createRigidArea(new Dimension(3, 0)));  
                   
                 o = cbMidiPort.getRenderer();  
                 if(o instanceof JLabel) ((JLabel )o).setHorizontalAlignment(SwingConstants.CENTER);  
                   
                 cbMidiPort.setPreferredSize(new Dimension(62, 18));  
                 cbMidiPort.setMinimumSize(cbMidiPort.getPreferredSize());  
                 cbMidiPort.setMaximumSize(cbMidiPort.getPreferredSize());  
                 p2.add(cbMidiPort);  
                   
                 p2.add(Box.createRigidArea(new Dimension(3, 0)));  
                   
                 o = cbMidiChannel.getRenderer();  
                 if(o instanceof JLabel) ((JLabel )o).setHorizontalAlignment(SwingConstants.CENTER);  
                   
                 cbMidiChannel.addItem("All");  
                 for(int i = 1; i <= 16; i++) cbMidiChannel.addItem("Channel " + String.valueOf(i));  
                 cbMidiChannel.setPreferredSize(new Dimension(80, 18));  
                 cbMidiChannel.setMinimumSize(cbMidiChannel.getPreferredSize());  
                 cbMidiChannel.setMaximumSize(cbMidiChannel.getPreferredSize());  
                   
                 p2.add(cbMidiChannel);  
                 p2.setAlignmentX(LEFT_ALIGNMENT);  
                 p2.setOpaque(false);  
                 p.add(p2);  
                 p.setBackground(new java.awt.Color(0x818181));  
                   
                 bgp.add(p);  
                   
                 bgp.add(Box.createRigidArea(new Dimension(4, 0)));  
                   
                 p = new JPanel();  
                 p.setOpaque(true);  
                 p.setBorder(BorderFactory.createEmptyBorder(3, 4, 3, 4));  
                 p.setLayout(new BoxLayout(p, BoxLayout.Y_AXIS));  
                 l = new JLabel(Res.gfxInstrumentMapTitle);  
                 l.setAlignmentX(LEFT_ALIGNMENT);  
                 l.setAlignmentX(LEFT_ALIGNMENT);  
                 p.add(l);  
                   
                 p.add(Box.createRigidArea(new Dimension(0, 3)));  
                   
                 //o = cbInstrumentMap.getRenderer();  
                 //if(o instanceof JLabel) ((JLabel )o).setHorizontalAlignment(SwingConstants.CENTER);  
                   
                 cbInstrumentMap.setPreferredSize(new Dimension(126, 18));  
                 cbInstrumentMap.setMinimumSize(cbInstrumentMap.getPreferredSize());  
                 cbInstrumentMap.setMaximumSize(cbInstrumentMap.getPreferredSize());  
                 cbInstrumentMap.setAlignmentX(LEFT_ALIGNMENT);  
                 p.add(cbInstrumentMap);  
                 p.setBackground(new java.awt.Color(0x818181));  
                 bgp.add(p);  
                   
                 bgp.add(Box.createRigidArea(new Dimension(4, 0)));  
                   
                 p = new JPanel();  
                 p.setOpaque(true);  
                 p.setBorder(BorderFactory.createEmptyBorder(3, 4, 3, 4));  
                 p.setLayout(new BoxLayout(p, BoxLayout.Y_AXIS));  
                 l = new JLabel(Res.gfxAudioOutputTitle);  
                 l.setAlignmentX(LEFT_ALIGNMENT);  
                 p.add(l);  
                   
                 //p.add(Box.createRigidArea(new Dimension(0, 3)));  
                   
                 p2 = new JPanel();  
                 p2.setBorder(BorderFactory.createEmptyBorder(3, 0, 0, 0));  
                 p2.setLayout(new BoxLayout(p2, BoxLayout.X_AXIS));  
                 p2.setOpaque(false);  
                 p2.setAlignmentX(LEFT_ALIGNMENT);  
                   
                 o = cbAudioDevice.getRenderer();  
                 if(o instanceof JLabel) ((JLabel )o).setHorizontalAlignment(SwingConstants.RIGHT);  
                   
                 cbAudioDevice.setPreferredSize(new Dimension(40, 18));  
                 cbAudioDevice.setMinimumSize(cbAudioDevice.getPreferredSize());  
                 cbAudioDevice.setMaximumSize(cbAudioDevice.getPreferredSize());  
                   
                 p2.add(cbAudioDevice);  
                 p2.add(Box.createRigidArea(new Dimension(3, 0)));  
                 btnChannelRouting = new PixmapButton(Res.gfxBtnCr, Res.gfxBtnCrRO);  
                 btnChannelRouting.setPressedIcon(Res.gfxBtnCrRO);  
                 btnChannelRouting.setEnabled(false);  
                 btnChannelRouting.setToolTipText(i18n.getLabel("ChannelOptions.routing"));  
952                                    
953                  btnChannelRouting.addActionListener(new ActionListener() {                  public
954                          public void                  VolumePane(final Channel channel) {
955                          actionPerformed(ActionEvent e) {                          this.channel = channel;
956                                  SamplerChannel c = channel.getChannelInfo();                          setOpaque(false);
957                                  new JSChannelOutputRoutingDlg(CC.getMainFrame(), c).setVisible(true);                          setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
958                                                    
959                          }                          btnVolume.setIcon(Res.iconVolume14);
960                  });                          btnVolume.setIconTextGap(2);
961                                            btnVolume.setAlignmentX(RIGHT_ALIGNMENT);
962                  p2.add(btnChannelRouting);                          btnVolume.setHorizontalAlignment(btnVolume.LEFT);
963                                            updateVolumeInfo(100);
964                  p.add(p2);                          Dimension d = btnVolume.getPreferredSize();
965                  p.setBackground(new java.awt.Color(0x818181));                          d.width = 57;
966                  p2 = new JPanel();                          btnVolume.setPreferredSize(d);
967                  p2.setLayout(new java.awt.BorderLayout());                          btnVolume.setMinimumSize(d);
968                  p.add(p2);                          
969                  bgp.add(p);                          add(btnVolume);
970                                            
971                  setContentPane(bgp);                          btnVolume.addActionListener(new ActionListener() {
972                                                    public void
973                  cbMidiDevice.addActionListener(new ActionListener() {                                  actionPerformed(ActionEvent e) {
974                          public void                                          if(popupVolume.isVisible()) {
975                          actionPerformed(ActionEvent e) { setMidiDevice(); }                                                  popupVolume.commit();
976                  });                                                  popupVolume.hide();
977                                                            } else {
978                  cbMidiPort.addActionListener(new ActionListener() {                                                  float vol = channel.getModel().getChannelInfo().getVolume();
979                          public void                                                  popupVolume.setCurrentVolume(vol);
980                          actionPerformed(ActionEvent e) { setMidiPort(); }                                                  popupVolume.show();
981                  });                                          }
982                                                    }
983                  cbMidiChannel.addActionListener(new ActionListener() {                          });
984                          public void                          
985                          actionPerformed(ActionEvent e) { setMidiChannel(); }                          popupVolume = new JSVolumeEditorPopup(btnVolume, VolumeType.CHANNEL);
986                  });                          
987                                            popupVolume.addActionListener(new ActionListener() {
988                  samplerListener = new SamplerAdapter() {                                  public void
989                          /** Invoked when the default MIDI instrument map is changed. */                                  actionPerformed(ActionEvent e) {
990                          public void                                          channel.getModel().setBackendVolume(popupVolume.getVolumeFactor());
991                          defaultMapChanged(SamplerEvent e) {                                  }
992                                  updateCbInstrumentMapToolTipText();                          });
993                                                            
994                          }                          btnVolume.addMouseListener(channel.getContextMenu());
                 };  
                   
                 CC.getSamplerModel().addSamplerListener(samplerListener);  
                   
                 cbInstrumentMap.addItem(noMap);  
                 cbInstrumentMap.addItem(defaultMap);  
                 for(MidiInstrumentMap map : CC.getSamplerModel().getMidiInstrumentMaps()) {  
                         cbInstrumentMap.addItem(map);  
995                  }                  }
996                                    
997                  int map = channel.getModel().getChannelInfo().getMidiInstrumentMapId();                  public void
998                  cbInstrumentMap.setSelectedItem(CC.getSamplerModel().getMidiInstrumentMapById(map));                  updateVolumeInfo(int volume) {
999                  if(cbInstrumentMap.getSelectedItem() == null) {                          if(CC.getViewConfig().isMeasurementUnitDecibel()) {
1000                          if(map == -1) cbInstrumentMap.setSelectedItem(noMap);                                  String s = numberFormat.format(HF.percentsToDecibels(volume));
1001                          else if(map == -2) {                                  btnVolume.setText(s + "dB");
1002                                  cbInstrumentMap.setSelectedItem(defaultMap);                          } else {
1003                                    btnVolume.setText(String.valueOf(volume) + "%");
1004                          }                          }
1005                  }                  }
                   
                 updateCbInstrumentMapToolTipText();  
                   
                 if(channel.getModel().getChannelInfo().getEngine() == null) {  
                         cbInstrumentMap.setEnabled(false);  
                 }  
                   
                 cbInstrumentMap.addActionListener(new ActionListener() {  
                         public void  
                         actionPerformed(ActionEvent e) { updateInstrumentMap(); }  
                 });  
                   
                 CC.getSamplerModel().addMidiInstrumentMapListListener(mapListListener);  
                   
                 cbAudioDevice.addActionListener(new ActionListener() {  
                         public void  
                         actionPerformed(ActionEvent e) { setBackendAudioDevice(); }  
                 });  
                   
                 channel.getModel().addSamplerChannelListener(new SamplerChannelAdapter() {  
                         public void  
                         channelChanged(SamplerChannelEvent e) { updateChannelProperties(); }  
                 });  
                   
                 CC.getSamplerModel().addMidiDeviceListListener(getHandler());  
                 CC.getSamplerModel().addAudioDeviceListListener(getHandler());  
                   
                 updateMidiDevices();  
                 updateAudioDevices();  
                 updateChannelProperties();  
1006          }          }
1007                    
1008          /**          public static class PowerButton extends PixmapToggleButton implements ActionListener {
1009           * Updates the channel settings. This method is invoked when changes to the                  private final Channel channel;
          * channel were made.  
          */  
         private void  
         updateChannelProperties() {  
                 SamplerModel sm = CC.getSamplerModel();  
                 SamplerChannel sc = channel.getModel().getChannelInfo();  
                   
                 MidiDeviceModel mm = sm.getMidiDeviceById(sc.getMidiInputDevice());  
                 AudioDeviceModel am = sm.getAudioDeviceById(sc.getAudioOutputDevice());  
                   
                 if(isUpdate()) CC.getLogger().warning("Unexpected update state!");  
1010                                    
1011                  setUpdate(true);                  PowerButton(Channel channel) {
1012                                            this(channel, Res.gfxPowerOff, Res.gfxPowerOn);
                 try {  
                         cbMidiDevice.setSelectedItem(mm == null ? null : mm.getDeviceInfo());  
                           
                         cbAudioDevice.setSelectedItem(am == null ? null : am.getDeviceInfo());  
                         btnChannelRouting.setEnabled(am != null);  
                 } catch(Exception x) {  
                         CC.getLogger().log(Level.WARNING, "Unkown error", x);  
1013                  }                  }
1014                                    
1015                  if(sc.getEngine() != null) {                  PowerButton(Channel channel, ImageIcon defaultIcon, ImageIcon selectedIcon) {
1016                          cbInstrumentMap.setEnabled(true);                          super(defaultIcon, selectedIcon);
                         int id = sc.getMidiInstrumentMapId();  
                         Object o;  
                         if(id == -2) o = defaultMap;  
                         else if(id == -1) o = noMap;  
                         else o = CC.getSamplerModel().getMidiInstrumentMapById(id);  
1017                                                    
1018                          if(cbInstrumentMap.getSelectedItem() != o) {                          this.channel = channel;
                                 cbInstrumentMap.setSelectedItem(o);  
                         }  
                 } else {  
                         cbInstrumentMap.setSelectedItem(noMap);  
                         cbInstrumentMap.setEnabled(false);  
                 }  
                   
                 setUpdate(false);  
         }  
           
         /**  
          * Updates the MIDI device list.  
          */  
         private void  
         updateMidiDevices() {  
                 SamplerModel sm = CC.getSamplerModel();  
                 SamplerChannel sc = channel.getModel().getChannelInfo();  
1019                                    
1020                  setUpdate(true);                          setSelected(true);
1021                                            addActionListener(this);
1022                  try {                          setToolTipText(i18n.getButtonLabel("Channel.ttRemoveChannel"));
                         cbMidiDevice.removeAllItems();  
                   
                         for(MidiDeviceModel m : sm.getMidiDevices())  
                                 cbMidiDevice.addItem(m.getDeviceInfo());  
                   
                         MidiDeviceModel mm = sm.getMidiDeviceById(sc.getMidiInputDevice());  
                         cbMidiDevice.setSelectedItem(mm == null ? null : mm.getDeviceInfo());  
                 } catch(Exception x) {  
                         CC.getLogger().log(Level.WARNING, "Unkown error", x);  
1023                  }                  }
                   
                 setUpdate(false);  
         }  
           
           
         private void  
         updateInstrumentMap() {  
                 updateCbInstrumentMapToolTipText();  
                   
                 int id = channel.getModel().getChannelInfo().getMidiInstrumentMapId();  
                 Object o = cbInstrumentMap.getSelectedItem();  
                 if(o == null && id == -1) return;  
1024                                    
1025                  int cbId;                  @Override
1026                  if(o == null || o == noMap) cbId = -1;                  public void
1027                  else if(o == defaultMap) cbId = -2;                  actionPerformed(ActionEvent e) {
1028                  else cbId = ((MidiInstrumentMap)o).getMapId();                          boolean b = preferences().getBoolProperty(CONFIRM_CHANNEL_REMOVAL);
1029                                            if(b) {
1030                  if(cbId == id) return;                                  String s = i18n.getMessage("Channel.remove?", channel.getChannelId());
1031                                                    if(!HF.showYesNoDialog(channel, s)) {
1032                  channel.getModel().setBackendMidiInstrumentMap(cbId);                                          setSelected(true);
1033          }                                          return;
1034                                            }
1035          private void                          }
1036          updateCbInstrumentMapToolTipText() {                          channel.remove();
                 if(cbInstrumentMap.getSelectedItem() != defaultMap) {  
                         cbInstrumentMap.setToolTipText(null);  
                         return;  
1037                  }                  }
1038                                    
1039                  MidiInstrumentMap m = CC.getSamplerModel().getDefaultMidiInstrumentMap();                  @Override
1040                  if(m != null) {                  public boolean
1041                          String s = i18n.getLabel("Channel.ttDefault", m.getName());                  contains(int x, int y) { return (x - 11)*(x - 11) + (y - 11)*(y - 11) < 71; }
                         cbInstrumentMap.setToolTipText(s);  
                 } else {  
                         cbInstrumentMap.setToolTipText(null);  
                 }  
1042          }          }
1043                    
1044          /**          public static class OptionsButton extends PixmapToggleButton
1045           * Updates the audio device list.                                          implements ActionListener, PropertyChangeListener {
          */  
         private void  
         updateAudioDevices() {  
                 SamplerModel sm = CC.getSamplerModel();  
                 SamplerChannel sc = channel.getModel().getChannelInfo();  
                   
                 setUpdate(true);  
                   
                 try {  
                         cbAudioDevice.removeAllItems();  
1046                                    
1047                          for(AudioDeviceModel m : sm.getAudioDevices())                  private final Channel channel;
                                 cbAudioDevice.addItem(m.getDeviceInfo());  
1048                                    
1049                          AudioDeviceModel am = sm.getAudioDeviceById(sc.getAudioOutputDevice());                  OptionsButton(Channel channel) {
1050                          cbAudioDevice.setSelectedItem(am == null ? null : am.getDeviceInfo());                          super(Res.gfxOptionsOff, Res.gfxOptionsOn);
                 } catch(Exception x) {  
                         CC.getLogger().log(Level.WARNING, "Unkown error", x);  
                 }  
                   
                 setUpdate(false);  
         }  
           
         private void  
         setMidiDevice() {  
                 MidiInputDevice mid = (MidiInputDevice)cbMidiDevice.getSelectedItem();  
                   
                 if(!isUpdate()) {  
                         if(mid != null) {  
                                 channel.getModel().setBackendMidiInputDevice(mid.getDeviceId());  
                         }  
1051                                                    
1052                          return;                          this.channel = channel;
1053                            
1054                            setRolloverIcon(Res.gfxOptionsOffRO);
1055                            this.setRolloverSelectedIcon(Res.gfxOptionsOnRO);
1056                            addActionListener(this);
1057                            setToolTipText(i18n.getButtonLabel("Channel.ttShowOptions"));
1058                  }                  }
1059                                    
1060                  if(midiDevice != null) midiDevice.removeMidiDeviceListener(getHandler());                  @Override
1061                                    public void
1062                  cbMidiPort.removeAllItems();                  actionPerformed(ActionEvent e) {
1063                                            ChannelView view = channel.viewTracker.getCurrentView();
                 if(mid == null) {  
                         midiDevice = null;  
                         cbMidiPort.setEnabled(false);  
1064                                                    
1065                          cbMidiChannel.setSelectedItem(null);                          if(isSelected() && view.getChannelOptionsView() == null) {
1066                          cbMidiChannel.setEnabled(false);                                  view.installChannelOptionsView();
1067                  } else {                                  JComponent c = view.getChannelOptionsView().getComponent();
1068                          midiDevice = CC.getSamplerModel().getMidiDeviceById(mid.getDeviceId());                                  channel.optionsPane.setContentPane(c);
1069                          if(midiDevice != null) midiDevice.addMidiDeviceListener(getHandler());                          }
1070                                                    
1071                          cbMidiPort.setEnabled(true);                          channel.showOptionsPane(isSelected());
1072                                                    
1073                          MidiPort[] ports = mid.getMidiPorts();                          String s;
1074                          for(MidiPort port : ports) cbMidiPort.addItem(port);                          if(isSelected()) s = i18n.getButtonLabel("Channel.ttHideOptions");
1075                            else s = i18n.getButtonLabel("Channel.ttShowOptions");
1076                                                    
1077                          int p = channel.getModel().getChannelInfo().getMidiInputPort();                          setToolTipText(s);
                         cbMidiPort.setSelectedItem(p >= 0 && p < ports.length ? ports[p] : null);  
1078                                                    
1079                          cbMidiChannel.setEnabled(true);                          s = JXCollapsiblePane.ANIMATION_STATE_KEY;
1080                          int c = channel.getModel().getChannelInfo().getMidiInputChannel();                          channel.optionsPane.addPropertyChangeListener(s, this);
                         cbMidiChannel.setSelectedItem(c == -1 ? "All" : "Channel " + (c + 1));  
1081                  }                  }
         }  
           
         private void  
         setMidiPort() {  
                 if(isUpdate()) return;  
1082                                    
1083                  channel.getModel().setBackendMidiInputPort(cbMidiPort.getSelectedIndex());                  @Override
         }  
           
         private void  
         setMidiChannel() {  
                 if(isUpdate()) return;  
                   
                 Object o = cbMidiChannel.getSelectedItem();  
                 if(o == null) return;  
                 String s = o.toString();  
                   
                 int c = s.equals("All") ? -1 : Integer.parseInt(s.substring(8)) - 1;  
                   
                 channel.getModel().setBackendMidiInputChannel(c);  
         }  
           
         private void  
         setBackendAudioDevice() {  
                 if(isUpdate()) return;  
                 AudioOutputDevice dev = (AudioOutputDevice)cbAudioDevice.getSelectedItem();  
                 if(dev != null) channel.getModel().setBackendAudioOutputDevice(dev.getDeviceId());  
         }  
           
         /**  
          * Determines whether the currently processed changes are due to update.  
          * @return <code>true</code> if the currently processed changes are due to update and  
          * <code>false</code> if the currently processed changes are due to user input.  
          */  
         private boolean  
         isUpdate() { return update; }  
           
         /**  
          * Sets whether the currently processed changes are due to update.  
          * @param b Specify <code>true</code> to indicate that the currently  
          * processed changes are due to update; <code>false</code>  
          * indicates that the currently processed changes are due to user input.  
          */  
         private void  
         setUpdate(boolean b) { update = b; }  
           
         protected void  
         onDestroy() {  
                 SamplerModel sm = CC.getSamplerModel();  
                   
                 sm.removeMidiDeviceListListener(getHandler());  
                 sm.removeAudioDeviceListListener(getHandler());  
                 sm.removeMidiInstrumentMapListListener(mapListListener);  
                 sm.removeSamplerListener(samplerListener);  
                   
                 if(midiDevice != null) {  
                         midiDevice.removeMidiDeviceListener(getHandler());  
                 }  
         }  
           
         private final Handler handler = new Handler();  
           
         private Handler  
         getHandler() { return handler; }  
           
         private class Handler implements MidiDeviceListListener, ListListener<AudioDeviceModel>,  
                                         MidiDeviceListener {  
                 /**  
                  * Invoked when a new MIDI device is created.  
                  * @param e A <code>MidiDeviceListEvent</code>  
                  * instance providing the event information.  
                  */  
1084                  public void                  public void
1085                  deviceAdded(MidiDeviceListEvent e) {                  propertyChange(PropertyChangeEvent e) {
1086                          cbMidiDevice.addItem(e.getMidiDeviceModel().getDeviceInfo());                          if(e.getNewValue() == "collapsed") {
1087                  }                                  ChannelView view = channel.viewTracker.getCurrentView();
1088                                            view.uninstallChannelOptionsView();
1089                  /**                                  channel.optionsPane.setContentPane(new JPanel());
1090                   * Invoked when a MIDI device is removed.                          }
                  * @param e A <code>MidiDeviceListEvent</code>  
                  * instance providing the event information.  
                  */  
                 public void  
                 deviceRemoved(MidiDeviceListEvent e) {  
                         cbMidiDevice.removeItem(e.getMidiDeviceModel().getDeviceInfo());  
1091                  }                  }
1092                                    
                 /**  
                  * Invoked when a new audio device is created.  
                  * @param e An <code>AudioDeviceListEvent</code>  
                  * instance providing the event information.  
                  */  
                 public void  
                 entryAdded(ListEvent<AudioDeviceModel> e) {  
                         cbAudioDevice.addItem(e.getEntry().getDeviceInfo());  
                 }  
           
                 /**  
                  * Invoked when an audio device is removed.  
                  * @param e An <code>AudioDeviceListEvent</code>  
                  * instance providing the event information.  
                  */  
1093                  public void                  public void
1094                  entryRemoved(ListEvent<AudioDeviceModel> e) {                  onDestroy() {
1095                          cbAudioDevice.removeItem(e.getEntry().getDeviceInfo());                          String s = JXCollapsiblePane.ANIMATION_STATE_KEY;
1096                            channel.optionsPane.removePropertyChangeListener(s, this);
1097                  }                  }
1098                                    
1099                  public void                  @Override
1100                  settingsChanged(MidiDeviceEvent e) {                  public boolean
1101                          if(isUpdate()) {                  contains(int x, int y) { return super.contains(x, y) & y < 13; }
                                 CC.getLogger().warning("Invalid update state");  
                                 return;  
                         }  
                           
                         setUpdate(true);  
                         int idx = cbMidiPort.getSelectedIndex();  
                         MidiInputDevice d = e.getMidiDeviceModel().getDeviceInfo();  
                           
                         cbMidiPort.removeAllItems();  
                         for(MidiPort port : d.getMidiPorts()) cbMidiPort.addItem(port);  
                           
                         if(idx >= cbMidiPort.getModel().getSize()) idx = 0;  
                           
                         setUpdate(false);  
                           
                         if(cbMidiPort.getModel().getSize() > 0) cbMidiPort.setSelectedIndex(idx);  
                 }  
1102          }          }
1103            }
1104          private class MapListListener implements ListListener<MidiInstrumentMap> {  
1105                  /** Invoked when a new MIDI instrument map is added to a list. */  class ChannelOptionsPane extends JXCollapsiblePane {
1106                  public void          ChannelOptionsPane() {
1107                  entryAdded(ListEvent<MidiInstrumentMap> e) {                  setAnimated(false);
1108                          cbInstrumentMap.insertItemAt(e.getEntry(), cbInstrumentMap.getItemCount());                  setCollapsed(true);
1109                          boolean b = channel.getModel().getChannelInfo().getEngine() != null;                  setAnimated(preferences().getBoolProperty(ANIMATED));
1110                          if(b && !cbInstrumentMap.isEnabled()) cbInstrumentMap.setEnabled(true);                  
1111                  }                  preferences().addPropertyChangeListener(ANIMATED, new PropertyChangeListener() {
1112                                    public void
1113                  /** Invoked when a new MIDI instrument map is removed from a list. */                          propertyChange(PropertyChangeEvent e) {
1114                  public void                                  setAnimated(preferences().getBoolProperty(ANIMATED));
                 entryRemoved(ListEvent<MidiInstrumentMap> e) {  
                         cbInstrumentMap.removeItem(e.getEntry());  
                         if(cbInstrumentMap.getItemCount() == 0) { // TODO: ?  
                                 cbInstrumentMap.setSelectedItem(noMap);  
                                 cbInstrumentMap.setEnabled(false);  
1115                          }                          }
1116                  }                  });
1117          }          }
1118            
1119            public void
1120            showOptionsPane(boolean show) { setCollapsed(!show); }
1121  }  }

Legend:
Removed from v.1545  
changed lines
  Added in v.1975

  ViewVC Help
Powered by ViewVC