/[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 911 - (show annotations) (download)
Mon Aug 7 18:25:58 2006 UTC (17 years, 8 months ago) by iliev
File size: 32631 byte(s)
updating to JSampler 0.3a

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

  ViewVC Help
Powered by ViewVC