/[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 1496 by iliev, Mon Nov 19 22:22:22 2007 UTC revision 1743 by iliev, Sat May 31 23:04:01 2008 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 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.Cursor;  
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    
34  import java.beans.PropertyChangeEvent;  import java.beans.PropertyChangeEvent;
35  import java.beans.PropertyChangeListener;  import java.beans.PropertyChangeListener;
36    
37  import java.util.logging.Level;  import java.text.NumberFormat;
38    
39    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.ButtonGroup;
43  import javax.swing.DefaultListCellRenderer;  import javax.swing.DefaultListCellRenderer;
44    import javax.swing.ImageIcon;
45  import javax.swing.JButton;  import javax.swing.JButton;
46  import javax.swing.JComboBox;  import javax.swing.JComponent;
47  import javax.swing.JLabel;  import javax.swing.JLabel;
48  import javax.swing.JMenuItem;  import javax.swing.JMenuItem;
49  import javax.swing.JPanel;  import javax.swing.JPanel;
50  import javax.swing.JPopupMenu;  import javax.swing.JPopupMenu;
51    import javax.swing.JRadioButtonMenuItem;
52  import javax.swing.JScrollPane;  import javax.swing.JScrollPane;
53  import javax.swing.JToggleButton;  import javax.swing.JToggleButton;
54  import javax.swing.JToolBar;  import javax.swing.JToolBar;
 import javax.swing.SwingConstants;  
 import javax.swing.Timer;  
55    
 import javax.swing.event.ChangeEvent;  
 import javax.swing.event.ChangeListener;  
   
 import net.sf.juife.Dial;  
56  import net.sf.juife.InformationDialog;  import net.sf.juife.InformationDialog;
 import net.sf.juife.JuifeUtils;  
57  import net.sf.juife.TitleBar;  import net.sf.juife.TitleBar;
58    
59  import org.jdesktop.swingx.JXCollapsiblePane;  import org.jdesktop.swingx.JXCollapsiblePane;
60    
 import org.jsampler.AudioDeviceModel;  
61  import org.jsampler.CC;  import org.jsampler.CC;
62  import org.jsampler.MidiDeviceModel;  import org.jsampler.HF;
 import org.jsampler.MidiInstrumentMap;  
63  import org.jsampler.SamplerChannelModel;  import org.jsampler.SamplerChannelModel;
 import org.jsampler.SamplerModel;  
64    
 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;  
65  import org.jsampler.event.SamplerChannelEvent;  import org.jsampler.event.SamplerChannelEvent;
66  import org.jsampler.event.SamplerChannelListEvent;  import org.jsampler.event.SamplerChannelListEvent;
67  import org.jsampler.event.SamplerChannelListListener;  import org.jsampler.event.SamplerChannelListListener;
68  import org.jsampler.event.SamplerChannelListener;  import org.jsampler.event.SamplerChannelListener;
69  import org.jsampler.event.SamplerEvent;  
70  import org.jsampler.event.SamplerListener;  import org.jsampler.view.JSChannel;
71    import org.jsampler.view.JSChannelsPane;
72    
73  import org.jsampler.view.std.JSChannelOutputRoutingDlg;  import org.jsampler.view.std.JSChannelOutputRoutingDlg;
74    import org.jsampler.view.std.JSFxSendsDlg;
75  import org.jsampler.view.std.JSFxSendsPane;  import org.jsampler.view.std.JSFxSendsPane;
76  import org.jsampler.view.std.JSInstrumentChooser;  import org.jsampler.view.std.JSInstrumentChooser;
77    import org.jsampler.view.std.JSVolumeEditorPopup;
78    
 import org.jvnet.lafwidget.animation.FadeConfigurationManager;  
 import org.jvnet.lafwidget.animation.FadeKind;  
   
 import org.jvnet.substance.SubstanceImageCreator;  
 import org.jvnet.substance.SubstanceLookAndFeel;  
   
 import org.linuxsampler.lscp.AudioOutputDevice;  
 import org.linuxsampler.lscp.MidiInputDevice;  
 import org.linuxsampler.lscp.MidiPort;  
79  import org.linuxsampler.lscp.SamplerChannel;  import org.linuxsampler.lscp.SamplerChannel;
 import org.linuxsampler.lscp.SamplerEngine;  
80    
81  import static org.jsampler.view.fantasia.FantasiaI18n.i18n;  import static org.jsampler.view.fantasia.FantasiaI18n.i18n;
82  import static org.jsampler.view.fantasia.FantasiaPrefs.*;  import static org.jsampler.view.fantasia.FantasiaPrefs.*;
83    import static org.jsampler.view.fantasia.FantasiaUtils.*;
84    import static org.jsampler.view.std.JSVolumeEditorPopup.VolumeType;
85    
86    
87  /**  /**
88   *   *
89   * @author Grigor Iliev   * @author Grigor Iliev
90   */   */
91  public class Channel extends org.jsampler.view.JSChannel {  public class Channel extends JSChannel {
92          private final JXCollapsiblePane mainPane;          private final JXCollapsiblePane mainPane;
93          private final ChannelScreen screen = new ChannelScreen(this);          private final ChannelOptionsPane optionsPane = new ChannelOptionsPane();
94          private final ChannelOptions optionsPane = new ChannelOptions(this);          
95            private final ViewTracker viewTracker;
96                    
97          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();  
98                    
99          private final EnhancedDial dialVolume = new EnhancedDial();          private final ContextMenu contextMenu;
100                    
101          private boolean selected = false;          private boolean selected = false;
102                    
103            private AnimatedPorpetyListener animatedPorpetyListener = new AnimatedPorpetyListener();
104            
105            class AnimatedPorpetyListener implements PropertyChangeListener {
106                    public void
107                    propertyChange(PropertyChangeEvent e) {
108                            mainPane.setAnimated(preferences().getBoolProperty(ANIMATED));
109                    }
110            }
111            
112            ////////////////////////////////
113            // ******* Mouse tracker *******
114            ////////////////////////////////
115            private static int mouseOverChannelId = -1;
116            private static boolean mousePressed = false;
117            
118            private static ActionListener guiListener = null;
119            
120            private static Channel oldMouseOverChannel = null;
121            private static Channel newMouseOverChannel = null;
122            
123            
124            private static void
125            mouseMoved() {
126                    //TODO: do this for all channels panes
127                    JSChannelsPane cp = CC.getMainFrame().getChannelsPane(0);
128                    for(int i = 0; i < cp.getChannelCount(); i++) {
129                            mouseMoved((Channel)cp.getChannel(i));
130                    }
131                    
132                    if(oldMouseOverChannel == newMouseOverChannel) return;
133                    
134                    if(oldMouseOverChannel != null) oldMouseOverChannel.mouseExited();
135                    
136                    if(newMouseOverChannel != null) {
137                            mouseOverChannelId = newMouseOverChannel.getChannelId();
138                            newMouseOverChannel.mouseEntered();
139                    }
140                    
141                    oldMouseOverChannel = newMouseOverChannel = null;
142            }
143            
144            private static void
145            mouseMoved(Channel c) {
146                    int id = c.getChannelId();
147                    if(c.mainPane.getMousePosition(true) != null) {
148                            newMouseOverChannel = c;
149                    } else if(id == mouseOverChannelId) {
150                            oldMouseOverChannel = c;
151                    }
152            }
153            
154            ////////////////////////////////
155            
156            
157          /**          /**
158           * Creates a new instance of <code>Channel</code> using the specified           * Creates a new instance of <code>Channel</code> using the specified
159           * non-<code>null</code> channel model.           * non-<code>null</code> channel model.
# Line 153  public class Channel extends org.jsample Line 178  public class Channel extends org.jsample
178                  super(model);                  super(model);
179                                    
180                  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);  
181                  optionsPane.setAlignmentX(JPanel.CENTER_ALIGNMENT);                  optionsPane.setAlignmentX(JPanel.CENTER_ALIGNMENT);
182                                    
183                  mainPane = new JXCollapsiblePane();                  mainPane = new JXCollapsiblePane();
184                    viewTracker = new ViewTracker();
185                    contextMenu = new ContextMenu();
186                    
187                  mainPane.getContentPane().setLayout (                  mainPane.getContentPane().setLayout (
188                          new BoxLayout(mainPane.getContentPane(), BoxLayout.Y_AXIS)                          new BoxLayout(mainPane.getContentPane(), BoxLayout.Y_AXIS)
189                  );                  );
190                                    
191                  mainPane.add(p);                  int viewIdx = preferences().getIntProperty(DEFAULT_CHANNEL_VIEW);
192                  mainPane.add(optionsPane);                  if(viewIdx == 0) {
193                            viewTracker.setView(new SmallChannelView(Channel.this));
194                    } else if(viewIdx == 1) {
195                            viewTracker.setView(new NormalChannelView(Channel.this));
196                    } else {
197                            viewTracker.setView(new NormalChannelView(Channel.this));
198                    }
199                                    
200                  setOpaque(false);                  setOpaque(false);
201                                    
                 int i = preferences().getIntProperty(MAXIMUM_CHANNEL_VOLUME);  
                 dialVolume.setMaximum(i);  
                 String mcv = MAXIMUM_CHANNEL_VOLUME;  
                 preferences().addPropertyChangeListener(mcv, new PropertyChangeListener() {  
                         public void  
                         propertyChange(PropertyChangeEvent e) {  
                                 int j = preferences().getIntProperty(MAXIMUM_CHANNEL_VOLUME);  
                                 dialVolume.setMaximum(j);  
                         }  
                 });  
                   
202                  getModel().addSamplerChannelListener(getHandler());                  getModel().addSamplerChannelListener(getHandler());
203                                    
204                  updateChannelInfo();                  updateChannelInfo();
# Line 292  public class Channel extends org.jsample Line 228  public class Channel extends org.jsample
228                  mainPane.setAnimated(preferences().getBoolProperty(ANIMATED));                  mainPane.setAnimated(preferences().getBoolProperty(ANIMATED));
229                  mainPane.setCollapsed(false);                  mainPane.setCollapsed(false);
230                                    
231                  preferences().addPropertyChangeListener(ANIMATED, new PropertyChangeListener() {                  preferences().addPropertyChangeListener(ANIMATED, animatedPorpetyListener);
                         public void  
                         propertyChange(PropertyChangeEvent e) {  
                                 mainPane.setAnimated(preferences().getBoolProperty(ANIMATED));  
                         }  
                 });  
232                                    
233                  if(listener != null) {                  if(listener != null) {
234                          javax.swing.SwingUtilities.invokeLater(new Runnable() {                          javax.swing.SwingUtilities.invokeLater(new Runnable() {
# Line 307  public class Channel extends org.jsample Line 238  public class Channel extends org.jsample
238                  }                  }
239                                    
240                  CC.getSamplerModel().addSamplerChannelListListener(getHandler());                  CC.getSamplerModel().addSamplerChannelListListener(getHandler());
241                    
242                    installGuiListener();
243            }
244            
245            private static void
246            installGuiListener() {
247                    if(guiListener != null) return;
248                    
249                    guiListener = new ActionListener() {
250                            public void
251                            actionPerformed(ActionEvent e) {
252                                    mouseMoved();
253                            }
254                    };
255                    
256                    ((MainFrame)CC.getMainFrame()).getGuiTimer().addActionListener(guiListener);
257            }
258            
259            private void
260            mouseEntered() {
261                    viewTracker.mouseEntered();
262            }
263            
264            private void
265            mouseExited() {
266                    viewTracker.mouseExited();
267          }          }
268                    
269          private void          private void
# Line 325  public class Channel extends org.jsample Line 282  public class Channel extends org.jsample
282                  sp.getViewport().scrollRectToVisible(new Rectangle(0, h - 2, 1, 1));                  sp.getViewport().scrollRectToVisible(new Rectangle(0, h - 2, 1, 1));
283          }          }
284                    
         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;  
         }  
           
285          /**          /**
286           * Determines whether the channel is selected.           * Determines whether the channel is selected.
287           * @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 360  public class Channel extends org.jsample Line 307  public class Channel extends org.jsample
307          /** Shows the channel properties. */          /** Shows the channel properties. */
308          public void          public void
309          expandChannel(boolean animated) {          expandChannel(boolean animated) {
                 if(btnOptions.isSelected()) return;  
                   
310                  boolean b = optionsPane.isAnimated();                  boolean b = optionsPane.isAnimated();
311                  optionsPane.setAnimated(animated);                  optionsPane.setAnimated(animated);
312                  btnOptions.doClick();                  viewTracker.getCurrentView().expandChannel();
313                  optionsPane.setAnimated(b);                  optionsPane.setAnimated(b);
314          }          }
315                    
           
         /** 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);  
         }  
           
316          /**          /**
317           * Updates the channel settings. This method is invoked when changes to the           * Updates the channel settings. This method is invoked when changes to the
318           * channel were made.           * channel were made.
319           */           */
320          private void          private void
321          updateChannelInfo() {          updateChannelInfo() {
322                  SamplerChannel sc = getChannelInfo();                  viewTracker.getCurrentView().updateChannelInfo();
323                            }
324                  screen.updateScreenInfo(sc);          
325                  updateMuteIcon(sc);          public void
326                            loadInstrument() {
327                  if(sc.isSoloChannel()) btnSolo.setIcon(Res.gfxSoloOn);                  JSInstrumentChooser dlg = FantasiaUtils.createInstrumentChooser(CC.getMainFrame());
328                  else btnSolo.setIcon(Res.gfxSoloOff);                  dlg.setVisible(true);
                   
                 dialVolume.setValue((int)(sc.getVolume() * 100));  
329                                    
330                  boolean b = sc.getEngine() != null;                  if(!dlg.isCancelled()) {
331                  dialVolume.setEnabled(b);                          SamplerChannelModel m = getModel();
332                  btnSolo.setEnabled(b);                          m.loadBackendInstrument(dlg.getInstrumentFile(), dlg.getInstrumentIndex());
333                  btnMute.setEnabled(b);                  }
334          }          }
335                    
336          /**          public void
337           * Updates the mute button with the proper icon regarding to information obtained          fallbackToOriginalView() {
338           * from <code>channel</code>.                  viewTracker.fallbackToOriginalView();
          * @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);  
339          }          }
340                    
341          private class EnhancedDial extends Dial {          public boolean
342                  EnhancedDial() {          isUsingOriginalView() {
343                          super(0, 100);                  return viewTracker.isUsingOriginalView();
                           
                         setMouseHandlerMode(MouseHandlerMode.LEFT_TO_RIGHT_AND_DOWN_TO_UP);  
                           
                         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(); }  
                         });  
                 }  
344          }          }
345                    
346          protected void          protected void
347          onDestroy() {          onDestroy() {
348                  CC.getSamplerModel().removeSamplerChannelListListener(getHandler());                  CC.getSamplerModel().removeSamplerChannelListListener(getHandler());
349                    preferences().removePropertyChangeListener(ANIMATED, animatedPorpetyListener);
350                    if(fxSendsDlg != null) fxSendsDlg.dispose();
351                    viewTracker.onDestroy();
352            }
353                    
354            public void
355            remove() {
356                    if(!mainPane.isAnimated()) {
357                            CC.getSamplerModel().removeBackendChannel(getChannelId());
358                            return;
359                    }
360                                    
361                  screen.onDestroy();                  String s = JXCollapsiblePane.ANIMATION_STATE_KEY;
362                  optionsPane.onDestroy();                  mainPane.addPropertyChangeListener(s, getHandler());
363                    mainPane.setCollapsed(true);
364            }
365            
366            public void
367            showOptionsPane(boolean show) { optionsPane.showOptionsPane(show); }
368            
369            public void
370            showFxSendsDialog() {
371                    if(fxSendsDlg != null && fxSendsDlg.isVisible()) {
372                            fxSendsDlg.toFront();
373                            return;
374                    }
375                    
376                    fxSendsDlg = new JSFxSendsDlg(new FxSendsPane(getModel()));
377                    fxSendsDlg.setVisible(true);
378          }          }
379                    
380          private final EventHandler eventHandler = new EventHandler();          private final EventHandler eventHandler = new EventHandler();
# Line 467  public class Channel extends org.jsample Line 382  public class Channel extends org.jsample
382          private EventHandler          private EventHandler
383          getHandler() { return eventHandler; }          getHandler() { return eventHandler; }
384                    
385          private class EventHandler implements SamplerChannelListener, SamplerChannelListListener {          private class EventHandler implements SamplerChannelListener,
386                                            SamplerChannelListListener, PropertyChangeListener {
387                  /**                  /**
388                   * Invoked when changes are made to a sampler channel.                   * Invoked when changes are made to a sampler channel.
389                   * @param e A <code>SamplerChannelEvent</code> instance                   * @param e A <code>SamplerChannelEvent</code> instance
# Line 483  public class Channel extends org.jsample Line 399  public class Channel extends org.jsample
399                   */                   */
400                  public void                  public void
401                  streamCountChanged(SamplerChannelEvent e) {                  streamCountChanged(SamplerChannelEvent e) {
402                          screen.updateStreamCount(getModel().getStreamCount());                          viewTracker.getCurrentView().updateStreamCount(getModel().getStreamCount());
403                  }                  }
404                    
405                  /**                  /**
# Line 493  public class Channel extends org.jsample Line 409  public class Channel extends org.jsample
409                   */                   */
410                  public void                  public void
411                  voiceCountChanged(SamplerChannelEvent e) {                  voiceCountChanged(SamplerChannelEvent e) {
412                          screen.updateVoiceCount(getModel().getVoiceCount());                          viewTracker.getCurrentView().updateVoiceCount(getModel().getVoiceCount());
413                  }                  }
414                                    
415                  /**                  /**
# Line 516  public class Channel extends org.jsample Line 432  public class Channel extends org.jsample
432                                  onDestroy();                                  onDestroy();
433                          }                          }
434                  }                  }
         }  
           
           
         private class PowerButton extends PixmapToggleButton  
                         implements ActionListener, PropertyChangeListener {  
                   
                 PowerButton() {  
                         super(Res.gfxPowerOff, Res.gfxPowerOn);  
                   
                         setSelected(true);  
                         addActionListener(this);  
                 }  
                   
                 public void  
                 actionPerformed(ActionEvent e) {  
                         if(!mainPane.isAnimated()) {  
                                 CC.getSamplerModel().removeBackendChannel(getChannelId());  
                                 return;  
                         }  
                           
                         String s = JXCollapsiblePane.ANIMATION_STATE_KEY;  
                         mainPane.addPropertyChangeListener(s, this);  
                         mainPane.setCollapsed(true);  
                 }  
435                                    
436                  public void                  public void
437                  propertyChange(PropertyChangeEvent e) {                  propertyChange(PropertyChangeEvent e) {
# Line 547  public class Channel extends org.jsample Line 439  public class Channel extends org.jsample
439                                  CC.getSamplerModel().removeBackendChannel(getChannelId());                                  CC.getSamplerModel().removeBackendChannel(getChannelId());
440                          }                          }
441                  }                  }
                   
                 public boolean  
                 contains(int x, int y) { return (x - 11)*(x - 11) + (y - 11)*(y - 11) < 71; }  
442          }          }
443                    
444          private class MuteButton extends PixmapButton implements ActionListener {          
445                  MuteButton() {          
446                          super(Res.gfxMuteOff);          class ViewTracker extends MouseAdapter implements PropertyChangeListener {
447                          //setDisabledIcon(Res.gfxMuteSoloDisabled);                  private ChannelView originalView;
448                          setDisabledIcon (                  private ChannelView mouseOverView;
449                                  SubstanceImageCreator.makeTransparent(this, Res.gfxMuteOff, 0.4)                  private ChannelView currentView;
                         );  
                         addActionListener(this);  
                 }  
450                                    
451                  public void                  private ChannelView.Type mouseOverViewType = null;
                 actionPerformed(ActionEvent e) {  
                         SamplerChannel sc = getChannelInfo();  
                         boolean b = true;  
452                                    
453                          /*                  ViewTracker() {
454                           * Changing the mute button icon now instead of                          
455                           * leaving the work to the notification mechanism of the LinuxSampler.                          
456                           */                          updateMouseOverViewType();
                         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);  
457                                                    
458                          Channel.this.getModel().setBackendMute(b);                          String s = DIFFERENT_CHANNEL_VIEW_ON_MOUSE_OVER;
459                            preferences().addPropertyChangeListener(s, this);
460                            
461                            s = CHANNEL_VIEW_ON_MOUSE_OVER;
462                            preferences().addPropertyChangeListener(s, this);
463                  }                  }
464                                    
465                  public boolean                  public boolean
466                  contains(int x, int y) { return (x > 5 && x < 23) && (y > 5 && y < 16); }                  isUsingOriginalView() {
467          }                          return currentView == originalView;
           
         private class SoloButton extends PixmapButton implements ActionListener {  
                 SoloButton() {  
                         super(Res.gfxSoloOff);  
                         //setDisabledIcon(Res.gfxMuteSoloDisabled);  
                         setDisabledIcon (  
                                 SubstanceImageCreator.makeTransparent(this, Res.gfxSoloOff, 0.4)  
                         );  
                         addActionListener(this);  
468                  }                  }
469                                    
470                  public void                  private void
471                  actionPerformed(ActionEvent e) {                  installListeners() {
472                          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);  
473                  }                  }
474                                    
475                  public boolean                  private void
476                  contains(int x, int y) { return (x > 5 && x < 23) && (y > 5 && y < 16); }                  uninstallListeners() {
477          }                          
           
         private class OptionsButton extends PixmapToggleButton implements ActionListener {  
                 OptionsButton() {  
                         super(Res.gfxOptionsOff, Res.gfxOptionsOn);  
                         setRolloverIcon(Res.gfxOptionsOffRO);  
                         this.setRolloverSelectedIcon(Res.gfxOptionsOnRO);  
                         addActionListener(this);  
478                  }                  }
479                                    
480                  public void                  private void
481                  actionPerformed(ActionEvent e) {                  updateMouseOverViewType() {
482                          showOptionsPane(isSelected());                          if(mouseOverView != null) {
483                                    mouseOverView.removeEnhancedMouseListener(this);
484                            }
485                                                    
486                          String s;                          mouseOverView = null;
487                          if(isSelected()) s = i18n.getButtonLabel("OptionsButton.ttHideOptions");                          
488                          else s = i18n.getButtonLabel("OptionsButton.ttShowOptions");                          boolean b;
489                            b = preferences().getBoolProperty(DIFFERENT_CHANNEL_VIEW_ON_MOUSE_OVER);
490                            if(!b) {
491                                    mouseOverViewType = null;
492                                    uninstallListeners();
493                                    return;
494                            }
495                                                    
496                          setToolTipText(s);                          int i = preferences().getIntProperty(CHANNEL_VIEW_ON_MOUSE_OVER);
497                            
498                            switch(i) {
499                                    case 0: mouseOverViewType = ChannelView.Type.SMALL; break;
500                                    case 1: mouseOverViewType = ChannelView.Type.NORMAL; break;
501                                    default:mouseOverViewType = null;
502                            }
503                            
504                            if(mouseOverViewType != null) {
505                                    installListeners();
506                            }
507                  }                  }
508                                    
509                  private void                  public ChannelView
510                  showOptionsPane(boolean show) {                  getMouseOverView() {
511                          optionsPane.setCollapsed(!show);                          if(mouseOverViewType == null) return null;
512                            
513                            if(mouseOverView == null) {
514                                    Channel channel = Channel.this;
515                                    
516                                    switch(mouseOverViewType) {
517                                    case SMALL: mouseOverView = new SmallChannelView(channel); break;
518                                    case NORMAL: mouseOverView = new NormalChannelView(channel); break;
519                                    default: mouseOverView = new NormalChannelView(channel);
520                                    }
521                                    
522                                    mouseOverView.addEnhancedMouseListener(this);
523                            }
524                            
525                            return mouseOverView;
526                  }                  }
527                                    
528                  public boolean                  public ChannelView
529                  contains(int x, int y) { return super.contains(x, y) & y < 13; }                  getCurrentView() { return 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 = new ScreenButton(i18n.getButtonLabel("ChannelScreen.btnInstr"));  
           
         private final JButton btnEditInstr =  
                 new ScreenButton(i18n.getButtonLabel("ChannelScreen.btnEditInstr"));  
         private final ScreenButtonBg sbbEditInstr = new ScreenButtonBg(btnEditInstr);  
           
         private final JButton btnFxSends =  
                 new ScreenButton(i18n.getButtonLabel("ChannelScreen.btnFxSends"));  
           
         private final JButton btnEngine  
                 = new ScreenButton(i18n.getButtonLabel("ChannelScreen.btnEngine"));  
           
         private final JPopupMenu menuEngines = new JPopupMenu();  
           
         private final JLabel lVolume = new ScreenLabel("");  
         private final JLabel lStreams = new ScreenLabel(" --");  
         private final JLabel lVoices = new ScreenLabel("-- ");  
           
         private InformationDialog fxSendsDlg = null;  
           
         private Dimension dimVolume;  
           
         private Timer timer;  
           
         ChannelScreen(final Channel channel) {  
                 super(Res.gfxChannelScreen);  
                 setPixmapInsets(new Insets(6, 6, 6, 6));  
                 setBorder(BorderFactory.createEmptyBorder(5, 4, 5, 4));  
                   
                 this.channel = channel;  
                   
                 setOpaque(false);  
530                                    
531                  setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));                  public ChannelView
532                    getOriginalView() { return originalView; }
533                                    
534                  btnInstr.setAlignmentX(CENTER_ALIGNMENT);                  public void
535                  btnInstr.setRolloverEnabled(false);                  setView(ChannelView view) {
536                  btnInstr.setBorder(BorderFactory.createEmptyBorder(3, 0, 0, 0));                          setView(view, true);
537                                    }
                 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, 0, 0, 0));  
