/[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 1445 - (show annotations) (download)
Mon Oct 15 20:55:33 2007 UTC (16 years, 6 months ago) by iliev
File size: 13947 byte(s)
* preparations for release 0.7a

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

  ViewVC Help
Powered by ViewVC