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

1 /*
2 * JSampler - a java front-end for LinuxSampler
3 *
4 * Copyright (C) 2005-2007 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.classic;
24
25 import java.awt.BorderLayout;
26 import java.awt.Color;
27 import java.awt.Cursor;
28 import java.awt.Dimension;
29 import java.awt.GridBagConstraints;
30 import java.awt.GridBagLayout;
31 import java.awt.Insets;
32
33 import java.awt.datatransfer.Transferable;
34
35 import java.awt.event.ActionEvent;
36 import java.awt.event.ActionListener;
37 import java.awt.event.HierarchyEvent;
38 import java.awt.event.HierarchyListener;
39 import java.awt.event.MouseAdapter;
40 import java.awt.event.MouseEvent;
41 import java.awt.event.MouseMotionAdapter;
42
43 import java.beans.PropertyChangeEvent;
44 import java.beans.PropertyChangeListener;
45
46 import java.net.URL;
47
48 import java.util.Vector;
49
50 import java.util.logging.Level;
51
52 import javax.swing.Action;
53 import javax.swing.AbstractAction;
54 import javax.swing.BorderFactory;
55 import javax.swing.Box;
56 import javax.swing.BoxLayout;
57 import javax.swing.JComponent;
58 import javax.swing.ImageIcon;
59 import javax.swing.JButton;
60 import javax.swing.JComboBox;
61 import javax.swing.JLabel;
62 import javax.swing.JPanel;
63 import javax.swing.JSeparator;
64 import javax.swing.JSlider;
65 import javax.swing.JToggleButton;
66 import javax.swing.TransferHandler;
67
68 import javax.swing.border.Border;
69 import javax.swing.border.LineBorder;
70 import javax.swing.border.TitledBorder;
71
72 import javax.swing.event.ChangeEvent;
73 import javax.swing.event.ChangeListener;
74
75 import net.sf.juife.InformationDialog;
76 import net.sf.juife.JuifeUtils;
77
78 import org.jsampler.AudioDeviceModel;
79 import org.jsampler.CC;
80 import org.jsampler.HF;
81 import org.jsampler.Instrument;
82 import org.jsampler.MidiDeviceModel;
83 import org.jsampler.MidiInstrumentMap;
84 import org.jsampler.SamplerChannelModel;
85 import org.jsampler.SamplerModel;
86
87 import org.jsampler.event.ListEvent;
88 import org.jsampler.event.ListListener;
89 import org.jsampler.event.MidiDeviceListEvent;
90 import org.jsampler.event.MidiDeviceListListener;
91 import org.jsampler.event.SamplerAdapter;
92 import org.jsampler.event.SamplerChannelAdapter;
93 import org.jsampler.event.SamplerChannelEvent;
94 import org.jsampler.event.SamplerChannelListEvent;
95 import org.jsampler.event.SamplerChannelListListener;
96 import org.jsampler.event.SamplerChannelListener;
97 import org.jsampler.event.SamplerEvent;
98
99 import org.linuxsampler.lscp.AudioOutputDevice;
100 import org.linuxsampler.lscp.MidiInputDevice;
101 import org.linuxsampler.lscp.MidiPort;
102 import org.linuxsampler.lscp.SamplerChannel;
103 import org.linuxsampler.lscp.SamplerEngine;
104
105 import static org.jsampler.view.classic.ClassicI18n.i18n;
106
107
108 /**
109 *
110 * @author Grigor Iliev
111 */
112 public class Channel extends org.jsampler.view.JSChannel {
113 private final static ImageIcon iconMuteOn;
114 private final static ImageIcon iconMuteOff;
115 private final static ImageIcon iconMutedBySolo;
116
117 private final static ImageIcon iconSoloOn;
118 private final static ImageIcon iconSoloOff;
119
120 private final static ImageIcon iconShowProperties;
121 private final static ImageIcon iconHideProperties;
122
123 private static Border borderSelected;
124 private static Border borderHighlighted;
125 private static Border borderDeselected;
126
127 private static Color chnColor;
128 private static Color borderColor;
129 private static Color borderHighlightedColor;
130 private static Color chnSelectedColor;
131 private static Color chnHighlightedColor;
132
133 private final static Vector<PropertyChangeListener> propertyChangeListeners
134 = new Vector<PropertyChangeListener>();
135
136 static {
137 String path = "org/jsampler/view/classic/res/icons/";
138 URL url = ClassLoader.getSystemClassLoader().getResource(path + "mute_on.png");
139 iconMuteOn = new ImageIcon(url);
140
141 url = ClassLoader.getSystemClassLoader().getResource(path + "mute_off.png");
142 iconMuteOff = new ImageIcon(url);
143
144 url = ClassLoader.getSystemClassLoader().getResource(path + "muted_by_solo.png");
145 iconMutedBySolo = new ImageIcon(url);
146
147 url = ClassLoader.getSystemClassLoader().getResource(path + "solo_on.png");
148 iconSoloOn = new ImageIcon(url);
149
150 url = ClassLoader.getSystemClassLoader().getResource(path + "solo_off.png");
151 iconSoloOff = new ImageIcon(url);
152
153 url = ClassLoader.getSystemClassLoader().getResource(path + "Back16.gif");
154 iconShowProperties = new ImageIcon(url);
155
156 iconHideProperties = Res.iconDown16;
157
158 if(ClassicPrefs.getCustomChannelBorderColor())
159 setBorderColor(ClassicPrefs.getChannelBorderColor());
160 else setBorderColor(ClassicPrefs.getDefaultChannelBorderColor());
161
162 if(ClassicPrefs.getCustomChannelBorderHlColor())
163 setBorderHighlightedColor(ClassicPrefs.getChannelBorderHlColor());
164 else setBorderHighlightedColor(ClassicPrefs.getDefaultChannelBorderHlColor());
165
166 borderSelected = new LineBorder(getBorderColor(), 2, true);
167 borderHighlighted = new LineBorder(getBorderHighlightedColor(), 2, true);
168 borderDeselected = BorderFactory.createEmptyBorder(2, 2, 2, 2);
169
170 chnColor = new JPanel().getBackground();
171
172 if(ClassicPrefs.getCustomSelectedChannelBgColor()) {
173 chnSelectedColor = ClassicPrefs.getSelectedChannelBgColor();
174 } else {
175 int r = chnColor.getRed() - 14 < 0 ? 0 : chnColor.getRed() - 14;
176 int g = chnColor.getGreen() - 8 < 0 ? 0 : chnColor.getGreen() - 8;
177 int b = chnColor.getBlue() - 3 < 0 ? 0 : chnColor.getBlue() - 3;
178
179 chnSelectedColor = new Color(r, g, b);
180 }
181
182 /*r = r + 5 > 255 ? 255 : r + 5;
183 g = g + 4 > 255 ? 255 : g + 4;
184 b = b + 1 > 255 ? 255 : b + 1;*/
185
186 chnHighlightedColor = new Color(chnColor.getRGB());
187 }
188
189 /**
190 * Registers the specified listener for receiving property change events.
191 * @param l The <code>PropertyChangeListener</code> to register.
192 */
193 public void
194 addPropertyChangeListener(PropertyChangeListener l) {
195 propertyChangeListeners.add(l);
196 }
197
198 /**
199 * Removes the specified listener.
200 * @param l The <code>PropertyChangeListener</code> to remove.
201 */
202 public void
203 removePropertyChangeListener(PropertyChangeListener l) {
204 propertyChangeListeners.remove(l);
205 }
206
207 /**
208 * Gets the border color that is used when the channel is selected.
209 * @return The border color that is used when the channel is selected.
210 */
211 public static Color
212 getBorderColor() { return borderColor; }
213
214 /**
215 * Sets the border color to be used when the channel is selected.
216 * @param c The border color to be used when the channel is selected.
217 */
218 public static void
219 setBorderColor(Color c) {
220 if(borderColor != null && borderColor.getRGB() == c.getRGB()) return;
221
222 Color oldColor = borderColor;
223 borderColor = c;
224 borderSelected = new LineBorder(getBorderColor(), 2, true);
225 firePropertyChanged("borderColor", oldColor, borderColor);
226 }
227
228 /**
229 * Gets the border color that is used when the mouse pointer is over a channel.
230 * @return The border color that is used when the mouse pointer is over a channel.
231 */
232 public static Color
233 getBorderHighlightedColor() { return borderHighlightedColor; }
234
235 /**
236 * Sets the border color to be used when the mouse pointer is over a channel.
237 * @param c The border color to be used when the mouse pointer is over a channel.
238 */
239 public static void
240 setBorderHighlightedColor(Color c) {
241 Color oldColor = borderHighlightedColor;
242 if(oldColor != null && oldColor.getRGB() == c.getRGB()) return;
243
244 borderHighlightedColor = c;
245 borderHighlighted = new LineBorder(getBorderHighlightedColor(), 2, true);
246 firePropertyChanged("borderHighlightedColor", oldColor, borderHighlightedColor);
247 }
248
249 /**
250 * Gets the background color that is used when a channel is selected.
251 * @return The background color that is used when a channel is selected.
252 */
253 public static Color
254 getSelectedChannelBgColor() { return chnSelectedColor; }
255
256 /**
257 * Sets the background color that is used when a channel is selected.
258 * @param c The background color to be used when a channel is selected.
259 */
260 public static void
261 setSelectedChannelBgColor(Color c) {
262 Color oldColor = chnSelectedColor;
263 if(oldColor != null && oldColor.getRGB() == c.getRGB()) return;
264
265 chnSelectedColor = c;
266 firePropertyChanged("selectedChannelBgColor", oldColor, chnSelectedColor);
267 }
268
269 /**
270 * Gets the background color that is used when the mouse pointer is over a channel.
271 * @return The background color that is used when the mouse pointer is over a channel.
272 */
273 public static Color
274 getHighlightedChannelBgColor() { return chnHighlightedColor; }
275
276 /**
277 * Sets the background color to be used when the mouse pointer is over a channel.
278 * @param c The background color to be used when the mouse pointer is over a channel.
279 */
280 public static void
281 setHighlightedChannelBgColor(Color c) {
282 Color oldColor = chnHighlightedColor;
283 if(oldColor != null && oldColor.getRGB() == c.getRGB()) return;
284
285 chnHighlightedColor = c;
286 firePropertyChanged("highlightedChannelBgColor", oldColor, chnHighlightedColor);
287 }
288
289 private static void
290 firePropertyChanged(String propertyName, Object oldValue, Object newValue) {
291 PropertyChangeEvent e =
292 new PropertyChangeEvent(Channel.class, propertyName, oldValue, newValue);
293
294 for(PropertyChangeListener l : propertyChangeListeners) l.propertyChange(e);
295 }
296
297
298 private final JPanel mainPane = new JPanel();
299 private final ChannelProperties propertiesPane;
300 private final JButton btnInstr = new InstrumentButton(i18n.getLabel("Channel.btnInstr"));
301 private final Action actInstr;
302 private final JButton btnMute = new JButton();
303 private final JButton btnSolo = new JButton();
304 private final JSlider slVolume = new JSlider(0, 100);
305 private final JLabel lVolume = new JLabel();
306 private final JLabel lVolImg = new JLabel(Res.iconVolume16);
307 private final JLabel lStreams = new JLabel("--");
308 private final JLabel lVoices = new JLabel("--");
309 private final JToggleButton btnProperties = new JToggleButton();
310
311 private static int count = 2;
312
313 private boolean selected = false;
314 private boolean mouseOver = false;
315
316
317 /**
318 * Creates a new instance of <code>Channel</code> using the specified
319 * non-<code>null</code> channel model.
320 * @param model The model to be used by this channel.
321 * @throws IllegalArgumentException If the model is <code>null</code>.
322 */
323 public
324 Channel(SamplerChannelModel model) {
325 super(model);
326
327 setBorder(BorderFactory.createEmptyBorder(1, 1, 1, 1));
328
329 mainPane.setLayout(new BoxLayout(mainPane, BoxLayout.Y_AXIS));
330 addMouseListener(getHandler());
331
332 JPanel p = new JPanel();
333 p.setOpaque(false);
334 p.setLayout(new BoxLayout(p, BoxLayout.X_AXIS));
335 p.setBorder(BorderFactory.createEmptyBorder(3, 3, 3, 3));
336
337 setToolTipText(i18n.getLabel("Channel.tt", getModel().getChannelId()));
338
339 Dimension d = btnInstr.getPreferredSize();
340 btnInstr.setMaximumSize(new Dimension(Short.MAX_VALUE, d.height));
341 p.add(btnInstr);
342 p.add(Box.createRigidArea(new Dimension(6, 0)));
343
344 lStreams.setHorizontalAlignment(JLabel.CENTER);
345 lVoices.setHorizontalAlignment(JLabel.CENTER);
346
347 JPanel statPane = new JPanel();
348 statPane.setOpaque(false);
349 statPane.setBorder(BorderFactory.createLoweredBevelBorder());
350 statPane.setLayout(new BoxLayout(statPane, BoxLayout.X_AXIS));
351 statPane.add(Box.createRigidArea(new Dimension(6, 0)));
352 statPane.add(lStreams);
353 statPane.add(new JLabel("/"));
354 statPane.add(lVoices);
355 statPane.add(Box.createRigidArea(new Dimension(6, 0)));
356
357 p.add(statPane);
358
359 p.add(Box.createRigidArea(new Dimension(6, 0)));
360
361 btnMute.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
362 p.add(btnMute);
363 p.add(Box.createRigidArea(new Dimension(6, 0)));
364
365 btnSolo.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
366 p.add(btnSolo);
367 p.add(Box.createRigidArea(new Dimension(6, 0)));
368
369 JPanel volumePane = new JPanel();
370 volumePane.setOpaque(false);
371 volumePane.setBorder(BorderFactory.createLoweredBevelBorder());
372 volumePane.setLayout(new BoxLayout(volumePane, BoxLayout.X_AXIS));
373 volumePane.add(Box.createRigidArea(new Dimension(6, 0)));
374
375 volumePane.add(lVolImg);
376 volumePane.add(Box.createRigidArea(new Dimension(1, 0)));
377
378 d = slVolume.getPreferredSize();
379 slVolume.setMaximumSize(new Dimension(d.width > 300 ? d.width : 300, d.height));
380 slVolume.setOpaque(false);
381 volumePane.add(slVolume);
382
383 lVolume.setBorder(BorderFactory.createEmptyBorder(3, 6, 3, 6));
384 lVolume.setHorizontalAlignment(lVolume.RIGHT);
385
386 // We use this to set the size of the lVolume that will be used in setVolume()
387 // to prevent the frequent resizing of lVolume
388 lVolume.setText("100%");
389
390 volumePane.add(lVolume);
391
392 p.add(volumePane);
393 p.add(Box.createRigidArea(new Dimension(6, 0)));
394
395 btnProperties.setContentAreaFilled(false);
396 btnProperties.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
397 btnProperties.setIcon(iconShowProperties);
398 btnProperties.setSelectedIcon(iconHideProperties);
399 p.add(btnProperties);
400
401 mainPane.add(p);
402
403 propertiesPane = new ChannelProperties(model);
404 propertiesPane.setBorder(BorderFactory.createEmptyBorder(0, 3, 3, 3));
405 propertiesPane.setVisible(false);
406 mainPane.add(propertiesPane);
407 add(mainPane);
408
409 d = getPreferredSize();
410 setMaximumSize(new Dimension(getMaximumSize().width, d.height));
411
412 getModel().addSamplerChannelListener(getHandler());
413
414 actInstr = new AbstractAction() {
415 public void
416 actionPerformed(ActionEvent e) {
417 if(actInstr.isEnabled()) loadInstrument();
418 }
419 };
420
421 btnInstr.addActionListener(actInstr);
422
423 btnMute.addActionListener(new ActionListener() {
424 public void
425 actionPerformed(ActionEvent e) { changeMute(); }
426 });
427
428 btnSolo.addActionListener(new ActionListener() {
429 public void
430 actionPerformed(ActionEvent e) { changeSolo(); }
431 });
432
433 slVolume.addChangeListener(new ChangeListener() {
434 public void
435 stateChanged(ChangeEvent e) { setVolume(); }
436 });
437
438 btnProperties.addActionListener(new ActionListener() {
439 public void
440 actionPerformed(ActionEvent e) {
441 showProperties(btnProperties.isSelected());
442
443 String s;
444 if(btnProperties.isSelected()) {
445 s = i18n.getButtonLabel("Channel.ttHideProps");
446 } else {
447 s = i18n.getButtonLabel("Channel.ttShowProps");
448 }
449
450 btnProperties.setToolTipText(s);
451 }
452 });
453
454 btnProperties.setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
455
456 String s;
457 if(btnProperties.isSelected()) s = i18n.getButtonLabel("Channel.ttHideProps");
458 else s = i18n.getButtonLabel("Channel.ttShowProps");
459
460 btnProperties.setToolTipText(s);
461
462 addPropertyChangeListener(getHandler());
463
464 updateChannelInfo();
465 }
466
467 public class InstrumentButton extends JButton {
468 private boolean dragging = false;
469
470 InstrumentButton(String s) {
471 super(s);
472
473 setTransferHandler(new TransferHandler("instrument"));
474
475 addMouseListener(new MouseAdapter() {
476 public void
477 mouseExited(MouseEvent e) {
478 if(!dragging) return;
479
480 int b1 = e.BUTTON1_DOWN_MASK;
481 if((e.getModifiersEx() & b1) != b1) return;
482
483 actInstr.setEnabled(false);
484 doClick(0);
485 actInstr.setEnabled(true);
486
487 JComponent c = (JComponent)e.getSource();
488 TransferHandler handler = c.getTransferHandler();
489 handler.exportAsDrag(c, e, TransferHandler.COPY);
490 }
491
492 public void
493 mouseReleased(MouseEvent e) { dragging = false; }
494 });
495
496 addMouseMotionListener(new MouseMotionAdapter() {
497 public void
498 mouseDragged(MouseEvent e) { dragging = true; }
499 });
500 }
501
502 public String
503 getInstrument() {
504 SamplerChannel sc = Channel.this.getChannelInfo();
505
506 if(sc.getInstrumentName() == null || sc.getInstrumentStatus() < 0)
507 return null;
508
509 Instrument instr = new Instrument();
510 instr.setName(sc.getInstrumentName());
511 instr.setInstrumentIndex(sc.getInstrumentIndex());
512 instr.setPath(sc.getInstrumentFile());
513 return instr.getDnDString();
514 }
515
516 public void setInstrument(String instr) {
517 if(!Instrument.isDnDString(instr)) return;
518
519 String[] args = instr.split("\n");
520 if(args.length < 6) return;
521
522 try {
523 int idx = Integer.parseInt(args[5]);
524 Channel.this.getModel().loadBackendInstrument(args[4], idx);
525 } catch(Exception x) {
526 CC.getLogger().log(Level.INFO, HF.getErrorMessage(x), x);
527 }
528 }
529 }
530
531 private final EventHandler eventHandler = new EventHandler();
532
533 private EventHandler
534 getHandler() { return eventHandler; }
535
536 private class EventHandler extends MouseAdapter implements SamplerChannelListener,
537 PropertyChangeListener, HierarchyListener {
538 /**
539 * Invoked when changes are made to a sampler channel.
540 * @param e A <code>SamplerChannelEvent</code> instance
541 * containing event information.
542 */
543 public void
544 channelChanged(SamplerChannelEvent e) { updateChannelInfo(); }
545
546 /**
547 * Invoked when the number of active disk streams has changed.
548 * @param e A <code>SamplerChannelEvent</code> instance
549 * containing event information.
550 */
551 public void
552 streamCountChanged(SamplerChannelEvent e) {
553 updateStreamCount(getModel().getStreamCount());
554 }
555
556 /**
557 * Invoked when the number of active voices has changed.
558 * @param e A <code>SamplerChannelEvent</code> instance
559 * containing event information.
560 */
561 public void
562 voiceCountChanged(SamplerChannelEvent e) {
563 updateVoiceCount(getModel().getVoiceCount());
564 }
565
566 public void
567 propertyChange(PropertyChangeEvent e) {
568 if (
569 e.getPropertyName() == "borderColor" ||
570 e.getPropertyName() == "borderHighlightedColor" ||
571 e.getPropertyName() == "selectedChannelBgColor" ||
572 e.getPropertyName() == "highlightedChannelBgColor"
573 ) {
574 updateColors(isSelected());
575 }
576 }
577
578 public void
579 mouseEntered(MouseEvent e) {
580 mouseOver = true;
581 updateColors(isSelected());
582 }
583
584 public void
585 mouseExited(MouseEvent e) {
586 if(getMousePosition(true) != null) return;
587
588 mouseOver = false;
589 updateColors(isSelected());
590 }
591
592
593
594 /** Called when the hierarchy has been changed. */
595 public void
596 hierarchyChanged(HierarchyEvent e) {
597 if((e.getChangeFlags() & e.SHOWING_CHANGED) == e.SHOWING_CHANGED) {
598 if(getMousePosition() == null) mouseExited(null);
599 else mouseEntered(null);
600 }
601 }
602 }
603
604 /**
605 * Determines whether the channel is selected.
606 * @return <code>true</code> if the channel is selected, <code>false</code> otherwise.
607 */
608 public boolean isSelected() { return selected; }
609
610 /**
611 * Sets the selection state of this channel.
612 * This method is invoked when the selection state of the channel has changed.
613 * @param select Specifies the new selection state of this channel;
614 * <code>true</code> to select the channel, <code>false</code> otherwise.
615 */
616 public void
617 setSelected(boolean select) {
618 updateColors(select);
619
620 selected = select;
621 }
622
623 /**
624 * Updates the channel background and border colors.
625 * @param selected Specifies the selection state of this channel.
626 */
627 private void
628 updateColors(boolean selected) {
629 if(selected) {
630 mainPane.setBorder(borderSelected);
631 mainPane.setBackground(chnSelectedColor);
632 } else {
633 if(mouseOver) {
634 mainPane.setBorder(borderHighlighted);
635 mainPane.setBackground(chnHighlightedColor);
636 } else {
637 mainPane.setBorder(borderDeselected);
638 mainPane.setBackground(chnColor);
639 }
640 }
641 }
642
643 /** Hides the channel properties. */
644 public void
645 collapseChannel() { if(btnProperties.isSelected()) btnProperties.doClick(); }
646
647 /** Shows the channel properties. */
648 public void
649 expandChannel() { if(!btnProperties.isSelected()) btnProperties.doClick(); }
650
651 /**
652 * Updates the channel settings. This method is invoked when changes to the
653 * channel were made.
654 */
655 private void
656 updateChannelInfo() {
657 SamplerChannel sc = getChannelInfo();
658
659 int status = sc.getInstrumentStatus();
660 if(status >= 0 && status < 100) {
661 btnInstr.setText(i18n.getLabel("Channel.loadingInstrument", status));
662 } else if(status == -1) {
663 btnInstr.setText(i18n.getLabel("Channel.btnInstr"));
664 } else if(status < -1) {
665 btnInstr.setText(i18n.getLabel("Channel.errorLoadingInstrument"));
666 } else {
667 if(sc.getInstrumentName() != null) btnInstr.setText(sc.getInstrumentName());
668 else btnInstr.setText(i18n.getLabel("Channel.btnInstr"));
669 }
670
671 updateMuteIcon(sc);
672
673 if(sc.isSoloChannel()) btnSolo.setIcon(iconSoloOn);
674 else btnSolo.setIcon(iconSoloOff);
675
676 slVolume.setValue((int)(sc.getVolume() * 100));
677
678 boolean b = sc.getEngine() != null;
679 slVolume.setEnabled(b);
680 btnSolo.setEnabled(b);
681 btnMute.setEnabled(b);
682 }
683
684 /** Invoked when the user clicks the mute button. */
685 private void
686 changeMute() {
687 SamplerChannel sc = getChannelInfo();
688 boolean b = true;
689
690 /*
691 * Changing the mute button icon now instead of
692 * leaving the work to the notification mechanism of the LinuxSampler.
693 */
694 if(sc.isMuted() && !sc.isMutedBySolo()) {
695 b = false;
696 boolean hasSolo = CC.getSamplerModel().hasSoloChannel();
697
698 if(sc.isSoloChannel() || !hasSolo) btnMute.setIcon(iconMuteOff);
699 else btnMute.setIcon(iconMutedBySolo);
700 } else btnMute.setIcon(iconMuteOn);
701
702 getModel().setBackendMute(b);
703 }
704
705 /** Invoked when the user clicks the solo button. */
706 private void
707 changeSolo() {
708 SamplerChannel sc = getChannelInfo();
709 boolean b = !sc.isSoloChannel();
710
711 /*
712 * Changing the solo button icon (and related) now instead of
713 * leaving the work to the notification mechanism of the LinuxSampler.
714 */
715 if(b) {
716 btnSolo.setIcon(iconSoloOn);
717 if(sc.isMutedBySolo()) btnMute.setIcon(iconMuteOff);
718 } else {
719 btnSolo.setIcon(iconSoloOff);
720 if(!sc.isMuted() && CC.getSamplerModel().getSoloChannelCount() > 1)
721 btnMute.setIcon(iconMutedBySolo);
722 }
723
724 getModel().setBackendSolo(b);
725 }
726
727 /** Invoked when the user changes the volume */
728 private void
729 setVolume() {
730 updateVolume();
731
732 if(slVolume.getValueIsAdjusting()) return;
733
734 int vol = (int)(getChannelInfo().getVolume() * 100);
735
736 if(vol == slVolume.getValue()) return;
737
738 /*
739 * If the model's volume is not equal to the slider
740 * value we assume that the change is due to user input.
741 * So we must update the volume at the backend too.
742 */
743 float volume = slVolume.getValue();
744 volume /= 100;
745 getModel().setBackendVolume(volume);
746 }
747
748 private void
749 updateVolume() {
750 int volume = slVolume.getValue();
751 slVolume.setToolTipText(i18n.getLabel("Channel.volume", volume));
752 lVolImg.setToolTipText(i18n.getLabel("Channel.volume", volume));
753
754 setVolumeLabel(volume);
755
756
757 }
758
759 private void
760 setVolumeLabel(int volume) {
761 Dimension d = lVolume.getPreferredSize();
762 lVolume.setText(String.valueOf(volume) + '%');
763 d = JuifeUtils.getUnionSize(d, lVolume.getPreferredSize());
764 lVolume.setMinimumSize(d);
765 lVolume.setPreferredSize(d);
766 lVolume.setMaximumSize(d);
767 }
768
769 /**
770 * Updates the mute button with the proper icon regarding to information obtained
771 * from <code>channel</code>.
772 * @param channel A <code>SamplerChannel</code> instance containing the new settings
773 * for this channel.
774 */
775 private void
776 updateMuteIcon(SamplerChannel channel) {
777 if(channel.isMutedBySolo()) btnMute.setIcon(iconMutedBySolo);
778 else if(channel.isMuted()) btnMute.setIcon(iconMuteOn);
779 else btnMute.setIcon(iconMuteOff);
780 }
781
782 /**
783 * Updates the number of active disk streams.
784 * @param count The new number of active disk streams.
785 */
786 private void
787 updateStreamCount(int count) {
788 Dimension d = lStreams.getPreferredSize();
789 lStreams.setText(count == 0 ? "--" : String.valueOf(count));
790 d = JuifeUtils.getUnionSize(d, lStreams.getPreferredSize());
791 lStreams.setMinimumSize(d);
792 lStreams.setPreferredSize(d);
793 lStreams.setMaximumSize(d);
794 }
795
796 /**
797 * Updates the number of active voices.
798 * @param count The new number of active voices.
799 */
800 private void
801 updateVoiceCount(int count) {
802 Dimension d = lVoices.getPreferredSize();
803 lVoices.setText(count == 0 ? "--" : String.valueOf(count));
804 d = JuifeUtils.getUnionSize(d, lVoices.getPreferredSize());
805 lVoices.setMinimumSize(d);
806 lVoices.setPreferredSize(d);
807 lVoices.setMaximumSize(d);
808 }
809
810 private void
811 showProperties(boolean show) {propertiesPane.setVisible(show); }
812
813 private void
814 loadInstrument() {
815 InstrumentChooser dlg = new InstrumentChooser(CC.getMainFrame());
816 dlg.setVisible(true);
817
818 if(dlg.isCancelled()) return;
819
820 SamplerEngine engine = getChannelInfo().getEngine();
821 if(dlg.getEngine() != null) {
822 if(engine == null || !dlg.getEngine().equals(engine.getName()));
823 getModel().setBackendEngineType(dlg.getEngine());
824 }
825
826 int idx = dlg.getInstrumentIndex();
827 getModel().loadBackendInstrument(dlg.getInstrumentFile(), idx);
828
829 }
830 }
831
832 class ChannelProperties extends JPanel {
833 private final JLabel lMidiDevice =
834 new JLabel(i18n.getLabel("ChannelProperties.lMidiDevice"));
835 private final JLabel lMidiPort =
836 new JLabel(i18n.getLabel("ChannelProperties.lMidiPort"));
837 private final JLabel lMidiChannel =
838 new JLabel(i18n.getLabel("ChannelProperties.lMidiChannel"));
839
840 private final JLabel lInstrumentMap =
841 new JLabel(i18n.getLabel("ChannelProperties.lInstrumentMap"));
842
843 private final JLabel lAudioDevice =
844 new JLabel(i18n.getLabel("ChannelProperties.lAudioDevice"));
845
846 private final JComboBox cbEngines = new JComboBox();
847
848 private final JComboBox cbInstrumentMap = new JComboBox();
849 private final JComboBox cbMidiDevice = new JComboBox();
850 private final JComboBox cbMidiPort = new JComboBox();
851 private final JComboBox cbMidiChannel = new JComboBox();
852 private final JComboBox cbAudioDevice = new JComboBox();
853
854 private final JButton btnFxSends = new JButton(Res.iconFxSends22);
855 private final JButton btnAudioProps = new JButton(Res.iconAudioProps16);
856 private InformationDialog fxSendsDlg = null;
857
858 private SamplerChannelModel channelModel = null;
859
860 private boolean update = false;
861
862 private class NoMap {
863 public String
864 toString() { return "[None]"; }
865 }
866
867 private NoMap noMap = new NoMap();
868
869 private class DefaultMap {
870 public String
871 toString() { return "[Default]"; }
872 }
873
874 private DefaultMap defaultMap = new DefaultMap();
875
876 /**
877 * Creates a new instance of <code>ChannelProperties</code> using the specified non-null
878 * channel model.
879 * @param model The model to be used by this channel properties pane.
880 */
881 ChannelProperties(SamplerChannelModel model) {
882 channelModel = model;
883
884 setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
885 setOpaque(false);
886
887 add(new JSeparator());
888
889 JPanel enginesPane = createEnginePane();
890
891 JPanel devicesPane = new JPanel();
892 devicesPane.setOpaque(false);
893 devicesPane.setLayout(new BoxLayout(devicesPane, BoxLayout.X_AXIS));
894
895 devicesPane.add(Box.createRigidArea(new Dimension(3, 0)));
896
897 devicesPane.add(createMidiPane());
898
899 devicesPane.add(Box.createRigidArea(new Dimension(3, 0)));
900
901 devicesPane.add(enginesPane);
902
903 devicesPane.add(Box.createRigidArea(new Dimension(3, 0)));
904
905 JPanel audioPane = createAudioPane();
906 Dimension d = audioPane.getPreferredSize();
907 d.height = Short.MAX_VALUE;
908
909 audioPane.setMaximumSize(d);
910 devicesPane.add(audioPane);
911
912 add(devicesPane);
913 add(Box.createRigidArea(new Dimension(0, 6)));
914
915 add(new JSeparator());
916
917 cbMidiChannel.addItem("All");
918 for(int i = 1; i <= 16; i++) cbMidiChannel.addItem(String.valueOf(i));
919
920 cbMidiDevice.addActionListener(new ActionListener() {
921 public void
922 actionPerformed(ActionEvent e) { setMidiDevice(); }
923 });
924
925 cbMidiPort.addActionListener(new ActionListener() {
926 public void
927 actionPerformed(ActionEvent e) { setMidiPort(); }
928 });
929
930 cbMidiChannel.addActionListener(new ActionListener() {
931 public void
932 actionPerformed(ActionEvent e) { setMidiChannel(); }
933 });
934
935 cbEngines.addActionListener(new ActionListener() {
936 public void
937 actionPerformed(ActionEvent e) { setEngineType(); }
938 });
939
940 cbAudioDevice.addActionListener(new ActionListener() {
941 public void
942 actionPerformed(ActionEvent e) { setAudioDevice(); }
943 });
944
945 getModel().addSamplerChannelListener(new SamplerChannelAdapter() {
946 public void
947 channelChanged(SamplerChannelEvent e) { updateChannelProperties(); }
948 });
949
950 CC.getSamplerModel().addSamplerListener(new SamplerAdapter() {
951 /** Invoked when the default MIDI instrument map is changed. */
952 public void
953 defaultMapChanged(SamplerEvent e) {
954 updateCbInstrumentMapToolTipText();
955
956 }
957 });
958
959 cbInstrumentMap.addItem(noMap);
960 cbInstrumentMap.addItem(defaultMap);
961 for(MidiInstrumentMap map : CC.getSamplerModel().getMidiInstrumentMaps()) {
962 cbInstrumentMap.addItem(map);
963 }
964
965 int map = getModel().getChannelInfo().getMidiInstrumentMapId();
966 cbInstrumentMap.setSelectedItem(CC.getSamplerModel().getMidiInstrumentMapById(map));
967 if(cbInstrumentMap.getSelectedItem() == null) {
968 if(map == -1) cbInstrumentMap.setSelectedItem(noMap);
969 else if(map == -2) {
970 cbInstrumentMap.setSelectedItem(defaultMap);
971 }
972 }
973
974 updateCbInstrumentMapToolTipText();
975
976 if(getModel().getChannelInfo().getEngine() == null) {
977 cbInstrumentMap.setEnabled(false);
978 }
979
980 cbInstrumentMap.addActionListener(new ActionListener() {
981 public void
982 actionPerformed(ActionEvent e) { updateInstrumentMap(); }
983 });
984
985 CC.getSamplerModel().addMidiDeviceListListener(getHandler());
986 CC.getSamplerModel().addAudioDeviceListListener(getHandler());
987 CC.getSamplerModel().addSamplerChannelListListener(getHandler());
988
989 CC.getSamplerModel().addMidiInstrumentMapListListener(new MapListListener());
990
991 btnAudioProps.setToolTipText(i18n.getLabel("ChannelProperties.routing"));
992 btnAudioProps.addActionListener(new ActionListener() {
993 public void
994 actionPerformed(ActionEvent e) {
995 SamplerChannel c = getModel().getChannelInfo();
996 new ChannelOutputRoutingDlg(CC.getMainFrame(), c).setVisible(true);
997
998 }
999 });
1000
1001 btnFxSends.setToolTipText(i18n.getButtonLabel("ChannelProperties.btnFxSends"));
1002 btnFxSends.addActionListener(new ActionListener() {
1003 public void
1004 actionPerformed(ActionEvent e) {
1005 if(fxSendsDlg != null && fxSendsDlg.isVisible()) {
1006 fxSendsDlg.toFront();
1007 return;
1008 }
1009
1010 FxSendsPane p = new FxSendsPane(getModel());
1011 int id = getModel().getChannelId();
1012 fxSendsDlg = new InformationDialog(CC.getMainFrame(), p);
1013 fxSendsDlg.setTitle(i18n.getLabel("FxSendsPane.title", id));
1014 fxSendsDlg.setModal(false);
1015 fxSendsDlg.showCloseButton(false);
1016 fxSendsDlg.setVisible(true);
1017 }
1018 });
1019
1020 updateMidiDevices();
1021 updateAudioDevices();
1022 updateChannelProperties();
1023 }
1024
1025 private JPanel
1026 createEnginePane() {
1027 for(SamplerEngine e : CC.getSamplerModel().getEngines()) cbEngines.addItem(e);
1028
1029 cbEngines.setMaximumSize(cbEngines.getPreferredSize());
1030
1031 JPanel p = new JPanel();
1032 p.setOpaque(false);
1033 p.setLayout(new BoxLayout(p, BoxLayout.Y_AXIS));
1034 p.add(cbEngines);
1035 p.setBorder(BorderFactory.createEmptyBorder(3, 3, 3, 3));
1036
1037 //enginesPane.add(Box.createGlue());
1038 JPanel enginesPane = new JPanel();
1039 enginesPane.setOpaque(false);
1040 enginesPane.setLayout(new BorderLayout());
1041 enginesPane.add(p, BorderLayout.SOUTH);
1042 //enginesPane.add(Box.createRigidArea(new Dimension(0, 3)));
1043
1044 String s = i18n.getLabel("ChannelProperties.enginesPane");
1045 enginesPane.setBorder(BorderFactory.createTitledBorder(s));
1046 Dimension d = new Dimension(enginesPane.getPreferredSize().width, Short.MAX_VALUE);
1047 enginesPane.setMaximumSize(d);
1048 return enginesPane;
1049 }
1050
1051 private JPanel
1052 createMidiPane() {
1053 JPanel midiPane = new JPanel();
1054 midiPane.setOpaque(false);
1055
1056 GridBagLayout gridbag = new GridBagLayout();
1057 GridBagConstraints c = new GridBagConstraints();
1058
1059 midiPane.setLayout(gridbag);
1060
1061 c.gridx = 1;
1062 c.gridy = 0;
1063 c.insets = new Insets(0, 3, 3, 3);
1064 gridbag.setConstraints(lMidiDevice, c);
1065 midiPane.add(lMidiDevice);
1066
1067 c.gridx = 2;
1068 c.gridy = 0;
1069 gridbag.setConstraints(lMidiPort, c);
1070 midiPane.add(lMidiPort);
1071
1072 c.gridx = 3;
1073 c.gridy = 0;
1074 gridbag.setConstraints(lMidiChannel, c);
1075 midiPane.add(lMidiChannel);
1076
1077 c.gridx = 4;
1078 c.gridy = 0;
1079 c.insets = new Insets(0, 10, 3, 3);
1080 gridbag.setConstraints(lInstrumentMap, c);
1081 midiPane.add(lInstrumentMap);
1082
1083 btnFxSends.setMargin(new Insets(0, 0, 0, 0));
1084 c.gridx = 0;
1085 c.gridy = 0;
1086 c.gridheight = 2;
1087 c.insets = new Insets(0, 5, 0, 8);
1088 gridbag.setConstraints(btnFxSends, c);
1089 midiPane.add(btnFxSends);
1090
1091 c.gridx = 1;
1092 c.gridy = 1;
1093 c.gridheight = 1;
1094 c.insets = new Insets(0, 4, 4, 3);
1095 c.fill = GridBagConstraints.HORIZONTAL;
1096 gridbag.setConstraints(cbMidiDevice, c);
1097 midiPane.add(cbMidiDevice);
1098
1099 c.gridx = 3;
1100 c.gridy = 1;
1101 gridbag.setConstraints(cbMidiChannel, c);
1102 midiPane.add(cbMidiChannel);
1103
1104 c.gridx = 2;
1105 c.gridy = 1;
1106 gridbag.setConstraints(cbMidiPort, c);
1107 midiPane.add(cbMidiPort);
1108
1109 c.gridx = 4;
1110 c.gridy = 1;
1111 c.weightx = 1.0;
1112 c.insets = new Insets(0, 10, 3, 3);
1113 gridbag.setConstraints(cbInstrumentMap, c);
1114 midiPane.add(cbInstrumentMap);
1115
1116 String s = i18n.getLabel("ChannelProperties.midiPane");
1117 TitledBorder border = BorderFactory.createTitledBorder(s);
1118 //border.setTitlePosition(border.TOP);
1119 midiPane.setBorder(border);
1120 return midiPane;
1121 }
1122
1123 private JPanel
1124 createAudioPane() {
1125 JPanel audioPane = new JPanel();
1126 audioPane.setOpaque(false);
1127
1128 GridBagLayout gridbag = new GridBagLayout();
1129 GridBagConstraints c = new GridBagConstraints();
1130
1131 audioPane.setLayout(gridbag);
1132
1133 c.gridx = 0;
1134 c.gridy = 0;
1135 c.insets = new Insets(0, 3, 3, 3);
1136 gridbag.setConstraints(lAudioDevice, c);
1137 audioPane.add(lAudioDevice);
1138
1139 c.gridx = 0;
1140 c.gridy = 1;
1141 c.fill = GridBagConstraints.HORIZONTAL;
1142 gridbag.setConstraints(cbAudioDevice, c);
1143 audioPane.add(cbAudioDevice);
1144
1145 btnAudioProps.setMargin(new Insets(0, 0, 0, 0));
1146 c.gridx = 1;
1147 c.gridy = 1;
1148 c.fill = GridBagConstraints.NONE;
1149 gridbag.setConstraints(btnAudioProps, c);
1150 audioPane.add(btnAudioProps);
1151
1152 String s = i18n.getLabel("ChannelProperties.audioPane");
1153 audioPane.setBorder(BorderFactory.createTitledBorder(s));
1154
1155 return audioPane;
1156 }
1157
1158 /**
1159 * Gets the model that is currently used by this channel properties pane.
1160 * @return model The <code>SamplerChannelModel</code> instance
1161 * that provides information about the channel whose settings are
1162 * represented by this channel properties pane.
1163 */
1164 public SamplerChannelModel
1165 getModel() { return channelModel; }
1166
1167
1168 private void
1169 updateInstrumentMap() {
1170 updateCbInstrumentMapToolTipText();
1171
1172 int id = getModel().getChannelInfo().getMidiInstrumentMapId();
1173 Object o = cbInstrumentMap.getSelectedItem();
1174 if(o == null && id == -1) return;
1175
1176 int cbId;
1177 if(o == null || o == noMap) cbId = -1;
1178 else if(o == defaultMap) cbId = -2;
1179 else cbId = ((MidiInstrumentMap)o).getMapId();
1180
1181 if(cbId == id) return;
1182
1183 channelModel.setBackendMidiInstrumentMap(cbId);
1184 }
1185
1186 private void
1187 updateCbInstrumentMapToolTipText() {
1188 if(cbInstrumentMap.getSelectedItem() != defaultMap) {
1189 cbInstrumentMap.setToolTipText(null);
1190 return;
1191 }
1192
1193 MidiInstrumentMap m = CC.getSamplerModel().getDefaultMidiInstrumentMap();
1194 if(m != null) {
1195 String s = i18n.getLabel("Channel.ttDefault", m.getName());
1196 cbInstrumentMap.setToolTipText(s);
1197 } else {
1198 cbInstrumentMap.setToolTipText(null);
1199 }
1200 }
1201
1202 /**
1203 * Updates the channel settings. This method is invoked when changes to the
1204 * channel were made.
1205 */
1206 private void
1207 updateChannelProperties() {
1208 SamplerModel sm = CC.getSamplerModel();
1209 SamplerChannel sc = getModel().getChannelInfo();
1210
1211 MidiDeviceModel mm = sm.getMidiDeviceById(sc.getMidiInputDevice());
1212 AudioDeviceModel am = sm.getAudioDeviceById(sc.getAudioOutputDevice());
1213
1214 if(isUpdate()) CC.getLogger().warning("Unexpected update state!");
1215
1216 setUpdate(true);
1217
1218 try {
1219 cbMidiDevice.setSelectedItem(mm == null ? null : mm.getDeviceInfo());
1220
1221 cbEngines.setSelectedItem(sc.getEngine());
1222
1223 cbAudioDevice.setSelectedItem(am == null ? null : am.getDeviceInfo());
1224 } catch(Exception x) {
1225 CC.getLogger().log(Level.WARNING, "Unkown error", x);
1226 }
1227
1228 if(sc.getEngine() != null) {
1229 if(cbInstrumentMap.getItemCount() > 0) cbInstrumentMap.setEnabled(true);
1230 } else {
1231 cbInstrumentMap.setSelectedItem(noMap);
1232 cbInstrumentMap.setEnabled(false);
1233 }
1234
1235 setUpdate(false);
1236 }
1237
1238 /**
1239 * Updates the MIDI device list.
1240 */
1241 private void
1242 updateMidiDevices() {
1243 SamplerModel sm = CC.getSamplerModel();
1244 SamplerChannel sc = getModel().getChannelInfo();
1245
1246 setUpdate(true);
1247
1248 try {
1249 cbMidiDevice.removeAllItems();
1250
1251 for(MidiDeviceModel m : sm.getMidiDevices())
1252 cbMidiDevice.addItem(m.getDeviceInfo());
1253
1254 MidiDeviceModel mm = sm.getMidiDeviceById(sc.getMidiInputDevice());
1255 cbMidiDevice.setSelectedItem(mm == null ? null : mm.getDeviceInfo());
1256 } catch(Exception x) {
1257 CC.getLogger().log(Level.WARNING, "Unkown error", x);
1258 }
1259
1260 setUpdate(false);
1261 }
1262
1263 /**
1264 * Updates the audio device list.
1265 */
1266 private void
1267 updateAudioDevices() {
1268 SamplerModel sm = CC.getSamplerModel();
1269 SamplerChannel sc = getModel().getChannelInfo();
1270
1271 setUpdate(true);
1272
1273 try {
1274 cbAudioDevice.removeAllItems();
1275
1276 for(AudioDeviceModel m : sm.getAudioDevices())
1277 cbAudioDevice.addItem(m.getDeviceInfo());
1278
1279 AudioDeviceModel am = sm.getAudioDeviceById(sc.getAudioOutputDevice());
1280 cbAudioDevice.setSelectedItem(am == null ? null : am.getDeviceInfo());
1281 } catch(Exception x) {
1282 CC.getLogger().log(Level.WARNING, "Unkown error", x);
1283 }
1284
1285 setUpdate(false);
1286 }
1287
1288 private void
1289 setMidiDevice() {
1290 MidiInputDevice mid = (MidiInputDevice)cbMidiDevice.getSelectedItem();
1291
1292 if(!isUpdate()) {
1293 if(mid != null) getModel().setBackendMidiInputDevice(mid.getDeviceId());
1294 return;
1295 }
1296
1297 cbMidiPort.removeAllItems();
1298
1299 if(mid == null) {
1300 cbMidiPort.setEnabled(false);
1301
1302 cbMidiChannel.setSelectedItem(null);
1303 cbMidiChannel.setEnabled(false);
1304 } else {
1305 cbMidiPort.setEnabled(true);
1306
1307 MidiPort[] ports = mid.getMidiPorts();
1308 for(MidiPort port : ports) cbMidiPort.addItem(port);
1309
1310 int p = getModel().getChannelInfo().getMidiInputPort();
1311 cbMidiPort.setSelectedItem(p >= 0 && p < ports.length ? ports[p] : null);
1312
1313 cbMidiChannel.setEnabled(true);
1314 int c = getModel().getChannelInfo().getMidiInputChannel();
1315 cbMidiChannel.setSelectedItem(c == -1 ? "All" : String.valueOf(c + 1));
1316 }
1317
1318
1319 }
1320
1321 private void
1322 setMidiPort() {
1323 if(isUpdate()) return;
1324
1325 getModel().setBackendMidiInputPort(cbMidiPort.getSelectedIndex());
1326 }
1327
1328 private void
1329 setMidiChannel() {
1330 if(isUpdate()) return;
1331
1332 Object o = cbMidiChannel.getSelectedItem();
1333 if(o == null) return;
1334
1335 int c = o.toString().equals("All") ? -1 : Integer.parseInt(o.toString()) - 1;
1336
1337 getModel().setBackendMidiInputChannel(c);
1338 }
1339
1340 /** Invoked when the user selects an engine. */
1341 private void
1342 setEngineType() {
1343 Object oldEngine = getModel().getChannelInfo().getEngine();
1344 SamplerEngine newEngine = (SamplerEngine)cbEngines.getSelectedItem();
1345
1346 if(oldEngine != null) { if(oldEngine.equals(newEngine)) return; }
1347 else if(newEngine == null) return;
1348
1349 getModel().setBackendEngineType(newEngine.getName());
1350
1351 }
1352
1353 private void
1354 setAudioDevice() {
1355 if(isUpdate()) return;
1356 AudioOutputDevice dev = (AudioOutputDevice)cbAudioDevice.getSelectedItem();
1357 if(dev != null) getModel().setBackendAudioOutputDevice(dev.getDeviceId());
1358 }
1359
1360 /**
1361 * Determines whether the currently processed changes are due to update.
1362 * @return <code>true</code> if the currently processed changes are due to update and
1363 * <code>false</code> if the currently processed changes are due to user input.
1364 */
1365 private boolean
1366 isUpdate() { return update; }
1367
1368 /**
1369 * Sets whether the currently processed changes are due to update.
1370 * @param b Specify <code>true</code> to indicate that the currently
1371 * processed changes are due to update; <code>false</code>
1372 * indicates that the currently processed changes are due to user input.
1373 */
1374 private void
1375 setUpdate(boolean b) { update = b; }
1376
1377 private final Handler handler = new Handler();
1378
1379 private Handler
1380 getHandler() { return handler; }
1381
1382 private class Handler implements MidiDeviceListListener,
1383 ListListener<AudioDeviceModel>, SamplerChannelListListener {
1384
1385 /**
1386 * Invoked when a new MIDI device is created.
1387 * @param e A <code>MidiDeviceListEvent</code>
1388 * instance providing the event information.
1389 */
1390 public void
1391 deviceAdded(MidiDeviceListEvent e) {
1392 cbMidiDevice.addItem(e.getMidiDeviceModel().getDeviceInfo());
1393 }
1394
1395 /**
1396 * Invoked when a MIDI device is removed.
1397 * @param e A <code>MidiDeviceListEvent</code>
1398 * instance providing the event information.
1399 */
1400 public void
1401 deviceRemoved(MidiDeviceListEvent e) {
1402 cbMidiDevice.removeItem(e.getMidiDeviceModel().getDeviceInfo());
1403 }
1404
1405 /**
1406 * Invoked when a new audio device is created.
1407 * @param e An <code>AudioDeviceListEvent</code>
1408 * instance providing the event information.
1409 */
1410 public void
1411 entryAdded(ListEvent<AudioDeviceModel> e) {
1412 cbAudioDevice.addItem(e.getEntry().getDeviceInfo());
1413 }
1414
1415 /**
1416 * Invoked when an audio device is removed.
1417 * @param e An <code>AudioDeviceListEvent</code>
1418 * instance providing the event information.
1419 */
1420 public void
1421 entryRemoved(ListEvent<AudioDeviceModel> e) {
1422 cbAudioDevice.removeItem(e.getEntry().getDeviceInfo());
1423 }
1424
1425 /**
1426 * Invoked when a new sampler channel is created.
1427 * @param e A <code>SamplerChannelListEvent</code>
1428 * instance providing the event information.
1429 */
1430 public void
1431 channelAdded(SamplerChannelListEvent e) { }
1432
1433 /**
1434 * Invoked when a sampler channel is removed.
1435 * @param e A <code>SamplerChannelListEvent</code>
1436 * instance providing the event information.
1437 */
1438 public void
1439 channelRemoved(SamplerChannelListEvent e) {
1440 // Some cleanup when the channel is removed.
1441 if(e.getChannelModel().getChannelId() == channelModel.getChannelId()) {
1442 CC.getSamplerModel().removeMidiDeviceListListener(getHandler());
1443 CC.getSamplerModel().removeAudioDeviceListListener(getHandler());
1444 }
1445 }
1446 }
1447
1448 private class MapListListener implements ListListener<MidiInstrumentMap> {
1449 /** Invoked when a new MIDI instrument map is added to a list. */
1450 public void
1451 entryAdded(ListEvent<MidiInstrumentMap> e) {
1452 //cbInstrumentMap.addItem(e.getEntry());
1453 cbInstrumentMap.insertItemAt(e.getEntry(), cbInstrumentMap.getItemCount());
1454 boolean b = getModel().getChannelInfo().getEngine() != null;
1455 if(b && !cbInstrumentMap.isEnabled()) cbInstrumentMap.setEnabled(true);
1456 }
1457
1458 /** Invoked when a new MIDI instrument map is removed from a list. */
1459 public void
1460 entryRemoved(ListEvent<MidiInstrumentMap> e) {
1461 cbInstrumentMap.removeItem(e.getEntry());
1462 if(cbInstrumentMap.getItemCount() == 0) {
1463 cbInstrumentMap.setSelectedItem(noMap);
1464 cbInstrumentMap.setEnabled(false);
1465 }
1466 }
1467 }
1468 }

  ViewVC Help
Powered by ViewVC