/[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 1143 by iliev, Mon Apr 2 21:18:31 2007 UTC revision 1737 by iliev, Thu May 8 17:26:19 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-2006 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 22  Line 22 
22    
23  package org.jsampler.view.fantasia;  package org.jsampler.view.fantasia;
24    
25  import java.awt.Cursor;  import java.awt.Container;
26  import java.awt.Dimension;  import java.awt.Dimension;
27  import java.awt.Insets;  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;
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.util.logging.Level;  import java.beans.PropertyChangeEvent;
35    import java.beans.PropertyChangeListener;
36    
37  import javax.swing.BorderFactory;  import java.text.NumberFormat;
38  import javax.swing.Box;  
39    import javax.swing.AbstractAction;
40    import javax.swing.Action;
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;
49  import javax.swing.JPanel;  import javax.swing.JPanel;
50    import javax.swing.JPopupMenu;
51    import javax.swing.JRadioButtonMenuItem;
52    import javax.swing.JScrollPane;
53  import javax.swing.JToggleButton;  import javax.swing.JToggleButton;
54  import javax.swing.SwingConstants;  import javax.swing.JToolBar;
   
 import javax.swing.event.ChangeEvent;  
 import javax.swing.event.ChangeListener;  
55    
56  import net.sf.juife.Dial;  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.jsampler.AudioDeviceModel;  import org.jdesktop.swingx.JXCollapsiblePane;
60    
61  import org.jsampler.CC;  import org.jsampler.CC;
62  import org.jsampler.MidiDeviceModel;  import org.jsampler.HF;
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.MidiDeviceListEvent;  
 import org.jsampler.event.MidiDeviceListListener;  
 import org.jsampler.event.SamplerChannelAdapter;  
65  import org.jsampler.event.SamplerChannelEvent;  import org.jsampler.event.SamplerChannelEvent;
66    import org.jsampler.event.SamplerChannelListEvent;
67    import org.jsampler.event.SamplerChannelListListener;
68  import org.jsampler.event.SamplerChannelListener;  import org.jsampler.event.SamplerChannelListener;
69    
70  import org.linuxsampler.lscp.AudioOutputDevice;  import org.jsampler.view.JSChannel;
71  import org.linuxsampler.lscp.MidiInputDevice;  import org.jsampler.view.JSChannelsPane;
72  import org.linuxsampler.lscp.MidiPort;  
73    import org.jsampler.view.std.JSChannelOutputRoutingDlg;
74    import org.jsampler.view.std.JSFxSendsPane;
75    import org.jsampler.view.std.JSInstrumentChooser;
76    import org.jsampler.view.std.JSVolumeEditorPopup;
77    
78  import org.linuxsampler.lscp.SamplerChannel;  import org.linuxsampler.lscp.SamplerChannel;
 import org.linuxsampler.lscp.SamplerEngine;  
79    
80  import static org.jsampler.view.fantasia.FantasiaI18n.i18n;  import static org.jsampler.view.fantasia.FantasiaI18n.i18n;
81    import static org.jsampler.view.fantasia.FantasiaPrefs.*;
82    import static org.jsampler.view.fantasia.FantasiaUtils.*;
83    import static org.jsampler.view.std.JSVolumeEditorPopup.VolumeType;
84    
85    
86  /**  /**
87   *   *
88   * @author Grigor Iliev   * @author Grigor Iliev
89   */   */
90  public class Channel extends org.jsampler.view.JSChannel {  public class Channel extends JSChannel {
91          private final ChannelScreen screen = new ChannelScreen(this);          private final JXCollapsiblePane mainPane;
92          private final ChannelOptions optionsPane = new ChannelOptions(this);          private final ChannelOptionsPane optionsPane = new ChannelOptionsPane();
93                    
94          private final PowerButton btnPower = new PowerButton();          private final ViewTracker viewTracker;
         private final MuteButton btnMute = new MuteButton();  
         private final SoloButton btnSolo = new SoloButton();  
         private final OptionsButton btnOptions = new OptionsButton();  
95                    
96          private final EnhancedDial dialVolume = new EnhancedDial();          private InformationDialog fxSendsDlg = null;
97            
98            private final ContextMenu contextMenu;
99                    
100          private boolean selected = false;          private boolean selected = false;
101                    
102            private AnimatedPorpetyListener animatedPorpetyListener = new AnimatedPorpetyListener();
103            
104            class AnimatedPorpetyListener implements PropertyChangeListener {
105                    public void
106                    propertyChange(PropertyChangeEvent e) {
107                            mainPane.setAnimated(preferences().getBoolProperty(ANIMATED));
108                    }
109            }
110            
111            ////////////////////////////////
112            // ******* Mouse tracker *******
113            ////////////////////////////////
114            private static int mouseOverChannelId = -1;
115            private static boolean mousePressed = false;
116            
117            private static ActionListener guiListener = null;
118            
119            private static Channel oldMouseOverChannel = null;
120            private static Channel newMouseOverChannel = null;
121            
122            
123            private static void
124            mouseMoved() {
125                    //TODO: do this for all channels panes
126                    JSChannelsPane cp = CC.getMainFrame().getChannelsPane(0);
127                    for(int i = 0; i < cp.getChannelCount(); i++) {
128                            mouseMoved((Channel)cp.getChannel(i));
129                    }
130                    
131                    if(oldMouseOverChannel == newMouseOverChannel) return;
132                    
133                    if(oldMouseOverChannel != null) oldMouseOverChannel.mouseExited();
134                    
135                    if(newMouseOverChannel != null) {
136                            mouseOverChannelId = newMouseOverChannel.getChannelId();
137                            newMouseOverChannel.mouseEntered();
138                    }
139                    
140                    oldMouseOverChannel = newMouseOverChannel = null;
141            }
142            
143            private static void
144            mouseMoved(Channel c) {
145                    int id = c.getChannelId();
146                    if(c.mainPane.getMousePosition(true) != null) {
147                            newMouseOverChannel = c;
148                    } else if(id == mouseOverChannelId) {
149                            oldMouseOverChannel = c;
150                    }
151            }
152            
153            ////////////////////////////////
154            
155            
156          /**          /**
157           * Creates a new instance of <code>Channel</code> using the specified           * Creates a new instance of <code>Channel</code> using the specified
158           * non-<code>null</code> channel model.           * non-<code>null</code> channel model.
# Line 99  public class Channel extends org.jsample Line 161  public class Channel extends org.jsample
161           */           */
162          public          public
163          Channel(SamplerChannelModel model) {          Channel(SamplerChannelModel model) {
164                    this(model, null);
165            }
166            
167            /**
168             * Creates a new instance of <code>Channel</code> using the specified
169             * non-<code>null</code> channel model.
170             * @param model The model to be used by this channel.
171             * @param listener A listener which is notified when the newly created
172             * channel is fully expanded on the screen.
173             * @throws IllegalArgumentException If the model is <code>null</code>.
174             */
175            public
176            Channel(SamplerChannelModel model, final ActionListener listener) {
177                  super(model);                  super(model);
178                                    
179                  setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));                  setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
                 JPanel p = new JPanel();  
                 p.setName("Channel");  
                 p.setLayout(new BoxLayout(p, BoxLayout.X_AXIS));  
                   
                 //p.add(Box.createRigidArea(new Dimension(3, 0)));  
                   
                 btnPower.setAlignmentY(JPanel.TOP_ALIGNMENT);  
                   
                 TitleBar tb = new TitleBar();  
                 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.iconMuteTitle));  
                 p2.add(btnMute);  
                 p2.add(new JLabel(Res.iconSoloTitle));  
                 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.iconVolumeTitle);  
                 l.setAlignmentX(JPanel.CENTER_ALIGNMENT);  
                 l.setBorder(BorderFactory.createEmptyBorder(0, 0, 2, 0));  
                 p2.add(l);  
                 dialVolume.setDialPixmap(Res.iconVolumeDial, 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.iconOptionsTitle);  
                 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);  
