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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2288 - (hide annotations) (download)
Wed Nov 23 21:19:44 2011 UTC (12 years, 6 months ago) by iliev
File size: 15909 byte(s)
* Added option to select a sampler engine in Add/Edit Instrument dialog
* Moved all Swing dependent code outside the JSampler core

1 iliev 787 /*
2     * JSampler - a java front-end for LinuxSampler
3     *
4 iliev 2288 * Copyright (C) 2005-2011 Grigor Iliev <grigor@grigoriliev.com>
5 iliev 787 *
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.Dimension;
27    
28     import java.awt.event.ActionEvent;
29     import java.awt.event.ActionListener;
30    
31     import javax.swing.AbstractAction;
32     import javax.swing.Action;
33     import javax.swing.BorderFactory;
34     import javax.swing.Box;
35     import javax.swing.BoxLayout;
36     import javax.swing.JComboBox;
37     import javax.swing.JLabel;
38     import javax.swing.JPanel;
39     import javax.swing.JScrollPane;
40     import javax.swing.JSplitPane;
41     import javax.swing.JTable;
42     import javax.swing.JToolBar;
43     import javax.swing.ListSelectionModel;
44    
45     import javax.swing.event.ListSelectionEvent;
46     import javax.swing.event.ListSelectionListener;
47    
48     import javax.swing.table.AbstractTableModel;
49     import javax.swing.table.TableColumn;
50    
51 iliev 2288 import net.sf.juife.swing.InformationDialog;
52     import net.sf.juife.swing.JuifeUtils;
53     import net.sf.juife.swing.NavigationPage;
54 iliev 787
55     import org.jsampler.CC;
56     import org.jsampler.MidiDeviceModel;
57    
58     import org.jsampler.event.MidiDeviceEvent;
59     import org.jsampler.event.MidiDeviceListEvent;
60     import org.jsampler.event.MidiDeviceListListener;
61     import org.jsampler.event.MidiDeviceListener;
62     import org.jsampler.event.ParameterEvent;
63     import org.jsampler.event.ParameterListener;
64    
65 iliev 2288 import org.jsampler.view.swing.NumberCellEditor;
66     import org.jsampler.view.swing.ParameterTable;
67     import org.jsampler.view.swing.SHF;
68 iliev 787
69     import org.linuxsampler.lscp.MidiInputDevice;
70     import org.linuxsampler.lscp.MidiPort;
71     import org.linuxsampler.lscp.Parameter;
72    
73     import static org.jsampler.view.classic.ClassicI18n.i18n;
74     import static org.jsampler.view.classic.MidiDevicesTableModel.*;
75    
76    
77     /**
78     *
79     * @author Grigor Iliev
80     */
81     public class MidiDevicesPage extends NavigationPage {
82     private final Action duplicateMidiDevice = new DuplicateMidiDevice();
83     private final Action removeMidiDevice = new RemoveMidiDevice();
84     private final Action midiDeviceProps = new MidiDeviceProps();
85    
86     private final ToolbarButton btnNewDevice = new ToolbarButton(A4n.addMidiDevice);
87     private final ToolbarButton btnDuplicateDevice = new ToolbarButton(duplicateMidiDevice);
88     private final ToolbarButton btnRemoveDevice = new ToolbarButton(removeMidiDevice);
89     private final ToolbarButton btnDeviceProps = new ToolbarButton(midiDeviceProps);
90    
91     private final JTable devicesTable = new JTable(new MidiDevicesTableModel());
92    
93     private final JLabel lPorts = new JLabel(i18n.getLabel("MidiDevicesPage.lPorts"));
94     private final JComboBox cbPorts = new JComboBox();
95    
96     ParameterTable portParamTable = new ParameterTable();
97    
98    
99     /** Creates a new instance of <code>MidiDevicesPage</code> */
100     public
101     MidiDevicesPage() {
102     setTitle(i18n.getLabel("MidiDevicesPage.title"));
103    
104     cbPorts.setEnabled(false);
105    
106     TableColumn tc = devicesTable.getColumnModel().getColumn(ACTIVE_COLUMN_INDEX);
107     tc.setPreferredWidth(tc.getMinWidth());
108    
109     NumberCellEditor nce = new NumberCellEditor();
110     nce.setMinimum(0);
111     nce.setMaximum(255);
112     tc = devicesTable.getColumnModel().getColumn(PORTS_COLUMN_INDEX);
113     tc.setCellEditor(nce);
114    
115     setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
116    
117     JToolBar tb = new JToolBar();
118     tb.setMaximumSize(new Dimension(Short.MAX_VALUE, tb.getPreferredSize().height));
119     tb.setFloatable(false);
120     tb.setAlignmentX(JPanel.RIGHT_ALIGNMENT);
121    
122 iliev 1143 tb.add(Box.createRigidArea(new Dimension(3, 0)));
123     tb.add(new JLabel(Res.iconMidi24));
124     tb.add(Box.createRigidArea(new Dimension(3, 0)));
125 iliev 787 tb.add(btnNewDevice);
126     tb.add(btnDuplicateDevice);
127     tb.add(btnRemoveDevice);
128     tb.addSeparator();
129     tb.add(btnDeviceProps);
130    
131     add(tb);
132    
133     JSplitPane splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT);
134    
135     devicesTable.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
136     JScrollPane sp = new JScrollPane(devicesTable);
137 iliev 911 Dimension d;
138     d = new Dimension(sp.getMinimumSize().width, sp.getPreferredSize().height);
139     sp.setPreferredSize(d);
140    
141 iliev 787 JPanel p = new JPanel();
142     p.setLayout(new BoxLayout(p, BoxLayout.Y_AXIS));
143     p.add(sp);
144     p.add(Box.createRigidArea(new Dimension(0, 8)));
145    
146     splitPane.setTopComponent(p);
147    
148     //add(Box.createRigidArea(new Dimension(0, 12)));
149    
150     JPanel portsPane = new JPanel();
151     portsPane.setLayout(new BoxLayout(portsPane, BoxLayout.Y_AXIS));
152    
153     p = new JPanel();
154     p.setLayout(new BoxLayout(p, BoxLayout.X_AXIS));
155     p.add(lPorts);
156     p.add(Box.createRigidArea(new Dimension(5, 0)));
157     p.add(cbPorts);
158     p.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
159     portsPane.add(p);
160    
161     p = new JPanel();
162     p.setLayout(new BorderLayout());
163     p.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
164 iliev 911
165     sp = new JScrollPane(portParamTable);
166     d = new Dimension(sp.getMinimumSize().width, sp.getPreferredSize().height);
167     sp.setPreferredSize(d);
168    
169     p.add(sp);
170 iliev 787 portsPane.add(p);
171    
172     portsPane.setBorder (
173     BorderFactory.createTitledBorder(i18n.getLabel("MidiDevicesPage.ports"))
174     );
175    
176     p = new JPanel();
177     p.setLayout(new BoxLayout(p, BoxLayout.Y_AXIS));
178     p.add(Box.createRigidArea(new Dimension(0, 5)));
179     p.add(portsPane);
180    
181     splitPane.setBottomComponent(p);
182     splitPane.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
183     splitPane.setAlignmentX(JPanel.RIGHT_ALIGNMENT);
184     splitPane.setDividerSize(3);
185 iliev 1143 splitPane.setContinuousLayout(true);
186 iliev 787 add(splitPane);
187    
188     splitPane.setDividerLocation(150);
189    
190     cbPorts.addActionListener(getHandler());
191    
192     devicesTable.getSelectionModel().addListSelectionListener(getHandler());
193     portParamTable.getModel().addParameterListener(getHandler());
194     }
195    
196     private MidiDeviceModel
197     getSelectedMidiDeviceModel() {
198     ListSelectionModel lsm = devicesTable.getSelectionModel();
199     if(lsm.isSelectionEmpty()) return null;
200    
201     return ((MidiDevicesTableModel)devicesTable.getModel()).getMidiDeviceModel (
202     lsm.getMinSelectionIndex()
203     );
204     }
205    
206     private final Handler handler = new Handler();
207    
208     private Handler
209     getHandler() { return handler; }
210    
211     private class Handler implements ActionListener, ListSelectionListener,
212     MidiDeviceListener, ParameterListener {
213     public void
214     actionPerformed(ActionEvent e) {
215     Object obj = cbPorts.getSelectedItem();
216     if(obj == null) {
217     portParamTable.getModel().setParameters(new Parameter[0]);
218     return;
219     }
220    
221     MidiPort port = (MidiPort)obj;
222    
223     portParamTable.getModel().setParameters(port.getAllParameters());
224     }
225    
226     public void
227     valueChanged(ListSelectionEvent e) {
228     if(e.getValueIsAdjusting()) return;
229    
230 iliev 1204 for(MidiDeviceModel m : CC.getSamplerModel().getMidiDevices()) {
231 iliev 787 m.removeMidiDeviceListener(this);
232     }
233    
234     ListSelectionModel lsm = (ListSelectionModel)e.getSource();
235    
236     if(lsm.isSelectionEmpty()) {
237     duplicateMidiDevice.setEnabled(false);
238     removeMidiDevice.setEnabled(false);
239     midiDeviceProps.setEnabled(false);
240    
241     cbPorts.removeAllItems();
242     cbPorts.setEnabled(false);
243     return;
244     }
245    
246     duplicateMidiDevice.setEnabled(true);
247     removeMidiDevice.setEnabled(true);
248     midiDeviceProps.setEnabled(true);
249    
250     MidiDeviceModel m;
251     m = ((MidiDevicesTableModel)devicesTable.getModel()).getMidiDeviceModel (
252     lsm.getMinSelectionIndex()
253     );
254    
255     cbPorts.removeAllItems();
256     for(MidiPort port : m.getDeviceInfo().getMidiPorts()) cbPorts.addItem(port);
257     cbPorts.setEnabled(true);
258    
259     m.addMidiDeviceListener(this);
260     }
261    
262     /** Invoked when when the settings of a particular MIDI device have changed. */
263     public void
264     settingsChanged(MidiDeviceEvent e) {
265     MidiInputDevice d = e.getMidiDeviceModel().getDeviceInfo();
266    
267     int idx = cbPorts.getSelectedIndex();
268     cbPorts.removeAllItems();
269     for(MidiPort port : d.getMidiPorts()) cbPorts.addItem(port);
270    
271     if(idx >= cbPorts.getModel().getSize()) idx = 0;
272    
273     if(cbPorts.getModel().getSize() > 0) cbPorts.setSelectedIndex(idx);
274     }
275    
276     /** Invoked when when the value of a particular parameter is changed. */
277     public void
278     parameterChanged(ParameterEvent e) {
279     MidiDeviceModel m = getSelectedMidiDeviceModel();
280     if(m == null) {
281     CC.getLogger().warning("Unexpected null MidiDeviceModel!");
282     return;
283     }
284    
285     int port = cbPorts.getSelectedIndex();
286     if(port == -1) {
287     CC.getLogger().warning("There is no MIDI port selected!");
288     return;
289     }
290    
291 iliev 1143 m.setBackendPortParameter(port, e.getParameter());
292 iliev 787 }
293     }
294    
295     private class DuplicateMidiDevice extends AbstractAction {
296     DuplicateMidiDevice() {
297     super("");
298    
299     putValue(SHORT_DESCRIPTION, i18n.getMenuLabel("ttDuplicateMidiDevice"));
300 iliev 911 putValue(Action.SMALL_ICON, Res.iconCopy16);
301 iliev 787
302     setEnabled(false);
303     }
304    
305     public void
306     actionPerformed(ActionEvent e) {
307 iliev 842 int i = devicesTable.getSelectedRow();
308     if(i < 0) {
309     CC.getLogger().info("There's no selected MIDI device to duplicate");
310     return;
311     }
312     MidiDeviceModel m;
313     m = ((MidiDevicesTableModel)devicesTable.getModel()).getMidiDeviceModel(i);
314     String d = m.getDeviceInfo().getDriverName();
315     Parameter[] pS = m.getDeviceInfo().getAdditionalParameters();
316 iliev 1143 CC.getSamplerModel().addBackendMidiDevice(d, pS);
317 iliev 787 }
318     }
319    
320     private class RemoveMidiDevice extends AbstractAction {
321     RemoveMidiDevice() {
322     super("");
323    
324     putValue(SHORT_DESCRIPTION, i18n.getMenuLabel("ttRemoveMidiDevice"));
325 iliev 911 putValue(Action.SMALL_ICON, Res.iconDelete16);
326 iliev 787
327     setEnabled(false);
328     }
329    
330     public void
331     actionPerformed(ActionEvent e) {
332     MidiDeviceModel m = getSelectedMidiDeviceModel();
333     if(m == null) {
334     CC.getLogger().warning("No selected MIDI device to remove!");
335     return;
336     }
337    
338 iliev 1143 CC.getSamplerModel().removeBackendMidiDevice(m.getDeviceId());
339 iliev 787 }
340     }
341    
342     private class MidiDeviceProps extends AbstractAction {
343     MidiDeviceProps() {
344     super("");
345    
346     putValue(SHORT_DESCRIPTION, i18n.getMenuLabel("ttMidiDeviceProps"));
347 iliev 911 putValue(Action.SMALL_ICON, Res.iconProps16);
348 iliev 787
349     setEnabled(false);
350     }
351    
352     public void
353     actionPerformed(ActionEvent e) { new DevicePropsDlg().setVisible(true); }
354     }
355    
356     private class DevicePropsDlg extends InformationDialog {
357     DevicePropsDlg() {
358 iliev 2288 super(SHF.getMainFrame(), i18n.getLabel("MidiDevicesPage.DevicePropsDlg"));
359 iliev 787
360     MidiDeviceModel m = getSelectedMidiDeviceModel();
361     ParameterTable table = new ParameterTable();
362     table.getModel().setParameters (
363     m.getDeviceInfo().getAdditionalParameters()
364     );
365    
366     JScrollPane sp = new JScrollPane(table);
367     sp.setPreferredSize(JuifeUtils.getUnionSize (
368     sp.getMinimumSize(), new Dimension(200, 200)
369     ));
370     setMainPane(sp);
371     }
372     }
373     }
374    
375     class MidiDevicesTableModel extends AbstractTableModel {
376     protected final static int ACTIVE_COLUMN_INDEX = 0;
377     protected final static int DEVICE_ID_COLUMN_INDEX = 1;
378     protected final static int PORTS_COLUMN_INDEX = 2;
379    
380     private final String[] columnNames = {
381     "",
382     i18n.getLabel("MidiDevicesTableModel.deviceID"),
383     i18n.getLabel("MidiDevicesTableModel.ports")
384     };
385    
386     private MidiDeviceModel[] deviceList;
387    
388     MidiDevicesTableModel() {
389     CC.getSamplerModel().addMidiDeviceListListener(getHandler());
390 iliev 1204 deviceList = CC.getSamplerModel().getMidiDevices();
391 iliev 787 for(MidiDeviceModel m : deviceList) m.addMidiDeviceListener(getHandler());
392     }
393    
394     public MidiDeviceModel
395     getMidiDeviceModel(int index) { return deviceList[index]; }
396    
397     // The Table Model implementation
398    
399     /**
400     * Gets the number of columns in the model.
401     * @return The number of columns in the model.
402     */
403     public int
404     getColumnCount() { return columnNames.length; }
405    
406     /**
407     * Gets the number of rows in the model.
408     * @return The number of rows in the model.
409     */
410     public int
411     getRowCount() { return deviceList.length; }
412    
413     /**
414     * Gets the name of the column at <code>columnIndex</code>.
415     * @return The name of the column at <code>columnIndex</code>.
416     */
417     public String
418     getColumnName(int col) { return columnNames[col]; }
419    
420     /**
421     * Gets the value for the cell at <code>columnIndex</code> and
422     * <code>rowIndex</code>.
423     * @param row The row whose value is to be queried.
424     * @param col The column whose value is to be queried.
425     * @return The value for the cell at <code>columnIndex</code> and
426     * <code>rowIndex</code>.
427     */
428     public Object
429     getValueAt(int row, int col) {
430     switch(col) {
431     case ACTIVE_COLUMN_INDEX:
432     return deviceList[row].getDeviceInfo().isActive();
433     case DEVICE_ID_COLUMN_INDEX:
434 iliev 1143 return deviceList[row].getDeviceId();
435 iliev 787 case PORTS_COLUMN_INDEX:
436     return deviceList[row].getDeviceInfo().getMidiPortCount();
437     }
438    
439     return null;
440     }
441    
442     /**
443     * Sets the value in the cell at <code>columnIndex</code>
444     * and <code>rowIndex</code> to <code>value</code>.
445     */
446     public void
447     setValueAt(Object value, int row, int col) {
448     switch(col) {
449     case ACTIVE_COLUMN_INDEX:
450     boolean active = (Boolean)value;
451     deviceList[row].getDeviceInfo().setActive(active);
452 iliev 1143 deviceList[row].setBackendActive(active);
453 iliev 787 break;
454     case PORTS_COLUMN_INDEX:
455     int ports = (Integer)value;
456 iliev 1143 getMidiDeviceModel(row).setBackendPortCount(ports);
457 iliev 787 break;
458     default: return;
459     }
460    
461     fireTableCellUpdated(row, col);
462     }
463    
464     /**
465     * Returns <code>true</code> if the cell at
466     * <code>rowIndex</code> and <code>columnIndex</code> is editable.
467     */
468     public boolean
469     isCellEditable(int row, int col) {
470     switch(col) {
471     case ACTIVE_COLUMN_INDEX:
472     return true;
473     case DEVICE_ID_COLUMN_INDEX:
474     return false;
475     case PORTS_COLUMN_INDEX:
476     return true;
477     default: return false;
478     }
479     }
480    
481     /**
482     * Returns the most specific superclass for all the cell values
483     * in the column. This is used by the <code>JTable</code> to set up a
484     * default renderer and editor for the column.
485     * @param columnIndex The index of the column.
486     * @return The common ancestor class of the object values in the model.
487     */
488     public Class
489     getColumnClass(int columnIndex) {
490     return getValueAt(0, columnIndex).getClass();
491     }
492     ///////
493    
494     private final Handler handler = new Handler();
495    
496     private Handler
497     getHandler() { return handler; }
498    
499     private class Handler implements MidiDeviceListener, MidiDeviceListListener {
500     /**
501     * Invoked when a new MIDI device is created.
502     * @param e A <code>MidiDeviceListEvent</code>
503     * instance providing the event information.
504     */
505     public void
506     deviceAdded(MidiDeviceListEvent e) {
507     for(MidiDeviceModel m : deviceList) m.removeMidiDeviceListener(this);
508 iliev 1204 deviceList = CC.getSamplerModel().getMidiDevices();
509 iliev 787 for(MidiDeviceModel m : deviceList) m.addMidiDeviceListener(this);
510     fireTableDataChanged();
511     }
512    
513     /**
514     * Invoked when a MIDI device is removed.
515     * @param e A <code>MidiDeviceListEvent</code>
516     * instance providing the event information.
517     */
518     public void
519     deviceRemoved(MidiDeviceListEvent e) {
520     for(MidiDeviceModel m : deviceList) m.removeMidiDeviceListener(this);
521 iliev 1204 deviceList = CC.getSamplerModel().getMidiDevices();
522 iliev 787 for(MidiDeviceModel m : deviceList) m.addMidiDeviceListener(this);
523     fireTableDataChanged();
524     }
525    
526     /** Invoked when when the settings of a particular MIDI device have changed. */
527     public void
528     settingsChanged(MidiDeviceEvent e) {
529     MidiInputDevice d = e.getMidiDeviceModel().getDeviceInfo();
530    
531     for(int i = 0; i < deviceList.length; i++) {
532     MidiInputDevice d2 = deviceList[i].getDeviceInfo();
533    
534 iliev 1143 if(d.getDeviceId() == d2.getDeviceId()) {
535 iliev 787 fireTableRowsUpdated(i, i);
536     }
537     }
538     }
539     }
540     }

  ViewVC Help
Powered by ViewVC