/[svn]/jsampler/trunk/src/org/jsampler/view/std/JSFxSendsPane.java
ViewVC logotype

Contents of /jsampler/trunk/src/org/jsampler/view/std/JSFxSendsPane.java

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1540 - (show annotations) (download)
Mon Dec 3 23:22:02 2007 UTC (16 years, 3 months ago) by iliev
File size: 12952 byte(s)
* Fantasia: by default the volume values are now shown in decibels
* Implemented support for retrieving instrument information
  from instrument files
* Some bugfixes and enhancements

1 /*
2 * JSampler - a java front-end for LinuxSampler
3 *
4 * Copyright (C) 2005-2007 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.std;
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.DefaultCellEditor;
37 import javax.swing.JButton;
38 import javax.swing.JComboBox;
39 import javax.swing.JLabel;
40 import javax.swing.JPanel;
41 import javax.swing.JScrollPane;
42 import javax.swing.JSlider;
43 import javax.swing.JSplitPane;
44 import javax.swing.JTable;
45 import javax.swing.JToolBar;
46
47 import javax.swing.event.ChangeEvent;
48 import javax.swing.event.ChangeListener;
49 import javax.swing.event.ListSelectionEvent;
50 import javax.swing.event.ListSelectionListener;
51
52 import javax.swing.table.AbstractTableModel;
53 import javax.swing.table.TableColumn;
54 import javax.swing.table.JTableHeader;
55
56 import net.sf.juife.event.TaskEvent;
57 import net.sf.juife.event.TaskListener;
58
59 import org.jsampler.AudioDeviceModel;
60 import org.jsampler.CC;
61 import org.jsampler.HF;
62 import org.jsampler.JSPrefs;
63 import org.jsampler.SamplerChannelModel;
64
65 import org.jsampler.event.EffectSendsAdapter;
66 import org.jsampler.event.EffectSendsEvent;
67 import org.jsampler.event.EffectSendsListener;
68
69
70 import org.jsampler.task.Channel;
71
72 import org.jsampler.view.FxSendTable;
73
74 import org.linuxsampler.lscp.FxSend;
75
76 import static org.jsampler.view.std.StdI18n.i18n;
77
78
79 /**
80 *
81 * @author Grigor Iliev
82 */
83 public class JSFxSendsPane extends JPanel implements ListSelectionListener {
84 private SamplerChannelModel channelModel;
85 private final FxSendTable fxSendsTable;
86
87 protected final Action actionAddFxSend = new AddFxSendAction();
88 protected final Action actionRemoveFxSend = new RemoveFxSendAction();
89
90 private final JComboBox cbMidiCtrls = new JComboBox();
91 private final JSlider slVolume = StdUtils.createVolumeSlider();
92
93 private final JLabel lMidiCtrl = new JLabel(i18n.getLabel("JSFxSendsPane.lMidiCtrl"));
94 private final JLabel lVolume = new JLabel(i18n.getLabel("JSFxSendsPane.lVolume"));
95
96 private final ChannelRoutingTable channelRoutingTable;
97
98 private FxSend fxSend = null;
99
100 /**
101 * Creates a new instance of <code>JSFxSendsPane</code>.
102 *
103 * @throws IllegalArgumentException If <code>model</code> is <code>null</code>.
104 */
105 public
106 JSFxSendsPane(SamplerChannelModel model) {
107 if(model == null)
108 throw new IllegalArgumentException("model should be non-null!");
109
110 channelModel = model;
111 fxSendsTable = new FxSendTable(channelModel);
112 channelRoutingTable = new ChannelRoutingTable();
113
114 setLayout(new BorderLayout());
115
116
117
118 JPanel rightPane = createRightPane();
119
120
121 JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
122 splitPane.setLeftComponent(createLeftPane());
123 splitPane.setRightComponent(rightPane);
124 splitPane.setContinuousLayout(true);
125 add(splitPane);
126
127 channelModel.addEffectSendsListener(getHandler());
128
129 fxSendsTable.getSelectionModel().addListSelectionListener(this);
130
131 if(channelModel.getChannelInfo().getEngine() == null) {
132 actionAddFxSend.setEnabled(false);
133 }
134 if(channelModel.getFxSendCount() == 0) {
135 actionRemoveFxSend.setEnabled(false);
136 } else {
137 fxSendsTable.setSelectedFxSend(channelModel.getFxSend(0));
138 }
139 updateFxSend();
140
141 Dimension d = getMinimumSize();
142 int w = d.width > 500 ? d.width : 500;
143 int h = d.height > 300 ? d.height : 300;
144 setPreferredSize(new Dimension(w, h));
145 splitPane.setDividerLocation(200);
146 }
147
148 protected JSPrefs
149 preferences() { return CC.getViewConfig().preferences(); }
150
151 protected JToolBar
152 createToolBar() {
153 JToolBar tb = new JToolBar();
154 tb.setMaximumSize(new Dimension(Short.MAX_VALUE, tb.getPreferredSize().height));
155 tb.setFloatable(false);
156 tb.setAlignmentX(JPanel.RIGHT_ALIGNMENT);
157
158 tb.add(new JButton(actionAddFxSend));
159 tb.add(new JButton(actionRemoveFxSend));
160
161 return tb;
162 }
163
164 protected JPanel
165 createLeftPane() {
166 JPanel leftPane = new JPanel();
167 leftPane.setLayout(new BorderLayout());
168
169 leftPane.add(createToolBar(), BorderLayout.NORTH);
170 leftPane.add(new JScrollPane(fxSendsTable));
171
172 return leftPane;
173 }
174
175 protected JPanel
176 createRightPane() {
177 for(int i = 0; i < 128; i++) cbMidiCtrls.addItem(new Integer(i));
178
179 cbMidiCtrls.addActionListener(new ActionListener() {
180 public void
181 actionPerformed(ActionEvent e) {
182 if(fxSend == null) return;
183
184 int fxs = fxSend.getFxSendId();
185 int ctrl = cbMidiCtrls.getSelectedIndex();
186
187 if(ctrl == fxSend.getMidiController()) {
188 return;
189 }
190
191 channelModel.setBackendFxSendMidiController(fxs, ctrl);
192 }
193 });
194
195 slVolume.addChangeListener(new ChangeListener() {
196 public void
197 stateChanged(ChangeEvent e) { setVolume(); }
198 });
199
200 JPanel rightPane = new JPanel();
201 rightPane.setLayout(new BorderLayout());
202
203 JPanel p = new JPanel();
204 p.setLayout(new BoxLayout(p, BoxLayout.Y_AXIS));
205
206 JPanel p2 = new JPanel();
207 p2.setLayout(new BoxLayout(p2, BoxLayout.X_AXIS));
208
209 p2.add(lVolume);
210 p2.add(Box.createRigidArea(new Dimension(6, 0)));
211 slVolume.setMinimumSize(slVolume.getPreferredSize());
212 p2.add(slVolume);
213 p2.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
214 p.add(p2);
215
216 p2 = new JPanel();
217
218 p2.setLayout(new BoxLayout(p2, BoxLayout.X_AXIS));
219 p2.add(lMidiCtrl);
220 p2.add(Box.createRigidArea(new Dimension(6, 0)));
221 p2.add(cbMidiCtrls);
222 p2.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
223 //p2.setAlignmentX(LEFT_ALIGNMENT);
224 p.add(p2);
225
226 rightPane.add(p, BorderLayout.NORTH);
227 rightPane.add(new JScrollPane(channelRoutingTable));
228
229 return rightPane;
230 }
231
232 private void
233 setVolume() {
234 if(fxSend == null || slVolume.getValueIsAdjusting()) return;
235
236 int i = (int)(fxSend.getLevel() * 100);
237 if(slVolume.getValue() == i) return;
238
239 float vol = slVolume.getValue();
240 vol /= 100;
241 channelModel.setBackendFxSendLevel(fxSend.getFxSendId(), vol);
242 }
243
244 public void
245 valueChanged(ListSelectionEvent e) {
246 if(e.getValueIsAdjusting()) return;
247
248 fxSend = fxSendsTable.getSelectedFxSend();
249 actionRemoveFxSend.setEnabled(fxSend != null);
250 updateFxSend();
251 }
252
253 private void
254 updateFxSend() {
255 boolean b = (fxSend != null);
256 cbMidiCtrls.setEnabled(b);
257 slVolume.setEnabled(b);
258 channelRoutingTable.setEnabled(b);
259 if(!b) {
260 slVolume.setValue(0);
261 cbMidiCtrls.setSelectedIndex(0);
262 return;
263 }
264
265 cbMidiCtrls.setSelectedIndex(fxSend.getMidiController());
266 slVolume.setValue((int)(fxSend.getLevel() * 100));
267 }
268
269 class AddFxSendAction extends AbstractAction {
270 private int fxSendId = -1;
271
272 AddFxSendAction() {
273 super(i18n.getLabel("JSFxSendsPane.AddFxSendAction"));
274
275 String s = i18n.getLabel("JSFxSendsPane.AddFxSendAction.tt");
276 putValue(SHORT_DESCRIPTION, s);
277 }
278
279 public void
280 actionPerformed(ActionEvent e) {
281 int id = channelModel.getChannelId();
282 final Channel.AddFxSend t = new Channel.AddFxSend(id, 0, "New effect send");
283
284 t.addTaskListener(new TaskListener() {
285 public void
286 taskPerformed(TaskEvent e) {
287 if(t.doneWithErrors()) {
288 fxSendId = -1;
289 return;
290 }
291 setFxSendId(t.getResult());
292 }
293 });
294 CC.getTaskQueue().add(t);
295 }
296
297 public int
298 getFxSendId() { return fxSendId; }
299
300 public void
301 setFxSendId(int id) { fxSendId = id; }
302 }
303
304 class RemoveFxSendAction extends AbstractAction {
305 RemoveFxSendAction() {
306 super(i18n.getLabel("JSFxSendsPane.RemoveFxSendAction"));
307
308 String s = i18n.getLabel("JSFxSendsPane.RemoveFxSendAction.tt");
309 putValue(SHORT_DESCRIPTION, s);
310 }
311
312 public void
313 actionPerformed(ActionEvent e) {
314 FxSend fxs = fxSendsTable.getSelectedFxSend();
315 if(fxs == null) return;
316 channelModel.removeBackendFxSend(fxs.getFxSendId());
317 }
318 }
319
320 class ChannelRoutingTable extends JTable {
321 private String[] columnToolTips = {
322 i18n.getLabel("JSFxSendsPane.ttAudioSrc"),
323 i18n.getLabel("JSFxSendsPane.ttAudioDst"),
324 };
325
326 ChannelRoutingTable() {
327 super(new ChannelRoutingTableModel());
328
329 JComboBox cb = new JComboBox();
330 int devId = channelModel.getChannelInfo().getAudioOutputDevice();
331 AudioDeviceModel adm = CC.getSamplerModel().getAudioDeviceById(devId);
332
333 int chns;
334 if(adm == null) {
335 chns = channelModel.getChannelInfo().getAudioOutputChannels();
336 } else {
337 chns = adm.getDeviceInfo().getAudioChannelCount();
338 }
339
340 for(Integer i = 0; i < chns; i++) cb.addItem(i);
341
342 TableColumn column = getColumnModel().getColumn(1);
343 column.setCellEditor(new DefaultCellEditor(cb));
344 }
345
346 protected JTableHeader
347 createDefaultTableHeader() {
348 return new JTableHeader(columnModel) {
349 public String getToolTipText(java.awt.event.MouseEvent e) {
350 java.awt.Point p = e.getPoint();
351 int i = columnModel.getColumnIndexAtX(p.x);
352 i = columnModel.getColumn(i).getModelIndex();
353 return columnToolTips[i];
354 }
355 };
356 }
357 }
358
359 class ChannelRoutingTableModel extends AbstractTableModel implements ListSelectionListener {
360 private String[] columnNames = {
361 i18n.getLabel("JSFxSendsPane.audioSrc"),
362 i18n.getLabel("JSFxSendsPane.audioDst")
363 };
364
365 ChannelRoutingTableModel() {
366 channelModel.addEffectSendsListener(new EffectSendsAdapter() {
367 /** Invoked when an effect send's setting are changed. */
368 public void
369 effectSendChanged(EffectSendsEvent e) {
370 if(fxSend == null) {
371 fireTableDataChanged();
372 return;
373 }
374
375 if(fxSend.equals(e.getFxSend())) {
376 int l;
377 l = e.getFxSend().getAudioOutputRouting().length;
378 fireTableRowsUpdated(0, l - 1);
379 }
380 }
381 });
382
383 fxSendsTable.getSelectionModel().addListSelectionListener(this);
384 }
385
386 public int
387 getColumnCount() { return columnNames.length; }
388
389 public String
390 getColumnName(int column) { return columnNames[column]; }
391
392 public int
393 getRowCount() {
394 if(fxSend == null) return 0;
395 return fxSend.getAudioOutputRouting().length;
396 }
397
398 public Object
399 getValueAt(int row, int column) {
400 switch(column) {
401 case 0:
402 return row;
403 case 1:
404 return fxSend.getAudioOutputRouting()[row];
405 default: return null;
406 }
407
408 }
409
410 public boolean
411 isCellEditable(int row, int column) {
412 switch(column) {
413 case 0:
414 return false;
415 case 1:
416 return true;
417 default: return false;
418 }
419 }
420
421 public void
422 setValueAt(Object value, int row, int column) {
423 if(column == 0) return;
424 int id = fxSend.getFxSendId();
425 int src = (Integer)getValueAt(row, 0);
426 int dst = (Integer)value;
427 channelModel.setBackendFxSendAudioOutputChannel(id, src, dst);
428 fxSend.getAudioOutputRouting()[row] = dst;
429
430 fireTableCellUpdated(row, column);
431 }
432
433 public void
434 valueChanged(ListSelectionEvent e) {
435 if(e.getValueIsAdjusting()) return;
436
437 fireTableDataChanged();
438 }
439 }
440
441 private final Handler eventHandler = new Handler();
442
443 private Handler
444 getHandler() { return eventHandler; }
445
446 private class Handler implements EffectSendsListener {
447 /** Invoked when a new effect send is added to a sampler channel. */
448 public void
449 effectSendAdded(EffectSendsEvent e) {
450 FxSend fxs = fxSendsTable.getSelectedFxSend();
451 if(fxs == null) return;
452 AddFxSendAction a = (AddFxSendAction)actionAddFxSend;
453 if(fxs.getFxSendId() != a.getFxSendId()) return;
454
455 fxSendsTable.requestFocus();
456 fxSendsTable.editSelectedFxSend();
457 a.setFxSendId(-1);
458 }
459
460 /** Invoked when an effect send is removed from a sampler channel. */
461 public void
462 effectSendRemoved(EffectSendsEvent e) {
463 if(channelModel.getFxSendCount() == 0) return;
464 int id = e.getFxSend().getFxSendId();
465 for(FxSend fxs : channelModel.getFxSends()) {
466 if(fxs.getFxSendId() > id) {
467 fxSendsTable.setSelectedFxSend(fxs);
468 return;
469 }
470 }
471 FxSend fxs = channelModel.getFxSend(channelModel.getFxSendCount() - 1);
472 fxSendsTable.setSelectedFxSend(fxs);
473 }
474
475 /** Invoked when an effect send's setting are changed. */
476 public void
477 effectSendChanged(EffectSendsEvent e) {
478 if(fxSend == null) return;
479 if(fxSend.equals(e.getFxSend())) {
480 fxSend = e.getFxSend();
481 updateFxSend();
482 }
483 }
484 }
485 }

  ViewVC Help
Powered by ViewVC