538                                    
539                  btnFxSends.setToolTipText(i18n.getButtonLabel("ChannelScreen.btnFxSends.tt"));                  public void
540                  btnFxSends.addActionListener(new ActionListener() {                  setView(ChannelView view, boolean manual) {
541                          public void                          boolean selected = false;
542                          actionPerformed(ActionEvent e) {                          if(currentView != null) selected = currentView.isOptionsButtonSelected();
543                                  if(fxSendsDlg != null && fxSendsDlg.isVisible()) {                          
544                                          fxSendsDlg.toFront();                          if(manual) {
545                                    if(originalView != null) {
546                                            originalView.removeEnhancedMouseListener(this);
547                                    }
548                                    
549                                    if(originalView != currentView) destroyOriginalView();
550                                    if(currentView != null && currentView.getType() == view.getType()) {
551                                            originalView = currentView;
552                                            originalView.addEnhancedMouseListener(this);
553                                            destroyView(view);
554                                            return;
555                                    }
556                                    
557                                    removeCurrentView();
558                                    
559                                    originalView = view;
560                                    originalView.addEnhancedMouseListener(this);
561                                    currentView = view;
562                            } else {
563                                    if(view.getType() == getCurrentView().getType()) {
564                                            destroyView(view);
565                                          return;                                          return;
566                                  }                                  }
567                                  FxSendsPane p = new FxSendsPane(channel.getModel());                                  
568                                  int id = channel.getModel().getChannelId();                                  removeCurrentView();
569                                  fxSendsDlg = new InformationDialog(CC.getMainFrame(), p);                                  currentView = view;
                                 fxSendsDlg.setTitle(i18n.getLabel("FxSendsDlg.title", id));  
                                 fxSendsDlg.setModal(false);  
                                 fxSendsDlg.showCloseButton(false);  
                                 fxSendsDlg.setVisible(true);  
570                          }                          }
571                  });                          
572                            currentView.setOptionsButtonSelected(selected);
573                            
574                            updateView();
575                    }
576                                    
577                  p.add(btnFxSends);                  private void
578                    updateView() {
579                            ChannelOptionsView view = getCurrentView().getChannelOptionsView();
580                            if(view != null) optionsPane.setContentPane(view.getComponent());
581                            
582                            updateChannelInfo();
583                                    
584                  p.add(Box.createRigidArea(new Dimension(6, 0)));                          mainPane.add(getCurrentView().getComponent());
585                            mainPane.add(optionsPane);
586                            mainPane.validate();
587                            mainPane.revalidate();
588                            mainPane.repaint();
589                    }
590                                    
591                  btnEngine.setIcon(Res.iconEngine12);                  public void
592                  p.add(btnEngine);                  fallbackToOriginalView() {
593                  //p.add(new Label("|"));                          if(currentView == originalView) return;
594                            
595                            boolean selected = false;
596                            if(currentView != null) selected = currentView.isOptionsButtonSelected();
597                            
598                            removeCurrentView();
599                            currentView = originalView;
600                            currentView.setOptionsButtonSelected(selected);
601                            
602                            updateView();
603                    }
604                                    
605                  //p.add(Box.createRigidArea(new Dimension(6, 0)));                  private void
606                    removeCurrentView() { removeView(currentView); }
607                                    
608                  //p.add(btnReset);                  private void
609                    destroyCurrentView() { destroyView(currentView); }
610                                    
611                  p.add(Box.createGlue());                  private void
612                    removeOriginalView() { removeView(originalView); }
613                                    
614                  lStreams.setFont(Res.fontScreenMono);                  private void
615                  lStreams.setHorizontalAlignment(JLabel.RIGHT);                  destroyOriginalView() { destroyView(originalView); }
                 p.add(lStreams);  
