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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1318 - (hide annotations) (download)
Sat Sep 1 13:46:04 2007 UTC (16 years, 8 months ago) by iliev
File size: 41872 byte(s)
* Fantasia: Added scrollbar to the channels pane
* Implemented automatic scrolling when new channel is
  created to ensure that it is visible on the screen

1 iliev 912 /*
2     * JSampler - a java front-end for LinuxSampler
3     *
4 iliev 1285 * Copyright (C) 2005-2007 Grigor Iliev <grigor@grigoriliev.com>
5 iliev 912 *
6     * This file is part of JSampler.
7     *
8     * JSampler is free software; you can redistribute it and/or modify
9     * it under the terms of the GNU General Public License version 2
10     * as published by the Free Software Foundation.
11     *
12     * JSampler is distributed in the hope that it will be useful,
13     * but WITHOUT ANY WARRANTY; without even the implied warranty of
14     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15     * GNU General Public License for more details.
16     *
17     * You should have received a copy of the GNU General Public License
18     * along with JSampler; if not, write to the Free Software
19     * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
20     * MA 02111-1307 USA
21     */
22    
23     package org.jsampler.view.fantasia;
24    
25     import java.awt.Cursor;
26     import java.awt.Dimension;
27 iliev 1285 import java.awt.Graphics;
28 iliev 912 import java.awt.Insets;
29    
30     import java.awt.event.ActionEvent;
31     import java.awt.event.ActionListener;
32     import java.awt.event.MouseAdapter;
33     import java.awt.event.MouseEvent;
34    
35 iliev 1285 import java.beans.PropertyChangeEvent;
36     import java.beans.PropertyChangeListener;
37    
38 iliev 912 import java.util.logging.Level;
39    
40 iliev 1285 import javax.swing.Action;
41 iliev 912 import javax.swing.BorderFactory;
42     import javax.swing.Box;
43     import javax.swing.BoxLayout;
44     import javax.swing.DefaultListCellRenderer;
45     import javax.swing.JButton;
46     import javax.swing.JComboBox;
47     import javax.swing.JLabel;
48 iliev 1285 import javax.swing.JMenuItem;
49 iliev 912 import javax.swing.JPanel;
50 iliev 1285 import javax.swing.JPopupMenu;
51 iliev 912 import javax.swing.JToggleButton;
52 iliev 1285 import javax.swing.JToolBar;
53 iliev 912 import javax.swing.SwingConstants;
54    
55     import javax.swing.event.ChangeEvent;
56     import javax.swing.event.ChangeListener;
57    
58     import net.sf.juife.Dial;
59 iliev 1285 import net.sf.juife.InformationDialog;
60 iliev 912 import net.sf.juife.JuifeUtils;
61     import net.sf.juife.TitleBar;
62    
63 iliev 1285 import org.jdesktop.swingx.JXCollapsiblePane;
64    
65 iliev 912 import org.jsampler.AudioDeviceModel;
66     import org.jsampler.CC;
67     import org.jsampler.MidiDeviceModel;
68 iliev 1285 import org.jsampler.MidiInstrumentMap;
69 iliev 912 import org.jsampler.SamplerChannelModel;
70     import org.jsampler.SamplerModel;
71    
72 iliev 1143 import org.jsampler.event.ListEvent;
73     import org.jsampler.event.ListListener;
74 iliev 1285 import org.jsampler.event.MidiDeviceEvent;
75 iliev 912 import org.jsampler.event.MidiDeviceListEvent;
76     import org.jsampler.event.MidiDeviceListListener;
77 iliev 1285 import org.jsampler.event.MidiDeviceListener;
78     import org.jsampler.event.SamplerAdapter;
79 iliev 912 import org.jsampler.event.SamplerChannelAdapter;
80     import org.jsampler.event.SamplerChannelEvent;
81 iliev 1285 import org.jsampler.event.SamplerChannelListEvent;
82     import org.jsampler.event.SamplerChannelListListener;
83 iliev 912 import org.jsampler.event.SamplerChannelListener;
84 iliev 1285 import org.jsampler.event.SamplerEvent;
85     import org.jsampler.event.SamplerListener;
86 iliev 912
87 iliev 1285 import org.jsampler.view.std.JSChannelOutputRoutingDlg;
88     import org.jsampler.view.std.JSFxSendsPane;
89     import org.jsampler.view.std.JSInstrumentChooser;
90    
91     import org.jvnet.lafwidget.animation.FadeConfigurationManager;
92     import org.jvnet.lafwidget.animation.FadeKind;
93    
94     import org.jvnet.substance.SubstanceImageCreator;
95     import org.jvnet.substance.SubstanceLookAndFeel;
96    
97 iliev 912 import org.linuxsampler.lscp.AudioOutputDevice;
98     import org.linuxsampler.lscp.MidiInputDevice;
99     import org.linuxsampler.lscp.MidiPort;
100     import org.linuxsampler.lscp.SamplerChannel;
101     import org.linuxsampler.lscp.SamplerEngine;
102    
103     import static org.jsampler.view.fantasia.FantasiaI18n.i18n;
104 iliev 1285 import static org.jsampler.view.fantasia.FantasiaPrefs.*;
105 iliev 912
106    
107     /**
108     *
109     * @author Grigor Iliev
110     */
111     public class Channel extends org.jsampler.view.JSChannel {
112 iliev 1285 private final JXCollapsiblePane mainPane;
113 iliev 912 private final ChannelScreen screen = new ChannelScreen(this);
114     private final ChannelOptions optionsPane = new ChannelOptions(this);
115    
116     private final PowerButton btnPower = new PowerButton();
117     private final MuteButton btnMute = new MuteButton();
118     private final SoloButton btnSolo = new SoloButton();
119     private final OptionsButton btnOptions = new OptionsButton();
120    
121     private final EnhancedDial dialVolume = new EnhancedDial();
122    
123     private boolean selected = false;
124    
125     /**
126     * Creates a new instance of <code>Channel</code> using the specified
127     * non-<code>null</code> channel model.
128     * @param model The model to be used by this channel.
129     * @throws IllegalArgumentException If the model is <code>null</code>.
130     */
131     public
132     Channel(SamplerChannelModel model) {
133 iliev 1318 this(model, null);
134     }
135    
136     /**
137     * Creates a new instance of <code>Channel</code> using the specified
138     * non-<code>null</code> channel model.
139     * @param model The model to be used by this channel.
140     * @param listener A listener which is notified when the newly created
141     * channel is fully expanded on the screen.
142     * @throws IllegalArgumentException If the model is <code>null</code>.
143     */
144     public
145     Channel(SamplerChannelModel model, final ActionListener listener) {
146 iliev 912 super(model);
147    
148     setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
149 iliev 1285 ChannelPane p = new ChannelPane();
150 iliev 912 p.setLayout(new BoxLayout(p, BoxLayout.X_AXIS));
151    
152     //p.add(Box.createRigidArea(new Dimension(3, 0)));
153    
154     btnPower.setAlignmentY(JPanel.TOP_ALIGNMENT);
155    
156 iliev 1285 JPanel tb = new JPanel();
157 iliev 912 tb.setBorder(BorderFactory.createEmptyBorder(3, 3, 0, 4));
158     tb.setLayout(new BoxLayout(tb, BoxLayout.X_AXIS));
159     tb.setOpaque(false);
160     tb.setAlignmentY(JPanel.TOP_ALIGNMENT);
161     tb.add(btnPower);
162     tb.setPreferredSize(new Dimension(tb.getPreferredSize().width, 58));
163     tb.setMinimumSize(tb.getPreferredSize());
164     tb.setMaximumSize(tb.getPreferredSize());
165     p.add(tb);
166    
167     //p.add(Box.createRigidArea(new Dimension(4, 0)));
168    
169     p.add(createVSeparator());
170    
171     //p.add(Box.createRigidArea(new Dimension(3, 0)));
172    
173     JPanel p2 = new JPanel();
174     p2.setOpaque(false);
175     p2.setLayout(new BoxLayout(p2, BoxLayout.Y_AXIS));
176     p2.setAlignmentY(JPanel.TOP_ALIGNMENT);
177     p2.setBorder(BorderFactory.createEmptyBorder(5, 3, 0, 2));
178     p2.add(screen);
179     p.add(p2);
180    
181     p.add(createVSeparator());
182    
183     p2 = new JPanel();
184     p2.setOpaque(false);
185     p2.setLayout(new BoxLayout(p2, BoxLayout.Y_AXIS));
186     p2.setAlignmentY(JPanel.TOP_ALIGNMENT);
187     p2.setBorder(BorderFactory.createEmptyBorder(4, 0, 0, 0));
188 iliev 1285 p2.add(new JLabel(Res.gfxMuteTitle));
189 iliev 912 p2.add(btnMute);
190 iliev 1285 p2.add(new JLabel(Res.gfxSoloTitle));
191 iliev 912 p2.add(btnSolo);
192    
193     p.add(p2);
194    
195     p.add(createVSeparator());
196    
197     p2 = new JPanel();
198     p2.setOpaque(false);
199     p2.setLayout(new BoxLayout(p2, BoxLayout.Y_AXIS));
200     p2.setAlignmentY(JPanel.TOP_ALIGNMENT);
201     p2.setBorder(BorderFactory.createEmptyBorder(4, 0, 0, 0));
202 iliev 1285 JLabel l = new JLabel(Res.gfxVolumeTitle);
203 iliev 912 l.setAlignmentX(JPanel.CENTER_ALIGNMENT);
204     l.setBorder(BorderFactory.createEmptyBorder(0, 0, 2, 0));
205     p2.add(l);
206 iliev 1285 dialVolume.setDialPixmap(Res.gfxVolumeDial, 30, 330);
207 iliev 912 dialVolume.setAlignmentX(JPanel.CENTER_ALIGNMENT);
208     p2.add(dialVolume);
209     p.add(p2);
210    
211     p.add(createVSeparator());
212    
213     p2 = new JPanel();
214     p2.setOpaque(false);
215     p2.setLayout(new BoxLayout(p2, BoxLayout.Y_AXIS));
216     p2.setAlignmentY(JPanel.TOP_ALIGNMENT);
217     p2.setBorder(BorderFactory.createEmptyBorder(27, 0, 0, 0));
218 iliev 1285 l = new JLabel(Res.gfxOptionsTitle);
219 iliev 912 l.setAlignmentX(JPanel.CENTER_ALIGNMENT);
220     l.setBorder(BorderFactory.createEmptyBorder(0, 0, 2, 0));
221     p2.add(l);
222    
223     p2.add(Box.createRigidArea(new Dimension(0, 3)));
224    
225     btnOptions.setAlignmentX(JPanel.CENTER_ALIGNMENT);
226     p2.add(btnOptions);
227     p.add(p2);
228    
229    
230     p.setPreferredSize(new Dimension(420, 60));
231     p.setMinimumSize(p.getPreferredSize());
232     p.setMaximumSize(p.getPreferredSize());
233     //p.setBorder(BorderFactory.createEmptyBorder(1, 0, 1, 0));
234    
235     p.setAlignmentX(JPanel.CENTER_ALIGNMENT);
236     optionsPane.setAlignmentX(JPanel.CENTER_ALIGNMENT);
237    
238 iliev 1285 mainPane = new JXCollapsiblePane();
239     mainPane.getContentPane().setLayout (
240     new BoxLayout(mainPane.getContentPane(), BoxLayout.Y_AXIS)
241     );
242 iliev 912
243 iliev 1285 mainPane.add(p);
244     mainPane.add(optionsPane);
245    
246     setOpaque(false);
247    
248 iliev 912 getModel().addSamplerChannelListener(getHandler());
249    
250     updateChannelInfo();
251 iliev 1285
252     add(mainPane);
253    
254 iliev 1318 if(listener != null) {
255     final String s = JXCollapsiblePane.ANIMATION_STATE_KEY;
256     mainPane.addPropertyChangeListener(s, new PropertyChangeListener() {
257     public void
258     propertyChange(PropertyChangeEvent e) {
259     if(e.getNewValue() == "expanded") {
260     mainPane.removePropertyChangeListener(s, this);
261     listener.actionPerformed(null);
262     }
263     }
264     });
265     }
266    
267 iliev 1285 mainPane.setAnimated(false);
268     mainPane.setCollapsed(true);
269     mainPane.setAnimated(preferences().getBoolProperty(ANIMATED));
270     mainPane.setCollapsed(false);
271    
272     preferences().addPropertyChangeListener(ANIMATED, new PropertyChangeListener() {
273     public void
274     propertyChange(PropertyChangeEvent e) {
275     mainPane.setAnimated(preferences().getBoolProperty(ANIMATED));
276     }
277     });
278 iliev 1318
279     if(listener != null) {
280     javax.swing.SwingUtilities.invokeLater(new Runnable() {
281     public void
282     run() { listener.actionPerformed(null); }
283     });
284     }
285 iliev 912 }
286    
287     private JPanel
288     createVSeparator() {
289 iliev 1285 PixmapPane p = new PixmapPane(Res.gfxVLine);
290 iliev 912 p.setAlignmentY(JPanel.TOP_ALIGNMENT);
291     p.setPreferredSize(new Dimension(2, 60));
292     p.setMinimumSize(p.getPreferredSize());
293     p.setMaximumSize(p.getPreferredSize());
294     return p;
295     }
296    
297     /**
298     * Determines whether the channel is selected.
299     * @return <code>true</code> if the channel is selected, <code>false</code> otherwise.
300     */
301     public boolean isSelected() { return selected; }
302    
303     /**
304     * Sets the selection state of this channel.
305     * This method is invoked when the selection state of the channel has changed.
306     * @param select Specifies the new selection state of this channel;
307     * <code>true</code> to select the channel, <code>false</code> otherwise.
308     */
309     public void
310     setSelected(boolean select) {
311    
312     selected = select;
313     }
314    
315     /** Shows the channel properties. */
316     public void
317 iliev 1285 expandChannel() { expandChannel(optionsPane.isAnimated()); }
318 iliev 912
319 iliev 1285 /** Shows the channel properties. */
320     public void
321     expandChannel(boolean animated) {
322     if(btnOptions.isSelected()) return;
323    
324     boolean b = optionsPane.isAnimated();
325     optionsPane.setAnimated(animated);
326     btnOptions.doClick();
327     optionsPane.setAnimated(b);
328     }
329 iliev 912
330 iliev 1285
331 iliev 912 /** Invoked when the user changes the volume */
332     private void
333     setVolume() {
334     screen.updateVolumeInfo(dialVolume.getValue());
335    
336     if(dialVolume.getValueIsAdjusting()) return;
337    
338     int vol = (int)(getChannelInfo().getVolume() * 100);
339    
340     if(vol == dialVolume.getValue()) return;
341    
342    
343     /*
344     * If the model's volume is not equal to the dial knob
345     * value we assume that the change is due to user input.
346     * So we must update the volume at the backend too.
347     */
348     float volume = dialVolume.getValue();
349     volume /= 100;
350 iliev 1143 getModel().setBackendVolume(volume);
351 iliev 912 }
352    
353     /**
354     * Updates the channel settings. This method is invoked when changes to the
355     * channel were made.
356     */
357     private void
358     updateChannelInfo() {
359     SamplerChannel sc = getChannelInfo();
360    
361     screen.updateScreenInfo(sc);
362     updateMuteIcon(sc);
363    
364 iliev 1285 if(sc.isSoloChannel()) btnSolo.setIcon(Res.gfxSoloOn);
365     else btnSolo.setIcon(Res.gfxSoloOff);
366 iliev 912
367     dialVolume.setValue((int)(sc.getVolume() * 100));
368    
369     boolean b = sc.getEngine() != null;
370     dialVolume.setEnabled(b);
371     btnSolo.setEnabled(b);
372     btnMute.setEnabled(b);
373     }
374    
375     /**
376     * Updates the mute button with the proper icon regarding to information obtained
377     * from <code>channel</code>.
378     * @param channel A <code>SamplerChannel</code> instance containing the new settings
379     * for this channel.
380     */
381     private void
382     updateMuteIcon(SamplerChannel channel) {
383 iliev 1285 if(channel.isMutedBySolo()) btnMute.setIcon(Res.gfxMutedBySolo);
384     else if(channel.isMuted()) btnMute.setIcon(Res.gfxMuteOn);
385     else btnMute.setIcon(Res.gfxMuteOff);
386 iliev 912 }
387    
388     private class EnhancedDial extends Dial {
389     EnhancedDial() {
390     super(0, 100);
391    
392     setMouseHandlerMode(MouseHandlerMode.LEFT_TO_RIGHT_AND_DOWN_TO_UP);
393    
394     addMouseListener(new MouseAdapter() {
395     public void
396     mouseClicked(MouseEvent e) {
397     if(e.getButton() == e.BUTTON3) {
398     setValue(getMaximum() / 2);
399     return;
400     }
401    
402     if(e.getButton() != e.BUTTON1) return;
403    
404     if(e.getClickCount() < 2) return;
405     setValue(getValueByPoint(e.getPoint()));
406     }
407     });
408    
409     addChangeListener(new ChangeListener() {
410     public void
411     stateChanged(ChangeEvent e) { setVolume(); }
412     });
413     }
414     }
415    
416     private final EventHandler eventHandler = new EventHandler();
417    
418     private EventHandler
419     getHandler() { return eventHandler; }
420    
421     private class EventHandler implements SamplerChannelListener {
422     /**
423     * Invoked when changes are made to a sampler channel.
424     * @param e A <code>SamplerChannelEvent</code> instance
425     * containing event information.
426     */
427     public void
428     channelChanged(SamplerChannelEvent e) { updateChannelInfo(); }
429    
430     /**
431     * Invoked when the number of active disk streams has changed.
432     * @param e A <code>SamplerChannelEvent</code> instance
433     * containing event information.
434     */
435     public void
436     streamCountChanged(SamplerChannelEvent e) {
437     screen.updateStreamCount(getModel().getStreamCount());
438     }
439    
440     /**
441     * Invoked when the number of active voices has changed.
442     * @param e A <code>SamplerChannelEvent</code> instance
443     * containing event information.
444     */
445     public void
446     voiceCountChanged(SamplerChannelEvent e) {
447     screen.updateVoiceCount(getModel().getVoiceCount());
448     }
449     }
450    
451    
452 iliev 1285 private class PowerButton extends PixmapToggleButton
453     implements ActionListener, PropertyChangeListener {
454    
455 iliev 912 PowerButton() {
456 iliev 1285 super(Res.gfxPowerOff, Res.gfxPowerOn);
457 iliev 912
458     setSelected(true);
459     addActionListener(this);
460     }
461    
462     public void
463     actionPerformed(ActionEvent e) {
464 iliev 1285 if(!mainPane.isAnimated()) {
465     CC.getSamplerModel().removeBackendChannel(getChannelId());
466     return;
467     }
468    
469     String s = JXCollapsiblePane.ANIMATION_STATE_KEY;
470     mainPane.addPropertyChangeListener(s, this);
471     mainPane.setCollapsed(true);
472 iliev 912 }
473    
474 iliev 1285 public void
475     propertyChange(PropertyChangeEvent e) {
476     if(e.getNewValue() == "collapsed") {
477     CC.getSamplerModel().removeBackendChannel(getChannelId());
478     }
479     }
480    
481 iliev 912 public boolean
482     contains(int x, int y) { return (x - 11)*(x - 11) + (y - 11)*(y - 11) < 71; }
483     }
484    
485     private class MuteButton extends PixmapButton implements ActionListener {
486     MuteButton() {
487 iliev 1285 super(Res.gfxMuteOff);
488     //setDisabledIcon(Res.gfxMuteSoloDisabled);
489     setDisabledIcon (
490     SubstanceImageCreator.makeTransparent(this, Res.gfxMuteOff, 0.4)
491     );
492 iliev 912 addActionListener(this);
493     }
494    
495     public void
496     actionPerformed(ActionEvent e) {
497     SamplerChannel sc = getChannelInfo();
498     boolean b = true;
499    
500     /*
501     * Changing the mute button icon now instead of
502     * leaving the work to the notification mechanism of the LinuxSampler.
503     */
504     if(sc.isMuted() && !sc.isMutedBySolo()) {
505     b = false;
506     boolean hasSolo = CC.getSamplerModel().hasSoloChannel();
507    
508 iliev 1285 if(sc.isSoloChannel() || !hasSolo) setIcon(Res.gfxMuteOff);
509     else setIcon(Res.gfxMutedBySolo);
510     } else setIcon(Res.gfxMuteOn);
511 iliev 912
512 iliev 1143 Channel.this.getModel().setBackendMute(b);
513 iliev 912 }
514    
515     public boolean
516     contains(int x, int y) { return (x > 5 && x < 23) && (y > 5 && y < 16); }
517     }
518    
519     private class SoloButton extends PixmapButton implements ActionListener {
520     SoloButton() {
521 iliev 1285 super(Res.gfxSoloOff);
522     //setDisabledIcon(Res.gfxMuteSoloDisabled);
523     setDisabledIcon (
524     SubstanceImageCreator.makeTransparent(this, Res.gfxSoloOff, 0.4)
525     );
526 iliev 912 addActionListener(this);
527     }
528    
529     public void
530     actionPerformed(ActionEvent e) {
531     SamplerChannel sc = getChannelInfo();
532     boolean b = !sc.isSoloChannel();
533    
534     /*
535     * Changing the solo button icon (and related) now instead of
536     * leaving the work to the notification mechanism of the LinuxSampler.
537     */
538     if(b) {
539 iliev 1285 setIcon(Res.gfxSoloOn);
540     if(sc.isMutedBySolo()) btnMute.setIcon(Res.gfxMuteOff);
541 iliev 912 } else {
542 iliev 1285 setIcon(Res.gfxSoloOff);
543 iliev 912 if(!sc.isMuted() && CC.getSamplerModel().getSoloChannelCount() > 1)
544 iliev 1285 btnMute.setIcon(Res.gfxMutedBySolo);
545 iliev 912 }
546    
547 iliev 1143 Channel.this.getModel().setBackendSolo(b);
548 iliev 912 }
549    
550     public boolean
551     contains(int x, int y) { return (x > 5 && x < 23) && (y > 5 && y < 16); }
552     }
553    
554     private class OptionsButton extends PixmapToggleButton implements ActionListener {
555     OptionsButton() {
556 iliev 1285 super(Res.gfxOptionsOff, Res.gfxOptionsOn);
557     setRolloverIcon(Res.gfxOptionsOffRO);
558     this.setRolloverSelectedIcon(Res.gfxOptionsOnRO);
559 iliev 912 addActionListener(this);
560     }
561    
562     public void
563     actionPerformed(ActionEvent e) {
564     showOptionsPane(isSelected());
565    
566     String s;
567     if(isSelected()) s = i18n.getButtonLabel("OptionsButton.ttHideOptions");
568     else s = i18n.getButtonLabel("OptionsButton.ttShowOptions");
569    
570     setToolTipText(s);
571     }
572    
573     private void
574     showOptionsPane(boolean show) {
575 iliev 1285 optionsPane.setCollapsed(!show);
576 iliev 912 }
577    
578     public boolean
579 iliev 1143 contains(int x, int y) { return super.contains(x, y) & y < 13; }
580 iliev 912 }
581     }
582    
583 iliev 1285 class ChannelPane extends PixmapPane {
584     ChannelPane() {
585     super(Res.gfxChannel);
586     setPixmapInsets(new Insets(3, 3, 3, 3));
587     }
588     }
589    
590     class ChannelScreen extends PixmapPane {
591 iliev 912 private final Channel channel;
592     private JButton btnInstr = new ScreenButton(i18n.getButtonLabel("ChannelScreen.btnInstr"));
593    
594 iliev 1285 private final JButton btnFxSends =
595     new ScreenButton(i18n.getButtonLabel("ChannelScreen.btnFxSends"));
596 iliev 912
597 iliev 1285 private final JButton btnEngine
598     = new ScreenButton(i18n.getButtonLabel("ChannelScreen.btnEngine"));
599    
600     private final JPopupMenu menuEngines = new JPopupMenu();
601    
602     private final JLabel lVolume = new Label();
603     private final JLabel lStreams = new Label("--");
604     private final JLabel lVoices = new Label("--");
605    
606     private InformationDialog fxSendsDlg = null;
607    
608     private Dimension dimVolume;
609    
610     class Label extends JLabel {
611     Label() { this(""); }
612    
613     Label(String s) {
614     super(s);
615     setFont(Res.fontScreen);
616     setForeground(new java.awt.Color(0xFFA300));
617     }
618     }
619    
620     ChannelScreen(final Channel channel) {
621     super(Res.gfxChannelScreen);
622     setPixmapInsets(new Insets(6, 6, 6, 6));
623     setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
624    
625 iliev 912 this.channel = channel;
626    
627 iliev 1285 setOpaque(false);
628 iliev 912
629     setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
630    
631     btnInstr.setAlignmentX(CENTER_ALIGNMENT);
632 iliev 1285 btnInstr.setRolloverEnabled(false);
633     btnInstr.setBorder(BorderFactory.createEmptyBorder(3, 0, 0, 0));
634 iliev 912
635     add(btnInstr);
636    
637     JPanel p = new JPanel();
638     p.setLayout(new BoxLayout(p, BoxLayout.X_AXIS));
639     p.setAlignmentX(CENTER_ALIGNMENT);
640 iliev 1285 p.setBorder(BorderFactory.createEmptyBorder(5, 0, 0, 0));
641 iliev 912
642 iliev 1285 btnFxSends.setToolTipText(i18n.getButtonLabel("ChannelScreen.btnFxSends.tt"));
643     btnFxSends.addActionListener(new ActionListener() {
644     public void
645     actionPerformed(ActionEvent e) {
646     if(fxSendsDlg != null && fxSendsDlg.isVisible()) {
647     fxSendsDlg.toFront();
648     return;
649     }
650     FxSendsPane p = new FxSendsPane(channel.getModel());
651     int id = channel.getModel().getChannelId();
652     fxSendsDlg = new InformationDialog(CC.getMainFrame(), p);
653     fxSendsDlg.setTitle(i18n.getLabel("FxSendsDlg.title", id));
654     fxSendsDlg.setModal(false);
655     fxSendsDlg.showCloseButton(false);
656     fxSendsDlg.setVisible(true);
657     }
658     });
659 iliev 912
660 iliev 1285 p.add(btnFxSends);
661    
662 iliev 912 p.add(Box.createRigidArea(new Dimension(6, 0)));
663    
664 iliev 1285 btnEngine.setIcon(Res.iconEngine12);
665     p.add(btnEngine);
666     //p.add(new Label("|"));
667 iliev 912
668 iliev 1285 //p.add(Box.createRigidArea(new Dimension(6, 0)));
669 iliev 912
670 iliev 1285 //p.add(btnReset);
671 iliev 912
672     p.add(Box.createGlue());
673    
674     p.add(lStreams);
675 iliev 1285 p.add(new Label("/"));
676 iliev 912 p.add(lVoices);
677    
678     p.add(Box.createRigidArea(new Dimension(12, 0)));
679    
680 iliev 1285 lVolume.setIcon(Res.iconVolume14);
681 iliev 912 lVolume.setAlignmentX(RIGHT_ALIGNMENT);
682 iliev 1285 updateVolumeInfo(100);
683     dimVolume = lVolume.getPreferredSize();
684 iliev 912 p.add(lVolume);
685     p.setPreferredSize(new Dimension(250, p.getPreferredSize().height));
686     p.setMinimumSize(p.getPreferredSize());
687     p.setMaximumSize(p.getPreferredSize());
688    
689 iliev 1285 //btnInstr.setBorder(BorderFactory.createEmptyBorder(3, 3, 3, 3));
690     p.setOpaque(false);
691 iliev 912 add(p);
692    
693    
694     setPreferredSize(new Dimension(270, 48));
695     setMinimumSize(getPreferredSize());
696     setMaximumSize(getPreferredSize());
697    
698 iliev 1285 createEngineMenu();
699 iliev 912 installListeners();
700     }
701    
702     private void
703 iliev 1285 createEngineMenu() {
704     for(final SamplerEngine engine : CC.getSamplerModel().getEngines()) {
705     JMenuItem mi = new JMenuItem(engine.getDescription());
706    
707     mi.addActionListener(new ActionListener() {
708     public void
709     actionPerformed(ActionEvent e) {
710     channel.getModel().setBackendEngineType(engine.getName());
711     }
712     });
713    
714     menuEngines.add(mi);
715     }
716     }
717    
718     private void
719 iliev 912 installListeners() {
720     btnInstr.addActionListener(new ActionListener() {
721     public void
722     actionPerformed(ActionEvent e) { loadInstrument(); }
723     });
724    
725 iliev 1285 btnEngine.addActionListener(new ActionListener() {
726 iliev 912 public void
727 iliev 1143 actionPerformed(ActionEvent e) {
728 iliev 1285 int y = btnEngine.getHeight() + 1;
729     menuEngines.show(btnEngine, 0, y);
730 iliev 1143 }
731 iliev 912 });
732     }
733 iliev 1285
734 iliev 912 private void
735     loadInstrument() {
736 iliev 1285 JSInstrumentChooser dlg = new JSInstrumentChooser(CC.getMainFrame());
737 iliev 912 dlg.setVisible(true);
738    
739     if(!dlg.isCancelled()) {
740     SamplerChannelModel m = channel.getModel();
741 iliev 1285 m.loadBackendInstrument(dlg.getInstrumentFile(), dlg.getInstrumentIndex());
742 iliev 912 }
743     }
744    
745     protected void
746     updateScreenInfo(SamplerChannel sc) {
747     int status = sc.getInstrumentStatus();
748     if(status >= 0 && status < 100) {
749     btnInstr.setText(i18n.getLabel("ChannelScreen.loadingInstrument", status));
750     } else if(status == -1) {
751     btnInstr.setText(i18n.getButtonLabel("ChannelScreen.btnInstr"));
752     } else if(status < -1) {
753     btnInstr.setText(i18n.getLabel("ChannelScreen.errorLoadingInstrument"));
754     } else {
755     if(sc.getInstrumentName() != null) btnInstr.setText(sc.getInstrumentName());
756     else btnInstr.setText(i18n.getButtonLabel("ChannelScreen.btnInstr"));
757     }
758    
759 iliev 1285 if(sc.getEngine() != null) {
760     String s = sc.getEngine().getDescription();
761     if(!s.equals(btnEngine.getText())) btnEngine.setText(s);
762     }
763 iliev 912
764     }
765    
766     protected void
767     updateVolumeInfo(int volume) {
768     lVolume.setText(i18n.getLabel("ChannelScreen.volume", volume));
769 iliev 1285 lVolume.setMinimumSize(dimVolume);
770     lVolume.setPreferredSize(dimVolume);
771 iliev 912
772     }
773    
774     /**
775     * Updates the number of active disk streams.
776     * @param count The new number of active disk streams.
777     */
778     protected void
779     updateStreamCount(int count) {
780     Dimension d = lStreams.getPreferredSize();
781     lStreams.setText(count == 0 ? "--" : String.valueOf(count));
782     d = JuifeUtils.getUnionSize(d, lStreams.getPreferredSize());
783     lStreams.setMinimumSize(d);
784     lStreams.setPreferredSize(d);
785     lStreams.setMaximumSize(d);
786     }
787    
788     /**
789     * Updates the number of active voices.
790     * @param count The new number of active voices.
791     */
792     protected void
793     updateVoiceCount(int count) {
794     Dimension d = lVoices.getPreferredSize();
795     lVoices.setText(count == 0 ? "--" : String.valueOf(count));
796     d = JuifeUtils.getUnionSize(d, lVoices.getPreferredSize());
797     lVoices.setMinimumSize(d);
798     lVoices.setPreferredSize(d);
799     lVoices.setMaximumSize(d);
800     }
801    
802 iliev 1285 class FxSendsPane extends JSFxSendsPane {
803     FxSendsPane(SamplerChannelModel model) {
804     super(model);
805    
806     actionAddFxSend.putValue(Action.SMALL_ICON, Res.iconNew16);
807     actionRemoveFxSend.putValue(Action.SMALL_ICON, Res.iconDelete16);
808     }
809    
810     protected JToolBar
811     createToolBar() {
812     JToolBar tb = new JToolBar();
813     Dimension d = new Dimension(Short.MAX_VALUE, tb.getPreferredSize().height);
814     tb.setMaximumSize(d);
815     tb.setFloatable(false);
816     tb.setAlignmentX(JPanel.RIGHT_ALIGNMENT);
817    
818     tb.add(new ToolbarButton(actionAddFxSend));
819     tb.add(new ToolbarButton(actionRemoveFxSend));
820    
821     return tb;
822     }
823     }
824    
825 iliev 912 static class ScreenButton extends JButton {
826     ScreenButton(String s) {
827     super(s);
828     setContentAreaFilled(false);
829     setFocusPainted(false);
830     setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
831     setMargin(new Insets(0, 0, 0, 0));
832 iliev 1285
833     putClientProperty (
834     SubstanceLookAndFeel.BUTTON_NO_MIN_SIZE_PROPERTY, Boolean.TRUE
835     );
836    
837     putClientProperty (
838     SubstanceLookAndFeel.BUTTON_PAINT_NEVER_PROPERTY, Boolean.TRUE
839     );
840    
841     putClientProperty(SubstanceLookAndFeel.FLAT_PROPERTY, Boolean.TRUE);
842    
843     FadeConfigurationManager.getInstance().disallowFades(FadeKind.ROLLOVER, this);
844    
845 iliev 912 setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
846 iliev 1285 setFont(Res.fontScreen);
847     setForeground(new java.awt.Color(0xFFA300));
848 iliev 912 }
849     }
850     }
851    
852 iliev 1285 class ChannelOptions extends JXCollapsiblePane {
853 iliev 912 private final Channel channel;
854 iliev 1285 private MidiDeviceModel midiDevice = null;
855 iliev 912
856 iliev 1285 private final JComboBox cbMidiDevice = new FantasiaComboBox();
857     private final JComboBox cbMidiPort = new FantasiaComboBox();
858     private final JComboBox cbMidiChannel = new FantasiaComboBox();
859     private final JComboBox cbInstrumentMap = new FantasiaComboBox();
860     private final JComboBox cbAudioDevice = new FantasiaComboBox();
861 iliev 912
862 iliev 1285 private final PixmapButton btnChannelRouting;
863    
864 iliev 912 private boolean update = false;
865    
866 iliev 1285 private final SamplerListener samplerListener;
867     private final MapListListener mapListListener = new MapListListener();
868    
869     private class NoMap {
870     public String
871     toString() { return "[None]"; }
872     }
873    
874     private NoMap noMap = new NoMap();
875    
876     private class DefaultMap {
877     public String
878     toString() { return "[Default]"; }
879     }
880    
881     private DefaultMap defaultMap = new DefaultMap();
882    
883     ChannelOptions(final Channel channel) {
884     setAnimated(false);
885     setCollapsed(true);
886     setAnimated(preferences().getBoolProperty(ANIMATED));
887    
888     preferences().addPropertyChangeListener(ANIMATED, new PropertyChangeListener() {
889     public void
890     propertyChange(PropertyChangeEvent e) {
891     setAnimated(preferences().getBoolProperty(ANIMATED));
892     }
893     });
894    
895     PixmapPane bgp = new PixmapPane(Res.gfxChannelOptions);
896     bgp.setPixmapInsets(new Insets(1, 1, 1, 1));
897    
898 iliev 912 this.channel = channel;
899    
900 iliev 1285 bgp.setBorder(BorderFactory.createEmptyBorder(5, 4, 5, 4));
901     bgp.setLayout(new BoxLayout(bgp, BoxLayout.X_AXIS));
902 iliev 912
903 iliev 1285 bgp.setPreferredSize(new Dimension(420, 44));
904     bgp.setMinimumSize(getPreferredSize());
905     bgp.setMaximumSize(getPreferredSize());
906 iliev 912
907     JPanel p = new JPanel();
908     p.setBorder(BorderFactory.createEmptyBorder(3, 4, 3, 4));
909     p.setLayout(new BoxLayout(p, BoxLayout.Y_AXIS));
910 iliev 1285 JLabel l = new JLabel(Res.gfxMidiInputTitle);
911 iliev 912 l.setAlignmentX(LEFT_ALIGNMENT);
912     p.add(l);
913    
914     JPanel p2 = new JPanel();
915     p2.setBorder(BorderFactory.createEmptyBorder(3, 0, 0, 0));
916     p2.setLayout(new BoxLayout(p2, BoxLayout.X_AXIS));
917    
918     Object o = cbMidiDevice.getRenderer();
919     if(o instanceof JLabel) ((JLabel )o).setHorizontalAlignment(SwingConstants.CENTER);
920    
921     cbMidiDevice.setPreferredSize(new Dimension(40, 18));
922     cbMidiDevice.setMinimumSize(cbMidiDevice.getPreferredSize());
923     cbMidiDevice.setMaximumSize(cbMidiDevice.getPreferredSize());
924     p2.add(cbMidiDevice);
925    
926     p2.add(Box.createRigidArea(new Dimension(3, 0)));
927    
928     o = cbMidiPort.getRenderer();
929     if(o instanceof JLabel) ((JLabel )o).setHorizontalAlignment(SwingConstants.CENTER);
930    
931 iliev 1285 cbMidiPort.setPreferredSize(new Dimension(62, 18));
932 iliev 912 cbMidiPort.setMinimumSize(cbMidiPort.getPreferredSize());
933     cbMidiPort.setMaximumSize(cbMidiPort.getPreferredSize());
934     p2.add(cbMidiPort);
935    
936     p2.add(Box.createRigidArea(new Dimension(3, 0)));
937    
938     o = cbMidiChannel.getRenderer();
939     if(o instanceof JLabel) ((JLabel )o).setHorizontalAlignment(SwingConstants.CENTER);
940    
941     cbMidiChannel.addItem("All");
942     for(int i = 1; i <= 16; i++) cbMidiChannel.addItem("Channel " + String.valueOf(i));
943     cbMidiChannel.setPreferredSize(new Dimension(80, 18));
944     cbMidiChannel.setMinimumSize(cbMidiChannel.getPreferredSize());
945     cbMidiChannel.setMaximumSize(cbMidiChannel.getPreferredSize());
946    
947     p2.add(cbMidiChannel);
948     p2.setAlignmentX(LEFT_ALIGNMENT);
949 iliev 1285 p2.setOpaque(false);
950 iliev 912 p.add(p2);
951 iliev 1285 p.setBackground(new java.awt.Color(0x818181));
952 iliev 912
953 iliev 1285 bgp.add(p);
954 iliev 912
955 iliev 1285 bgp.add(Box.createRigidArea(new Dimension(4, 0)));
956 iliev 912
957     p = new JPanel();
958     p.setOpaque(true);
959     p.setBorder(BorderFactory.createEmptyBorder(3, 4, 3, 4));
960     p.setLayout(new BoxLayout(p, BoxLayout.Y_AXIS));
961 iliev 1285 l = new JLabel(Res.gfxInstrumentMapTitle);
962 iliev 912 l.setAlignmentX(LEFT_ALIGNMENT);
963     l.setAlignmentX(LEFT_ALIGNMENT);
964     p.add(l);
965    
966     p.add(Box.createRigidArea(new Dimension(0, 3)));
967    
968 iliev 1285 //o = cbInstrumentMap.getRenderer();
969     //if(o instanceof JLabel) ((JLabel )o).setHorizontalAlignment(SwingConstants.CENTER);
970 iliev 912
971 iliev 1285 cbInstrumentMap.setPreferredSize(new Dimension(126, 18));
972     cbInstrumentMap.setMinimumSize(cbInstrumentMap.getPreferredSize());
973     cbInstrumentMap.setMaximumSize(cbInstrumentMap.getPreferredSize());
974     cbInstrumentMap.setAlignmentX(LEFT_ALIGNMENT);
975     p.add(cbInstrumentMap);
976     p.setBackground(new java.awt.Color(0x818181));
977     bgp.add(p);
978 iliev 912
979 iliev 1285 bgp.add(Box.createRigidArea(new Dimension(4, 0)));
980 iliev 912
981     p = new JPanel();
982     p.setOpaque(true);
983     p.setBorder(BorderFactory.createEmptyBorder(3, 4, 3, 4));
984     p.setLayout(new BoxLayout(p, BoxLayout.Y_AXIS));
985 iliev 1285 l = new JLabel(Res.gfxAudioOutputTitle);
986 iliev 912 l.setAlignmentX(LEFT_ALIGNMENT);
987     p.add(l);
988    
989 iliev 1285 //p.add(Box.createRigidArea(new Dimension(0, 3)));
990 iliev 912
991 iliev 1285 p2 = new JPanel();
992     p2.setBorder(BorderFactory.createEmptyBorder(3, 0, 0, 0));
993     p2.setLayout(new BoxLayout(p2, BoxLayout.X_AXIS));
994     p2.setOpaque(false);
995     p2.setAlignmentX(LEFT_ALIGNMENT);
996    
997 iliev 912 o = cbAudioDevice.getRenderer();
998     if(o instanceof JLabel) ((JLabel )o).setHorizontalAlignment(SwingConstants.RIGHT);
999    
1000 iliev 1285 cbAudioDevice.setPreferredSize(new Dimension(40, 18));
1001 iliev 912 cbAudioDevice.setMinimumSize(cbAudioDevice.getPreferredSize());
1002     cbAudioDevice.setMaximumSize(cbAudioDevice.getPreferredSize());
1003    
1004 iliev 1285 p2.add(cbAudioDevice);
1005     p2.add(Box.createRigidArea(new Dimension(3, 0)));
1006     btnChannelRouting = new PixmapButton(Res.gfxBtnCr, Res.gfxBtnCrRO);
1007     btnChannelRouting.setPressedIcon(Res.gfxBtnCrRO);
1008     btnChannelRouting.setEnabled(false);
1009     btnChannelRouting.setToolTipText(i18n.getLabel("ChannelOptions.routing"));
1010 iliev 912
1011 iliev 1285 btnChannelRouting.addActionListener(new ActionListener() {
1012     public void
1013     actionPerformed(ActionEvent e) {
1014     SamplerChannel c = channel.getChannelInfo();
1015     new JSChannelOutputRoutingDlg(CC.getMainFrame(), c).setVisible(true);
1016    
1017     }
1018     });
1019    
1020     p2.add(btnChannelRouting);
1021    
1022     p.add(p2);
1023     p.setBackground(new java.awt.Color(0x818181));
1024     p2 = new JPanel();
1025     p2.setLayout(new java.awt.BorderLayout());
1026     p.add(p2);
1027     bgp.add(p);
1028    
1029     setContentPane(bgp);
1030    
1031 iliev 912 cbMidiDevice.addActionListener(new ActionListener() {
1032     public void
1033     actionPerformed(ActionEvent e) { setMidiDevice(); }
1034     });
1035    
1036     cbMidiPort.addActionListener(new ActionListener() {
1037     public void
1038     actionPerformed(ActionEvent e) { setMidiPort(); }
1039     });
1040    
1041     cbMidiChannel.addActionListener(new ActionListener() {
1042     public void
1043     actionPerformed(ActionEvent e) { setMidiChannel(); }
1044     });
1045    
1046 iliev 1285 samplerListener = new SamplerAdapter() {
1047     /** Invoked when the default MIDI instrument map is changed. */
1048 iliev 912 public void
1049 iliev 1285 defaultMapChanged(SamplerEvent e) {
1050     updateCbInstrumentMapToolTipText();
1051    
1052     }
1053     };
1054    
1055     CC.getSamplerModel().addSamplerListener(samplerListener);
1056    
1057     cbInstrumentMap.addItem(noMap);
1058     cbInstrumentMap.addItem(defaultMap);
1059     for(MidiInstrumentMap map : CC.getSamplerModel().getMidiInstrumentMaps()) {
1060     cbInstrumentMap.addItem(map);
1061     }
1062    
1063     int map = channel.getModel().getChannelInfo().getMidiInstrumentMapId();
1064     cbInstrumentMap.setSelectedItem(CC.getSamplerModel().getMidiInstrumentMapById(map));
1065     if(cbInstrumentMap.getSelectedItem() == null) {
1066     if(map == -1) cbInstrumentMap.setSelectedItem(noMap);
1067     else if(map == -2) {
1068     cbInstrumentMap.setSelectedItem(defaultMap);
1069     }
1070     }
1071    
1072     updateCbInstrumentMapToolTipText();
1073    
1074     if(channel.getModel().getChannelInfo().getEngine() == null) {
1075     cbInstrumentMap.setEnabled(false);
1076     }
1077    
1078     cbInstrumentMap.addActionListener(new ActionListener() {
1079     public void
1080     actionPerformed(ActionEvent e) { updateInstrumentMap(); }
1081 iliev 912 });
1082    
1083 iliev 1285 CC.getSamplerModel().addSamplerChannelListListener(getHandler());
1084     CC.getSamplerModel().addMidiInstrumentMapListListener(mapListListener);
1085    
1086 iliev 912 cbAudioDevice.addActionListener(new ActionListener() {
1087     public void
1088 iliev 1143 actionPerformed(ActionEvent e) { setBackendAudioDevice(); }
1089 iliev 912 });
1090    
1091     channel.getModel().addSamplerChannelListener(new SamplerChannelAdapter() {
1092     public void
1093     channelChanged(SamplerChannelEvent e) { updateChannelProperties(); }
1094     });
1095    
1096     CC.getSamplerModel().addMidiDeviceListListener(getHandler());
1097     CC.getSamplerModel().addAudioDeviceListListener(getHandler());
1098    
1099     updateMidiDevices();
1100     updateAudioDevices();
1101     updateChannelProperties();
1102     }
1103    
1104     /**
1105     * Updates the channel settings. This method is invoked when changes to the
1106     * channel were made.
1107     */
1108     private void
1109     updateChannelProperties() {
1110     SamplerModel sm = CC.getSamplerModel();
1111     SamplerChannel sc = channel.getModel().getChannelInfo();
1112    
1113 iliev 1204 MidiDeviceModel mm = sm.getMidiDeviceById(sc.getMidiInputDevice());
1114     AudioDeviceModel am = sm.getAudioDeviceById(sc.getAudioOutputDevice());
1115 iliev 912
1116     if(isUpdate()) CC.getLogger().warning("Unexpected update state!");
1117    
1118     setUpdate(true);
1119    
1120     try {
1121     cbMidiDevice.setSelectedItem(mm == null ? null : mm.getDeviceInfo());
1122    
1123     cbAudioDevice.setSelectedItem(am == null ? null : am.getDeviceInfo());
1124 iliev 1285 btnChannelRouting.setEnabled(am != null);
1125 iliev 912 } catch(Exception x) {
1126     CC.getLogger().log(Level.WARNING, "Unkown error", x);
1127     }
1128    
1129 iliev 1285 if(sc.getEngine() != null) {
1130     cbInstrumentMap.setEnabled(true);
1131     int id = sc.getMidiInstrumentMapId();
1132     Object o;
1133     if(id == -2) o = defaultMap;
1134     else if(id == -1) o = noMap;
1135     else o = CC.getSamplerModel().getMidiInstrumentMapById(id);
1136    
1137     if(cbInstrumentMap.getSelectedItem() != o) {
1138     cbInstrumentMap.setSelectedItem(o);
1139     }
1140     } else {
1141     cbInstrumentMap.setSelectedItem(noMap);
1142     cbInstrumentMap.setEnabled(false);
1143     }
1144    
1145 iliev 912 setUpdate(false);
1146     }
1147    
1148     /**
1149     * Updates the MIDI device list.
1150     */
1151     private void
1152     updateMidiDevices() {
1153     SamplerModel sm = CC.getSamplerModel();
1154     SamplerChannel sc = channel.getModel().getChannelInfo();
1155    
1156     setUpdate(true);
1157    
1158     try {
1159     cbMidiDevice.removeAllItems();
1160    
1161 iliev 1204 for(MidiDeviceModel m : sm.getMidiDevices())
1162 iliev 912 cbMidiDevice.addItem(m.getDeviceInfo());
1163    
1164 iliev 1204 MidiDeviceModel mm = sm.getMidiDeviceById(sc.getMidiInputDevice());
1165 iliev 912 cbMidiDevice.setSelectedItem(mm == null ? null : mm.getDeviceInfo());
1166     } catch(Exception x) {
1167     CC.getLogger().log(Level.WARNING, "Unkown error", x);
1168     }
1169    
1170     setUpdate(false);
1171     }
1172    
1173 iliev 1285
1174     private void
1175     updateInstrumentMap() {
1176     updateCbInstrumentMapToolTipText();
1177    
1178     int id = channel.getModel().getChannelInfo().getMidiInstrumentMapId();
1179     Object o = cbInstrumentMap.getSelectedItem();
1180     if(o == null && id == -1) return;
1181    
1182     int cbId;
1183     if(o == null || o == noMap) cbId = -1;
1184     else if(o == defaultMap) cbId = -2;
1185     else cbId = ((MidiInstrumentMap)o).getMapId();
1186    
1187     if(cbId == id) return;
1188    
1189     channel.getModel().setBackendMidiInstrumentMap(cbId);
1190     }
1191    
1192     private void
1193     updateCbInstrumentMapToolTipText() {
1194     if(cbInstrumentMap.getSelectedItem() != defaultMap) {
1195     cbInstrumentMap.setToolTipText(null);
1196     return;
1197     }
1198    
1199     MidiInstrumentMap m = CC.getSamplerModel().getDefaultMidiInstrumentMap();
1200     if(m != null) {
1201     String s = i18n.getLabel("Channel.ttDefault", m.getName());
1202     cbInstrumentMap.setToolTipText(s);
1203     } else {
1204     cbInstrumentMap.setToolTipText(null);
1205     }
1206     }
1207    
1208 iliev 912 /**
1209     * Updates the audio device list.
1210     */
1211     private void
1212     updateAudioDevices() {
1213     SamplerModel sm = CC.getSamplerModel();
1214     SamplerChannel sc = channel.getModel().getChannelInfo();
1215    
1216     setUpdate(true);
1217    
1218     try {
1219     cbAudioDevice.removeAllItems();
1220    
1221 iliev 1204 for(AudioDeviceModel m : sm.getAudioDevices())
1222 iliev 912 cbAudioDevice.addItem(m.getDeviceInfo());
1223    
1224 iliev 1204 AudioDeviceModel am = sm.getAudioDeviceById(sc.getAudioOutputDevice());
1225 iliev 912 cbAudioDevice.setSelectedItem(am == null ? null : am.getDeviceInfo());
1226     } catch(Exception x) {
1227     CC.getLogger().log(Level.WARNING, "Unkown error", x);
1228     }
1229    
1230     setUpdate(false);
1231     }
1232    
1233     private void
1234     setMidiDevice() {
1235     MidiInputDevice mid = (MidiInputDevice)cbMidiDevice.getSelectedItem();
1236    
1237     if(!isUpdate()) {
1238 iliev 1143 if(mid != null) {
1239     channel.getModel().setBackendMidiInputDevice(mid.getDeviceId());
1240     }
1241    
1242 iliev 912 return;
1243     }
1244    
1245 iliev 1285 if(midiDevice != null) midiDevice.removeMidiDeviceListener(getHandler());
1246    
1247 iliev 912 cbMidiPort.removeAllItems();
1248    
1249     if(mid == null) {
1250 iliev 1285 midiDevice = null;
1251 iliev 912 cbMidiPort.setEnabled(false);
1252    
1253     cbMidiChannel.setSelectedItem(null);
1254     cbMidiChannel.setEnabled(false);
1255     } else {
1256 iliev 1285 midiDevice = CC.getSamplerModel().getMidiDeviceById(mid.getDeviceId());
1257     if(midiDevice != null) midiDevice.addMidiDeviceListener(getHandler());
1258    
1259 iliev 912 cbMidiPort.setEnabled(true);
1260    
1261     MidiPort[] ports = mid.getMidiPorts();
1262     for(MidiPort port : ports) cbMidiPort.addItem(port);
1263    
1264     int p = channel.getModel().getChannelInfo().getMidiInputPort();
1265     cbMidiPort.setSelectedItem(p >= 0 && p < ports.length ? ports[p] : null);
1266    
1267     cbMidiChannel.setEnabled(true);
1268     int c = channel.getModel().getChannelInfo().getMidiInputChannel();
1269     cbMidiChannel.setSelectedItem(c == -1 ? "All" : "Channel " + (c + 1));
1270     }
1271     }
1272    
1273     private void
1274     setMidiPort() {
1275     if(isUpdate()) return;
1276    
1277 iliev 1143 channel.getModel().setBackendMidiInputPort(cbMidiPort.getSelectedIndex());
1278 iliev 912 }
1279    
1280     private void
1281     setMidiChannel() {
1282     if(isUpdate()) return;
1283    
1284     Object o = cbMidiChannel.getSelectedItem();
1285     if(o == null) return;
1286     String s = o.toString();
1287    
1288     int c = s.equals("All") ? -1 : Integer.parseInt(s.substring(8)) - 1;
1289    
1290 iliev 1143 channel.getModel().setBackendMidiInputChannel(c);
1291 iliev 912 }
1292    
1293     private void
1294 iliev 1143 setBackendAudioDevice() {
1295 iliev 912 if(isUpdate()) return;
1296     AudioOutputDevice dev = (AudioOutputDevice)cbAudioDevice.getSelectedItem();
1297 iliev 1143 if(dev != null) channel.getModel().setBackendAudioOutputDevice(dev.getDeviceId());
1298 iliev 912 }
1299    
1300     /**
1301     * Determines whether the currently processed changes are due to update.
1302     * @return <code>true</code> if the currently processed changes are due to update and
1303     * <code>false</code> if the currently processed changes are due to user input.
1304     */
1305     private boolean
1306     isUpdate() { return update; }
1307    
1308     /**
1309     * Sets whether the currently processed changes are due to update.
1310     * @param b Specify <code>true</code> to indicate that the currently
1311     * processed changes are due to update; <code>false</code>
1312     * indicates that the currently processed changes are due to user input.
1313     */
1314     private void
1315     setUpdate(boolean b) { update = b; }
1316    
1317     private final Handler handler = new Handler();
1318    
1319     private Handler
1320     getHandler() { return handler; }
1321    
1322 iliev 1285 private class Handler implements MidiDeviceListListener, ListListener<AudioDeviceModel>,
1323     SamplerChannelListListener, MidiDeviceListener {
1324 iliev 912 /**
1325     * Invoked when a new MIDI device is created.
1326     * @param e A <code>MidiDeviceListEvent</code>
1327     * instance providing the event information.
1328     */
1329     public void
1330     deviceAdded(MidiDeviceListEvent e) {
1331     cbMidiDevice.addItem(e.getMidiDeviceModel().getDeviceInfo());
1332     }
1333    
1334     /**
1335     * Invoked when a MIDI device is removed.
1336     * @param e A <code>MidiDeviceListEvent</code>
1337     * instance providing the event information.
1338     */
1339     public void
1340     deviceRemoved(MidiDeviceListEvent e) {
1341     cbMidiDevice.removeItem(e.getMidiDeviceModel().getDeviceInfo());
1342     }
1343    
1344     /**
1345     * Invoked when a new audio device is created.
1346     * @param e An <code>AudioDeviceListEvent</code>
1347     * instance providing the event information.
1348     */
1349     public void
1350 iliev 1143 entryAdded(ListEvent<AudioDeviceModel> e) {
1351     cbAudioDevice.addItem(e.getEntry().getDeviceInfo());
1352 iliev 912 }
1353    
1354     /**
1355     * Invoked when an audio device is removed.
1356     * @param e An <code>AudioDeviceListEvent</code>
1357     * instance providing the event information.
1358     */
1359     public void
1360 iliev 1143 entryRemoved(ListEvent<AudioDeviceModel> e) {
1361     cbAudioDevice.removeItem(e.getEntry().getDeviceInfo());
1362 iliev 912 }
1363 iliev 1285
1364     /**
1365     * Invoked when a new sampler channel is created.
1366     * @param e A <code>SamplerChannelListEvent</code>
1367     * instance providing the event information.
1368     */
1369     public void
1370     channelAdded(SamplerChannelListEvent e) { }
1371    
1372     /**
1373     * Invoked when a sampler channel is removed.
1374     * @param e A <code>SamplerChannelListEvent</code>
1375     * instance providing the event information.
1376     */
1377     public void
1378     channelRemoved(SamplerChannelListEvent e) {
1379     // Some cleanup when the channel is removed.
1380     if(e.getChannelModel().getChannelId() == channel.getChannelId()) {
1381     SamplerModel sm = CC.getSamplerModel();
1382    
1383     sm.removeMidiDeviceListListener(getHandler());
1384     sm.removeAudioDeviceListListener(getHandler());
1385     sm.removeMidiInstrumentMapListListener(mapListListener);
1386     sm.removeSamplerListener(samplerListener);
1387     sm.removeSamplerChannelListListener(getHandler());
1388    
1389     if(midiDevice != null) {
1390     midiDevice.removeMidiDeviceListener(getHandler());
1391     }
1392     }
1393     }
1394    
1395     public void
1396     settingsChanged(MidiDeviceEvent e) {
1397     if(isUpdate()) {
1398     CC.getLogger().warning("Invalid update state");
1399     return;
1400     }
1401    
1402     setUpdate(true);
1403     int idx = cbMidiPort.getSelectedIndex();
1404     MidiInputDevice d = e.getMidiDeviceModel().getDeviceInfo();
1405    
1406     cbMidiPort.removeAllItems();
1407     for(MidiPort port : d.getMidiPorts()) cbMidiPort.addItem(port);
1408    
1409     if(idx >= cbMidiPort.getModel().getSize()) idx = 0;
1410    
1411     setUpdate(false);
1412    
1413     if(cbMidiPort.getModel().getSize() > 0) cbMidiPort.setSelectedIndex(idx);
1414     }
1415 iliev 912 }
1416 iliev 1285
1417     private class MapListListener implements ListListener<MidiInstrumentMap> {
1418     /** Invoked when a new MIDI instrument map is added to a list. */
1419     public void
1420     entryAdded(ListEvent<MidiInstrumentMap> e) {
1421     cbInstrumentMap.insertItemAt(e.getEntry(), cbInstrumentMap.getItemCount());
1422     boolean b = channel.getModel().getChannelInfo().getEngine() != null;
1423     if(b && !cbInstrumentMap.isEnabled()) cbInstrumentMap.setEnabled(true);
1424     }
1425    
1426     /** Invoked when a new MIDI instrument map is removed from a list. */
1427     public void
1428     entryRemoved(ListEvent<MidiInstrumentMap> e) {
1429     cbInstrumentMap.removeItem(e.getEntry());
1430     if(cbInstrumentMap.getItemCount() == 0) { // TODO: ?
1431     cbInstrumentMap.setSelectedItem(noMap);
1432     cbInstrumentMap.setEnabled(false);
1433     }
1434     }
1435     }
1436 iliev 912 }

  ViewVC Help
Powered by ViewVC