/[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 842 - (show annotations) (download)
Thu Mar 16 18:08:34 2006 UTC (18 years, 1 month ago) by iliev
File size: 16880 byte(s)
Updating to version 0.2a

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

  ViewVC Help
Powered by ViewVC