180                  optionsPane.setAlignmentX(JPanel.CENTER_ALIGNMENT);                  optionsPane.setAlignmentX(JPanel.CENTER_ALIGNMENT);
                 add(p);  
                 add(optionsPane);  
181                                    
182                  setOpaque(true);                  mainPane = new JXCollapsiblePane();
183                    viewTracker = new ViewTracker();
184                    contextMenu = new ContextMenu();
185                    
186                    mainPane.getContentPane().setLayout (
187                            new BoxLayout(mainPane.getContentPane(), BoxLayout.Y_AXIS)
188                    );
189                    
190                    int viewIdx = preferences().getIntProperty(DEFAULT_CHANNEL_VIEW);
191                    if(viewIdx == 0) {
192                            viewTracker.setView(new SmallChannelView(Channel.this));
193                    } else if(viewIdx == 1) {
194                            viewTracker.setView(new NormalChannelView(Channel.this));
195                    } else {
196                            viewTracker.setView(new NormalChannelView(Channel.this));
197                    }
198                    
199                    setOpaque(false);
200                                    
201                  getModel().addSamplerChannelListener(getHandler());                  getModel().addSamplerChannelListener(getHandler());
202                                    
203                  updateChannelInfo();                  updateChannelInfo();
204                    
205                    add(mainPane);
206                    
207                    if(listener != null) {
208                            final String s = JXCollapsiblePane.ANIMATION_STATE_KEY;
209                            mainPane.addPropertyChangeListener(s, new PropertyChangeListener() {
210                                    public void
211                                    propertyChange(PropertyChangeEvent e) {
212                                            if(e.getNewValue() == "expanded") {
213                                                    // TODO: this should be done regardles the listener != null?
214                                                    mainPane.removePropertyChangeListener(s, this);
215                                                    ///////
216                                                    listener.actionPerformed(null);
217                                                    ensureChannelIsVisible();
218                                            } else if(e.getNewValue() == "expanding/collapsing") {
219                                                    ensureChannelIsVisible();
220                                            }
221                                    }
222                            });
223                    }
224                    
225                    mainPane.setAnimated(false);
226                    mainPane.setCollapsed(true);
227                    mainPane.setAnimated(preferences().getBoolProperty(ANIMATED));
228                    mainPane.setCollapsed(false);
229                    
230                    preferences().addPropertyChangeListener(ANIMATED, animatedPorpetyListener);
231                    
232                    if(listener != null) {
233                            javax.swing.SwingUtilities.invokeLater(new Runnable() {
234                                    public void
235                                    run() { listener.actionPerformed(null); }
236                            });
237                    }
238                    
239                    CC.getSamplerModel().addSamplerChannelListListener(getHandler());
240                    
241                    installGuiListener();
242            }
243            
244            private static void
245            installGuiListener() {
246                    if(guiListener != null) return;
247                    
248                    guiListener = new ActionListener() {
249                            public void
250                            actionPerformed(ActionEvent e) {
251                                    mouseMoved();
252                            }
253                    };
254                    
255                    ((MainFrame)CC.getMainFrame()).getGuiTimer().addActionListener(guiListener);
256          }          }
257                    
258          private JPanel          private void
259          createVSeparator() {          mouseEntered() {
260                  JPanel p = new JPanel();                  viewTracker.mouseEntered();
261                  p.setName("VSeparator");          }
262                  p.setOpaque(false);          
263                  p.setAlignmentY(JPanel.TOP_ALIGNMENT);          private void
264                  p.setPreferredSize(new Dimension(2, 60));          mouseExited() {
265                  p.setMinimumSize(p.getPreferredSize());                  viewTracker.mouseExited();
266                  p.setMaximumSize(p.getPreferredSize());          }
267                  return p;          
268            private void
269            ensureChannelIsVisible() {
270                    Container p = getParent();
271                    JScrollPane sp = null;
272                    while(p != null) {
273                            if(p instanceof JScrollPane) {
274                                    sp = (JScrollPane)p;
275                                    break;
276                            }
277                            p = p.getParent();
278                    }
279                    if(sp == null) return;
280                    int h = sp.getViewport().getView().getHeight();
281                    sp.getViewport().scrollRectToVisible(new Rectangle(0, h - 2, 1, 1));
282          }          }
283                    
284          /**          /**
# Line 233  public class Channel extends org.jsample Line 301  public class Channel extends org.jsample
301                    
302          /** Shows the channel properties. */          /** Shows the channel properties. */
303          public void          public void
304          expandChannel() { if(!btnOptions.isSelected()) btnOptions.doClick(); }          expandChannel() { expandChannel(optionsPane.isAnimated()); }
           
305                    
306          /** Invoked when the user changes the volume */          /** Shows the channel properties. */
307          private void          public void
308          setVolume() {          expandChannel(boolean animated) {
309                  screen.updateVolumeInfo(dialVolume.getValue());                  boolean b = optionsPane.isAnimated();
310                                    optionsPane.setAnimated(animated);
311                  if(dialVolume.getValueIsAdjusting()) return;                  viewTracker.getCurrentView().expandChannel();
312                                    optionsPane.setAnimated(b);
                 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);  
313          }          }
314                    
315          /**          /**
# Line 264  public class Channel extends org.jsample Line 318  public class Channel extends org.jsample
318           */           */
319          private void          private void
320          updateChannelInfo() {          updateChannelInfo() {
321                  SamplerChannel sc = getChannelInfo();                  viewTracker.getCurrentView().updateChannelInfo();
322            }
323            
324            public void
325            loadInstrument() {
326                    JSInstrumentChooser dlg = FantasiaUtils.createInstrumentChooser(CC.getMainFrame());
327                    dlg.setVisible(true);
328                                    
329                  screen.updateScreenInfo(sc);                  if(!dlg.isCancelled()) {
330                  updateMuteIcon(sc);                          SamplerChannelModel m = getModel();
331                            m.loadBackendInstrument(dlg.getInstrumentFile(), dlg.getInstrumentIndex());
332                    }
333            }
334            
335            public void
336            fallbackToOriginalView() {
337                    viewTracker.fallbackToOriginalView();
338            }
339            
340            public boolean
341            isUsingOriginalView() {
342                    return viewTracker.isUsingOriginalView();
343            }
344            
345            protected void
346            onDestroy() {
347                    CC.getSamplerModel().removeSamplerChannelListListener(getHandler());
348                    preferences().removePropertyChangeListener(ANIMATED, animatedPorpetyListener);
349                                    
350                  if(sc.isSoloChannel()) btnSolo.setIcon(Res.iconSoloOn);                  viewTracker.onDestroy();
351                  else btnSolo.setIcon(Res.iconSoloOff);          }
352                                    
353                  dialVolume.setValue((int)(sc.getVolume() * 100));          public void
354            remove() {
355                    if(!mainPane.isAnimated()) {
356                            CC.getSamplerModel().removeBackendChannel(getChannelId());
357                            return;
358                    }
359                                    
360                  boolean b = sc.getEngine() != null;                  String s = JXCollapsiblePane.ANIMATION_STATE_KEY;
361                  dialVolume.setEnabled(b);                  mainPane.addPropertyChangeListener(s, getHandler());
362                  btnSolo.setEnabled(b);                  mainPane.setCollapsed(true);
                 btnMute.setEnabled(b);  
363          }          }
364                    
365          /**          public void
366           * Updates the mute button with the proper icon regarding to information obtained          showOptionsPane(boolean show) { optionsPane.showOptionsPane(show); }
          * from <code>channel</code>.  
          * @param channel A <code>SamplerChannel</code> instance containing the new settings  
          * for this channel.  
          */  
         private void  
         updateMuteIcon(SamplerChannel channel) {  
                 if(channel.isMutedBySolo()) btnMute.setIcon(Res.iconMutedBySolo);  
                 else if(channel.isMuted()) btnMute.setIcon(Res.iconMuteOn);  
                 else btnMute.setIcon(Res.iconMuteOff);  
         }  
