/[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 1204 - (show annotations) (download)
Thu May 24 21:43:45 2007 UTC (16 years, 11 months ago) by iliev
File size: 16929 byte(s)
upgrading to version 0.5a

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

  ViewVC Help
Powered by ViewVC