/[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 2288 - (show annotations) (download)
Wed Nov 23 21:19:44 2011 UTC (12 years, 4 months ago) by iliev
File size: 48269 byte(s)
* Added option to select a sampler engine in Add/Edit Instrument dialog
* Moved all Swing dependent code outside the JSampler core

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

  ViewVC Help
Powered by ViewVC