367                    
368          private class EnhancedDial extends Dial {          public void
369                  EnhancedDial() {          showFxSendsDialog() {
370                          super(0, 100);                  if(fxSendsDlg != null && fxSendsDlg.isVisible()) {
371                                                    fxSendsDlg.toFront();
372                          setMouseHandlerMode(MouseHandlerMode.LEFT_TO_RIGHT_AND_DOWN_TO_UP);                          return;
                           
                         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(); }  
                         });  
373                  }                  }
374                    FxSendsPane p = new FxSendsPane(getModel());
375                    int id = getModel().getChannelId();
376                    fxSendsDlg = new InformationDialog(CC.getMainFrame(), p);
377                    fxSendsDlg.setTitle(i18n.getLabel("FxSendsDlg.title", id));
378                    fxSendsDlg.setModal(false);
379                    fxSendsDlg.showCloseButton(false);
380                    fxSendsDlg.setVisible(true);
381          }          }
382                    
383          private final EventHandler eventHandler = new EventHandler();          private final EventHandler eventHandler = new EventHandler();
# Line 326  public class Channel extends org.jsample Line 385  public class Channel extends org.jsample
385          private EventHandler          private EventHandler
386          getHandler() { return eventHandler; }          getHandler() { return eventHandler; }
387                    
388          private class EventHandler implements SamplerChannelListener {          private class EventHandler implements SamplerChannelListener,
389                                            SamplerChannelListListener, PropertyChangeListener {
390                  /**                  /**
391                   * Invoked when changes are made to a sampler channel.                   * Invoked when changes are made to a sampler channel.
392                   * @param e A <code>SamplerChannelEvent</code> instance                   * @param e A <code>SamplerChannelEvent</code> instance
# Line 342  public class Channel extends org.jsample Line 402  public class Channel extends org.jsample
402                   */                   */
403                  public void                  public void
404                  streamCountChanged(SamplerChannelEvent e) {                  streamCountChanged(SamplerChannelEvent e) {
405                          screen.updateStreamCount(getModel().getStreamCount());                          viewTracker.getCurrentView().updateStreamCount(getModel().getStreamCount());
406                  }                  }
407                    
408                  /**                  /**
# Line 352  public class Channel extends org.jsample Line 412  public class Channel extends org.jsample
412                   */                   */
413                  public void                  public void
414                  voiceCountChanged(SamplerChannelEvent e) {                  voiceCountChanged(SamplerChannelEvent e) {
415                          screen.updateVoiceCount(getModel().getVoiceCount());                          viewTracker.getCurrentView().updateVoiceCount(getModel().getVoiceCount());
416                  }                  }
         }  
           
           
         private class PowerButton extends PixmapToggleButton implements ActionListener {  
                 PowerButton() {  
                         super(Res.iconPowerOff, Res.iconPowerOn);  
417                                    
418                          setSelected(true);                  /**
419                          addActionListener(this);                   * Invoked when a new sampler channel is created.
420                     * @param e A <code>SamplerChannelListEvent</code>
421                     * instance providing the event information.
422                     */
423                    public void
424                    channelAdded(SamplerChannelListEvent e) { }
425            
426                    /**
427                     * Invoked when a sampler channel is removed.
428                     * @param e A <code>SamplerChannelListEvent</code>
429                     * instance providing the event information.
430                     */
431                    public void
432                    channelRemoved(SamplerChannelListEvent e) {
433                            // Some cleanup when the channel is removed.
434                            if(e.getChannelModel().getChannelId() == getChannelId()) {
435                                    onDestroy();
436                            }
437                  }                  }
438                                    
439                  public void                  public void
440                  actionPerformed(ActionEvent e) {                  propertyChange(PropertyChangeEvent e) {
441                          CC.getSamplerModel().removeBackendChannel(getChannelId());                          if(e.getNewValue() == "collapsed") {
442                                    CC.getSamplerModel().removeBackendChannel(getChannelId());
443                            }
444                  }                  }
                   
                 public boolean  
                 contains(int x, int y) { return (x - 11)*(x - 11) + (y - 11)*(y - 11) < 71; }  
445          }          }
446                    
447          private class MuteButton extends PixmapButton implements ActionListener {          
448                  MuteButton() {          
449                          super(Res.iconMuteOff);          class ViewTracker extends MouseAdapter implements PropertyChangeListener {
450                          setDisabledIcon(Res.iconMuteSoloDisabled);                  private ChannelView originalView;
451                          addActionListener(this);                  private ChannelView mouseOverView;
452                  }                  private ChannelView currentView;
453                                    
454                  public void                  private ChannelView.Type mouseOverViewType = null;
                 actionPerformed(ActionEvent e) {  
                         SamplerChannel sc = getChannelInfo();  
                         boolean b = true;  
455                                    
456                          /*                  ViewTracker() {
457                           * Changing the mute button icon now instead of                          
458                           * leaving the work to the notification mechanism of the LinuxSampler.                          
459                           */                          updateMouseOverViewType();
                         if(sc.isMuted() && !sc.isMutedBySolo()) {  
                                 b = false;  
                                 boolean hasSolo = CC.getSamplerModel().hasSoloChannel();  
                           
                                 if(sc.isSoloChannel() || !hasSolo) setIcon(Res.iconMuteOff);  
                                 else setIcon(Res.iconMutedBySolo);  
                         } else setIcon(Res.iconMuteOn);  
460                                                    
461                          Channel.this.getModel().setBackendMute(b);                          String s = DIFFERENT_CHANNEL_VIEW_ON_MOUSE_OVER;
462                            preferences().addPropertyChangeListener(s, this);
463                            
464                            s = CHANNEL_VIEW_ON_MOUSE_OVER;
465                            preferences().addPropertyChangeListener(s, this);
466                  }                  }
467                                    
468                  public boolean                  public boolean
469                  contains(int x, int y) { return (x > 5 && x < 23) && (y > 5 && y < 16); }                  isUsingOriginalView() {
470          }                          return currentView == originalView;
           
         private class SoloButton extends PixmapButton implements ActionListener {  
                 SoloButton() {  
                         super(Res.iconSoloOff);  
                         setDisabledIcon(Res.iconMuteSoloDisabled);  
                         addActionListener(this);  
471                  }                  }
472                                    
473                  public void                  private void
474                  actionPerformed(ActionEvent e) {                  installListeners() {
475                          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.iconSoloOn);  
                                 if(sc.isMutedBySolo()) btnMute.setIcon(Res.iconMuteOff);  
                         } else {  
                                 setIcon(Res.iconSoloOff);  
                                 if(!sc.isMuted() && CC.getSamplerModel().getSoloChannelCount() > 1)  
                                         btnMute.setIcon(Res.iconMutedBySolo);  
                         }  
                   
                         Channel.this.getModel().setBackendSolo(b);  
476                  }                  }
477                                    
478                  public boolean                  private void
479                  contains(int x, int y) { return (x > 5 && x < 23) && (y > 5 && y < 16); }                  uninstallListeners() {
480          }                          
           
         private class OptionsButton extends PixmapToggleButton implements ActionListener {  
                 OptionsButton() {  
                         super(Res.iconOptionsOff, Res.iconOptionsOn);  
                         setRolloverIcon(Res.iconOptionsOffRO);  
                         this.setRolloverSelectedIcon(Res.iconOptionsOnRO);  
                         addActionListener(this);  
481                  }                  }
482                                    
483                  public void                  private void
484                  actionPerformed(ActionEvent e) {                  updateMouseOverViewType() {
485                          showOptionsPane(isSelected());                          if(mouseOverView != null) {
486                                    mouseOverView.removeEnhancedMouseListener(this);
487                            }
488                                                    
489                          String s;                          mouseOverView = null;
                         if(isSelected()) s = i18n.getButtonLabel("OptionsButton.ttHideOptions");  
                         else s = i18n.getButtonLabel("OptionsButton.ttShowOptions");  
490                                                    
491                          setToolTipText(s);                          boolean b;
492                            b = preferences().getBoolProperty(DIFFERENT_CHANNEL_VIEW_ON_MOUSE_OVER);
493                            if(!b) {
494                                    mouseOverViewType = null;
495                                    uninstallListeners();
496                                    return;
497                            }
498                            
499                            int i = preferences().getIntProperty(CHANNEL_VIEW_ON_MOUSE_OVER);
500                            
501                            switch(i) {
502                                    case 0: mouseOverViewType = ChannelView.Type.SMALL; break;
503                                    case 1: mouseOverViewType = ChannelView.Type.NORMAL; break;
504                                    default:mouseOverViewType = null;
505                            }
506                            
507                            if(mouseOverViewType != null) {
508                                    installListeners();
509                            }
510                  }                  }
511                                    
512                  private void                  public ChannelView
513                  showOptionsPane(boolean show) {                  getMouseOverView() {
514                          optionsPane.setVisible(show);                          if(mouseOverViewType == null) return null;
515                          MainFrame.repack(CC.getMainFrame());                          
516                            if(mouseOverView == null) {
517                                    Channel channel = Channel.this;
518                                    
519                                    switch(mouseOverViewType) {
520                                    case SMALL: mouseOverView = new SmallChannelView(channel); break;
521                                    case NORMAL: mouseOverView = new NormalChannelView(channel); break;
522                                    default: mouseOverView = new NormalChannelView(channel);
523                                    }
524                                    
525                                    mouseOverView.addEnhancedMouseListener(this);
526                            }
527                            
528                            return mouseOverView;
529                  }                  }
530                                    
531                  public boolean                  public ChannelView
532                  contains(int x, int y) { return super.contains(x, y) & y < 13; }                  getCurrentView() { return currentView; }
         }  
 }  
   
 class ChannelScreen extends JPanel {  
         private final Channel channel;  
         private JButton btnInstr = new ScreenButton(i18n.getButtonLabel("ChannelScreen.btnInstr"));  
         private JButton btnReset = new ScreenButton(i18n.getButtonLabel("ChannelScreen.btnReset"));  
         private JButton btnDuplicate =  
                 new ScreenButton(i18n.getButtonLabel("ChannelScreen.btnDuplicate"));  
           
         private final JLabel lVolume = new JLabel();  
         private final JLabel lStreams = new JLabel("--");  
         private final JLabel lVoices = new JLabel("--");  
           
         ChannelScreen(Channel channel) {  
                 this.channel = channel;  
533                                    
534                  setName("ChannelScreen");                  public ChannelView
535                  setOpaque(true);                  getOriginalView() { return originalView; }
536                                    
537                  setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));                  public void
538                    setView(ChannelView view) {
539                            setView(view, true);
540                    }
541                    
542                    public void
543                    setView(ChannelView view, boolean manual) {
544                            boolean selected = false;
545                            if(currentView != null) selected = currentView.isOptionsButtonSelected();
546                            
547                            if(manual) {
548                                    if(originalView != null) {
549                                            originalView.removeEnhancedMouseListener(this);
550                                    }
551                                    
552                                    if(originalView != currentView) destroyOriginalView();
553                                    if(currentView != null && currentView.getType() == view.getType()) {
554                                            originalView = currentView;
555                                            originalView.addEnhancedMouseListener(this);
556                                            destroyView(view);
557                                            return;
558                                    }
559                                    
560                                    removeCurrentView();
561                                    
562                                    originalView = view;
563                                    originalView.addEnhancedMouseListener(this);
564                                    currentView = view;
565                            } else {
566                                    if(view.getType() == getCurrentView().getType()) {
567                                            destroyView(view);
568                                            return;
569                                    }
570                                    
571                                    removeCurrentView();
572                                    currentView = view;
573                            }
574                            
575                            currentView.setOptionsButtonSelected(selected);
576                            
577                            updateView();
578                    }
579                                    
580                  btnInstr.setBorder(BorderFactory.createEmptyBorder(10, 0, 0, 0));                  private void
581                  btnInstr.setAlignmentX(CENTER_ALIGNMENT);                  updateView() {
582                            ChannelOptionsView view = getCurrentView().getChannelOptionsView();
583                            if(view != null) optionsPane.setContentPane(view.getComponent());
584                            
585                            updateChannelInfo();
586                                    
587                  add(btnInstr);                          mainPane.add(getCurrentView().getComponent());
588                            mainPane.add(optionsPane);
589                            mainPane.validate();
590                            mainPane.revalidate();
591                            mainPane.repaint();
592                    }
593                                    
594                  JPanel p = new JPanel();                  public void
595                  p.setOpaque(false);                  fallbackToOriginalView() {
596                  p.setLayout(new BoxLayout(p, BoxLayout.X_AXIS));                          if(currentView == originalView) return;
597                  p.setAlignmentX(CENTER_ALIGNMENT);                          
598                  p.setBorder(BorderFactory.createEmptyBorder(10, 0, 0, 0));                          boolean selected = false;
599                  //lVolume.setFont(lVolume.getFont().deriveFont(java.awt.Font.PLAIN));                          if(currentView != null) selected = currentView.isOptionsButtonSelected();
600                            
601                            removeCurrentView();
602                            currentView = originalView;
603                            currentView.setOptionsButtonSelected(selected);
604                            
605                            updateView();
606                    }
607                                    
608                  p.add(btnDuplicate);                  private void
609                    removeCurrentView() { removeView(currentView); }
610                                    
611                  p.add(Box.createRigidArea(new Dimension(6, 0)));                  private void
612                    destroyCurrentView() { destroyView(currentView); }
613                                    
614                  p.add(new JLabel("|"));                  private void
615                    removeOriginalView() { removeView(originalView); }
616                                    
617                  p.add(Box.createRigidArea(new Dimension(6, 0)));                  private void
618                    destroyOriginalView() { destroyView(originalView); }
619                                    
620                  p.add(btnReset);                  private void
621                    removeView(ChannelView view) {
622                            if(view == null) return;
623                            
624                            mainPane.remove(view.getComponent());
625                            mainPane.remove(optionsPane);
626                                    
627                            destroyView(view);
628                    }
629                                    
630                  p.add(Box.createGlue());                  private void
631                    destroyView(ChannelView view) {
632                            if(view == null) return;
633                            
634                            view.uninstallView();
635                            
636                            view = null;
637                    }
638                                    
639                  p.add(lStreams);                  public boolean
640                  p.add(new JLabel("/"));                  isMouseOverEnabled() { return mouseOverViewType != null; }
                 p.add(lVoices);  