616                                    
617                  JLabel l = new ScreenLabel("/");                  private void
618                  l.setFont(Res.fontScreenMono);                  removeView(ChannelView view) {
619                  p.add(l);                          if(view == null) return;
620                            
621                            mainPane.remove(view.getComponent());
622                            mainPane.remove(optionsPane);
623                                    
624                            destroyView(view);
625                    }
626                                    
627                  lVoices.setFont(Res.fontScreenMono);                  private void
628                  p.add(lVoices);                  destroyView(ChannelView view) {
629                            if(view == null) return;
630                            
631                            view.uninstallView();
632                            
633                            view = null;
634                    }
635                                    
636                  lVolume.setIcon(Res.iconVolume14);                  public boolean
637                  lVolume.setAlignmentX(RIGHT_ALIGNMENT);                  isMouseOverEnabled() { return mouseOverViewType != null; }
                 updateVolumeInfo(100);  
                 dimVolume = lVolume.getPreferredSize();  
                 p.add(lVolume);  
                 p.setPreferredSize(new Dimension(250, p.getPreferredSize().height));  
                 p.setMinimumSize(p.getPreferredSize());  
                 p.setMaximumSize(p.getPreferredSize());  
638                                    
639                  //btnInstr.setBorder(BorderFactory.createEmptyBorder(3, 3, 3, 3));                  private void
640                  p.setOpaque(false);                  mouseEntered() {
641                  add(p);                          if(!isMouseOverEnabled()) return;
642                            if(getCurrentView().getType() == getMouseOverView().getType()) return;
643                            
644                            JSChannel[] channels = CC.getMainFrame().getChannelsPane(0).getChannels();
645                            for(JSChannel c : channels) {
646                                    if(c == Channel.this) continue;
647                                    
648                                    Channel chn = (Channel)c;
649                                    if(!(chn).isUsingOriginalView()) chn.fallbackToOriginalView();
650                            }
651                            
652                            setView(getMouseOverView(), false);
653                    }
654                                    
655                    private void
656                    mouseExited() {
657                            if(!isMouseOverEnabled()) return;
658                            if(getCurrentView().getType() == originalView.getType()) return;
659                            
660                            fallbackToOriginalView();
661                    }
662                                    
663                  setPreferredSize(new Dimension(270, 48));                  public void
664                  setMinimumSize(getPreferredSize());                  mouseEntered(MouseEvent e) {
665                  setMaximumSize(getPreferredSize());                          guiListener.actionPerformed(null);
666                    }
667                                    
668                  createEngineMenu();                  public void
669                  installListeners();                  mouseExited(MouseEvent e) {
670          }                          guiListener.actionPerformed(null);
671                            }
672          protected void                  
673          onDestroy() { timer.stop(); }                  public void
674                            mousePressed(MouseEvent e) {
675          private void                          mousePressed = true;
676          createEngineMenu() {                  }
677                  for(final SamplerEngine engine : CC.getSamplerModel().getEngines()) {                  
678                          JMenuItem mi = new JMenuItem(engine.getDescription());                  public void
679                    mouseReleased(MouseEvent e) {
680                            mousePressed = false;
681                    }
682                    
683                    public void
684                    onDestroy() {
685                            destroyCurrentView();
686                            destroyOriginalView();
687                                                    
688                          mi.addActionListener(new ActionListener() {                          uninstallListeners();
689                                  public void                          
690                                  actionPerformed(ActionEvent e) {                          if(currentView != null) {
691                                          channel.getModel().setBackendEngineType(engine.getName());                                  currentView.removeEnhancedMouseListener(this);
692                                  }                          }
693                          });                          
694                            if(mouseOverView != null) {
695                                    mouseOverView.removeEnhancedMouseListener(this);
696                            }
697                            
698                            String s = DIFFERENT_CHANNEL_VIEW_ON_MOUSE_OVER;
699                            preferences().removePropertyChangeListener(s, this);
700                                                    
701                          menuEngines.add(mi);                          s = CHANNEL_VIEW_ON_MOUSE_OVER;
702                            preferences().removePropertyChangeListener(s, this);
703                    }
704                    
705                    public void
706                    propertyChange(PropertyChangeEvent e) {
707                            updateMouseOverViewType();
708                  }                  }
709          }          }
710                    
711          private void          class EditInstrumentAction extends AbstractAction implements SamplerChannelListener {
712          installListeners() {                  EditInstrumentAction() {
713                  btnInstr.addActionListener(new ActionListener() {                          super(i18n.getMenuLabel("channels.editInstrument"));
714                          public void                          channelChanged(null);
715                          actionPerformed(ActionEvent e) { loadInstrument(); }                          getModel().addSamplerChannelListener(this);
716                  });                  }
717                                    
718                  btnEditInstr.addActionListener(new ActionListener() {                  public void
719                          public void                  actionPerformed(ActionEvent e) {
720                          actionPerformed(ActionEvent e) {                          CC.getSamplerModel().editBackendInstrument(getChannelId());
721                                  CC.getSamplerModel().editBackendInstrument(channel.getChannelId());                  }
                         }  
                 });  
722                                    
723                  btnEngine.addActionListener(new ActionListener() {                  public void
724                          public void                  channelChanged(SamplerChannelEvent e) {
725                          actionPerformed(ActionEvent e) {                          boolean b = getChannelInfo().getInstrumentStatus() == 100;
726                                  int y = btnEngine.getHeight() + 1;                          setEnabled(b);
727                                  menuEngines.show(btnEngine, 0, y);                  }
                         }  
                 });  
728                                    
729                  addMouseListener(getHandler());                  public void
730                  addHierarchyListener(getHandler());                  streamCountChanged(SamplerChannelEvent e) { }
731                                    
732                  ActionListener l = new ActionListener() {                  public void
733                          public void                  voiceCountChanged(SamplerChannelEvent e) { }
                         actionPerformed(ActionEvent e) {  
                                 if(getMousePosition(true) != null) {  
                                         getHandler().mouseEntered(null);  
                                 } else {  
                                         getHandler().mouseExited(null);  
                                 }  
                         }  
                 };  
                 timer = new Timer(1000, l);  
                 timer.start();  
734          }          }
735                    
736          private void          class FxSendsAction extends AbstractAction {
737          loadInstrument() {                  FxSendsAction() {
738                  JSInstrumentChooser dlg = FantasiaUtils.createInstrumentChooser(CC.getMainFrame());                          super(i18n.getMenuLabel("channels.fxSends"));
739                  dlg.setVisible(true);                  }
740                                    
741                  if(!dlg.isCancelled()) {                  public void
742                          SamplerChannelModel m = channel.getModel();                  actionPerformed(ActionEvent e) {
743                          m.loadBackendInstrument(dlg.getInstrumentFile(), dlg.getInstrumentIndex());                          showFxSendsDialog();
744                  }                  }
745          }          }
746                    
747          protected void          class ChannelRoutingAction extends AbstractAction implements SamplerChannelListener {
748          updateScreenInfo(SamplerChannel sc) {                  ChannelRoutingAction() {
749                  int status = sc.getInstrumentStatus();                          super(i18n.getMenuLabel("channels.channelRouting"));
750                  if(status >= 0 && status < 100) {                          channelChanged(null);
751                          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"));  
752                  }                  }
753                                    
754                  instrumentPane.update();                  public void
755                            actionPerformed(ActionEvent e) {
756                  if(sc.getEngine() != null) {                          SamplerChannel c = getChannelInfo();
757                          String s = sc.getEngine().getDescription();                          new JSChannelOutputRoutingDlg(CC.getMainFrame(), c).setVisible(true);
                         if(!s.equals(btnEngine.getText())) btnEngine.setText(s);  
758                  }                  }
759                                    
760                    public void
761                    channelChanged(SamplerChannelEvent e) {
762                            boolean b = getChannelInfo().getAudioOutputDevice() != -1;
763                            setEnabled(b);
764                    }
765                    
766                    public void
767                    streamCountChanged(SamplerChannelEvent e) { }
768                    
769                    public void
770                    voiceCountChanged(SamplerChannelEvent e) { }
771          }          }
772                    
773          protected void          class SetSmallViewAction extends AbstractAction {
774          updateVolumeInfo(int volume) {                  SetSmallViewAction() {
775                  lVolume.setText(i18n.getLabel("ChannelScreen.volume", volume));                          super(i18n.getMenuLabel("channels.smallView"));
776                  lVolume.setMinimumSize(dimVolume);                  }
                 lVolume.setPreferredSize(dimVolume);  
777                                    
778                    public void
779                    actionPerformed(ActionEvent e) {
780                            viewTracker.setView(new SmallChannelView(Channel.this));
781                    }
782          }          }
783                    
784          /**          class SetNormalViewAction extends AbstractAction {
785           * Updates the number of active disk streams.                  SetNormalViewAction() {
786           * @param count The new number of active disk streams.                          super(i18n.getMenuLabel("channels.normalView"));
787           */                  }
788          protected void                  
789          updateStreamCount(int count) {                  public void
790                  Dimension d = lStreams.getPreferredSize();                  actionPerformed(ActionEvent e) {
791                  lStreams.setText(count == 0 ? "--" : String.valueOf(count));                          viewTracker.setView(new NormalChannelView(Channel.this));
792                  d = JuifeUtils.getUnionSize(d, lStreams.getPreferredSize());                  }
                 lStreams.setMinimumSize(d);  
                 lStreams.setPreferredSize(d);  
                 lStreams.setMaximumSize(d);  
793          }          }
794                    
795          /**          public ContextMenu
796           * Updates the number of active voices.          getContextMenu() { return contextMenu; }
          * @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);  
         }  
797                    
798          class InstrumentPane extends JPanel {          class ContextMenu extends MouseAdapter {
799                  private final JPanel leftPane = new JPanel();                  private JPopupMenu menu = null;
                 private final JPanel rightPane = new JPanel();  
800                                    
801                  InstrumentPane() {                  protected JRadioButtonMenuItem rbmiSmallView;
802                          setOpaque(false);                  protected JRadioButtonMenuItem rbmiNormalView;
803                          setLayout(new BoxLayout(this, BoxLayout.X_AXIS));                  
804                          add(leftPane);                  ContextMenu() {
                         add(btnInstr);  
                         add(rightPane);  
                         add(sbbEditInstr);  
                         btnEditInstr.setToolTipText(i18n.getLabel("ChannelScreen.btnEditInstr.tt"));  
                         sbbEditInstr.setVisible(false);  
                         setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 6));  
805                                                    
                         update();  
806                  }                  }
807                                    
808                  public void                  private void
809                  update() {                  createMenu() {
810                          int a = btnInstr.getMinimumSize().width;                          menu = new JPopupMenu();
811                          int b = 0;                          menu.add(new JMenuItem(new EditInstrumentAction()));
812                          if(sbbEditInstr.isVisible()) b = sbbEditInstr.getPreferredSize().width;                          menu.addSeparator();
                           
                         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;  
813                                                    
814                          int j = i;                          rbmiSmallView = new JRadioButtonMenuItem(new SetSmallViewAction());
815                          if(sbbEditInstr.isVisible()) j -= sbbEditInstr.getPreferredSize().width;                          rbmiNormalView = new JRadioButtonMenuItem(new SetNormalViewAction());
816                          if(i < 0 || j < 0) i = j = 0;                          if(viewTracker.getOriginalView() instanceof SmallChannelView) {
817                                    rbmiSmallView.setSelected(true);
818                            } else if(viewTracker.getOriginalView() instanceof NormalChannelView) {
819                                    rbmiNormalView.setSelected(true);
820                            }
821                                                    
822                          Dimension d = new Dimension(i, 1);                          ButtonGroup group = new ButtonGroup();
823                          leftPane.setMinimumSize(d);                          group.add(rbmiSmallView);
824                          leftPane.setPreferredSize(d);                          group.add(rbmiNormalView);
                         leftPane.setMaximumSize(d);  
825                                                    
826                          d = new Dimension(j, 1);                          menu.add(rbmiSmallView);
827                          rightPane.setMinimumSize(d);                          menu.add(rbmiNormalView);
                         rightPane.setPreferredSize(d);  
                         rightPane.setMaximumSize(d);  
828                                                    
829                          validate();                          menu.addSeparator();
830                            menu.add(new JMenuItem(new FxSendsAction()));
831                            menu.add(new JMenuItem(new ChannelRoutingAction()));
832                    }
833                    
834                    private JPopupMenu
835                    getMenu() {
836                            if(menu == null) createMenu();
837                            return menu;
838                    }
839                    
840                    public void
841                    mousePressed(MouseEvent e) {
842                            if(e.isPopupTrigger()) show(e);
843                    }
844            
845                    public void
846                    mouseReleased(MouseEvent e) {
847                            if(e.isPopupTrigger()) show(e);
848                    }
849            
850                    void
851                    show(MouseEvent e) {
852                            getMenu().show(e.getComponent(), e.getX(), e.getY());
853                  }                  }
854          }          }
855                    
# Line 977  class ChannelScreen extends PixmapPane { Line 876  class ChannelScreen extends PixmapPane {
876                  }                  }
877          }          }
878                    
879          static class ScreenButton extends JButton {          public static class StreamVoiceCountPane extends JPanel {
880                  ScreenButton(String s) {                  private final Channel channel;
881                          super(s);                  
882                          setContentAreaFilled(false);                  private final JLabel lStreams = createScreenLabel(" --");
883                          setFocusPainted(false);                  private final JLabel lSlash = createScreenLabel("/");
884                          setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));                  private final JLabel lVoices = createScreenLabel("-- ");
885                          setMargin(new Insets(0, 0, 0, 0));                  
886                                            public
887                          putClientProperty (                  StreamVoiceCountPane(Channel channel) {
888                                  SubstanceLookAndFeel.BUTTON_NO_MIN_SIZE_PROPERTY, Boolean.TRUE                          this.channel = channel;
                         );  
889                                                    
890                          putClientProperty (                          setOpaque(false);
891                                  SubstanceLookAndFeel.BUTTON_PAINT_NEVER_PROPERTY, Boolean.TRUE                          setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
892                          );                          lStreams.setFont(Res.fontScreenMono);
893                            lStreams.setHorizontalAlignment(JLabel.RIGHT);
894                            lStreams.setToolTipText(i18n.getLabel("Channel.streamVoiceCount"));
895                                                    
896                          putClientProperty(SubstanceLookAndFeel.FLAT_PROPERTY, Boolean.TRUE);                          Dimension d = lStreams.getPreferredSize();
897                            lStreams.setMinimumSize(d);
898                            lStreams.setPreferredSize(d);
899                            lStreams.setMaximumSize(d);
900                            add(lStreams);
901                                                    
902                          FadeConfigurationManager.getInstance().disallowFades(FadeKind.ROLLOVER, this);                          lSlash.setFont(Res.fontScreenMono);
903                            lSlash.setToolTipText(i18n.getLabel("Channel.streamVoiceCount"));
904                            add(lSlash);
905                                                    
906                          setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));                          lVoices.setFont(Res.fontScreenMono);
907                          setFont(Res.fontScreen);                          lVoices.setToolTipText(i18n.getLabel("Channel.streamVoiceCount"));
                         setForeground(new java.awt.Color(0xFFA300));  
                 }  
                   
                 protected void  
                 paintComponent(Graphics g) {  
                         Graphics2D g2d = (Graphics2D)g;  
908                                                    
909                          g2d.setRenderingHint (                          d = lStreams.getPreferredSize();
910                                  java.awt.RenderingHints.KEY_TEXT_ANTIALIASING,                          lVoices.setMinimumSize(d);
911                                  java.awt.RenderingHints.VALUE_TEXT_ANTIALIAS_ON                          lVoices.setPreferredSize(d);
912                          );                          lVoices.setMaximumSize(d);
913                            add(lVoices);
914                                                    
915                          super.paintComponent(g2d);                          lStreams.addMouseListener(channel.getContextMenu());
916                            lSlash.addMouseListener(channel.getContextMenu());
917                            lVoices.addMouseListener(channel.getContextMenu());
918                  }                  }
919          }                  
920                            public void
921          static class ScreenButtonBg extends PixmapPane {                  updateStreamCount(int count) {
922                  ScreenButtonBg(JButton btn) {                          lStreams.setText(count == 0 ? " --" : String.valueOf(count));
                         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));  
923                  }                  }
924                                    
925                  public Dimension                  public void
926                  getPreferredSize() {                  updateVoiceCount(int count) {
927                          return new Dimension(super.getPreferredSize().width, 13);                          lVoices.setText(count == 0 ? "-- " : String.valueOf(count));
928                  }                  }
929          }          }
930                    
931                    public static class VolumePane extends JPanel {
932                            private final Channel channel;
933          static class ScreenLabel extends JLabel {                  private final JButton btnVolume = createScreenButton("");
934                  ScreenLabel() { this(""); }                  private JSVolumeEditorPopup popupVolume;
935                                    
936                  ScreenLabel(String s) {                  private static NumberFormat numberFormat = NumberFormat.getInstance();
937                          super(s);                  static { numberFormat.setMaximumFractionDigits(1); }
                         setFont(Res.fontScreen);  
                         setForeground(new java.awt.Color(0xFFA300));  
                 }  
938                                    
939                  protected void                  public
940                  paintComponent(Graphics g) {                  VolumePane(final Channel channel) {
941                          Graphics2D g2d = (Graphics2D)g;                          this.channel = channel;
942                            setOpaque(false);
943                            setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
944                                                    
945                          g2d.setRenderingHint (                          btnVolume.setIcon(Res.iconVolume14);
946                                  java.awt.RenderingHints.KEY_TEXT_ANTIALIASING,                          btnVolume.setIconTextGap(2);
947                                  java.awt.RenderingHints.VALUE_TEXT_ANTIALIAS_ON                          btnVolume.setAlignmentX(RIGHT_ALIGNMENT);
948                          );                          btnVolume.setHorizontalAlignment(btnVolume.LEFT);
949                            updateVolumeInfo(100);
950                            Dimension d = btnVolume.getPreferredSize();
951                            d.width = 57;
952                            btnVolume.setPreferredSize(d);
953                            btnVolume.setMinimumSize(d);
954                                                    
955                          super.paintComponent(g2d);                          add(btnVolume);
                 }  
         }  
           
         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;  
956                                                    
957                          if(!sbbEditInstr.isVisible()) {                          btnVolume.addActionListener(new ActionListener() {
958                                  sbbEditInstr.setVisible(true);                                  public void
959                                  instrumentPane.update();                                  actionPerformed(ActionEvent e) {
960                          }                                          if(popupVolume.isVisible()) {
961                  }                                                  popupVolume.commit();
962                                                                    popupVolume.hide();
963                  public void                                          } else {
964                  mouseExited(MouseEvent e)  {                                                  float vol = channel.getModel().getChannelInfo().getVolume();
965                          if(getMousePosition(true) != null) return;                                                  popupVolume.setCurrentVolume(vol);
966                          if(sbbEditInstr.isVisible()) {                                                  popupVolume.show();
967                                  sbbEditInstr.setVisible(false);                                          }
968                                  instrumentPane.update();                                  }
969                          }                          });
970                            
971                            popupVolume = new JSVolumeEditorPopup(btnVolume, VolumeType.CHANNEL);
972                            
973                            popupVolume.addActionListener(new ActionListener() {
974                                    public void
975                                    actionPerformed(ActionEvent e) {
976                                            channel.getModel().setBackendVolume(popupVolume.getVolumeFactor());
977                                    }
978                            });
979                            
980                            btnVolume.addMouseListener(channel.getContextMenu());
981                  }                  }
982                                    
                 /** Called when the hierarchy has been changed. */  
