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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 842 - (show annotations) (download)
Thu Mar 16 18:08:34 2006 UTC (18 years ago) by iliev
File size: 29499 byte(s)
Updating to version 0.2a

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

  ViewVC Help
Powered by ViewVC