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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 912 - (show annotations) (download)
Mon Aug 7 18:34:40 2006 UTC (17 years, 7 months ago) by iliev
File size: 28630 byte(s)
* updating to JSampler 0.3a

1 /*
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