983                  public void                  public void
984                  hierarchyChanged(HierarchyEvent e) {                  updateVolumeInfo(int volume) {
985                          if((e.getChangeFlags() & e.SHOWING_CHANGED) == e.SHOWING_CHANGED) {                          if(CC.getViewConfig().isMeasurementUnitDecibel()) {
986                                  if(getMousePosition() == null) mouseExited(null);                                  String s = numberFormat.format(HF.percentsToDecibels(volume));
987                                  else mouseEntered(null);                                  btnVolume.setText(s + "dB");
988                            } else {
989                                    btnVolume.setText(String.valueOf(volume) + "%");
990                          }                          }
991                  }                  }
992          }          }
 }  
   
 class ChannelOptions extends JXCollapsiblePane {  
         private final Channel channel;  
         private MidiDeviceModel midiDevice = null;  
993                    
994          private final JComboBox cbMidiDevice = new FantasiaComboBox();          public static class PowerButton extends PixmapToggleButton implements ActionListener {
995          private final JComboBox cbMidiPort = new FantasiaComboBox();                  private final Channel channel;
         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) {  
                 setAnimated(false);  
                 setCollapsed(true);  
                 setAnimated(preferences().getBoolProperty(ANIMATED));  
996                                    
997                  preferences().addPropertyChangeListener(ANIMATED, new PropertyChangeListener() {                  PowerButton(Channel channel) {
998                          public void                          this(channel, Res.gfxPowerOff, Res.gfxPowerOn);
999                          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"));  
1000                                    
1001                  btnChannelRouting.addActionListener(new ActionListener() {                  PowerButton(Channel channel, ImageIcon defaultIcon, ImageIcon selectedIcon) {
1002                          public void                          super(defaultIcon, selectedIcon);
                         actionPerformed(ActionEvent e) {  
                                 SamplerChannel c = channel.getChannelInfo();  
                                 new JSChannelOutputRoutingDlg(CC.getMainFrame(), c).setVisible(true);  
1003                                                    
1004                          }                          this.channel = channel;
                 });  
                   
                 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(); }  
                 });  
1005                                    
1006                  cbMidiPort.addActionListener(new ActionListener() {                          setSelected(true);
1007                          public void                          addActionListener(this);
1008                          actionPerformed(ActionEvent e) { setMidiPort(); }                          setToolTipText(i18n.getButtonLabel("Channel.ttRemoveChannel"));
                 });  
                   
                 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);  
1009                  }                  }
1010                                    
1011                  int map = channel.getModel().getChannelInfo().getMidiInstrumentMapId();                  public void
1012                  cbInstrumentMap.setSelectedItem(CC.getSamplerModel().getMidiInstrumentMapById(map));                  actionPerformed(ActionEvent e) {
1013                  if(cbInstrumentMap.getSelectedItem() == null) {                          boolean b = preferences().getBoolProperty(CONFIRM_CHANNEL_REMOVAL);
1014                          if(map == -1) cbInstrumentMap.setSelectedItem(noMap);                          if(b) {
1015                          else if(map == -2) {                                  String s = i18n.getMessage("Channel.remove?", channel.getChannelId());
1016                                  cbInstrumentMap.setSelectedItem(defaultMap);                                  if(!HF.showYesNoDialog(channel, s)) {
1017                                            setSelected(true);
1018                                            return;
1019                                    }
1020                          }                          }
1021                            channel.remove();
1022                  }                  }
1023                                    
1024                  updateCbInstrumentMapToolTipText();                  public boolean
1025                                    contains(int x, int y) { return (x - 11)*(x - 11) + (y - 11)*(y - 11) < 71; }
                 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();  
