/[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 1143 - (hide annotations) (download)
Mon Apr 2 21:18:31 2007 UTC (17 years ago) by iliev
File size: 28905 byte(s)
* upgrading to version 0.4a

1 iliev 912 /*
2     * JSampler - a java front-end for LinuxSampler
3     *
4 iliev 1143 * Copyright (C) 2005-2006 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     import java.awt.Insets;
28    
29     import java.awt.event.ActionEvent;
30     import java.awt.event.ActionListener;
31     import java.awt.event.MouseAdapter;
32     import java.awt.event.MouseEvent;
33    
34     import java.util.logging.Level;
35    
36     import javax.swing.BorderFactory;
37     import javax.swing.Box;
38     import javax.swing.BoxLayout;
39     import javax.swing.DefaultListCellRenderer;
40     import javax.swing.JButton;
41     import javax.swing.JComboBox;
42     import javax.swing.JLabel;
43     import javax.swing.JPanel;
44     import javax.swing.JToggleButton;
45     import javax.swing.SwingConstants;
46    
47     import javax.swing.event.ChangeEvent;
48     import javax.swing.event.ChangeListener;
49    
50     import net.sf.juife.Dial;
51     import net.sf.juife.JuifeUtils;
52     import net.sf.juife.TitleBar;
53    
54     import org.jsampler.AudioDeviceModel;
55     import org.jsampler.CC;
56     import org.jsampler.MidiDeviceModel;
57     import org.jsampler.SamplerChannelModel;
58     import org.jsampler.SamplerModel;
59    
60 iliev 1143 import org.jsampler.event.ListEvent;
61     import org.jsampler.event.ListListener;
62 iliev 912 import org.jsampler.event.MidiDeviceListEvent;
63     import org.jsampler.event.MidiDeviceListListener;
64     import org.jsampler.event.SamplerChannelAdapter;
65     import org.jsampler.event.SamplerChannelEvent;
66     import org.jsampler.event.SamplerChannelListener;
67    
68     import org.linuxsampler.lscp.AudioOutputDevice;
69     import org.linuxsampler.lscp.MidiInputDevice;
70     import org.linuxsampler.lscp.MidiPort;
71     import org.linuxsampler.lscp.SamplerChannel;
72     import org.linuxsampler.lscp.SamplerEngine;
73    
74     import static org.jsampler.view.fantasia.FantasiaI18n.i18n;
75    
76    
77     /**
78     *
79     * @author Grigor Iliev
80     */
81     public class Channel extends org.jsampler.view.JSChannel {
82     private final ChannelScreen screen = new ChannelScreen(this);
83     private final ChannelOptions optionsPane = new ChannelOptions(this);
84    
85     private final PowerButton btnPower = new PowerButton();
86     private final MuteButton btnMute = new MuteButton();
87     private final SoloButton btnSolo = new SoloButton();
88     private final OptionsButton btnOptions = new OptionsButton();
89    
90     private final EnhancedDial dialVolume = new EnhancedDial();
91    
92     private boolean selected = false;
93    
94     /**
95     * Creates a new instance of <code>Channel</code> using the specified
96     * non-<code>null</code> channel model.
97     * @param model The model to be used by this channel.
98     * @throws IllegalArgumentException If the model is <code>null</code>.
99     */
100     public
101     Channel(SamplerChannelModel model) {
102     super(model);
103    
104     setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
105     JPanel p = new JPanel();
106     p.setName("Channel");
107     p.setLayout(new BoxLayout(p, BoxLayout.X_AXIS));
108    
109     //p.add(Box.createRigidArea(new Dimension(3, 0)));
110    
111     btnPower.setAlignmentY(JPanel.TOP_ALIGNMENT);
112    
113     TitleBar tb = new TitleBar();
114     tb.setBorder(BorderFactory.createEmptyBorder(3, 3, 0, 4));
115     tb.setLayout(new BoxLayout(tb, BoxLayout.X_AXIS));
116     tb.setOpaque(false);
117     tb.setAlignmentY(JPanel.TOP_ALIGNMENT);
118     tb.add(btnPower);
119     tb.setPreferredSize(new Dimension(tb.getPreferredSize().width, 58));
120     tb.setMinimumSize(tb.getPreferredSize());
121     tb.setMaximumSize(tb.getPreferredSize());
122     p.add(tb);
123    
124     //p.add(Box.createRigidArea(new Dimension(4, 0)));
125    
126     p.add(createVSeparator());
127    
128     //p.add(Box.createRigidArea(new Dimension(3, 0)));
129    
130     JPanel p2 = new JPanel();
131     p2.setOpaque(false);
132     p2.setLayout(new BoxLayout(p2, BoxLayout.Y_AXIS));
133     p2.setAlignmentY(JPanel.TOP_ALIGNMENT);
134     p2.setBorder(BorderFactory.createEmptyBorder(5, 3, 0, 2));
135     p2.add(screen);
136     p.add(p2);
137    
138     p.add(createVSeparator());
139    
140     p2 = new JPanel();
141     p2.setOpaque(false);
142     p2.setLayout(new BoxLayout(p2, BoxLayout.Y_AXIS));
143     p2.setAlignmentY(JPanel.TOP_ALIGNMENT);
144     p2.setBorder(BorderFactory.createEmptyBorder(4, 0, 0, 0));
145     p2.add(new JLabel(Res.iconMuteTitle));
146     p2.add(btnMute);
147     p2.add(new JLabel(Res.iconSoloTitle));
148     p2.add(btnSolo);
149    
150     p.add(p2);
151    
152     p.add(createVSeparator());
153    
154     p2 = new JPanel();
155     p2.setOpaque(false);
156     p2.setLayout(new BoxLayout(p2, BoxLayout.Y_AXIS));
157     p2.setAlignmentY(JPanel.TOP_ALIGNMENT);
158     p2.setBorder(BorderFactory.createEmptyBorder(4, 0, 0, 0));
159     JLabel l = new JLabel(Res.iconVolumeTitle);
160     l.setAlignmentX(JPanel.CENTER_ALIGNMENT);
161     l.setBorder(BorderFactory.createEmptyBorder(0, 0, 2, 0));
162     p2.add(l);
163     dialVolume.setDialPixmap(Res.iconVolumeDial, 30, 330);
164     dialVolume.setAlignmentX(JPanel.CENTER_ALIGNMENT);
165     p2.add(dialVolume);
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(27, 0, 0, 0));
175     l = new JLabel(Res.iconOptionsTitle);
176     l.setAlignmentX(JPanel.CENTER_ALIGNMENT);
177     l.setBorder(BorderFactory.createEmptyBorder(0, 0, 2, 0));
178     p2.add(l);
179    
180     p2.add(Box.createRigidArea(new Dimension(0, 3)));
181    
182     btnOptions.setAlignmentX(JPanel.CENTER_ALIGNMENT);
183     p2.add(btnOptions);
184     p.add(p2);
185    
186    
187     p.setPreferredSize(new Dimension(420, 60));
188     p.setMinimumSize(p.getPreferredSize());
189     p.setMaximumSize(p.getPreferredSize());
190     //p.setBorder(BorderFactory.createEmptyBorder(1, 0, 1, 0));
191    
192     p.setAlignmentX(JPanel.CENTER_ALIGNMENT);
193     optionsPane.setAlignmentX(JPanel.CENTER_ALIGNMENT);
194     add(p);
195     add(optionsPane);
196    
197     setOpaque(true);
198    
199     getModel().addSamplerChannelListener(getHandler());
200    
201     updateChannelInfo();
202     }
203    
204     private JPanel
205     createVSeparator() {
206     JPanel p = new JPanel();
207     p.setName("VSeparator");
208     p.setOpaque(false);
209     p.setAlignmentY(JPanel.TOP_ALIGNMENT);
210     p.setPreferredSize(new Dimension(2, 60));
211     p.setMinimumSize(p.getPreferredSize());
212     p.setMaximumSize(p.getPreferredSize());
213     return p;
214     }
215    
216     /**
217     * Determines whether the channel is selected.
218     * @return <code>true</code> if the channel is selected, <code>false</code> otherwise.
219     */
220     public boolean isSelected() { return selected; }
221    
222     /**
223     * Sets the selection state of this channel.
224     * This method is invoked when the selection state of the channel has changed.
225     * @param select Specifies the new selection state of this channel;
226     * <code>true</code> to select the channel, <code>false</code> otherwise.
227     */
228     public void
229     setSelected(boolean select) {
230    
231     selected = select;
232     }
233    
234     /** Shows the channel properties. */
235     public void
236     expandChannel() { if(!btnOptions.isSelected()) btnOptions.doClick(); }
237    
238    
239     /** Invoked when the user changes the volume */
240     private void
241     setVolume() {
242     screen.updateVolumeInfo(dialVolume.getValue());
243    
244     if(dialVolume.getValueIsAdjusting()) return;
245    
246     int vol = (int)(getChannelInfo().getVolume() * 100);
247    
248     if(vol == dialVolume.getValue()) return;
249    
250    
251     /*
252     * If the model's volume is not equal to the dial knob
253     * value we assume that the change is due to user input.
254     * So we must update the volume at the backend too.
255     */
256     float volume = dialVolume.getValue();
257     volume /= 100;
258 iliev 1143 getModel().setBackendVolume(volume);
259 iliev 912 }
260    
261     /**
262     * Updates the channel settings. This method is invoked when changes to the
263     * channel were made.
264     */
265     private void
266     updateChannelInfo() {
267     SamplerChannel sc = getChannelInfo();
268    
269     screen.updateScreenInfo(sc);
270     updateMuteIcon(sc);
271    
272     if(sc.isSoloChannel()) btnSolo.setIcon(Res.iconSoloOn);
273     else btnSolo.setIcon(Res.iconSoloOff);
274    
275     dialVolume.setValue((int)(sc.getVolume() * 100));
276    
277     boolean b = sc.getEngine() != null;
278     dialVolume.setEnabled(b);
279     btnSolo.setEnabled(b);
280     btnMute.setEnabled(b);
281     }
282    
283     /**
284     * Updates the mute button with the proper icon regarding to information obtained
285     * from <code>channel</code>.
286     * @param channel A <code>SamplerChannel</code> instance containing the new settings
287     * for this channel.
288     */
289     private void
290     updateMuteIcon(SamplerChannel channel) {
291     if(channel.isMutedBySolo()) btnMute.setIcon(Res.iconMutedBySolo);
292     else if(channel.isMuted()) btnMute.setIcon(Res.iconMuteOn);
293     else btnMute.setIcon(Res.iconMuteOff);
294     }
295    
296     private class EnhancedDial extends Dial {
297     EnhancedDial() {
298     super(0, 100);
299    
300     setMouseHandlerMode(MouseHandlerMode.LEFT_TO_RIGHT_AND_DOWN_TO_UP);
301    
302     addMouseListener(new MouseAdapter() {
303     public void
304     mouseClicked(MouseEvent e) {
305     if(e.getButton() == e.BUTTON3) {
306     setValue(getMaximum() / 2);
307     return;
308     }
309    
310     if(e.getButton() != e.BUTTON1) return;
311    
312     if(e.getClickCount() < 2) return;
313     setValue(getValueByPoint(e.getPoint()));
314     }
315     });
316    
317     addChangeListener(new ChangeListener() {
318     public void
319     stateChanged(ChangeEvent e) { setVolume(); }
320     });
321     }
322     }
323    
324     private final EventHandler eventHandler = new EventHandler();
325    
326     private EventHandler
327     getHandler() { return eventHandler; }
328    
329     private class EventHandler implements SamplerChannelListener {
330     /**
331     * Invoked when changes are made to a sampler channel.
332     * @param e A <code>SamplerChannelEvent</code> instance
333     * containing event information.
334     */
335     public void
336     channelChanged(SamplerChannelEvent e) { updateChannelInfo(); }
337    
338     /**
339     * Invoked when the number of active disk streams has changed.
340     * @param e A <code>SamplerChannelEvent</code> instance
341     * containing event information.
342     */
343     public void
344     streamCountChanged(SamplerChannelEvent e) {
345     screen.updateStreamCount(getModel().getStreamCount());
346     }
347    
348     /**
349     * Invoked when the number of active voices has changed.
350     * @param e A <code>SamplerChannelEvent</code> instance
351     * containing event information.
352     */
353     public void
354     voiceCountChanged(SamplerChannelEvent e) {
355     screen.updateVoiceCount(getModel().getVoiceCount());
356     }
357     }
358    
359    
360     private class PowerButton extends PixmapToggleButton implements ActionListener {
361     PowerButton() {
362     super(Res.iconPowerOff, Res.iconPowerOn);
363    
364     setSelected(true);
365     addActionListener(this);
366     }
367    
368     public void
369     actionPerformed(ActionEvent e) {
370 iliev 1143 CC.getSamplerModel().removeBackendChannel(getChannelId());
371 iliev 912 }
372    
373     public boolean
374     contains(int x, int y) { return (x - 11)*(x - 11) + (y - 11)*(y - 11) < 71; }
375     }
376    
377     private class MuteButton extends PixmapButton implements ActionListener {
378     MuteButton() {
379     super(Res.iconMuteOff);
380 iliev 1143 setDisabledIcon(Res.iconMuteSoloDisabled);
381 iliev 912 addActionListener(this);
382     }
383    
384     public void
385     actionPerformed(ActionEvent e) {
386     SamplerChannel sc = getChannelInfo();
387     boolean b = true;
388    
389     /*
390     * Changing the mute button icon now instead of
391     * leaving the work to the notification mechanism of the LinuxSampler.
392     */
393     if(sc.isMuted() && !sc.isMutedBySolo()) {
394     b = false;
395     boolean hasSolo = CC.getSamplerModel().hasSoloChannel();
396    
397     if(sc.isSoloChannel() || !hasSolo) setIcon(Res.iconMuteOff);
398     else setIcon(Res.iconMutedBySolo);
399     } else setIcon(Res.iconMuteOn);
400    
401 iliev 1143 Channel.this.getModel().setBackendMute(b);
402 iliev 912 }
403    
404     public boolean
405     contains(int x, int y) { return (x > 5 && x < 23) && (y > 5 && y < 16); }
406     }
407    
408     private class SoloButton extends PixmapButton implements ActionListener {
409     SoloButton() {
410     super(Res.iconSoloOff);
411 iliev 1143 setDisabledIcon(Res.iconMuteSoloDisabled);
412 iliev 912 addActionListener(this);
413     }
414    
415     public void
416     actionPerformed(ActionEvent e) {
417     SamplerChannel sc = getChannelInfo();
418     boolean b = !sc.isSoloChannel();
419    
420     /*
421     * Changing the solo button icon (and related) now instead of
422     * leaving the work to the notification mechanism of the LinuxSampler.
423     */
424     if(b) {
425     setIcon(Res.iconSoloOn);
426     if(sc.isMutedBySolo()) btnMute.setIcon(Res.iconMuteOff);
427     } else {
428     setIcon(Res.iconSoloOff);
429     if(!sc.isMuted() && CC.getSamplerModel().getSoloChannelCount() > 1)
430     btnMute.setIcon(Res.iconMutedBySolo);
431     }
432    
433 iliev 1143 Channel.this.getModel().setBackendSolo(b);
434 iliev 912 }
435    
436     public boolean
437     contains(int x, int y) { return (x > 5 && x < 23) && (y > 5 && y < 16); }
438     }
439    
440     private class OptionsButton extends PixmapToggleButton implements ActionListener {
441     OptionsButton() {
442     super(Res.iconOptionsOff, Res.iconOptionsOn);
443 iliev 1143 setRolloverIcon(Res.iconOptionsOffRO);
444     this.setRolloverSelectedIcon(Res.iconOptionsOnRO);
445 iliev 912 addActionListener(this);
446     }
447    
448     public void
449     actionPerformed(ActionEvent e) {
450     showOptionsPane(isSelected());
451    
452     String s;
453     if(isSelected()) s = i18n.getButtonLabel("OptionsButton.ttHideOptions");
454     else s = i18n.getButtonLabel("OptionsButton.ttShowOptions");
455    
456     setToolTipText(s);
457     }
458    
459     private void
460     showOptionsPane(boolean show) {
461     optionsPane.setVisible(show);
462     MainFrame.repack(CC.getMainFrame());
463     }
464    
465     public boolean
466 iliev 1143 contains(int x, int y) { return super.contains(x, y) & y < 13; }
467 iliev 912 }
468     }
469    
470     class ChannelScreen extends JPanel {
471     private final Channel channel;
472     private JButton btnInstr = new ScreenButton(i18n.getButtonLabel("ChannelScreen.btnInstr"));
473     private JButton btnReset = new ScreenButton(i18n.getButtonLabel("ChannelScreen.btnReset"));
474     private JButton btnDuplicate =
475     new ScreenButton(i18n.getButtonLabel("ChannelScreen.btnDuplicate"));
476    
477     private final JLabel lVolume = new JLabel();
478     private final JLabel lStreams = new JLabel("--");
479     private final JLabel lVoices = new JLabel("--");
480    
481     ChannelScreen(Channel channel) {
482     this.channel = channel;
483    
484     setName("ChannelScreen");
485     setOpaque(true);
486    
487     setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
488    
489     btnInstr.setBorder(BorderFactory.createEmptyBorder(10, 0, 0, 0));
490     btnInstr.setAlignmentX(CENTER_ALIGNMENT);
491    
492     add(btnInstr);
493    
494     JPanel p = new JPanel();
495     p.setOpaque(false);
496     p.setLayout(new BoxLayout(p, BoxLayout.X_AXIS));
497     p.setAlignmentX(CENTER_ALIGNMENT);
498     p.setBorder(BorderFactory.createEmptyBorder(10, 0, 0, 0));
499     //lVolume.setFont(lVolume.getFont().deriveFont(java.awt.Font.PLAIN));
500    
501     p.add(btnDuplicate);
502    
503     p.add(Box.createRigidArea(new Dimension(6, 0)));
504    
505     p.add(new JLabel("|"));
506    
507     p.add(Box.createRigidArea(new Dimension(6, 0)));
508    
509     p.add(btnReset);
510    
511     p.add(Box.createGlue());
512    
513     p.add(lStreams);
514     p.add(new JLabel("/"));
515     p.add(lVoices);
516    
517     p.add(Box.createRigidArea(new Dimension(12, 0)));
518    
519     lVolume.setAlignmentX(RIGHT_ALIGNMENT);
520     p.add(lVolume);
521     p.setPreferredSize(new Dimension(250, p.getPreferredSize().height));
522     p.setMinimumSize(p.getPreferredSize());
523     p.setMaximumSize(p.getPreferredSize());
524    
525     add(p);
526    
527    
528     setPreferredSize(new Dimension(270, 48));
529     setMinimumSize(getPreferredSize());
530     setMaximumSize(getPreferredSize());
531    
532     installListeners();
533     }
534    
535     private void
536     installListeners() {
537     btnInstr.addActionListener(new ActionListener() {
538     public void
539     actionPerformed(ActionEvent e) { loadInstrument(); }
540     });
541    
542     btnReset.addActionListener(new ActionListener() {
543     public void
544 iliev 1143 actionPerformed(ActionEvent e) { channel.getModel().resetBackendChannel(); }
545 iliev 912 });
546    
547     btnDuplicate.addActionListener(new ActionListener() {
548     public void
549 iliev 1143 actionPerformed(ActionEvent e) {
550     channel.getModel().duplicateBackendChannel();
551     }
552 iliev 912 });
553     }
554    
555     private void
556     loadInstrument() {
557     InstrumentChooser dlg = new InstrumentChooser(CC.getMainFrame());
558     dlg.setVisible(true);
559    
560     if(!dlg.isCancelled()) {
561     SamplerChannelModel m = channel.getModel();
562 iliev 1143 m.loadBackendInstrument(dlg.getFileName(), dlg.getInstrumentIndex());
563 iliev 912 }
564     }
565    
566     protected void
567     updateScreenInfo(SamplerChannel sc) {
568     int status = sc.getInstrumentStatus();
569     if(status >= 0 && status < 100) {
570     btnInstr.setText(i18n.getLabel("ChannelScreen.loadingInstrument", status));
571     } else if(status == -1) {
572     btnInstr.setText(i18n.getButtonLabel("ChannelScreen.btnInstr"));
573     } else if(status < -1) {
574     btnInstr.setText(i18n.getLabel("ChannelScreen.errorLoadingInstrument"));
575     } else {
576     if(sc.getInstrumentName() != null) btnInstr.setText(sc.getInstrumentName());
577     else btnInstr.setText(i18n.getButtonLabel("ChannelScreen.btnInstr"));
578     }
579    
580    
581    
582     }
583    
584     protected void
585     updateVolumeInfo(int volume) {
586     lVolume.setText(i18n.getLabel("ChannelScreen.volume", volume));
587    
588     }
589    
590     /**
591     * Updates the number of active disk streams.
592     * @param count The new number of active disk streams.
593     */
594     protected void
595     updateStreamCount(int count) {
596     Dimension d = lStreams.getPreferredSize();
597     lStreams.setText(count == 0 ? "--" : String.valueOf(count));
598     d = JuifeUtils.getUnionSize(d, lStreams.getPreferredSize());
599     lStreams.setMinimumSize(d);
600     lStreams.setPreferredSize(d);
601     lStreams.setMaximumSize(d);
602     }
603    
604     /**
605     * Updates the number of active voices.
606     * @param count The new number of active voices.
607     */
608     protected void
609     updateVoiceCount(int count) {
610     Dimension d = lVoices.getPreferredSize();
611     lVoices.setText(count == 0 ? "--" : String.valueOf(count));
612     d = JuifeUtils.getUnionSize(d, lVoices.getPreferredSize());
613     lVoices.setMinimumSize(d);
614     lVoices.setPreferredSize(d);
615     lVoices.setMaximumSize(d);
616     }
617    
618     static class ScreenButton extends JButton {
619     ScreenButton(String s) {
620     super(s);
621     setContentAreaFilled(false);
622     setFocusPainted(false);
623     setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
624     setMargin(new Insets(0, 0, 0, 0));
625     setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
626     }
627     }
628     }
629    
630     class ChannelOptions extends JPanel {
631     private final Channel channel;
632    
633     private final JComboBox cbMidiDevice = new JComboBox();
634     private final JComboBox cbMidiPort = new JComboBox();
635     private final JComboBox cbMidiChannel = new JComboBox();
636     private final JComboBox cbEngine = new JComboBox();
637     private final JComboBox cbAudioDevice = new JComboBox();
638    
639     private boolean update = false;
640    
641     ChannelOptions(Channel channel) {
642     this.channel = channel;
643    
644     setName("ChannelOptions");
645     setVisible(false);
646     setBorder(BorderFactory.createEmptyBorder(5, 4, 5, 4));
647     setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
648    
649     setPreferredSize(new Dimension(420, 44));
650     setMinimumSize(getPreferredSize());
651     setMaximumSize(getPreferredSize());
652    
653     JPanel p = new JPanel();
654     p.setOpaque(true);
655     p.setBorder(BorderFactory.createEmptyBorder(3, 4, 3, 4));
656     p.setLayout(new BoxLayout(p, BoxLayout.Y_AXIS));
657     JLabel l = new JLabel(Res.iconMidiInputTitle);
658     l.setAlignmentX(LEFT_ALIGNMENT);
659     p.add(l);
660    
661     JPanel p2 = new JPanel();
662     p2.setBorder(BorderFactory.createEmptyBorder(3, 0, 0, 0));
663     p2.setLayout(new BoxLayout(p2, BoxLayout.X_AXIS));
664    
665     Object o = cbMidiDevice.getRenderer();
666     if(o instanceof JLabel) ((JLabel )o).setHorizontalAlignment(SwingConstants.CENTER);
667    
668     cbMidiDevice.setPreferredSize(new Dimension(40, 18));
669     cbMidiDevice.setMinimumSize(cbMidiDevice.getPreferredSize());
670     cbMidiDevice.setMaximumSize(cbMidiDevice.getPreferredSize());
671     p2.add(cbMidiDevice);
672    
673     p2.add(Box.createRigidArea(new Dimension(3, 0)));
674    
675     o = cbMidiPort.getRenderer();
676     if(o instanceof JLabel) ((JLabel )o).setHorizontalAlignment(SwingConstants.CENTER);
677    
678     cbMidiPort.setPreferredSize(new Dimension(67, 18));
679     cbMidiPort.setMinimumSize(cbMidiPort.getPreferredSize());
680     cbMidiPort.setMaximumSize(cbMidiPort.getPreferredSize());
681     p2.add(cbMidiPort);
682    
683     p2.add(Box.createRigidArea(new Dimension(3, 0)));
684    
685     o = cbMidiChannel.getRenderer();
686     if(o instanceof JLabel) ((JLabel )o).setHorizontalAlignment(SwingConstants.CENTER);
687    
688     cbMidiChannel.addItem("All");
689     for(int i = 1; i <= 16; i++) cbMidiChannel.addItem("Channel " + String.valueOf(i));
690     cbMidiChannel.setPreferredSize(new Dimension(80, 18));
691     cbMidiChannel.setMinimumSize(cbMidiChannel.getPreferredSize());
692     cbMidiChannel.setMaximumSize(cbMidiChannel.getPreferredSize());
693    
694     p2.add(cbMidiChannel);
695     p2.setAlignmentX(LEFT_ALIGNMENT);
696     p.add(p2);
697    
698     add(p);
699    
700     add(Box.createRigidArea(new Dimension(4, 0)));
701    
702     p = new JPanel();
703     p.setOpaque(true);
704     p.setBorder(BorderFactory.createEmptyBorder(3, 4, 3, 4));
705     p.setLayout(new BoxLayout(p, BoxLayout.Y_AXIS));
706     l = new JLabel(Res.iconEngineTitle);
707     l.setAlignmentX(LEFT_ALIGNMENT);
708     l.setAlignmentX(LEFT_ALIGNMENT);
709     p.add(l);
710    
711     p.add(Box.createRigidArea(new Dimension(0, 3)));
712    
713     o = cbEngine.getRenderer();
714     if(o instanceof JLabel) ((JLabel )o).setHorizontalAlignment(SwingConstants.CENTER);
715    
716     for(SamplerEngine e : CC.getSamplerModel().getEngines()) cbEngine.addItem(e);
717     cbEngine.setPreferredSize(new Dimension(125, 18));
718     cbEngine.setMinimumSize(cbEngine.getPreferredSize());
719     cbEngine.setMaximumSize(cbEngine.getPreferredSize());
720     cbEngine.setAlignmentX(LEFT_ALIGNMENT);
721     p.add(cbEngine);
722    
723     add(p);
724    
725     add(Box.createRigidArea(new Dimension(4, 0)));
726    
727     p = new JPanel();
728     p.setOpaque(true);
729     p.setBorder(BorderFactory.createEmptyBorder(3, 4, 3, 4));
730     p.setLayout(new BoxLayout(p, BoxLayout.Y_AXIS));
731     l = new JLabel(Res.iconAudioOutputTitle);
732     l.setAlignmentX(LEFT_ALIGNMENT);
733     l.setAlignmentX(LEFT_ALIGNMENT);
734     p.add(l);
735    
736     p.add(Box.createRigidArea(new Dimension(0, 3)));
737    
738     o = cbAudioDevice.getRenderer();
739     if(o instanceof JLabel) ((JLabel )o).setHorizontalAlignment(SwingConstants.RIGHT);
740    
741     cbAudioDevice.setPreferredSize(new Dimension(61, 18));
742     cbAudioDevice.setMinimumSize(cbAudioDevice.getPreferredSize());
743     cbAudioDevice.setMaximumSize(cbAudioDevice.getPreferredSize());
744     cbAudioDevice.setAlignmentX(LEFT_ALIGNMENT);
745     p.add(cbAudioDevice);
746    
747     add(p);
748    
749     cbMidiDevice.addActionListener(new ActionListener() {
750     public void
751     actionPerformed(ActionEvent e) { setMidiDevice(); }
752     });
753    
754     cbMidiPort.addActionListener(new ActionListener() {
755     public void
756     actionPerformed(ActionEvent e) { setMidiPort(); }
757     });
758    
759     cbMidiChannel.addActionListener(new ActionListener() {
760     public void
761     actionPerformed(ActionEvent e) { setMidiChannel(); }
762     });
763    
764     cbEngine.addActionListener(new ActionListener() {
765     public void
766     actionPerformed(ActionEvent e) { setEngineType(); }
767     });
768    
769     cbAudioDevice.addActionListener(new ActionListener() {
770     public void
771 iliev 1143 actionPerformed(ActionEvent e) { setBackendAudioDevice(); }
772 iliev 912 });
773    
774     channel.getModel().addSamplerChannelListener(new SamplerChannelAdapter() {
775     public void
776     channelChanged(SamplerChannelEvent e) { updateChannelProperties(); }
777     });
778    
779     CC.getSamplerModel().addMidiDeviceListListener(getHandler());
780     CC.getSamplerModel().addAudioDeviceListListener(getHandler());
781    
782     updateMidiDevices();
783     updateAudioDevices();
784     updateChannelProperties();
785     }
786    
787     /**
788     * Updates the channel settings. This method is invoked when changes to the
789     * channel were made.
790     */
791     private void
792     updateChannelProperties() {
793     SamplerModel sm = CC.getSamplerModel();
794     SamplerChannel sc = channel.getModel().getChannelInfo();
795    
796     MidiDeviceModel mm = sm.getMidiDeviceModel(sc.getMidiInputDevice());
797     AudioDeviceModel am = sm.getAudioDeviceModel(sc.getAudioOutputDevice());
798    
799     if(isUpdate()) CC.getLogger().warning("Unexpected update state!");
800    
801     setUpdate(true);
802    
803     try {
804     cbMidiDevice.setSelectedItem(mm == null ? null : mm.getDeviceInfo());
805    
806     cbEngine.setSelectedItem(sc.getEngine());
807    
808     cbAudioDevice.setSelectedItem(am == null ? null : am.getDeviceInfo());
809     } catch(Exception x) {
810     CC.getLogger().log(Level.WARNING, "Unkown error", x);
811     }
812    
813     setUpdate(false);
814     }
815    
816     /**
817     * Updates the MIDI device list.
818     */
819     private void
820     updateMidiDevices() {
821     SamplerModel sm = CC.getSamplerModel();
822     SamplerChannel sc = channel.getModel().getChannelInfo();
823    
824     setUpdate(true);
825    
826     try {
827     cbMidiDevice.removeAllItems();
828    
829     for(MidiDeviceModel m : sm.getMidiDeviceModels())
830     cbMidiDevice.addItem(m.getDeviceInfo());
831    
832     MidiDeviceModel mm = sm.getMidiDeviceModel(sc.getMidiInputDevice());
833     cbMidiDevice.setSelectedItem(mm == null ? null : mm.getDeviceInfo());
834     } catch(Exception x) {
835     CC.getLogger().log(Level.WARNING, "Unkown error", x);
836     }
837    
838     setUpdate(false);
839     }
840    
841     /**
842     * Updates the audio device list.
843     */
844     private void
845     updateAudioDevices() {
846     SamplerModel sm = CC.getSamplerModel();
847     SamplerChannel sc = channel.getModel().getChannelInfo();
848    
849     setUpdate(true);
850    
851     try {
852     cbAudioDevice.removeAllItems();
853    
854     for(AudioDeviceModel m : sm.getAudioDeviceModels())
855     cbAudioDevice.addItem(m.getDeviceInfo());
856    
857     AudioDeviceModel am = sm.getAudioDeviceModel(sc.getAudioOutputDevice());
858     cbAudioDevice.setSelectedItem(am == null ? null : am.getDeviceInfo());
859     } catch(Exception x) {
860     CC.getLogger().log(Level.WARNING, "Unkown error", x);
861     }
862    
863     setUpdate(false);
864     }
865    
866     private void
867     setMidiDevice() {
868     MidiInputDevice mid = (MidiInputDevice)cbMidiDevice.getSelectedItem();
869    
870     if(!isUpdate()) {
871 iliev 1143 if(mid != null) {
872     channel.getModel().setBackendMidiInputDevice(mid.getDeviceId());
873     }
874    
875 iliev 912 return;
876     }
877    
878     cbMidiPort.removeAllItems();
879    
880     if(mid == null) {
881     cbMidiPort.setEnabled(false);
882    
883     cbMidiChannel.setSelectedItem(null);
884     cbMidiChannel.setEnabled(false);
885     } else {
886     cbMidiPort.setEnabled(true);
887    
888     MidiPort[] ports = mid.getMidiPorts();
889     for(MidiPort port : ports) cbMidiPort.addItem(port);
890    
891     int p = channel.getModel().getChannelInfo().getMidiInputPort();
892     cbMidiPort.setSelectedItem(p >= 0 && p < ports.length ? ports[p] : null);
893    
894     cbMidiChannel.setEnabled(true);
895     int c = channel.getModel().getChannelInfo().getMidiInputChannel();
896     cbMidiChannel.setSelectedItem(c == -1 ? "All" : "Channel " + (c + 1));
897     }
898     }
899    
900     private void
901     setMidiPort() {
902     if(isUpdate()) return;
903    
904 iliev 1143 channel.getModel().setBackendMidiInputPort(cbMidiPort.getSelectedIndex());
905 iliev 912 }
906    
907     private void
908     setMidiChannel() {
909     if(isUpdate()) return;
910    
911     Object o = cbMidiChannel.getSelectedItem();
912     if(o == null) return;
913     String s = o.toString();
914    
915     int c = s.equals("All") ? -1 : Integer.parseInt(s.substring(8)) - 1;
916    
917 iliev 1143 channel.getModel().setBackendMidiInputChannel(c);
918 iliev 912 }
919    
920     /** Invoked when the user selects an engine. */
921     private void
922     setEngineType() {
923     Object oldEngine = channel.getModel().getChannelInfo().getEngine();
924     SamplerEngine newEngine = (SamplerEngine)cbEngine.getSelectedItem();
925    
926     if(oldEngine != null) { if(oldEngine.equals(newEngine)) return; }
927     else if(newEngine == null) return;
928    
929 iliev 1143 channel.getModel().setBackendEngineType(newEngine.getName());
930 iliev 912
931     }
932    
933     private void
934 iliev 1143 setBackendAudioDevice() {
935 iliev 912 if(isUpdate()) return;
936     AudioOutputDevice dev = (AudioOutputDevice)cbAudioDevice.getSelectedItem();
937 iliev 1143 if(dev != null) channel.getModel().setBackendAudioOutputDevice(dev.getDeviceId());
938 iliev 912 }
939    
940     /**
941     * Determines whether the currently processed changes are due to update.
942     * @return <code>true</code> if the currently processed changes are due to update and
943     * <code>false</code> if the currently processed changes are due to user input.
944     */
945     private boolean
946     isUpdate() { return update; }
947    
948     /**
949     * Sets whether the currently processed changes are due to update.
950     * @param b Specify <code>true</code> to indicate that the currently
951     * processed changes are due to update; <code>false</code>
952     * indicates that the currently processed changes are due to user input.
953     */
954     private void
955     setUpdate(boolean b) { update = b; }
956    
957     private final Handler handler = new Handler();
958    
959     private Handler
960     getHandler() { return handler; }
961    
962 iliev 1143 private class Handler implements MidiDeviceListListener, ListListener<AudioDeviceModel> {
963 iliev 912 /**
964     * Invoked when a new MIDI device is created.
965     * @param e A <code>MidiDeviceListEvent</code>
966     * instance providing the event information.
967     */
968     public void
969     deviceAdded(MidiDeviceListEvent e) {
970     cbMidiDevice.addItem(e.getMidiDeviceModel().getDeviceInfo());
971     }
972    
973     /**
974     * Invoked when a MIDI device is removed.
975     * @param e A <code>MidiDeviceListEvent</code>
976     * instance providing the event information.
977     */
978     public void
979     deviceRemoved(MidiDeviceListEvent e) {
980     cbMidiDevice.removeItem(e.getMidiDeviceModel().getDeviceInfo());
981     }
982    
983     /**
984     * Invoked when a new audio device is created.
985     * @param e An <code>AudioDeviceListEvent</code>
986     * instance providing the event information.
987     */
988     public void
989 iliev 1143 entryAdded(ListEvent<AudioDeviceModel> e) {
990     cbAudioDevice.addItem(e.getEntry().getDeviceInfo());
991 iliev 912 }
992    
993     /**
994     * Invoked when an audio device is removed.
995     * @param e An <code>AudioDeviceListEvent</code>
996     * instance providing the event information.
997     */
998     public void
999 iliev 1143 entryRemoved(ListEvent<AudioDeviceModel> e) {
1000     cbAudioDevice.removeItem(e.getEntry().getDeviceInfo());
1001 iliev 912 }
1002     }
1003     }

  ViewVC Help
Powered by ViewVC