641                                    
642                  p.add(Box.createRigidArea(new Dimension(12, 0)));                  private void
643                    mouseEntered() {
644                            if(!isMouseOverEnabled()) return;
645                            if(getCurrentView().getType() == getMouseOverView().getType()) return;
646                            
647                            JSChannel[] channels = CC.getMainFrame().getChannelsPane(0).getChannels();
648                            for(JSChannel c : channels) {
649                                    if(c == Channel.this) continue;
650                                    
651                                    Channel chn = (Channel)c;
652                                    if(!(chn).isUsingOriginalView()) chn.fallbackToOriginalView();
653                            }
654                            
655                            setView(getMouseOverView(), false);
656                    }
657                                    
658                  lVolume.setAlignmentX(RIGHT_ALIGNMENT);                  private void
659                  p.add(lVolume);                  mouseExited() {
660                  p.setPreferredSize(new Dimension(250, p.getPreferredSize().height));                          if(!isMouseOverEnabled()) return;
661                  p.setMinimumSize(p.getPreferredSize());                          if(getCurrentView().getType() == originalView.getType()) return;
662                  p.setMaximumSize(p.getPreferredSize());                          
663                            fallbackToOriginalView();
664                    }
665                                    
666                  add(p);                  public void
667                    mouseEntered(MouseEvent e) {
668                            guiListener.actionPerformed(null);
669                    }
670                                    
671                    public void
672                    mouseExited(MouseEvent e) {
673                            guiListener.actionPerformed(null);
674                    }
675                                    
676                  setPreferredSize(new Dimension(270, 48));                  public void
677                  setMinimumSize(getPreferredSize());                  mousePressed(MouseEvent e) {
678                  setMaximumSize(getPreferredSize());                          mousePressed = true;
679                    }
680                                    
681                  installListeners();                  public void
682          }                  mouseReleased(MouseEvent e) {
683                                    mousePressed = false;
684          private void                  }
         installListeners() {  
                 btnInstr.addActionListener(new ActionListener() {  
                         public void  
                         actionPerformed(ActionEvent e) { loadInstrument(); }  
                 });  
           
                 btnReset.addActionListener(new ActionListener() {  
                         public void  
                         actionPerformed(ActionEvent e) { channel.getModel().resetBackendChannel(); }  
                 });  
685                                    
686                  btnDuplicate.addActionListener(new ActionListener() {                  public void
687                          public void                  onDestroy() {
688                          actionPerformed(ActionEvent e) {                          destroyCurrentView();
689                                  channel.getModel().duplicateBackendChannel();                          destroyOriginalView();
690                            
691                            uninstallListeners();
692                            
693                            if(currentView != null) {
694                                    currentView.removeEnhancedMouseListener(this);
695                          }                          }
696                  });                          
697          }                          if(mouseOverView != null) {
698                                    mouseOverView.removeEnhancedMouseListener(this);
699          private void                          }
700          loadInstrument() {                          
701                  InstrumentChooser dlg = new InstrumentChooser(CC.getMainFrame());                          String s = DIFFERENT_CHANNEL_VIEW_ON_MOUSE_OVER;
702                  dlg.setVisible(true);                          preferences().removePropertyChangeListener(s, this);
703                            
704                            s = CHANNEL_VIEW_ON_MOUSE_OVER;
705                            preferences().removePropertyChangeListener(s, this);
706                    }
707                                    
708                  if(!dlg.isCancelled()) {                  public void
709                          SamplerChannelModel m = channel.getModel();                  propertyChange(PropertyChangeEvent e) {
710                          m.loadBackendInstrument(dlg.getFileName(), dlg.getInstrumentIndex());                          updateMouseOverViewType();
711                  }                  }
712          }          }
713                    
714          protected void          class EditInstrumentAction extends AbstractAction implements SamplerChannelListener {
715          updateScreenInfo(SamplerChannel sc) {                  EditInstrumentAction() {
716                  int status = sc.getInstrumentStatus();                          super(i18n.getMenuLabel("channels.editInstrument"));
717                  if(status >= 0 && status < 100) {                          channelChanged(null);
718                          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"));  
719                  }                  }
           
720                                    
721                    public void
722                    actionPerformed(ActionEvent e) {
723                            CC.getSamplerModel().editBackendInstrument(getChannelId());
724                    }
725                                    
726          }                  public void
727                            channelChanged(SamplerChannelEvent e) {
728          protected void                          boolean b = getChannelInfo().getInstrumentStatus() == 100;
729          updateVolumeInfo(int volume) {                          setEnabled(b);
730                  lVolume.setText(i18n.getLabel("ChannelScreen.volume", volume));                  }
731                                    
732                    public void
733                    streamCountChanged(SamplerChannelEvent e) { }
734                    
735                    public void
736                    voiceCountChanged(SamplerChannelEvent e) { }
737          }          }
738                    
739          /**          class FxSendsAction extends AbstractAction {
740           * Updates the number of active disk streams.                  FxSendsAction() {
741           * @param count The new number of active disk streams.                          super(i18n.getMenuLabel("channels.fxSends"));
742           */                  }
743          protected void                  
744          updateStreamCount(int count) {                  public void
745                  Dimension d = lStreams.getPreferredSize();                  actionPerformed(ActionEvent e) {
746                  lStreams.setText(count == 0 ? "--" : String.valueOf(count));                          showFxSendsDialog();
                 d = JuifeUtils.getUnionSize(d, lStreams.getPreferredSize());  
                 lStreams.setMinimumSize(d);  
                 lStreams.setPreferredSize(d);  
                 lStreams.setMaximumSize(d);  
         }  
           
         /**  
          * Updates the number of active voices.  
          * @param count The new number of active voices.  
          */  
         protected void  
         updateVoiceCount(int count) {  
                 Dimension d = lVoices.getPreferredSize();  
                 lVoices.setText(count == 0 ? "--" : String.valueOf(count));  
                 d = JuifeUtils.getUnionSize(d, lVoices.getPreferredSize());  
                 lVoices.setMinimumSize(d);  
                 lVoices.setPreferredSize(d);  
                 lVoices.setMaximumSize(d);  
         }  
           
         static class ScreenButton extends JButton {  
                 ScreenButton(String s) {  
                         super(s);  
                         setContentAreaFilled(false);  
                         setFocusPainted(false);  
                         setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));  
                         setMargin(new Insets(0, 0, 0, 0));  
                         setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));  
