/[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 912 - (hide annotations) (download)
Mon Aug 7 18:34:40 2006 UTC (17 years, 8 months ago) by iliev
File size: 28630 byte(s)
* updating to JSampler 0.3a

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

  ViewVC Help
Powered by ViewVC