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

Contents of /jsampler/trunk/src/org/jsampler/view/classic/MidiDevicesPage.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: 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 /*
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.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 import net.sf.juife.swing.InformationDialog;
52 import net.sf.juife.swing.JuifeUtils;
53 import net.sf.juife.swing.NavigationPage;
54
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 import org.jsampler.view.swing.NumberCellEditor;
66 import org.jsampler.view.swing.ParameterTable;
67 import org.jsampler.view.swing.SHF;
68
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 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 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 Dimension d;
138 d = new Dimension(sp.getMinimumSize().width, sp.getPreferredSize().height);
139 sp.setPreferredSize(d);
140
141 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
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 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 splitPane.setContinuousLayout(true);
186 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 for(MidiDeviceModel m : CC.getSamplerModel().getMidiDevices()) {
231 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 m.setBackendPortParameter(port, e.getParameter());
292 }
293 }
294
295 private class DuplicateMidiDevice extends AbstractAction {
296 DuplicateMidiDevice() {
297 super("");
298
299 putValue(SHORT_DESCRIPTION, i18n.getMenuLabel("ttDuplicateMidiDevice"));
300 putValue(Action.SMALL_ICON, Res.iconCopy16);
301
302 setEnabled(false);
303 }
304
305 public void
306 actionPerformed(ActionEvent e) {
307 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 CC.getSamplerModel().addBackendMidiDevice(d, pS);
317 }
318 }
319
320 private class RemoveMidiDevice extends AbstractAction {
321 RemoveMidiDevice() {
322 super("");
323
324 putValue(SHORT_DESCRIPTION, i18n.getMenuLabel("ttRemoveMidiDevice"));
325 putValue(Action.SMALL_ICON, Res.iconDelete16);
326
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 CC.getSamplerModel().removeBackendMidiDevice(m.getDeviceId());
339 }
340 }
341
342 private class MidiDeviceProps extends AbstractAction {
343 MidiDeviceProps() {
344 super("");
345
346 putValue(SHORT_DESCRIPTION, i18n.getMenuLabel("ttMidiDeviceProps"));
347 putValue(Action.SMALL_ICON, Res.iconProps16);
348
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 super(SHF.getMainFrame(), i18n.getLabel("MidiDevicesPage.DevicePropsDlg"));
359
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 deviceList = CC.getSamplerModel().getMidiDevices();
391 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 return deviceList[row].getDeviceId();
435 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 deviceList[row].setBackendActive(active);
453 break;
454 case PORTS_COLUMN_INDEX:
455 int ports = (Integer)value;
456 getMidiDeviceModel(row).setBackendPortCount(ports);
457 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 deviceList = CC.getSamplerModel().getMidiDevices();
509 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 deviceList = CC.getSamplerModel().getMidiDevices();
522 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 if(d.getDeviceId() == d2.getDeviceId()) {
535 fireTableRowsUpdated(i, i);
536 }
537 }
538 }
539 }
540 }

  ViewVC Help
Powered by ViewVC