747                  }                  }
748          }          }
 }  
   
 class ChannelOptions extends JPanel {  
         private final Channel channel;  
749                    
750          private final JComboBox cbMidiDevice = new JComboBox();          class ChannelRoutingAction extends AbstractAction implements SamplerChannelListener {
751          private final JComboBox cbMidiPort = new JComboBox();                  ChannelRoutingAction() {
752          private final JComboBox cbMidiChannel = new JComboBox();                          super(i18n.getMenuLabel("channels.channelRouting"));
753          private final JComboBox cbEngine = new JComboBox();                          channelChanged(null);
754          private final JComboBox cbAudioDevice = new JComboBox();                          getModel().addSamplerChannelListener(this);
755                            }
         private boolean update = false;  
           
         ChannelOptions(Channel channel) {  
                 this.channel = channel;  
                   
                 setName("ChannelOptions");  
                 setVisible(false);  
                 setBorder(BorderFactory.createEmptyBorder(5, 4, 5, 4));  
                 setLayout(new BoxLayout(this, BoxLayout.X_AXIS));  
                   
                 setPreferredSize(new Dimension(420, 44));  
                 setMinimumSize(getPreferredSize());  
                 setMaximumSize(getPreferredSize());  
                   
                 JPanel p = new JPanel();  
                 p.setOpaque(true);  
                 p.setBorder(BorderFactory.createEmptyBorder(3, 4, 3, 4));  
                 p.setLayout(new BoxLayout(p, BoxLayout.Y_AXIS));  
                 JLabel l = new JLabel(Res.iconMidiInputTitle);  
                 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(67, 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);  
                 p.add(p2);  
                   
                 add(p);  
                   
                 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.iconEngineTitle);  
                 l.setAlignmentX(LEFT_ALIGNMENT);  
                 l.setAlignmentX(LEFT_ALIGNMENT);  
                 p.add(l);  
                   
                 p.add(Box.createRigidArea(new Dimension(0, 3)));  
                   
                 o = cbEngine.getRenderer();  
                 if(o instanceof JLabel) ((JLabel )o).setHorizontalAlignment(SwingConstants.CENTER);  
                   
                 for(SamplerEngine e : CC.getSamplerModel().getEngines()) cbEngine.addItem(e);  
                 cbEngine.setPreferredSize(new Dimension(125, 18));  
                 cbEngine.setMinimumSize(cbEngine.getPreferredSize());  
                 cbEngine.setMaximumSize(cbEngine.getPreferredSize());  
                 cbEngine.setAlignmentX(LEFT_ALIGNMENT);  
                 p.add(cbEngine);  
                   
                 add(p);  
                   
                 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.iconAudioOutputTitle);  
                 l.setAlignmentX(LEFT_ALIGNMENT);  
                 l.setAlignmentX(LEFT_ALIGNMENT);  
                 p.add(l);  
                   
                 p.add(Box.createRigidArea(new Dimension(0, 3)));  
                   
                 o = cbAudioDevice.getRenderer();  
                 if(o instanceof JLabel) ((JLabel )o).setHorizontalAlignment(SwingConstants.RIGHT);  
                   
                 cbAudioDevice.setPreferredSize(new Dimension(61, 18));  
                 cbAudioDevice.setMinimumSize(cbAudioDevice.getPreferredSize());  
                 cbAudioDevice.setMaximumSize(cbAudioDevice.getPreferredSize());  
                 cbAudioDevice.setAlignmentX(LEFT_ALIGNMENT);  
                 p.add(cbAudioDevice);  
                   
                 add(p);  
                   
                 cbMidiDevice.addActionListener(new ActionListener() {  
                         public void  
                         actionPerformed(ActionEvent e) { setMidiDevice(); }  
                 });  
                   
                 cbMidiPort.addActionListener(new ActionListener() {  
                         public void  
                         actionPerformed(ActionEvent e) { setMidiPort(); }  
                 });  
                   
                 cbMidiChannel.addActionListener(new ActionListener() {  
                         public void  
                         actionPerformed(ActionEvent e) { setMidiChannel(); }  
                 });  
756                                    
757                  cbEngine.addActionListener(new ActionListener() {                  public void
758                          public void                  actionPerformed(ActionEvent e) {
759                          actionPerformed(ActionEvent e) { setEngineType(); }                          SamplerChannel c = getChannelInfo();
760                  });                          new JSChannelOutputRoutingDlg(CC.getMainFrame(), c).setVisible(true);
761                    }
762                                    
763                  cbAudioDevice.addActionListener(new ActionListener() {                  public void
764                          public void                  channelChanged(SamplerChannelEvent e) {
765                          actionPerformed(ActionEvent e) { setBackendAudioDevice(); }                          boolean b = getChannelInfo().getAudioOutputDevice() != -1;
766                  });                          setEnabled(b);
767                    }
768                                    
769                  channel.getModel().addSamplerChannelListener(new SamplerChannelAdapter() {                  public void
770                          public void                  streamCountChanged(SamplerChannelEvent e) { }
                         channelChanged(SamplerChannelEvent e) { updateChannelProperties(); }  
                 });  
771                                    
772                  CC.getSamplerModel().addMidiDeviceListListener(getHandler());                  public void
773                  CC.getSamplerModel().addAudioDeviceListListener(getHandler());                  voiceCountChanged(SamplerChannelEvent e) { }
774            }
775            
776            class SetSmallViewAction extends AbstractAction {
777                    SetSmallViewAction() {
778                            super(i18n.getMenuLabel("channels.smallView"));
779                    }
780                                    
781                  updateMidiDevices();                  public void
782                  updateAudioDevices();                  actionPerformed(ActionEvent e) {
783                  updateChannelProperties();                          viewTracker.setView(new SmallChannelView(Channel.this));
784                    }
785          }          }
786                    
787          /**          class SetNormalViewAction extends AbstractAction {
788           * Updates the channel settings. This method is invoked when changes to the                  SetNormalViewAction() {
789           * channel were made.                          super(i18n.getMenuLabel("channels.normalView"));
790           */                  }
         private void  
         updateChannelProperties() {  
                 SamplerModel sm = CC.getSamplerModel();  
                 SamplerChannel sc = channel.getModel().getChannelInfo();  
791                                    
792                  MidiDeviceModel mm = sm.getMidiDeviceModel(sc.getMidiInputDevice());                  public void
793                  AudioDeviceModel am = sm.getAudioDeviceModel(sc.getAudioOutputDevice());                  actionPerformed(ActionEvent e) {
794                            viewTracker.setView(new NormalChannelView(Channel.this));
795                    }
796            }
797            
798            public ContextMenu
799            getContextMenu() { return contextMenu; }
800            
801            class ContextMenu extends MouseAdapter {
802                    private JPopupMenu menu = null;
803                                    
804                  if(isUpdate()) CC.getLogger().warning("Unexpected update state!");                  protected JRadioButtonMenuItem rbmiSmallView;
805                    protected JRadioButtonMenuItem rbmiNormalView;
806                                    
807                  setUpdate(true);                  ContextMenu() {
808                            
809                    }
810                                    
811                  try {                  private void
812                          cbMidiDevice.setSelectedItem(mm == null ? null : mm.getDeviceInfo());                  createMenu() {
813                            menu = new JPopupMenu();
814                            menu.add(new JMenuItem(new EditInstrumentAction()));
815                            menu.addSeparator();
816                                                    
817                          cbEngine.setSelectedItem(sc.getEngine());                          rbmiSmallView = new JRadioButtonMenuItem(new SetSmallViewAction());
818                            rbmiNormalView = new JRadioButtonMenuItem(new SetNormalViewAction());
819                            if(viewTracker.getOriginalView() instanceof SmallChannelView) {
820                                    rbmiSmallView.setSelected(true);
821                            } else if(viewTracker.getOriginalView() instanceof NormalChannelView) {
822                                    rbmiNormalView.setSelected(true);
823                            }
824                            
825                            ButtonGroup group = new ButtonGroup();
826                            group.add(rbmiSmallView);
827                            group.add(rbmiNormalView);
828                                                    
829                          cbAudioDevice.setSelectedItem(am == null ? null : am.getDeviceInfo());                          menu.add(rbmiSmallView);
830                  } catch(Exception x) {                          menu.add(rbmiNormalView);
831                          CC.getLogger().log(Level.WARNING, "Unkown error", x);                          
832                            menu.addSeparator();
833                            menu.add(new JMenuItem(new FxSendsAction()));
834                            menu.add(new JMenuItem(new ChannelRoutingAction()));
835                  }                  }
836                                    
837                  setUpdate(false);                  private JPopupMenu
838                    getMenu() {
839                            if(menu == null) createMenu();
840                            return menu;
841                    }
842                    
843                    public void
844                    mousePressed(MouseEvent e) {
845                            if(e.isPopupTrigger()) show(e);
846                    }
847            
848                    public void
849                    mouseReleased(MouseEvent e) {
850                            if(e.isPopupTrigger()) show(e);
851                    }
852            
853                    void
854                    show(MouseEvent e) {
855                            getMenu().show(e.getComponent(), e.getX(), e.getY());
856                    }
857          }          }
858                    
859          /**          class FxSendsPane extends JSFxSendsPane {
860           * Updates the MIDI device list.                  FxSendsPane(SamplerChannelModel model) {
861           */                          super(model);
862          private void                          
863          updateMidiDevices() {                          actionAddFxSend.putValue(Action.SMALL_ICON, Res.iconNew16);
864                  SamplerModel sm = CC.getSamplerModel();                          actionRemoveFxSend.putValue(Action.SMALL_ICON, Res.iconDelete16);
865                  SamplerChannel sc = channel.getModel().getChannelInfo();                  }
                   
                 setUpdate(true);  
                   
                 try {  
                         cbMidiDevice.removeAllItems();  
866                                    
867                          for(MidiDeviceModel m : sm.getMidiDeviceModels())                  protected JToolBar
868                                  cbMidiDevice.addItem(m.getDeviceInfo());                  createToolBar() {
869                            JToolBar tb = new JToolBar();
870                            Dimension d = new Dimension(Short.MAX_VALUE, tb.getPreferredSize().height);
871                            tb.setMaximumSize(d);
872                            tb.setFloatable(false);
873                            tb.setAlignmentX(JPanel.RIGHT_ALIGNMENT);
874                            
875                            tb.add(new ToolbarButton(actionAddFxSend));
876                            tb.add(new ToolbarButton(actionRemoveFxSend));
877                                    
878                          MidiDeviceModel mm = sm.getMidiDeviceModel(sc.getMidiInputDevice());                          return tb;
                         cbMidiDevice.setSelectedItem(mm == null ? null : mm.getDeviceInfo());  
                 } catch(Exception x) {  
                         CC.getLogger().log(Level.WARNING, "Unkown error", x);  
879                  }                  }
                   
                 setUpdate(false);  
