/[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 1729 by iliev, Thu Feb 14 16:52:36 2008 UTC revision 1730 by iliev, Wed Apr 30 23:31:08 2008 UTC
# Line 23  Line 23 
23  package org.jsampler.view.fantasia;  package org.jsampler.view.fantasia;
24    
25  import java.awt.Container;  import java.awt.Container;
 import java.awt.Dimension;  
 import java.awt.Graphics;  
 import java.awt.Graphics2D;  
 import java.awt.Insets;  
26  import java.awt.Rectangle;  import java.awt.Rectangle;
27    
28  import java.awt.event.ActionEvent;  import java.awt.event.ActionEvent;
29  import java.awt.event.ActionListener;  import java.awt.event.ActionListener;
 import java.awt.event.HierarchyEvent;  
 import java.awt.event.HierarchyListener;  
 import java.awt.event.MouseAdapter;  
 import java.awt.event.MouseEvent;  
30    
31  import java.beans.PropertyChangeEvent;  import java.beans.PropertyChangeEvent;
32  import java.beans.PropertyChangeListener;  import java.beans.PropertyChangeListener;
33    
 import java.text.NumberFormat;  
   
 import java.util.logging.Level;  
   
 import javax.swing.Action;  
 import javax.swing.BorderFactory;  
 import javax.swing.Box;  
34  import javax.swing.BoxLayout;  import javax.swing.BoxLayout;
35  import javax.swing.DefaultListCellRenderer;  import javax.swing.DefaultListCellRenderer;
36  import javax.swing.JButton;  import javax.swing.JButton;
 import javax.swing.JComboBox;  
37  import javax.swing.JComponent;  import javax.swing.JComponent;
 import javax.swing.JLabel;  
 import javax.swing.JMenuItem;  
38  import javax.swing.JPanel;  import javax.swing.JPanel;
 import javax.swing.JPopupMenu;  
39  import javax.swing.JScrollPane;  import javax.swing.JScrollPane;
40  import javax.swing.JToggleButton;  import javax.swing.JToggleButton;
 import javax.swing.JToolBar;  
 import javax.swing.SwingConstants;  
 import javax.swing.Timer;  
41    
 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;  
42  import net.sf.juife.TitleBar;  import net.sf.juife.TitleBar;
43    
44  import org.jdesktop.swingx.JXCollapsiblePane;  import org.jdesktop.swingx.JXCollapsiblePane;
45    
 import org.jsampler.AudioDeviceModel;  
46  import org.jsampler.CC;  import org.jsampler.CC;
47  import org.jsampler.HF;  import org.jsampler.HF;
 import org.jsampler.MidiDeviceModel;  
 import org.jsampler.MidiInstrumentMap;  
48  import org.jsampler.SamplerChannelModel;  import org.jsampler.SamplerChannelModel;
 import org.jsampler.SamplerModel;  
49    
 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;  
50  import org.jsampler.event.SamplerChannelEvent;  import org.jsampler.event.SamplerChannelEvent;
51  import org.jsampler.event.SamplerChannelListEvent;  import org.jsampler.event.SamplerChannelListEvent;
52  import org.jsampler.event.SamplerChannelListListener;  import org.jsampler.event.SamplerChannelListListener;
53  import org.jsampler.event.SamplerChannelListener;  import org.jsampler.event.SamplerChannelListener;
 import org.jsampler.event.SamplerEvent;  
 import org.jsampler.event.SamplerListener;  
   
 import org.jsampler.view.std.JSChannelOutputRoutingDlg;  
 import org.jsampler.view.std.JSFxSendsPane;  
 import org.jsampler.view.std.JSInstrumentChooser;  
 import org.jsampler.view.std.JSVolumeEditorPopup;  
54    
 import org.jvnet.substance.SubstanceImageCreator;  
   
 import org.linuxsampler.lscp.AudioOutputDevice;  
 import org.linuxsampler.lscp.MidiInputDevice;  
 import org.linuxsampler.lscp.MidiPort;  
 import org.linuxsampler.lscp.SamplerChannel;  
 import org.linuxsampler.lscp.SamplerEngine;  
   
 import static org.jsampler.view.fantasia.FantasiaI18n.i18n;  
55  import static org.jsampler.view.fantasia.FantasiaPrefs.*;  import static org.jsampler.view.fantasia.FantasiaPrefs.*;
 import static org.jsampler.view.fantasia.FantasiaUtils.*;  
 import static org.jsampler.view.std.JSVolumeEditorPopup.VolumeType;  
56    
57    
58  /**  /**
# Line 119  import static org.jsampler.view.std.JSVo Line 61  import static org.jsampler.view.std.JSVo
61   */   */
62  public class Channel extends org.jsampler.view.JSChannel {  public class Channel extends org.jsampler.view.JSChannel {
63          private final JXCollapsiblePane mainPane;          private final JXCollapsiblePane mainPane;
64          private final ChannelScreen screen = new ChannelScreen(this);          private ChannelView channelView;
65          private final ChannelOptions optionsPane = new ChannelOptions(this);          private ChannelOptionsView channelOptionsView;
66            private final ChannelOptionsPane optionsPane = new ChannelOptionsPane();
67                    
68          private final PowerButton btnPower = new PowerButton();          private boolean selected = false;
         private final MuteButton btnMute = new MuteButton();  
         private final SoloButton btnSolo = new SoloButton();  
         private final OptionsButton btnOptions = new OptionsButton();  
69                    
70          private final EnhancedDial dialVolume = new EnhancedDial();          private AnimatedPorpetyListener animatedPorpetyListener = new AnimatedPorpetyListener();
71                    
72          private boolean selected = false;          class AnimatedPorpetyListener implements PropertyChangeListener {
73                    public void
74                    propertyChange(PropertyChangeEvent e) {
75                            mainPane.setAnimated(preferences().getBoolProperty(ANIMATED));
76                    }
77            }
78                    
79          /**          /**
80           * Creates a new instance of <code>Channel</code> using the specified           * Creates a new instance of <code>Channel</code> using the specified
# Line 155  public class Channel extends org.jsample Line 100  public class Channel extends org.jsample
100                  super(model);                  super(model);
101                                    
102                  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);  
103                  optionsPane.setAlignmentX(JPanel.CENTER_ALIGNMENT);                  optionsPane.setAlignmentX(JPanel.CENTER_ALIGNMENT);
104                                    
105                  mainPane = new JXCollapsiblePane();                  mainPane = new JXCollapsiblePane();
# Line 249  public class Channel extends org.jsample Line 107  public class Channel extends org.jsample
107                          new BoxLayout(mainPane.getContentPane(), BoxLayout.Y_AXIS)                          new BoxLayout(mainPane.getContentPane(), BoxLayout.Y_AXIS)
108                  );                  );
109                                    
110                  mainPane.add(p);                  channelView = new NormalChannelView(this);
111                    channelOptionsView = channelView.getChannelOptionsView();
112                    
113                    optionsPane.setContentPane(channelOptionsView.getComponent());
114                    
115                    mainPane.add(channelView.getComponent());
116                  mainPane.add(optionsPane);                  mainPane.add(optionsPane);
117                                    
118                  setOpaque(false);                  setOpaque(false);
119                                    
                 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());  
                         }  
                 });  
                   
120                  getModel().addSamplerChannelListener(getHandler());                  getModel().addSamplerChannelListener(getHandler());
121                                    
122                  updateChannelInfo();                  updateChannelInfo();
# Line 293  public class Channel extends org.jsample Line 146  public class Channel extends org.jsample
146                  mainPane.setAnimated(preferences().getBoolProperty(ANIMATED));                  mainPane.setAnimated(preferences().getBoolProperty(ANIMATED));
147                  mainPane.setCollapsed(false);                  mainPane.setCollapsed(false);
148                                    
149                  preferences().addPropertyChangeListener(ANIMATED, new PropertyChangeListener() {                  preferences().addPropertyChangeListener(ANIMATED, animatedPorpetyListener);
                         public void  
                         propertyChange(PropertyChangeEvent e) {  
                                 mainPane.setAnimated(preferences().getBoolProperty(ANIMATED));  
                         }  
                 });  
150                                    
151                  if(listener != null) {                  if(listener != null) {
152                          javax.swing.SwingUtilities.invokeLater(new Runnable() {                          javax.swing.SwingUtilities.invokeLater(new Runnable() {
# Line 326  public class Channel extends org.jsample Line 174  public class Channel extends org.jsample
174                  sp.getViewport().scrollRectToVisible(new Rectangle(0, h - 2, 1, 1));                  sp.getViewport().scrollRectToVisible(new Rectangle(0, h - 2, 1, 1));
175          }          }
176                    
         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;  
         }  
           
177          /**          /**
178           * Determines whether the channel is selected.           * Determines whether the channel is selected.
179           * @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.
# Line 361  public class Channel extends org.jsample Line 199  public class Channel extends org.jsample
199          /** Shows the channel properties. */          /** Shows the channel properties. */
200          public void          public void
201          expandChannel(boolean animated) {          expandChannel(boolean animated) {
                 if(btnOptions.isSelected()) return;  
                   
202                  boolean b = optionsPane.isAnimated();                  boolean b = optionsPane.isAnimated();
203                  optionsPane.setAnimated(animated);                  optionsPane.setAnimated(animated);
204                  btnOptions.doClick();                  channelView.expandChannel();
205                  optionsPane.setAnimated(b);                  optionsPane.setAnimated(b);
206          }          }
207                    
           
         /** 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);  
         }  
           
208          /**          /**
209           * Updates the channel settings. This method is invoked when changes to the           * Updates the channel settings. This method is invoked when changes to the
210           * channel were made.           * channel were made.
211           */           */
212          private void          private void
213          updateChannelInfo() {          updateChannelInfo() {
214                  SamplerChannel sc = getChannelInfo();                  channelView.updateChannelInfo();
215                                    channelOptionsView.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);  
         }  
           
         /**  
          * Updates the mute button with the proper icon regarding to information obtained  
          * from <code>channel</code>.  
          * @param channel A <code>SamplerChannel</code> instance containing the new settings  
          * for this channel.  
          */  
         private void  
         updateMuteIcon(SamplerChannel channel) {  
                 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(); }  
                         });  
                 }  