1026          }          }
1027                    
1028          /**          public static class OptionsButton extends PixmapToggleButton
1029           * Updates the channel settings. This method is invoked when changes to the                                          implements ActionListener, PropertyChangeListener {
          * 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!");  
1030                                    
1031                  setUpdate(true);                  private final Channel channel;
1032                                    
1033                  try {                  OptionsButton(Channel channel) {
1034                          cbMidiDevice.setSelectedItem(mm == null ? null : mm.getDeviceInfo());                          super(Res.gfxOptionsOff, Res.gfxOptionsOn);
1035                                                    
1036                          cbAudioDevice.setSelectedItem(am == null ? null : am.getDeviceInfo());                          this.channel = channel;
                         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);  
1037                                                    
1038                          if(cbInstrumentMap.getSelectedItem() != o) {                          setRolloverIcon(Res.gfxOptionsOffRO);
1039                                  cbInstrumentMap.setSelectedItem(o);                          this.setRolloverSelectedIcon(Res.gfxOptionsOnRO);
1040                          }                          addActionListener(this);
1041                  } else {                          setToolTipText(i18n.getButtonLabel("Channel.ttShowOptions"));
                         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;  
1042                  }                  }
1043                                    
1044                  if(midiDevice != null) midiDevice.removeMidiDeviceListener(getHandler());                  public void
1045                                    actionPerformed(ActionEvent e) {
1046                  cbMidiPort.removeAllItems();                          ChannelView view = channel.viewTracker.getCurrentView();
                   
                 if(mid == null) {  
                         midiDevice = null;  
                         cbMidiPort.setEnabled(false);  
1047                                                    
1048                          cbMidiChannel.setSelectedItem(null);                          if(isSelected() && view.getChannelOptionsView() == null) {
1049                          cbMidiChannel.setEnabled(false);                                  view.installChannelOptionsView();
1050                  } else {                                  JComponent c = view.getChannelOptionsView().getComponent();
1051                          midiDevice = CC.getSamplerModel().getMidiDeviceById(mid.getDeviceId());                                  channel.optionsPane.setContentPane(c);
1052                          if(midiDevice != null) midiDevice.addMidiDeviceListener(getHandler());                          }
1053                                                    
1054                          cbMidiPort.setEnabled(true);                          channel.showOptionsPane(isSelected());
1055                                                    
1056                          MidiPort[] ports = mid.getMidiPorts();                          String s;
1057                          for(MidiPort port : ports) cbMidiPort.addItem(port);                          if(isSelected()) s = i18n.getButtonLabel("Channel.ttHideOptions");
1058                            else s = i18n.getButtonLabel("Channel.ttShowOptions");
1059                                                    
1060                          int p = channel.getModel().getChannelInfo().getMidiInputPort();                          setToolTipText(s);
                         cbMidiPort.setSelectedItem(p >= 0 && p < ports.length ? ports[p] : null);  
1061                                                    
1062                          cbMidiChannel.setEnabled(true);                          s = JXCollapsiblePane.ANIMATION_STATE_KEY;
1063                          int c = channel.getModel().getChannelInfo().getMidiInputChannel();                          channel.optionsPane.addPropertyChangeListener(s, this);
                         cbMidiChannel.setSelectedItem(c == -1 ? "All" : "Channel " + (c + 1));  
1064                  }                  }
         }  
           
         private void  
         setMidiPort() {  
                 if(isUpdate()) return;  
1065                                    
                 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.  
                  */  