880          }          }
881                    
882          /**          public static class StreamVoiceCountPane extends JPanel {
883           * Updates the audio device list.                  private final Channel channel;
          */  
         private void  
         updateAudioDevices() {  
                 SamplerModel sm = CC.getSamplerModel();  
                 SamplerChannel sc = channel.getModel().getChannelInfo();  
                   
                 setUpdate(true);  
884                                    
885                  try {                  private final JLabel lStreams = createScreenLabel(" --");
886                          cbAudioDevice.removeAllItems();                  private final JLabel lSlash = createScreenLabel("/");
887                    private final JLabel lVoices = createScreenLabel("-- ");
888                                    
889                          for(AudioDeviceModel m : sm.getAudioDeviceModels())                  public
890                                  cbAudioDevice.addItem(m.getDeviceInfo());                  StreamVoiceCountPane(Channel channel) {
891                            this.channel = channel;
892                            
893                            setOpaque(false);
894                            setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
895                            lStreams.setFont(Res.fontScreenMono);
896                            lStreams.setHorizontalAlignment(JLabel.RIGHT);
897                            lStreams.setToolTipText(i18n.getLabel("Channel.streamVoiceCount"));
898                            
899                            Dimension d = lStreams.getPreferredSize();
900                            lStreams.setMinimumSize(d);
901                            lStreams.setPreferredSize(d);
902                            lStreams.setMaximumSize(d);
903                            add(lStreams);
904                            
905                            lSlash.setFont(Res.fontScreenMono);
906                            lSlash.setToolTipText(i18n.getLabel("Channel.streamVoiceCount"));
907                            add(lSlash);
908                            
909                            lVoices.setFont(Res.fontScreenMono);
910                            lVoices.setToolTipText(i18n.getLabel("Channel.streamVoiceCount"));
911                            
912                            d = lStreams.getPreferredSize();
913                            lVoices.setMinimumSize(d);
914                            lVoices.setPreferredSize(d);
915                            lVoices.setMaximumSize(d);
916                            add(lVoices);
917                            
918                            lStreams.addMouseListener(channel.getContextMenu());
919                            lSlash.addMouseListener(channel.getContextMenu());
920                            lVoices.addMouseListener(channel.getContextMenu());
921                    }
922                                    
923                          AudioDeviceModel am = sm.getAudioDeviceModel(sc.getAudioOutputDevice());                  public void
924                          cbAudioDevice.setSelectedItem(am == null ? null : am.getDeviceInfo());                  updateStreamCount(int count) {
925                  } catch(Exception x) {                          lStreams.setText(count == 0 ? " --" : String.valueOf(count));
                         CC.getLogger().log(Level.WARNING, "Unkown error", x);  
926                  }                  }
927                                    
928                  setUpdate(false);                  public void
929                    updateVoiceCount(int count) {
930                            lVoices.setText(count == 0 ? "-- " : String.valueOf(count));
931                    }
932          }          }
933                    
934          private void          public static class VolumePane extends JPanel {
935          setMidiDevice() {                  private final Channel channel;
936                  MidiInputDevice mid = (MidiInputDevice)cbMidiDevice.getSelectedItem();                  private final JButton btnVolume = createScreenButton("");
937                    private JSVolumeEditorPopup popupVolume;
938                                    
939                  if(!isUpdate()) {                  private static NumberFormat numberFormat = NumberFormat.getInstance();
940                          if(mid != null) {                  static { numberFormat.setMaximumFractionDigits(1); }
                                 channel.getModel().setBackendMidiInputDevice(mid.getDeviceId());  
                         }  
                           
                         return;  
                 }  
941                                    
942                  cbMidiPort.removeAllItems();                  public
943                                    VolumePane(final Channel channel) {
944                  if(mid == null) {                          this.channel = channel;
945                          cbMidiPort.setEnabled(false);                          setOpaque(false);
946                            setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
947                                                    
948                          cbMidiChannel.setSelectedItem(null);                          btnVolume.setIcon(Res.iconVolume14);
949                          cbMidiChannel.setEnabled(false);                          btnVolume.setIconTextGap(2);
950                  } else {                          btnVolume.setAlignmentX(RIGHT_ALIGNMENT);
951                          cbMidiPort.setEnabled(true);                          btnVolume.setHorizontalAlignment(btnVolume.LEFT);
952                            updateVolumeInfo(100);
953                            Dimension d = btnVolume.getPreferredSize();
954                            d.width = 57;
955                            btnVolume.setPreferredSize(d);
956                            btnVolume.setMinimumSize(d);
957                                                    
958                          MidiPort[] ports = mid.getMidiPorts();                          add(btnVolume);
                         for(MidiPort port : ports) cbMidiPort.addItem(port);  
959                                                    
960                          int p = channel.getModel().getChannelInfo().getMidiInputPort();                          btnVolume.addActionListener(new ActionListener() {
961                          cbMidiPort.setSelectedItem(p >= 0 && p < ports.length ? ports[p] : null);                                  public void
962                                    actionPerformed(ActionEvent e) {
963                                            if(popupVolume.isVisible()) {
964                                                    popupVolume.commit();
965                                                    popupVolume.hide();
966                                            } else {
967                                                    float vol = channel.getModel().getChannelInfo().getVolume();
968                                                    popupVolume.setCurrentVolume(vol);
969                                                    popupVolume.show();
970                                            }
971                                    }
972                            });
973                            
974                            popupVolume = new JSVolumeEditorPopup(btnVolume, VolumeType.CHANNEL);
975                            
976                            popupVolume.addActionListener(new ActionListener() {
977                                    public void
978                                    actionPerformed(ActionEvent e) {
979                                            channel.getModel().setBackendVolume(popupVolume.getVolumeFactor());
980                                    }
981                            });
982                                                    
983                          cbMidiChannel.setEnabled(true);                          btnVolume.addMouseListener(channel.getContextMenu());
                         int c = channel.getModel().getChannelInfo().getMidiInputChannel();  
                         cbMidiChannel.setSelectedItem(c == -1 ? "All" : "Channel " + (c + 1));  
984                  }                  }
         }  
           
         private void  
         setMidiPort() {  
                 if(isUpdate()) return;  
985                                    
986                  channel.getModel().setBackendMidiInputPort(cbMidiPort.getSelectedIndex());                  public void
987                    updateVolumeInfo(int volume) {
988                            if(CC.getViewConfig().isMeasurementUnitDecibel()) {
989                                    String s = numberFormat.format(HF.percentsToDecibels(volume));
990                                    btnVolume.setText(s + "dB");
991                            } else {
992                                    btnVolume.setText(String.valueOf(volume) + "%");
993                            }
994                    }
995          }          }
996                    
997          private void          public static class PowerButton extends PixmapToggleButton implements ActionListener {
998          setMidiChannel() {                  private final Channel channel;
                 if(isUpdate()) return;  
                   
                 Object o = cbMidiChannel.getSelectedItem();  
                 if(o == null) return;  
                 String s = o.toString();  
999                                    
1000                  int c = s.equals("All") ? -1 : Integer.parseInt(s.substring(8)) - 1;                  PowerButton(Channel channel) {
1001                            this(channel, Res.gfxPowerOff, Res.gfxPowerOn);
1002                    }
1003                                    
1004                  channel.getModel().setBackendMidiInputChannel(c);                  PowerButton(Channel channel, ImageIcon defaultIcon, ImageIcon selectedIcon) {
1005          }                          super(defaultIcon, selectedIcon);
1006                                    
1007          /** Invoked when the user selects an engine. */                          this.channel = channel;
         private void  
         setEngineType() {  
                 Object oldEngine = channel.getModel().getChannelInfo().getEngine();  
                 SamplerEngine newEngine = (SamplerEngine)cbEngine.getSelectedItem();  
1008                                    
1009                  if(oldEngine != null) { if(oldEngine.equals(newEngine)) return; }                          setSelected(true);
1010                  else if(newEngine == null) return;                          addActionListener(this);
1011                            setToolTipText(i18n.getButtonLabel("Channel.ttRemoveChannel"));
1012                    }
1013                                    
1014                  channel.getModel().setBackendEngineType(newEngine.getName());                  public void
1015                    actionPerformed(ActionEvent e) {
1016                            boolean b = preferences().getBoolProperty(CONFIRM_CHANNEL_REMOVAL);
1017                            if(b) {
1018                                    String s = i18n.getMessage("Channel.remove?", channel.getChannelId());
1019                                    if(!HF.showYesNoDialog(channel, s)) {
1020                                            setSelected(true);
1021                                            return;
1022                                    }
1023                            }
1024                            channel.remove();
1025                    }
1026                                    
1027                    public boolean
1028                    contains(int x, int y) { return (x - 11)*(x - 11) + (y - 11)*(y - 11) < 71; }
1029          }          }
1030                    
1031          private void          public static class OptionsButton extends PixmapToggleButton
1032          setBackendAudioDevice() {                                          implements ActionListener, PropertyChangeListener {
1033                  if(isUpdate()) return;                  
1034                  AudioOutputDevice dev = (AudioOutputDevice)cbAudioDevice.getSelectedItem();                  private final Channel channel;
1035                  if(dev != null) channel.getModel().setBackendAudioOutputDevice(dev.getDeviceId());                  
1036          }                  OptionsButton(Channel channel) {
1037                                    super(Res.gfxOptionsOff, Res.gfxOptionsOn);
1038          /**                          
1039           * Determines whether the currently processed changes are due to update.                          this.channel = channel;
1040           * @return <code>true</code> if the currently processed changes are due to update and                          
1041           * <code>false</code> if the currently processed changes are due to user input.                          setRolloverIcon(Res.gfxOptionsOffRO);
1042           */                          this.setRolloverSelectedIcon(Res.gfxOptionsOnRO);
1043          private boolean                          addActionListener(this);
1044          isUpdate() { return update; }                          setToolTipText(i18n.getButtonLabel("Channel.ttShowOptions"));
           
         /**  
          * 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; }  
           
         private final Handler handler = new Handler();  
           
         private Handler  
         getHandler() { return handler; }  
           
         private class Handler implements MidiDeviceListListener, ListListener<AudioDeviceModel> {  
                 /**  
                  * Invoked when a new MIDI device is created.  
                  * @param e A <code>MidiDeviceListEvent</code>  
                  * instance providing the event information.  
                  */  
                 public void  
                 deviceAdded(MidiDeviceListEvent e) {  
                         cbMidiDevice.addItem(e.getMidiDeviceModel().getDeviceInfo());  
1045                  }                  }
1046                            
                 /**  
                  * Invoked when a MIDI device is removed.  
                  * @param e A <code>MidiDeviceListEvent</code>  
                  * instance providing the event information.  
                  */  
1047                  public void                  public void
1048                  deviceRemoved(MidiDeviceListEvent e) {                  actionPerformed(ActionEvent e) {
1049                          cbMidiDevice.removeItem(e.getMidiDeviceModel().getDeviceInfo());                          ChannelView view = channel.viewTracker.getCurrentView();
1050                            
1051                            if(isSelected() && view.getChannelOptionsView() == null) {
1052                                    view.installChannelOptionsView();
1053                                    JComponent c = view.getChannelOptionsView().getComponent();
1054                                    channel.optionsPane.setContentPane(c);
1055                            }
1056                            
1057                            channel.showOptionsPane(isSelected());
1058                            
1059                            String s;
1060                            if(isSelected()) s = i18n.getButtonLabel("Channel.ttHideOptions");
1061                            else s = i18n.getButtonLabel("Channel.ttShowOptions");
1062                            
1063                            setToolTipText(s);
1064                            
1065                            s = JXCollapsiblePane.ANIMATION_STATE_KEY;
1066                            channel.optionsPane.addPropertyChangeListener(s, this);
1067                  }                  }
1068                                    
                 /**  
                  * Invoked when a new audio device is created.  
                  * @param e An <code>AudioDeviceListEvent</code>  
                  * instance providing the event information.  
                  */  
1069                  public void                  public void
1070                  entryAdded(ListEvent<AudioDeviceModel> e) {                  propertyChange(PropertyChangeEvent e) {
1071                          cbAudioDevice.addItem(e.getEntry().getDeviceInfo());                          if(e.getNewValue() == "collapsed") {
1072                                    ChannelView view = channel.viewTracker.getCurrentView();
1073                                    view.uninstallChannelOptionsView();
1074                                    channel.optionsPane.setContentPane(new JPanel());
1075                            }
1076                  }                  }
1077                            
                 /**  
                  * Invoked when an audio device is removed.  
                  * @param e An <code>AudioDeviceListEvent</code>  
                  * instance providing the event information.  
                  */  
1078                  public void                  public void
1079                  entryRemoved(ListEvent<AudioDeviceModel> e) {                  onDestroy() {
1080                          cbAudioDevice.removeItem(e.getEntry().getDeviceInfo());                          String s = JXCollapsiblePane.ANIMATION_STATE_KEY;
1081                            channel.optionsPane.removePropertyChangeListener(s, this);
1082                  }                  }
1083                    
1084                    public boolean
1085                    contains(int x, int y) { return super.contains(x, y) & y < 13; }
1086            }
1087    }
1088    
1089    class ChannelOptionsPane extends JXCollapsiblePane {
1090            ChannelOptionsPane() {
1091                    setAnimated(false);
1092                    setCollapsed(true);
1093                    setAnimated(preferences().getBoolProperty(ANIMATED));
1094                    
1095                    preferences().addPropertyChangeListener(ANIMATED, new PropertyChangeListener() {
1096                            public void
1097                            propertyChange(PropertyChangeEvent e) {
1098                                    setAnimated(preferences().getBoolProperty(ANIMATED));
1099                            }
1100                    });
1101          }          }
1102            
1103            public void
1104            showOptionsPane(boolean show) { setCollapsed(!show); }
1105  }  }

Legend:
Removed from v.1143  
changed lines
  Added in v.1737

  ViewVC Help
Powered by ViewVC