216          }          }
217                    
218          protected void          protected void
219          onDestroy() {          onDestroy() {
220                  CC.getSamplerModel().removeSamplerChannelListListener(getHandler());                  CC.getSamplerModel().removeSamplerChannelListListener(getHandler());
221                    preferences().removePropertyChangeListener(ANIMATED, animatedPorpetyListener);
222                    
223                    channelView.uninstallView();
224                    channelOptionsView.uninstallView();
225            }
226                    
227            public void
228            remove() {
229                    if(!mainPane.isAnimated()) {
230                            CC.getSamplerModel().removeBackendChannel(getChannelId());
231                            return;
232                    }
233                                    
234                  screen.onDestroy();                  String s = JXCollapsiblePane.ANIMATION_STATE_KEY;
235                  optionsPane.onDestroy();                  mainPane.addPropertyChangeListener(s, getHandler());
236                    mainPane.setCollapsed(true);
237          }          }
238                    
239            public void
240            showOptionsPane(boolean show) { optionsPane.showOptionsPane(show); }
241            
242          private final EventHandler eventHandler = new EventHandler();          private final EventHandler eventHandler = new EventHandler();
243                    
244          private EventHandler          private EventHandler
245          getHandler() { return eventHandler; }          getHandler() { return eventHandler; }
246                    
247          private class EventHandler implements SamplerChannelListener, SamplerChannelListListener {          private class EventHandler implements SamplerChannelListener,
248                                            SamplerChannelListListener, PropertyChangeListener {
249                  /**                  /**
250                   * Invoked when changes are made to a sampler channel.                   * Invoked when changes are made to a sampler channel.
251                   * @param e A <code>SamplerChannelEvent</code> instance                   * @param e A <code>SamplerChannelEvent</code> instance
# Line 493  public class Channel extends org.jsample Line 261  public class Channel extends org.jsample
261                   */                   */
262                  public void                  public void
263                  streamCountChanged(SamplerChannelEvent e) {                  streamCountChanged(SamplerChannelEvent e) {
264                          screen.updateStreamCount(getModel().getStreamCount());                          channelView.updateStreamCount(getModel().getStreamCount());
265                  }                  }
266                    
267                  /**                  /**
# Line 503  public class Channel extends org.jsample Line 271  public class Channel extends org.jsample
271                   */                   */
272                  public void                  public void
273                  voiceCountChanged(SamplerChannelEvent e) {                  voiceCountChanged(SamplerChannelEvent e) {
274                          screen.updateVoiceCount(getModel().getVoiceCount());                          channelView.updateVoiceCount(getModel().getVoiceCount());
275                  }                  }
276                                    
277                  /**                  /**
# Line 526  public class Channel extends org.jsample Line 294  public class Channel extends org.jsample
294                                  onDestroy();                                  onDestroy();
295                          }                          }
296                  }                  }
         }  
           
           
         private class PowerButton extends PixmapToggleButton  
                         implements ActionListener, PropertyChangeListener {  
                   
                 PowerButton() {  
                         super(Res.gfxPowerOff, Res.gfxPowerOn);  
                   
                         setSelected(true);  
                         addActionListener(this);  
                         setToolTipText(i18n.getButtonLabel("Channel.ttRemoveChannel"));  
                 }  
                   
                 public void  
                 actionPerformed(ActionEvent e) {  
                         boolean b = preferences().getBoolProperty(CONFIRM_CHANNEL_REMOVAL);  
                         if(b) {  
                                 String s = i18n.getMessage("Channel.remove?", getChannelId());  
                                 if(!HF.showYesNoDialog(Channel.this, s)) {  
                                         setSelected(true);  
                                         return;  
                                 }  
                         }  
                         remove();  
                 }  
                   
                 private void  
                 remove() {  
                         if(!mainPane.isAnimated()) {  
                                 CC.getSamplerModel().removeBackendChannel(getChannelId());  
                                 return;  
                         }  
                           
                         String s = JXCollapsiblePane.ANIMATION_STATE_KEY;  
                         mainPane.addPropertyChangeListener(s, this);  
                         mainPane.setCollapsed(true);  
                 }  
297                                    
298                  public void                  public void
299                  propertyChange(PropertyChangeEvent e) {                  propertyChange(PropertyChangeEvent e) {
# Line 571  public class Channel extends org.jsample Line 301  public class Channel extends org.jsample
301                                  CC.getSamplerModel().removeBackendChannel(getChannelId());                                  CC.getSamplerModel().removeBackendChannel(getChannelId());
302                          }                          }
303                  }                  }
                   
                 public boolean  
                 contains(int x, int y) { return (x - 11)*(x - 11) + (y - 11)*(y - 11) < 71; }  
         }  
           
         private class MuteButton extends PixmapButton implements ActionListener {  
                 MuteButton() {  
                         super(Res.gfxMuteOff);  
                         //setDisabledIcon(Res.gfxMuteSoloDisabled);  
                         setDisabledIcon (  
                                 SubstanceImageCreator.makeTransparent(this, Res.gfxMuteOff, 0.4)  
                         );  
                         addActionListener(this);  
                 }  
                   
                 public void  
                 actionPerformed(ActionEvent e) {  
                         SamplerChannel sc = getChannelInfo();  
                         boolean b = true;  
                   
                         /*  
                          * Changing the mute button icon now instead of  
                          * leaving the work to the notification mechanism of the LinuxSampler.  
                          */  
                         if(sc.isMuted() && !sc.isMutedBySolo()) {  
                                 b = false;  
                                 boolean hasSolo = CC.getSamplerModel().hasSoloChannel();  
                           
                                 if(sc.isSoloChannel() || !hasSolo) setIcon(Res.gfxMuteOff);  
                                 else setIcon(Res.gfxMutedBySolo);  
                         } else setIcon(Res.gfxMuteOn);  
                           
                         Channel.this.getModel().setBackendMute(b);  
                 }  
                   
                 public boolean  
                 contains(int x, int y) { return (x > 5 && x < 23) && (y > 5 && y < 16); }  
         }  
           
         private class SoloButton extends PixmapButton implements ActionListener {  
                 SoloButton() {  
                         super(Res.gfxSoloOff);  
                         //setDisabledIcon(Res.gfxMuteSoloDisabled);  
                         setDisabledIcon (  
                                 SubstanceImageCreator.makeTransparent(this, Res.gfxSoloOff, 0.4)  
                         );  
                         addActionListener(this);  
                 }  
                   
                 public void  
                 actionPerformed(ActionEvent e) {  
                         SamplerChannel sc = getChannelInfo();  
                         boolean b = !sc.isSoloChannel();  
                   
                         /*  
                          * Changing the solo button icon (and related) now instead of  
                          * leaving the work to the notification mechanism of the LinuxSampler.  
                          */  
                         if(b) {  
                                 setIcon(Res.gfxSoloOn);  
                                 if(sc.isMutedBySolo()) btnMute.setIcon(Res.gfxMuteOff);  
                         } else {  
                                 setIcon(Res.gfxSoloOff);  
                                 if(!sc.isMuted() && CC.getSamplerModel().getSoloChannelCount() > 1)  
                                         btnMute.setIcon(Res.gfxMutedBySolo);  
                         }  
                   
                         Channel.this.getModel().setBackendSolo(b);  
                 }  
                   
                 public boolean  
                 contains(int x, int y) { return (x > 5 && x < 23) && (y > 5 && y < 16); }  
         }  
           
         private class OptionsButton extends PixmapToggleButton implements ActionListener {  
                 OptionsButton() {  
                         super(Res.gfxOptionsOff, Res.gfxOptionsOn);  
                         setRolloverIcon(Res.gfxOptionsOffRO);  
                         this.setRolloverSelectedIcon(Res.gfxOptionsOnRO);  
                         addActionListener(this);  
                         setToolTipText(i18n.getButtonLabel("Channel.ttShowOptions"));  
                 }  
                   
                 public void  
                 actionPerformed(ActionEvent e) {  
                         showOptionsPane(isSelected());  
                           
                         String s;  
                         if(isSelected()) s = i18n.getButtonLabel("Channel.ttHideOptions");  
                         else s = i18n.getButtonLabel("Channel.ttShowOptions");  
                           
                         setToolTipText(s);  
                 }  
                   
                 private void  
                 showOptionsPane(boolean show) {  
                         optionsPane.setCollapsed(!show);  
                 }  
                   
                 public boolean  
                 contains(int x, int y) { return super.contains(x, y) & y < 13; }  
         }  
 }  
   
 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));  
                   
                 this.channel = channel;  
                 popupVolume = new JSVolumeEditorPopup(btnVolume, VolumeType.CHANNEL);  
                   
                 setOpaque(false);  
                   
                 setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));  
                   
                 btnInstr.setAlignmentX(CENTER_ALIGNMENT);  
                 btnInstr.setRolloverEnabled(false);  
                 btnInstr.setBorder(BorderFactory.createEmptyBorder(3, 0, 0, 0));  
                   
                 instrumentPane = new InstrumentPane();  
                 add(instrumentPane);  
                   
                 JPanel p = new JPanel();  
                 p.setLayout(new BoxLayout(p, BoxLayout.X_AXIS));  
                 p.setAlignmentX(CENTER_ALIGNMENT);  
                 p.setBorder(BorderFactory.createEmptyBorder(5, 2, 0, 0));  
                   
                 btnFxSends.setToolTipText(i18n.getButtonLabel("ChannelScreen.btnFxSends.tt"));  
                 btnFxSends.addActionListener(new ActionListener() {  
                         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);  
                         }  
                 });  
                   
                 p.add(btnFxSends);  
                   
                 //p.add(Box.createRigidArea(new Dimension(6, 0)));  
                 p.add(Box.createGlue());  
                   
                 btnEngine.setIcon(Res.iconEngine12);  
                 btnEngine.setIconTextGap(1);  
                 p.add(btnEngine);  
                 //p.add(new Label("|"));  
                   
                 //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);  
                   
                 btnVolume.addActionListener(new ActionListener() {  
                         public void  
                         actionPerformed(ActionEvent e) {  
                                 if(popupVolume.isVisible()) {  
                                         popupVolume.commit();  
                                         popupVolume.hide();  
                                 } else {  
                                         float vol = channel.getModel().getChannelInfo().getVolume();  
                                         popupVolume.setCurrentVolume(vol);  
                                         popupVolume.show();  
                                 }  
                         }  
                 });  
                   
                 popupVolume.addActionListener(new ActionListener() {  
                         public void  
                         actionPerformed(ActionEvent e) {  
                                 channel.getModel().setBackendVolume(popupVolume.getVolumeFactor());  
                         }  
                 });  
                   
                 p.add(btnVolume);  
                 p.setPreferredSize(new Dimension(260, p.getPreferredSize().height));  
                 p.setMinimumSize(p.getPreferredSize());  
                 p.setMaximumSize(p.getPreferredSize());  
                   
                 //btnInstr.setBorder(BorderFactory.createEmptyBorder(3, 3, 3, 3));  
                 p.setOpaque(false);  
                 add(p);  
                   
                   
                 setPreferredSize(new Dimension(270, 48));  
                 setMinimumSize(getPreferredSize());  
                 setMaximumSize(getPreferredSize());  
                   
                 createEngineMenu();  
                 installListeners();  
         }  
           
         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());  
                           
                         mi.addActionListener(new ActionListener() {  
                                 public void  
                                 actionPerformed(ActionEvent e) {  
                                         channel.getModel().setBackendEngineType(engine.getName());  
                                 }  
                         });  
                           
                         menuEngines.add(mi);  
                 }  
         }  
           
         private void  
         installListeners() {  
                 btnInstr.addActionListener(new ActionListener() {  
                         public void  
                         actionPerformed(ActionEvent e) { loadInstrument(); }  
                 });  
                   
                 btnEditInstr.addActionListener(new ActionListener() {  
                         public void  
                         actionPerformed(ActionEvent e) {  
                                 CC.getSamplerModel().editBackendInstrument(channel.getChannelId());  
                         }  
                 });  
                   
                 btnEngine.addActionListener(new ActionListener() {  
                         public void  
                         actionPerformed(ActionEvent e) {  
                                 int y = btnEngine.getHeight() + 1;  
                                 menuEngines.show(btnEngine, 0, y);  
                         }  
                 });  
                   
                 addMouseListener(getHandler());  
                 addHierarchyListener(getHandler());  
                   
                 ActionListener l = new ActionListener() {  
                         public void  
                         actionPerformed(ActionEvent e) {  
                                 if(getMousePosition(true) != null) {  
                                         getHandler().mouseEntered(null);  
                                 } else {  
                                         getHandler().mouseExited(null);  
                                 }  
                         }  
                 };  
                 timer = new Timer(1000, l);  
                 timer.start();  
         }  
           
         private void  
         loadInstrument() {  
                 JSInstrumentChooser dlg = FantasiaUtils.createInstrumentChooser(CC.getMainFrame());  
                 dlg.setVisible(true);  
                   
                 if(!dlg.isCancelled()) {  
                         SamplerChannelModel m = channel.getModel();  
                         m.loadBackendInstrument(dlg.getInstrumentFile(), dlg.getInstrumentIndex());  
                 }  
         }  
           
         protected void  
         updateScreenInfo(SamplerChannel sc) {  
                 int status = sc.getInstrumentStatus();  
                 if(status >= 0 && status < 100) {  
                         btnInstr.setText(i18n.getLabel("ChannelScreen.loadingInstrument", status));  
                 } 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());  
                         }  
                 }  
                   
         }  
           
         protected void  
         updateVolumeInfo(int volume) {  
                 if(CC.getViewConfig().isMeasurementUnitDecibel()) {  
                         String s = numberFormat.format(HF.percentsToDecibels(volume));  
                         btnVolume.setText(s + "dB");  
                 } else {  
                         btnVolume.setText(String.valueOf(volume) + "%");  
                 }  
         }  
           
         /**  
          * Updates the number of active disk streams.  
          * @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);  
         }  
           
         class InstrumentPane extends JPanel {  
                 private final JPanel leftPane = new JPanel();  
                 private final JPanel rightPane = new JPanel();  
                   
                 InstrumentPane() {  
                         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));  
                           
                         update();  
                 }  
                   
                 public void  
                 update() {  
                         int a = btnInstr.getMinimumSize().width;  
                         int b = 0;  
                         if(sbbEditInstr.isVisible()) b = sbbEditInstr.getPreferredSize().width;  
                           
                         int max = 254 - b;  
                         if(a > max) a = max;  
                           
                         int h = btnInstr.getPreferredSize().height;  
                         btnInstr.setPreferredSize(new Dimension(a, h));  
                         h = btnInstr.getMaximumSize().height;  
                         btnInstr.setMaximumSize(new Dimension(a, h));  
                           
                           
                         int i = (254 - btnInstr.getPreferredSize().width) / 2;  
                           
                         int j = i;  
                         if(sbbEditInstr.isVisible()) j -= sbbEditInstr.getPreferredSize().width;  
                         if(i < 0 || j < 0) i = j = 0;  
                           
                         Dimension d = new Dimension(i, 1);  
                         leftPane.setMinimumSize(d);  
                         leftPane.setPreferredSize(d);  
                         leftPane.setMaximumSize(d);  
                           
                         d = new Dimension(j, 1);  
                         rightPane.setMinimumSize(d);  
                         rightPane.setPreferredSize(d);  
                         rightPane.setMaximumSize(d);  
                           
                         validate();  
                 }  
         }  
           
         class FxSendsPane extends JSFxSendsPane {  
                 FxSendsPane(SamplerChannelModel model) {  
                         super(model);  
                           
                         actionAddFxSend.putValue(Action.SMALL_ICON, Res.iconNew16);  
                         actionRemoveFxSend.putValue(Action.SMALL_ICON, Res.iconDelete16);  
                 }  
                   
                 protected JToolBar  
                 createToolBar() {  
                         JToolBar tb = new JToolBar();  
                         Dimension d = new Dimension(Short.MAX_VALUE, tb.getPreferredSize().height);  
                         tb.setMaximumSize(d);  
                         tb.setFloatable(false);  
                         tb.setAlignmentX(JPanel.RIGHT_ALIGNMENT);  
                           
                         tb.add(new ToolbarButton(actionAddFxSend));  
                         tb.add(new ToolbarButton(actionRemoveFxSend));  
                   
                         return tb;  
                 }  
         }  
           
         static class ScreenButtonBg extends PixmapPane {  
                 ScreenButtonBg(JButton btn) {  
                         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));  
                 }  
                   
                 public Dimension  
                 getPreferredSize() {  
                         return new Dimension(super.getPreferredSize().width, 13);  
                 }  
         }  
           
           
         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;  
                           
                         if(!sbbEditInstr.isVisible()) {  
                                 sbbEditInstr.setVisible(true);  
                                 instrumentPane.update();  
                         }  
                 }  
                   
                 public void  
                 mouseExited(MouseEvent e)  {  
                         if(getMousePosition(true) != null) return;  
                         if(sbbEditInstr.isVisible()) {  
                                 sbbEditInstr.setVisible(false);  
                                 instrumentPane.update();  
                         }  
                 }  
                   
                 /** Called when the hierarchy has been changed. */  
                 public void  
                 hierarchyChanged(HierarchyEvent e) {  
                         if((e.getChangeFlags() & e.SHOWING_CHANGED) == e.SHOWING_CHANGED) {  
                                 if(getMousePosition() == null) mouseExited(null);  
                                 else mouseEntered(null);  
                         }  
                 }  
