/[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 1204 - (show annotations) (download)
Thu May 24 21:43:45 2007 UTC (16 years, 10 months ago) by iliev
File size: 28891 byte(s)
upgrading to version 0.5a

1 /*
2 * JSampler - a java front-end for LinuxSampler
3 *
4 * Copyright (C) 2005-2006 Grigor Iliev <grigor@grigoriliev.com>
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.ListEvent;
61 import org.jsampler.event.ListListener;
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.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 getModel().setBackendVolume(volume);
259 }
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 CC.getSamplerModel().removeBackendChannel(getChannelId());
371 }
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 setDisabledIcon(Res.iconMuteSoloDisabled);
381 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 Channel.this.getModel().setBackendMute(b);
402 }
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 setDisabledIcon(Res.iconMuteSoloDisabled);
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().setBackendSolo(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 setRolloverIcon(Res.iconOptionsOffRO);
444 this.setRolloverSelectedIcon(Res.iconOptionsOnRO);
445 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 contains(int x, int y) { return super.contains(x, y) & y < 13; }
467 }
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 actionPerformed(ActionEvent e) { channel.getModel().resetBackendChannel(); }
545 });
546
547 btnDuplicate.addActionListener(new ActionListener() {
548 public void
549 actionPerformed(ActionEvent e) {
550 channel.getModel().duplicateBackendChannel();
551 }
552 });
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 m.loadBackendInstrument(dlg.getFileName(), dlg.getInstrumentIndex());
563 }
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 actionPerformed(ActionEvent e) { setBackendAudioDevice(); }
772 });
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.getMidiDeviceById(sc.getMidiInputDevice());
797 AudioDeviceModel am = sm.getAudioDeviceById(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.getMidiDevices())
830 cbMidiDevice.addItem(m.getDeviceInfo());
831
832 MidiDeviceModel mm = sm.getMidiDeviceById(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.getAudioDevices())
855 cbAudioDevice.addItem(m.getDeviceInfo());
856
857 AudioDeviceModel am = sm.getAudioDeviceById(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 if(mid != null) {
872 channel.getModel().setBackendMidiInputDevice(mid.getDeviceId());
873 }
874
875 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 channel.getModel().setBackendMidiInputPort(cbMidiPort.getSelectedIndex());
905 }
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 channel.getModel().setBackendMidiInputChannel(c);
918 }
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 channel.getModel().setBackendEngineType(newEngine.getName());
930
931 }
932
933 private void
934 setBackendAudioDevice() {
935 if(isUpdate()) return;
936 AudioOutputDevice dev = (AudioOutputDevice)cbAudioDevice.getSelectedItem();
937 if(dev != null) channel.getModel().setBackendAudioOutputDevice(dev.getDeviceId());
938 }
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 private class Handler implements MidiDeviceListListener, ListListener<AudioDeviceModel> {
963 /**
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 entryAdded(ListEvent<AudioDeviceModel> e) {
990 cbAudioDevice.addItem(e.getEntry().getDeviceInfo());
991 }
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 entryRemoved(ListEvent<AudioDeviceModel> e) {
1000 cbAudioDevice.removeItem(e.getEntry().getDeviceInfo());
1001 }
1002 }
1003 }

  ViewVC Help
Powered by ViewVC