1066                  public void                  public void
1067                  deviceAdded(MidiDeviceListEvent e) {                  propertyChange(PropertyChangeEvent e) {
1068                          cbMidiDevice.addItem(e.getMidiDeviceModel().getDeviceInfo());                          if(e.getNewValue() == "collapsed") {
1069                  }                                  ChannelView view = channel.viewTracker.getCurrentView();
1070                                            view.uninstallChannelOptionsView();
1071                  /**                                  channel.optionsPane.setContentPane(new JPanel());
1072                   * 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());  
1073                  }                  }
1074                                    
                 /**  
                  * 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.  
                  */  
1075                  public void                  public void
1076                  entryRemoved(ListEvent<AudioDeviceModel> e) {                  onDestroy() {
1077                          cbAudioDevice.removeItem(e.getEntry().getDeviceInfo());                          String s = JXCollapsiblePane.ANIMATION_STATE_KEY;
1078                            channel.optionsPane.removePropertyChangeListener(s, this);
1079                  }                  }
1080                                    
1081                  public void                  public boolean
1082                  settingsChanged(MidiDeviceEvent e) {                  contains(int x, int y) { return super.contains(x, y) & y < 13; }
                         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);  
                 }  
1083          }          }
1084            }
1085          private class MapListListener implements ListListener<MidiInstrumentMap> {  
1086                  /** Invoked when a new MIDI instrument map is added to a list. */  class ChannelOptionsPane extends JXCollapsiblePane {
1087                  public void          ChannelOptionsPane() {
1088                  entryAdded(ListEvent<MidiInstrumentMap> e) {                  setAnimated(false);
1089                          cbInstrumentMap.insertItemAt(e.getEntry(), cbInstrumentMap.getItemCount());                  setCollapsed(true);
1090                          boolean b = channel.getModel().getChannelInfo().getEngine() != null;                  setAnimated(preferences().getBoolProperty(ANIMATED));
1091                          if(b && !cbInstrumentMap.isEnabled()) cbInstrumentMap.setEnabled(true);                  
1092                  }                  preferences().addPropertyChangeListener(ANIMATED, new PropertyChangeListener() {
1093                                    public void
1094                  /** Invoked when a new MIDI instrument map is removed from a list. */                          propertyChange(PropertyChangeEvent e) {
1095                  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);  
1096                          }                          }
1097                  }                  });
1098          }          }
1099            
1100            public void
1101            showOptionsPane(boolean show) { setCollapsed(!show); }
1102  }  }

Legend:
Removed from v.1496  
changed lines
  Added in v.1743

  ViewVC Help
Powered by ViewVC