304          }          }
305  }  }
306    
307  class ChannelOptions extends JXCollapsiblePane {  class ChannelOptionsPane extends JXCollapsiblePane {
308          private final Channel channel;          ChannelOptionsPane() {
         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();  
           
         ChannelOptions(final Channel channel) {  
309                  setAnimated(false);                  setAnimated(false);
310                  setCollapsed(true);                  setCollapsed(true);
311                  setAnimated(preferences().getBoolProperty(ANIMATED));                  setAnimated(preferences().getBoolProperty(ANIMATED));
# Line 1144  class ChannelOptions extends JXCollapsib Line 316  class ChannelOptions extends JXCollapsib
316                                  setAnimated(preferences().getBoolProperty(ANIMATED));                                  setAnimated(preferences().getBoolProperty(ANIMATED));
317                          }                          }
318                  });                  });
                   
                 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"));  
                   
                 btnChannelRouting.addActionListener(new ActionListener() {  
                         public void  
                         actionPerformed(ActionEvent e) {  
                                 SamplerChannel c = channel.getChannelInfo();  
                                 new JSChannelOutputRoutingDlg(CC.getMainFrame(), c).setVisible(true);  
                           
                         }  
                 });  
                   
                 p2.add(btnChannelRouting);  
                   
                 p.add(p2);  
                 p.setBackground(new java.awt.Color(0x818181));  
                 p2 = new JPanel();  
                 p2.setLayout(new java.awt.BorderLayout());  
                 p.add(p2);  
                 bgp.add(p);  
                   
                 setContentPane(bgp);  
                   
                 cbMidiDevice.addActionListener(new ActionListener() {  
                         public void  
                         actionPerformed(ActionEvent e) { setMidiDevice(); }  
                 });  
                   
                 cbMidiPort.addActionListener(new ActionListener() {  
                         public void  
                         actionPerformed(ActionEvent e) { setMidiPort(); }  
                 });  
                   
                 cbMidiChannel.addActionListener(new ActionListener() {  
                         public void  
                         actionPerformed(ActionEvent e) { setMidiChannel(); }  
                 });  
                   
                 samplerListener = new SamplerAdapter() {  
                         /** Invoked when the default MIDI instrument map is changed. */  
                         public void  
                         defaultMapChanged(SamplerEvent e) {  
                                 updateCbInstrumentMapToolTipText();  
                                   
                         }  
                 };  
                   
                 CC.getSamplerModel().addSamplerListener(samplerListener);  
                   
                 cbInstrumentMap.addItem(noMap);  
                 cbInstrumentMap.addItem(defaultMap);  
                 for(MidiInstrumentMap map : CC.getSamplerModel().getMidiInstrumentMaps()) {  
                         cbInstrumentMap.addItem(map);  
                 }  
                   
                 int map = channel.getModel().getChannelInfo().getMidiInstrumentMapId();  
                 cbInstrumentMap.setSelectedItem(CC.getSamplerModel().getMidiInstrumentMapById(map));  
                 if(cbInstrumentMap.getSelectedItem() == null) {  
                         if(map == -1) cbInstrumentMap.setSelectedItem(noMap);  
                         else if(map == -2) {  
                                 cbInstrumentMap.setSelectedItem(defaultMap);  
                         }  
                 }  
                   
                 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();  
         }  
           
         /**  
          * Updates the channel settings. This method is invoked when changes to the  
          * 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!");  
                   
                 setUpdate(true);  
                   
                 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);  
                 }  
                   
                 if(sc.getEngine() != null) {  
                         cbInstrumentMap.setEnabled(true);  
                         int id = sc.getMidiInstrumentMapId();  
                         Object o;  
                         if(id == -2) o = defaultMap;  
                         else if(id == -1) o = noMap;  
                         else o = CC.getSamplerModel().getMidiInstrumentMapById(id);  
                           
                         if(cbInstrumentMap.getSelectedItem() != o) {  
                                 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();  
                   
                 setUpdate(true);  
                   
                 try {  
                         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);  
                 }  
                   
                 setUpdate(false);  
         }  
           
           
         private void  
         updateInstrumentMap() {  
                 updateCbInstrumentMapToolTipText();  
                   
                 int id = channel.getModel().getChannelInfo().getMidiInstrumentMapId();  
                 Object o = cbInstrumentMap.getSelectedItem();  
                 if(o == null && id == -1) return;  
                   
                 int cbId;  
                 if(o == null || o == noMap) cbId = -1;  
                 else if(o == defaultMap) cbId = -2;  
                 else cbId = ((MidiInstrumentMap)o).getMapId();  
                   
                 if(cbId == id) return;  
                   
                 channel.getModel().setBackendMidiInstrumentMap(cbId);  
         }  
           
         private void  
         updateCbInstrumentMapToolTipText() {  
                 if(cbInstrumentMap.getSelectedItem() != defaultMap) {  
                         cbInstrumentMap.setToolTipText(null);  
                         return;  
                 }  
                   
                 MidiInstrumentMap m = CC.getSamplerModel().getDefaultMidiInstrumentMap();  
                 if(m != null) {  
                         String s = i18n.getLabel("Channel.ttDefault", m.getName());  
                         cbInstrumentMap.setToolTipText(s);  
                 } else {  
                         cbInstrumentMap.setToolTipText(null);  
                 }  
         }  
           
         /**  
          * Updates the audio device list.  
          */  
         private void  
         updateAudioDevices() {  
                 SamplerModel sm = CC.getSamplerModel();  
                 SamplerChannel sc = channel.getModel().getChannelInfo();  
                   
                 setUpdate(true);  
                   
                 try {  
                         cbAudioDevice.removeAllItems();  
                   
                         for(AudioDeviceModel m : sm.getAudioDevices())  
                                 cbAudioDevice.addItem(m.getDeviceInfo());  
                   
                         AudioDeviceModel am = sm.getAudioDeviceById(sc.getAudioOutputDevice());  
                         cbAudioDevice.setSelectedItem(am == null ? null : am.getDeviceInfo());  
                 } 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());  
                         }  
                           
                         return;  
                 }  
                   
                 if(midiDevice != null) midiDevice.removeMidiDeviceListener(getHandler());  
                   
                 cbMidiPort.removeAllItems();  
                   
                 if(mid == null) {  
                         midiDevice = null;  
                         cbMidiPort.setEnabled(false);  
                           
                         cbMidiChannel.setSelectedItem(null);  
                         cbMidiChannel.setEnabled(false);  
                 } else {  
                         midiDevice = CC.getSamplerModel().getMidiDeviceById(mid.getDeviceId());  
                         if(midiDevice != null) midiDevice.addMidiDeviceListener(getHandler());  
                           
                         cbMidiPort.setEnabled(true);  
                           
                         MidiPort[] ports = mid.getMidiPorts();  
                         for(MidiPort port : ports) cbMidiPort.addItem(port);  
                           
                         int p = channel.getModel().getChannelInfo().getMidiInputPort();  
                         cbMidiPort.setSelectedItem(p >= 0 && p < ports.length ? ports[p] : null);  
                           
                         cbMidiChannel.setEnabled(true);  
                         int c = channel.getModel().getChannelInfo().getMidiInputChannel();  
                         cbMidiChannel.setSelectedItem(c == -1 ? "All" : "Channel " + (c + 1));  
                 }  
         }  
           
         private void  
         setMidiPort() {  
                 if(isUpdate()) return;  
                   
                 channel.getModel().setBackendMidiInputPort(cbMidiPort.getSelectedIndex());  
         }  
           
         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.  
                  */  
                 public void  
                 deviceAdded(MidiDeviceListEvent e) {  
                         cbMidiDevice.addItem(e.getMidiDeviceModel().getDeviceInfo());  
                 }  
           
                 /**  
                  * 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());  
                 }  
                   
                 /**  
                  * 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.  
                  */  
                 public void  
                 entryRemoved(ListEvent<AudioDeviceModel> e) {  
                         cbAudioDevice.removeItem(e.getEntry().getDeviceInfo());  
                 }  
                   
                 public void  
                 settingsChanged(MidiDeviceEvent e) {  
                         if(isUpdate()) {  
                                 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);  
                 }  
319          }          }
320                    
321          private class MapListListener implements ListListener<MidiInstrumentMap> {          public void
322                  /** Invoked when a new MIDI instrument map is added to a list. */          showOptionsPane(boolean show) { setCollapsed(!show); }
                 public void  
                 entryAdded(ListEvent<MidiInstrumentMap> e) {  
                         cbInstrumentMap.insertItemAt(e.getEntry(), cbInstrumentMap.getItemCount());  
                         boolean b = channel.getModel().getChannelInfo().getEngine() != null;  
                         if(b && !cbInstrumentMap.isEnabled()) cbInstrumentMap.setEnabled(true);  
                 }  
           
                 /** Invoked when a new MIDI instrument map is removed from a list. */  
                 public void  
                 entryRemoved(ListEvent<MidiInstrumentMap> e) {  
                         cbInstrumentMap.removeItem(e.getEntry());  
                         if(cbInstrumentMap.getItemCount() == 0) { // TODO: ?  
                                 cbInstrumentMap.setSelectedItem(noMap);  
                                 cbInstrumentMap.setEnabled(false);  
                         }  
                 }  
         }  
323  }  }

Legend:
Removed from v.1729  
changed lines
  Added in v.1730

  ViewVC Help
Powered by ViewVC