/[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 787 - (show annotations) (download)
Mon Oct 10 16:03:12 2005 UTC (18 years, 6 months ago) by iliev
File size: 16814 byte(s)
* The first alpha-release of JSampler

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

  ViewVC Help
Powered by ViewVC