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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 911 - (hide annotations) (download)
Mon Aug 7 18:25:58 2006 UTC (17 years, 8 months ago) by iliev
File size: 32631 byte(s)
updating to JSampler 0.3a

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

  ViewVC Help
Powered by ViewVC