/[svn]/jsampler/trunk/src/org/jsampler/view/fantasia/PianoKeyboardPane.java
ViewVC logotype

Contents of /jsampler/trunk/src/org/jsampler/view/fantasia/PianoKeyboardPane.java

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1818 - (show annotations) (download)
Wed Dec 24 17:29:47 2008 UTC (15 years, 3 months ago) by iliev
File size: 16589 byte(s)
* Added support for controlling the global sampler-wide limit of
  maximum voices and disk streams
  (choose Edit/Preferences, then click the `General' tab)
* Fantasia: store the view configuration of audio/MIDI devices and sampler
  channels in the LSCP script when exporting sampler configuration
* Fantasia: Implemented multiple sampler channels' selection
* Fantasia: Added option to move sampler channels up and down
  in the channels list
* Fantasia: Added option to move sampler channels
  to another channels panels

1 /*
2 * JSampler - a java front-end for LinuxSampler
3 *
4 * Copyright (C) 2005-2008 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.fantasia;
24
25 import java.awt.AlphaComposite;
26 import java.awt.Color;
27 import java.awt.Composite;
28 import java.awt.Dimension;
29 import java.awt.GradientPaint;
30 import java.awt.Graphics;
31 import java.awt.Graphics2D;
32 import java.awt.GridBagConstraints;
33 import java.awt.GridBagLayout;
34 import java.awt.Insets;
35 import java.awt.Paint;
36 import java.awt.RenderingHints;
37
38 import java.awt.event.ActionEvent;
39 import java.awt.event.ActionListener;
40 import java.awt.event.FocusEvent;
41 import java.awt.event.FocusListener;
42 import java.awt.event.MouseEvent;
43 import java.awt.event.MouseAdapter;
44
45 import java.awt.geom.Line2D;
46 import java.awt.geom.Rectangle2D;
47
48 import java.beans.PropertyChangeEvent;
49 import java.beans.PropertyChangeListener;
50
51 import javax.swing.BorderFactory;
52 import javax.swing.Box;
53 import javax.swing.BoxLayout;
54 import javax.swing.ImageIcon;
55 import javax.swing.JButton;
56 import javax.swing.JPanel;
57 import javax.swing.JToggleButton;
58
59 import javax.swing.event.ListSelectionEvent;
60 import javax.swing.event.ListSelectionListener;
61
62 import net.sf.juife.event.TaskEvent;
63 import net.sf.juife.event.TaskListener;
64
65 import org.jsampler.CC;
66 import org.jsampler.SamplerChannelModel;
67
68 import org.jsampler.event.SamplerChannelAdapter;
69 import org.jsampler.event.SamplerChannelEvent;
70 import org.jsampler.event.SamplerChannelListListener;
71 import org.jsampler.event.SamplerChannelListEvent;
72
73 import org.jsampler.view.JSChannel;
74 import org.jsampler.view.fantasia.basic.*;
75 import org.jsampler.view.std.JSPianoRoll;
76
77 import org.linuxsampler.lscp.Instrument;
78 import org.linuxsampler.lscp.SamplerChannel;
79
80 import org.linuxsampler.lscp.event.MidiDataEvent;
81 import org.linuxsampler.lscp.event.MidiDataListener;
82
83 import static javax.swing.Action.SMALL_ICON;
84 import static org.jsampler.task.Global.GetFileInstrument;
85 import static org.jsampler.view.fantasia.FantasiaI18n.i18n;
86
87 /**
88 *
89 * @author Grigor Iliev
90 */
91 public class PianoKeyboardPane extends FantasiaPanel
92 implements ListSelectionListener, SamplerChannelListListener {
93
94 protected final JToggleButton btnPower = new PowerButton();
95 private final FantasiaLabel lDisplay = new FantasiaLabel(" ", true);
96 //private final PitchWheel pitchWheel = new PitchWheel();
97 //private final ModWheel modWheel = new ModWheel();
98 private final JSPianoRoll pianoRoll = new JSPianoRoll();
99 private SamplerChannelModel channel = null;
100
101 private String file = null;
102 private int index = -1;
103
104 public
105 PianoKeyboardPane() {
106 pianoRoll.actionDecreaseKeyNumber.putValue(SMALL_ICON, Res.gfxBtnDecrease);
107 pianoRoll.actionIncreaseKeyNumber.putValue(SMALL_ICON, Res.gfxBtnIncrease);
108 pianoRoll.actionScrollLeft.putValue(SMALL_ICON, Res.gfxBtnScrollLeft);
109 pianoRoll.actionScrollRight.putValue(SMALL_ICON, Res.gfxBtnScrollRight);
110
111 setOpaque(false);
112
113 GridBagLayout gridbag = new GridBagLayout();
114 GridBagConstraints c = new GridBagConstraints();
115
116 setLayout(gridbag);
117
118 setBorder(BorderFactory.createEmptyBorder(0, 3, 5, 3));
119
120 c.fill = GridBagConstraints.NONE;
121
122 c.gridx = 0;
123 c.gridy = 0;
124 c.anchor = GridBagConstraints.NORTHWEST;
125 c.insets = new Insets(3, 3, 3, 3);
126 gridbag.setConstraints(btnPower, c);
127 add(btnPower);
128
129 JPanel p = createVSeparator();
130 c.gridx = 1;
131 c.gridy = 0;
132 c.gridheight = 2;
133 c.insets = new Insets(3, 0, 5, 3);
134 c.fill = GridBagConstraints.VERTICAL;
135 c.weighty = 1.0;
136 gridbag.setConstraints(p, c);
137 add(p);
138
139 /*c.gridx = 2;
140 c.gridy = 1;
141 c.gridheight = 1;
142 c.insets = new Insets(0, 3, 5, 3);
143 c.anchor = GridBagConstraints.CENTER;
144 gridbag.setConstraints(pitchWheel, c);
145 add(pitchWheel);
146
147 c.gridx = 3;
148 c.gridy = 1;
149 c.insets = new Insets(0, 0, 5, 6);
150 gridbag.setConstraints(modWheel, c);
151 add(modWheel);*/
152
153 p = new KeyRangePropsPane();
154
155 c.gridx = 2;
156 c.gridy = 0;
157 c.gridwidth = 3;
158 c.gridheight = 1;
159 c.insets = new Insets(0, 0, 0, 0);
160 c.fill = GridBagConstraints.NONE;
161 c.weighty = 0.0;
162 c.anchor = GridBagConstraints.WEST;
163 gridbag.setConstraints(p, c);
164 add(p);
165
166 p = new KeyRangePropsPane();
167
168 c.gridx = 8;
169 c.gridy = 0;
170 c.gridwidth = 1;
171 c.anchor = GridBagConstraints.EAST;
172 c.insets = new Insets(0, 0, 0, 10);
173 gridbag.setConstraints(p, c);
174 add(p);
175
176 lDisplay.setPreferredSize(new Dimension(300, lDisplay.getPreferredSize().height));
177
178 c.gridx = 6;
179 c.gridy = 0;
180 c.insets = new Insets(3, 3, 3, 12);
181 c.fill = GridBagConstraints.NONE;
182 c.weightx = 0.0;
183 gridbag.setConstraints(lDisplay, c);
184 add(lDisplay);
185
186 p = new JPanel();
187 p.setOpaque(false);
188 c.gridx = 5;
189 c.gridy = 0;
190 c.insets = new Insets(0, 0, 0, 0);
191 c.fill = GridBagConstraints.HORIZONTAL;
192 c.weightx = 1.0;
193 gridbag.setConstraints(p, c);
194 add(p);
195
196 p = new JPanel();
197 p.setOpaque(false);
198 c.gridx = 7;
199 c.gridy = 0;
200 gridbag.setConstraints(p, c);
201 add(p);
202
203 pianoRoll.setFocusable(false);
204 pianoRoll.setBackground(new Color(0x2e2e2e));
205 //pianoRoll.setOpaque(false);
206
207 disablePianoRoll();
208
209 c.gridx = 4;
210 c.gridy = 1;
211 c.gridwidth = 5;
212 c.insets = new Insets(0, 3, 0, 12);
213 c.fill = GridBagConstraints.BOTH;
214 c.weightx = 1.0;
215 c.weighty = 1.0;
216 gridbag.setConstraints(pianoRoll, c);
217 add(pianoRoll);
218
219 CC.getSamplerModel().addSamplerChannelListListener(this);
220 pianoRoll.addMidiDataListener(getHandler());
221
222 updateKeyRange();
223
224 PropertyChangeListener l = new PropertyChangeListener() {
225 public void
226 propertyChange(PropertyChangeEvent e) {
227 updateKeyRange();
228 }
229 };
230
231 CC.preferences().addPropertyChangeListener("midiKeyboard.firstKey", l);
232 CC.preferences().addPropertyChangeListener("midiKeyboard.lastKey", l);
233
234 addFocusListener(getHandler());
235
236 MouseAdapter l2 = new MouseAdapter() {
237 public void
238 mouseClicked(MouseEvent e) { requestFocusInWindow(); }
239 };
240
241 addKeyListener(pianoRoll.getKeyListener());
242 pianoRoll.registerKeys(this);
243
244 addMouseListener(l2);
245 pianoRoll.addMouseListener(l2);
246 lDisplay.addMouseListener(l2);
247 }
248
249 public JSPianoRoll
250 getPianoRoll() { return pianoRoll; }
251
252 private void
253 updateKeyRange() {
254 int firstKey = CC.preferences().getIntProperty("midiKeyboard.firstKey");
255 int lastKey = CC.preferences().getIntProperty("midiKeyboard.lastKey");
256 pianoRoll.setKeyRange(firstKey, lastKey);
257 }
258
259 @Override public void
260 valueChanged(ListSelectionEvent e) {
261 if(e.getValueIsAdjusting()) return;
262
263 JSChannel[] chnS = CC.getMainFrame().getSelectedChannelsPane().getSelectedChannels();
264 if(chnS == null || chnS.length == 0) {
265 disconnectChannel();
266 return;
267 }
268
269 if(chnS[0].getModel() == channel) return;
270 disconnectChannel();
271 connectChannel(chnS[0].getModel());
272 }
273
274 private void
275 updateInstrumentInfo() {
276 final GetFileInstrument i = new GetFileInstrument(file, index);
277
278 i.addTaskListener(new TaskListener() {
279 public void
280 taskPerformed(TaskEvent e) {
281 if(i.doneWithErrors()) return;
282 updatePianoKeyboard(i.getResult());
283 }
284 });
285
286 CC.getTaskQueue().add(i);
287 }
288
289 private void
290 disablePianoRoll() {
291 pianoRoll.reset(true);
292 pianoRoll.setPlayingEnabled(false);
293 }
294
295 private void
296 updatePianoKeyboard(Instrument instr) {
297 // The selected channel may have changed before this update
298 // due to concurency, so also checking whether file is null
299 if(instr == null || file == null) {
300 disablePianoRoll();
301 return;
302 }
303
304 pianoRoll.setPlayingEnabled(true);
305
306 pianoRoll.setShouldRepaint(false);
307 pianoRoll.reset(true);
308 pianoRoll.setDisabled(instr.getKeyMapping(), false);
309 pianoRoll.setKeyswitches(instr.getKeyswitchMapping(), true);
310 pianoRoll.setShouldRepaint(true);
311 pianoRoll.repaint();
312 }
313
314 private void
315 connectChannel(SamplerChannelModel chn) {
316 channel = chn;
317 channel.addMidiDataListener(pianoRoll);
318 channel.addSamplerChannelListener(getHandler());
319
320 updateDisplay();
321
322 file = channel.getChannelInfo().getInstrumentFile();
323 if(file == null) {
324 disablePianoRoll();
325 return;
326 }
327 index = channel.getChannelInfo().getInstrumentIndex();
328 updateInstrumentInfo();
329 }
330
331 private void
332 disconnectChannel() {
333 if(channel != null) {
334 channel.removeMidiDataListener(pianoRoll);
335 channel.removeSamplerChannelListener(getHandler());
336 channel = null;
337 file = null;
338 index = -1;
339 disablePianoRoll();
340 }
341
342 updateDisplay();
343 }
344
345 @Override public void
346 channelAdded(SamplerChannelListEvent e) {
347 updateDisplay();
348 }
349
350 @Override public void
351 channelRemoved(SamplerChannelListEvent e) {
352 if(e.getChannelModel() == channel) {
353 disconnectChannel();
354 }
355
356 updateDisplay();
357 }
358
359 private JPanel
360 createVSeparator() {
361 PixmapPane p = new PixmapPane(Res.gfxVLine);
362 p.setAlignmentY(JPanel.TOP_ALIGNMENT);
363 p.setMinimumSize(new Dimension(2, 30));
364 p.setPreferredSize(new Dimension(2, 60));
365 p.setMaximumSize(new Dimension(2, Short.MAX_VALUE));
366 return p;
367 }
368
369 private Color color1 = new Color(0x7a7a7a);
370 private Color color2 = new Color(0x5e5e5e);
371 private Color color3 = new Color(0x2e2e2e);
372
373 @Override
374 public void
375 paintComponent(Graphics g) {
376 Graphics2D g2 = (Graphics2D)g;
377
378 Paint oldPaint = g2.getPaint();
379 Composite oldComposite = g2.getComposite();
380
381 Insets insets = this.getInsets();
382 double x1 = insets.left;
383 double y1 = insets.top;
384
385 double w = getSize().getWidth();
386 double x2 = w - insets.right - 1;
387 double h = getSize().getHeight();
388 double y2 = h - insets.bottom - 1;
389
390 FantasiaPainter.paintGradient(g2, x1, y1, x2, y2 - 10, color1, color2);
391
392 g2.setRenderingHint (
393 RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_OFF
394 );
395
396 double y3 = y2 - 10;
397 if(y3 < 0) y3 = 0;
398
399 Rectangle2D.Double rect = new Rectangle2D.Double(x1, y3, x2 - x1 + 1, 11);
400
401 GradientPaint gr = new GradientPaint (
402 0.0f, (float)y3, color2,
403 0.0f, (float)h, color3
404 );
405
406 g2.setPaint(gr);
407 g2.fill(rect);
408
409 drawOutBorder(g2, x1, y1, x2, y2);
410
411 double prX = pianoRoll.getLocation().getX();
412 double prY = pianoRoll.getLocation().getY();
413 drawInBorder (
414 g2, prX - 2, prY - 2,
415 prX + pianoRoll.getSize().getWidth() + 1, prY + pianoRoll.getSize().getHeight() - 3
416 );
417
418 g2.setPaint(oldPaint);
419 g2.setComposite(oldComposite);
420 }
421
422 private void
423 drawOutBorder(Graphics2D g2, double x1, double y1, double x2, double y2) {
424 AlphaComposite ac = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.40f);
425 g2.setComposite(ac);
426
427 g2.setPaint(Color.WHITE);
428 Line2D.Double l = new Line2D.Double(x1, y1, x2, y1);
429 g2.draw(l);
430
431 g2.setComposite(ac.derive(0.20f));
432 l = new Line2D.Double(x1, y1 + 1, x2, y1 + 1);
433 g2.draw(l);
434
435 g2.setComposite(ac.derive(0.255f));
436
437 l = new Line2D.Double(x1, y1, x1, y2);
438 g2.draw(l);
439
440 g2.setComposite(ac.derive(0.40f));
441 g2.setPaint(Color.BLACK);
442
443 //l = new Line2D.Double(x1, y2, x2, y2);
444 //g2.draw(l);
445
446 g2.setComposite(ac.derive(0.20f));
447
448 l = new Line2D.Double(x2, y1, x2, y2);
449 g2.draw(l);
450 }
451
452 private void
453 drawInBorder(Graphics2D g2, double x1, double y1, double x2, double y2) {
454 AlphaComposite ac = AlphaComposite.getInstance(AlphaComposite.SRC_OVER, 0.40f);
455 g2.setComposite(ac);
456
457 g2.setPaint(Color.WHITE);
458 Line2D.Double l = new Line2D.Double(x1, y2, x2, y2);
459 //g2.draw(l);
460
461 g2.setComposite(ac.derive(0.255f));
462
463 l = new Line2D.Double(x2 - 1, y1 + 1, x2 - 1, y2 + 1);
464 g2.draw(l);
465
466 g2.setComposite(ac.derive(0.13f));
467
468 l = new Line2D.Double(x2, y1, x2, y2);
469 g2.draw(l);
470
471 g2.setComposite(ac.derive(0.20f));
472 g2.setPaint(Color.BLACK);
473
474 l = new Line2D.Double(x1, y1, x2, y1);
475 g2.draw(l);
476
477 g2.setComposite(ac.derive(0.40f));
478 g2.setPaint(Color.BLACK);
479
480 l = new Line2D.Double(x1 + 1, y1 + 1, x2 - 1, y1 + 1);
481 g2.draw(l);
482
483 g2.setComposite(ac.derive(0.20f));
484
485 l = new Line2D.Double(x1, y1, x1, y2);
486 g2.draw(l);
487
488 g2.setComposite(ac.derive(0.40f));
489
490 l = new Line2D.Double(x1 + 1, y1 + 1, x1 + 1, y2 + 1);
491 g2.draw(l);
492 }
493
494 private void
495 updateDisplay() {
496 // TODO: called too often?
497 if(channel == null) {
498 lDisplay.setText(i18n.getLabel("PianoKeyboardPane.noChannel"));
499 return;
500 }
501
502 SamplerChannel sc = channel.getChannelInfo();
503 String s = CC.getMainFrame().getChannelPath(channel);
504
505 StringBuffer sb = new StringBuffer();
506 sb.append(i18n.getLabel("PianoKeyboardPane.channel", s)).append(" - ");
507
508 int status = sc.getInstrumentStatus();
509 if(status >= 0 && status < 100) {
510 sb.append(i18n.getLabel("ChannelScreen.loadingInstrument", status));
511 } else if(status == -1) {
512 sb.append(i18n.getLabel("PianoKeyboardPane.noInstrument"));
513 } else if(status < -1) {
514 sb.append(i18n.getLabel("ChannelScreen.errorLoadingInstrument"));
515 } else {
516 if(sc.getInstrumentName() != null) sb.append(sc.getInstrumentName());
517 }
518
519 lDisplay.setText(sb.toString());
520 }
521
522
523 class KeyRangePropsPane extends JPanel {
524 private final JButton btnIncrease =
525 new PixmapButton(pianoRoll.actionIncreaseKeyNumber, Res.gfxBtnIncrease);
526
527 private final JButton btnDecrease =
528 new PixmapButton(pianoRoll.actionDecreaseKeyNumber, Res.gfxBtnDecrease);
529
530 private final JButton btnScrollLeft =
531 new PixmapButton(pianoRoll.actionScrollLeft, Res.gfxBtnScrollLeft);
532
533 private final JButton btnScrollRight =
534 new PixmapButton(pianoRoll.actionScrollRight, Res.gfxBtnScrollRight);
535
536 KeyRangePropsPane() {
537 setOpaque(false);
538 setLayout(new BoxLayout(this, BoxLayout.X_AXIS));
539
540 btnIncrease.setFocusable(false);
541 btnDecrease.setFocusable(false);
542 btnScrollLeft.setFocusable(false);
543 btnScrollRight.setFocusable(false);
544
545
546 btnDecrease.setPressedIcon(Res.gfxBtnDecreaseRO);
547 add(btnDecrease);
548
549 btnIncrease.setPressedIcon(Res.gfxBtnIncreaseRO);
550 add(btnIncrease);
551
552 add(Box.createRigidArea(new Dimension(6, 0)));
553
554 btnScrollLeft.setPressedIcon(Res.gfxBtnScrollLeftRO);
555 add(btnScrollLeft);
556
557 btnScrollRight.setPressedIcon(Res.gfxBtnScrollRightRO);
558 add(btnScrollRight);
559 }
560 }
561
562
563 public static class PowerButton extends PixmapToggleButton implements ActionListener {
564 PowerButton() {
565 this(Res.gfxPowerOff, Res.gfxPowerOn);
566 }
567
568 PowerButton(ImageIcon defaultIcon, ImageIcon selectedIcon) {
569 super(defaultIcon, selectedIcon);
570
571 setSelected(true);
572 addActionListener(this);
573 }
574
575 @Override
576 public void
577 actionPerformed(ActionEvent e) {
578 boolean b = isSelected();
579 MainFrame frm = (MainFrame)CC.getMainFrame();
580 if(frm == null) return;
581 frm.setMidiKeyboardVisible(b);
582 }
583
584 @Override
585 public boolean
586 contains(int x, int y) { return (x - 11)*(x - 11) + (y - 11)*(y - 11) < 71; }
587 }
588
589 private final Handler handler = new Handler();
590
591 private Handler
592 getHandler() { return handler; }
593
594 private class Handler extends SamplerChannelAdapter implements FocusListener, MidiDataListener {
595 @Override
596 public void
597 midiDataArrived(MidiDataEvent e) {
598 if(channel == null) return;
599 channel.sendBackendMidiData(e);
600 }
601
602 @Override
603 public void
604 channelChanged(SamplerChannelEvent e) {
605 updateDisplay();
606
607 String newFile = channel.getChannelInfo().getInstrumentFile();
608 int newIndex = channel.getChannelInfo().getInstrumentIndex();
609
610 if(channel.getChannelInfo().getInstrumentStatus() != 100) {
611 //don't use disablePianoRoll because of unnecessary repainting
612 pianoRoll.setAllKeysPressed(false);
613 pianoRoll.removeAllKeyswitches();
614 pianoRoll.setAllKeysDisabled(true);
615 pianoRoll.setPlayingEnabled(false);
616 return;
617 }
618
619 if(newFile == null) {
620 if(file != null) disablePianoRoll();
621 file = null;
622 index = -1;
623 return;
624 }
625
626 if(newFile.equals(file) && newIndex == index) return;
627
628 file = newFile;
629 index = newIndex;
630 updateInstrumentInfo();
631 }
632
633 @Override
634 public void
635 focusGained(FocusEvent e) {
636
637 }
638
639 @Override
640 public void
641 focusLost(FocusEvent e) {
642
643 }
644 }
645 }

  ViewVC Help
Powered by ViewVC