/[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 1285 - (hide annotations) (download)
Fri Aug 10 19:55:03 2007 UTC (16 years, 8 months ago) by iliev
File size: 40867 byte(s)
* Updated to version 0.6a. The Fantasia distribution is now
  capable of controlling all features available in LinuxSampler

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

  ViewVC Help
Powered by ViewVC