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

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

  ViewVC Help
Powered by ViewVC