/[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 1285 - (show annotations) (download)
Fri Aug 10 19:55:03 2007 UTC (16 years, 8 months ago) by iliev
File size: 45928 byte(s)
* Updated to version 0.6a. The Fantasia distribution is now
  capable of controlling all features available in LinuxSampler

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

  ViewVC Help
Powered by ViewVC