Source code: jm/gui/helper/HelperGUI.java
1 /*
2 <This Java Class is part of the jMusic API version 1.4, February 2003.>
3
4 Copyright (C) 2000 Andrew Sorensen & Andrew Brown
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or any
9 later version.
10 This program is distributed in the hope that it will be useful, but
11 WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public Licens
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17 */
18
19 package jm.gui.helper;
20
21 import jm.JMC;
22 import jm.music.data.*;
23 import jm.util.*;
24 import jm.audio.*;
25 import java.awt.*;
26 import java.awt.event.*;
27 import jm.midi.MidiSynth;
28
29 /**
30 * This jMusic utility is designed to be extended by user classes. It will
31 * provide a simple graphical interface that speeds up the cycle of
32 * composing-auditioning-recomposing by minimising the need for recompiling
33 * simple changes. It is especially useful for novice Java programmers.
34 *
35 * To use the HelperGUI class write a standard jMusic class that extends
36 * this class. It shopuld have a main() method and a constructor.
37 * Make a super() call in the constructor. Overwrite the
38 * compose() method [which returns a Score object] and include the compositional
39 * logic in that method.
40 *
41 * To render a score as an audio file, an Instrument array needs to be declared
42 * and assigned to the Instrument array varianble 'insts' - which is already
43 * declared in the HelperGUI class. As in this
44 * example code fragment:
45 * Instrument sine = new SineInst(44100);
46 * Instrument[] instArray = {sine};
47 * insts = instArray;
48 *
49 * There are five variables each with a slider that can be accessed to change
50 * values in the composition. Each variable, named 'variableA' to 'variableE',
51 * returns an integer values between 0 and 127.
52 *
53 * @author Andrew Brown
54 */
55
56 // To make this class use swing composents replace the GUI attributes (Button etc.)
57 // with ones starting with the letter J (JButton etc.) add a
58 // javax.swing import statement and use the commented
59 // getContentPane().add(controls) statement below.
60
61 public class HelperGUI extends Frame implements JMC, ActionListener, AdjustmentListener{
62 //-------------------
63 // Attributes
64 //-------------------
65 protected Score score = new Score();
66 private Button composeBtn, playBtn, stopBtn, showBtn, sketchBtn,
67 histogramBtn, printBtn, saveBtn, renderBtn, notateBtn,
68 audioViewBtn, audioPlayBtn, audioStopBtn, xmlOpenBtn, xmlSaveBtn;
69 private TextField midiName, audioName;
70 private Scrollbar sliderA, sliderB, sliderC, sliderD, sliderE;
71 private Label labelA, labelB, labelC, labelD, labelE;
72 private Label commentLabA, commentLabB, commentLabC,
73 commentLabD, commentLabE;
74 protected Instrument[] insts;
75 protected int variableA, variableB, variableC, variableD, variableE;
76 private MidiSynth ms = new MidiSynth();
77 // Is there are open JavaSound synth?
78 private boolean playing = false;
79
80 /*
81 // for testing only
82 public static void main(String[] args) {
83 new HelperGUI();
84 }*/
85
86 //-------------------
87 // Constructor
88 //-------------------
89 public HelperGUI() {
90 super("jMusic Helper GUI");
91 //Panel bg = this.getContentPane();
92 this.setLayout(new BorderLayout());
93 Panel controls = new Panel();
94 controls.setLayout(new GridLayout(13, 1));
95 //this.getContentPane().add(controls);
96 this.add(controls, "North");
97 Panel sliders = new Panel();
98 sliders.setLayout(new GridLayout(6, 1));
99 this.add(sliders, "Center");
100
101 Panel composeBtnPanel = new Panel();
102 Panel viewBtnPanel1 = new Panel();
103 Panel viewBtnPanel2 = new Panel();
104 Panel midiSaveBtnPanel = new Panel();
105 Panel midiPlayBtnPanel = new Panel();
106 Panel audioViewBtnPanel = new Panel();
107 Panel audioSaveBtnPanel = new Panel();
108 Panel xmlBtnPanel = new Panel();
109 //Panel audioPlayBtnPanel = new Panel();
110 Label create = new Label("Create and View");
111 create.setAlignment(Label.CENTER);
112 controls.add(create);
113 controls.add(composeBtnPanel);
114 controls.add(viewBtnPanel1);
115 controls.add(viewBtnPanel2);
116 Label midi = new Label("MIDI Options");
117 midi.setAlignment(Label.CENTER);
118 controls.add(midi);
119 controls.add(midiPlayBtnPanel);
120 controls.add(midiSaveBtnPanel);
121 Label audio = new Label("Audio Options");
122 audio.setAlignment(Label.CENTER);
123 controls.add(audio);
124 controls.add(audioSaveBtnPanel);
125 controls.add(audioViewBtnPanel);
126 //controls.add(audioPlayBtnPanel);
127 Label xmlHeader = new Label("XML Options");
128 xmlHeader.setAlignment(Label.CENTER);
129 controls.add(xmlHeader);
130 controls.add(xmlBtnPanel);
131
132 Label variables = new Label("Control compositional parameters");
133 variables.setAlignment(Label.CENTER);
134 controls.add(variables);
135
136 // butons
137 composeBtn = new Button("Compose");
138 composeBtn.addActionListener(this);
139 composeBtnPanel.add(composeBtn);
140
141 playBtn = new Button("Play.midi()");
142 playBtn.addActionListener(this);
143 playBtn.setEnabled(false);
144 midiPlayBtnPanel.add(playBtn);
145
146 stopBtn = new Button("Stop MIDI");
147 stopBtn.addActionListener(this);
148 stopBtn.setEnabled(false);
149 midiPlayBtnPanel.add(stopBtn);
150
151 showBtn = new Button("View.show()");
152 showBtn.addActionListener(this);
153 showBtn.setEnabled(false);
154 viewBtnPanel1.add(showBtn);
155
156 notateBtn = new Button("View.notate()");
157 notateBtn.addActionListener(this);
158 notateBtn.setEnabled(false);
159 viewBtnPanel1.add(notateBtn);
160
161 printBtn = new Button("View.print()");
162 printBtn.addActionListener(this);
163 printBtn.setEnabled(false);
164 viewBtnPanel1.add(printBtn);
165
166 sketchBtn = new Button("View.sketch()");
167 sketchBtn.addActionListener(this);
168 sketchBtn.setEnabled(false);
169 viewBtnPanel2.add(sketchBtn);
170
171 histogramBtn = new Button("View.histogram()");
172 histogramBtn.addActionListener(this);
173 histogramBtn.setEnabled(false);
174 viewBtnPanel2.add(histogramBtn);
175
176 saveBtn = new Button("Write.midi()");
177 saveBtn.addActionListener(this);
178 saveBtn.setEnabled(false);
179 midiSaveBtnPanel.add(saveBtn);
180
181 midiName = new TextField("FileName.mid", 20);
182 midiSaveBtnPanel.add(midiName);
183
184 audioViewBtn = new Button("View.au()");
185 audioViewBtn.addActionListener(this);
186 audioViewBtn.setEnabled(false);
187 audioViewBtnPanel.add(audioViewBtn);
188
189 renderBtn = new Button("Write.au()");
190 renderBtn.addActionListener(this);
191 renderBtn.setEnabled(false);
192 audioSaveBtnPanel.add(renderBtn);
193
194 audioName = new TextField("FileName.au", 20);
195 audioSaveBtnPanel.add(audioName);
196
197 audioPlayBtn = new Button("Play.au()");
198 audioPlayBtn.addActionListener(this);
199 audioPlayBtn.setEnabled(false);
200 audioViewBtnPanel.add(audioPlayBtn);
201 //audioPlayBtnPanel.add(audioPlayBtn);
202
203 xmlOpenBtn = new Button("Read.xml()");
204 xmlOpenBtn.addActionListener(this);
205 xmlOpenBtn.setEnabled(true);
206 xmlBtnPanel.add(xmlOpenBtn);
207
208 xmlSaveBtn = new Button("Write.xml()");
209 xmlSaveBtn.addActionListener(this);
210 xmlSaveBtn.setEnabled(false);
211 xmlBtnPanel.add(xmlSaveBtn);
212
213 // not yet implemented!
214 /*
215 audioStopBtn = new Button("Stop Audio");
216 audioStopBtn.addActionListener(this);
217 audioStopBtn.setEnabled(false);
218 audioPlayBtnPanel.add(audioStopBtn);
219 */
220
221 //sliders
222 Panel sliderAPanel = new Panel(new GridLayout(1, 3));
223 labelA = new Label(" variableA = 0");
224 sliderAPanel.add(labelA);
225 sliderA = new Scrollbar(Scrollbar.HORIZONTAL, 0, 15, 0, (127+ 15));
226 sliderA.addAdjustmentListener(this);
227 sliderAPanel.add(sliderA);
228 commentLabA = new Label(" No Comment ");
229 sliderAPanel.add(commentLabA);
230 sliders.add(sliderAPanel);
231
232 Panel sliderBPanel = new Panel(new GridLayout(1,3));
233 labelB = new Label(" variableB = 0");
234 sliderBPanel.add(labelB);
235 sliderB = new Scrollbar(Scrollbar.HORIZONTAL, 0, 15, 0, (127+ 15));
236 sliderB.addAdjustmentListener(this);
237 sliderBPanel.add(sliderB);
238 commentLabB = new Label(" No Comment ");
239 sliderBPanel.add(commentLabB);
240 sliders.add(sliderBPanel);
241
242 Panel sliderCPanel = new Panel(new GridLayout(1,3));
243 labelC = new Label(" variableC = 0");
244 sliderCPanel.add(labelC);
245 sliderC = new Scrollbar(Scrollbar.HORIZONTAL, 0, 15, 0, (127+ 15));
246 sliderC.addAdjustmentListener(this);
247 sliderCPanel.add(sliderC);
248 commentLabC = new Label(" No Comment ");
249 sliderCPanel.add(commentLabC);
250 sliders.add(sliderCPanel);
251
252 Panel sliderDPanel = new Panel(new GridLayout(1,3));
253 labelD = new Label(" variableD = 0");
254 sliderDPanel.add(labelD);
255 sliderD = new Scrollbar(Scrollbar.HORIZONTAL, 0, 15, 0, (127+ 15));
256 sliderD.addAdjustmentListener(this);
257 sliderDPanel.add(sliderD);
258 commentLabD = new Label(" No Comment ");
259 sliderDPanel.add(commentLabD);
260 sliders.add(sliderDPanel);
261
262 Panel sliderEPanel = new Panel(new GridLayout(1,3));
263 labelE = new Label(" variableE = 0");
264 sliderEPanel.add(labelE);
265 sliderE = new Scrollbar(Scrollbar.HORIZONTAL, 0, 15, 0, (127+ 15));
266 sliderE.addAdjustmentListener(this);
267 sliderEPanel.add(sliderE);
268 commentLabE = new Label(" No Comment ");
269 sliderEPanel.add(commentLabE);
270 sliders.add(sliderEPanel);
271
272 // filler
273 Label filler = new Label(" ");
274 sliders.add(filler);
275 //this.pack();
276 this.setBounds(0, 0, 350, 600);
277 this.setVisible(true);
278
279 composeBtn.requestFocus();
280 }
281
282 //-------------------
283 // methods
284 //-------------------
285
286 /**
287 * Specify the value for vaiable A
288 */
289 public void setVariableA(int value) {
290 setVariableA(value, "No Comment");
291 }
292
293 /**
294 * Specify the value and comment for vaiable A
295 */
296 public void setVariableA(int value, String comment) {
297 if (value >=0 && value <= 127) {
298 sliderA.setValue(value);
299 labelA.setText(" variableA = " + value + " ");
300 variableA = value;
301 }
302 if (comment.length() > 18) {
303 commentLabA.setText(" " + comment.substring(0, 16) + "...");
304 } else commentLabA.setText(" " + comment +" ");
305 }
306
307 /**
308 * Specify the value for vaiable B
309 */
310 public void setVariableB(int value) {
311 setVariableB(value, "No Comment");
312 }
313
314 /**
315 * Specify the value and comment for vaiable B
316 */
317 public void setVariableB(int value, String comment) {
318 if (value >=0 && value <= 127) {
319 sliderB.setValue(value);
320 labelB.setText(" variableB = " + value + " ");
321 variableB = value;
322 }
323 if (comment.length() > 18) {
324 commentLabB.setText(" " + comment.substring(0, 16) + "...");
325 } else commentLabB.setText(" " + comment +" ");
326 }
327
328 /**
329 * Specify the value for vaiable C
330 */
331 public void setVariableC(int value) {
332 setVariableC(value, "No Comment");
333 }
334
335
336 /**
337 * Specify the value and string for vaiable C
338 */
339 public void setVariableC(int value, String comment) {
340 if (value >=0 && value <= 127) {
341 sliderC.setValue(value);
342 labelC.setText(" variableC = " + value + " ");
343 variableC = value;
344 }
345 if (comment.length() > 18) {
346 commentLabC.setText(" " + comment.substring(0, 16) + "...");
347 } else commentLabC.setText(" " + comment +" ");
348 }
349
350 /**
351 * Specify the value for vaiable D
352 */
353 public void setVariableD(int value) {
354 setVariableD(value, "No Comment");
355 }
356
357 /**
358 * Specify the value and string for vaiable D
359 */
360 public void setVariableD(int value, String comment) {
361 if (value >=0 && value <= 127) {
362 sliderD.setValue(value);
363 labelD.setText(" variableD = " + value + " ");
364 variableD = value;
365 }
366 if (comment.length() > 18) {
367 commentLabD.setText(" " + comment.substring(0, 16) + "...");
368 } else commentLabD.setText(" " + comment +" ");
369 }
370
371 /**
372 * Specify the value for vaiable E
373 */
374 public void setVariableE(int value) {
375 setVariableE(value, "No Comment");
376 }
377
378 /**
379 * Specify the value and string for vaiable E
380 */
381 public void setVariableE(int value, String comment) {
382 if (value >=0 && value <= 127) {
383 sliderE.setValue(value);
384 labelE.setText(" variableE = " + value + " ");
385 variableE = value;
386 }
387 if (comment.length() > 18) {
388 commentLabE.setText(" " + comment.substring(0, 16) + "...");
389 } else commentLabE.setText(" " + comment +" ");
390 }
391
392 /**
393 * Handle the button clicks in the GUI
394 */
395 public void actionPerformed(ActionEvent e) {
396 if (e.getSource() == composeBtn) composeScore();
397 if (e.getSource() == playBtn) playScore();
398 if (e.getSource() == stopBtn) stopScore();
399 if (e.getSource() == showBtn) showScore();
400 if (e.getSource() == notateBtn) notateScore();
401 if (e.getSource() == printBtn) printScore();
402 if (e.getSource() == sketchBtn) sketchScore();
403 if (e.getSource() == histogramBtn) histogramScore();
404 if (e.getSource() == saveBtn) saveScore();
405 if (e.getSource() == renderBtn) renderScore();
406 if (e.getSource() == audioViewBtn) viewAudio();
407 if (e.getSource() == audioPlayBtn) playAudio();
408 if (e.getSource() == audioStopBtn) stopAudio();
409 if (e.getSource() == xmlOpenBtn) xmlOpen();
410 if (e.getSource() == xmlSaveBtn) xmlSave();
411 }
412
413 private void composeScore() {
414 // get composed score
415 score = compose();
416 makeBtnsVisible();
417 }
418
419 private void makeBtnsVisible() {
420 // show availible buttons
421 playBtn.setEnabled(true);
422 stopBtn.setEnabled(true);
423 showBtn.setEnabled(true);
424 notateBtn.setEnabled(true);
425 printBtn.setEnabled(true);
426 sketchBtn.setEnabled(true);
427 histogramBtn.setEnabled(true);
428 saveBtn.setEnabled(true);
429 xmlSaveBtn.setEnabled(true);
430 // show audio buttons if audio used
431 if (insts != null) {
432 renderBtn.setEnabled(true);
433 }
434 }
435
436
437 /**
438 * This method should be overridden by classes that
439 * extend the HelperGUI class.
440 */
441 protected Score compose() {
442 // Simple example composition
443 Phrase phrase = new Phrase();
444 Score s = new Score(new Part(phrase));
445 //for(int i = 0; i < 8; i++) {
446 Note n = new Note (48 + (int)(Math.random() * variableA), 0.5 + variableB * 0.25);
447 phrase.addNote(n);
448 //}
449
450 //Instrument[] tempInsts = {new SineInst(44100)};
451 //insts = tempInsts;
452 return s;
453 }
454
455 /** Start MIDI playback */
456 private void playScore() {
457 if (playing) ms.stop();
458 try {
459 ms.play(score);
460 playing = true;
461 } catch (Exception e) {
462 System.err.println("JavaSound MIDI Playback Error:" + e);
463 return;
464 }
465 }
466
467 /** halt MIDI playback */
468 private void stopScore() {
469 if (playing) {
470 ms.stop();
471 playing = false;
472 }
473 }
474
475 /** Display a score with the show score viewer */
476 private void showScore() {
477 View.show(score, this.getSize().width + 15, 0);
478 }
479
480 /** Display a score with the notation viewer */
481 private void notateScore() {
482 View.notate(score, this.getSize().width + 15, 0);
483 }
484
485
486 /** print score data to the CLI */
487 private void printScore() {
488 View.print(score);
489 }
490
491 /** Display a score in the histogram viewer */
492 private void histogramScore() {
493 View.histogram(score, 0, this.getSize().width + 15, 0);
494 }
495
496 /** Display a score with the sketch score viewer */
497 private void sketchScore() {
498 View.sketch(score, this.getSize().width + 15, 0);
499 }
500
501 /** Save score as a standard MIDI file */
502 private void saveScore() {
503 String fileName = midiName.getText().trim();
504 if (fileName != null){
505 Write.midi(score, fileName);
506 } else Write.midi(score);
507 }
508
509 /** Save the score as an audio file */
510 private void renderScore() {
511 String fileName = audioName.getText().trim();
512 if (fileName != null){
513 Write.au(score, fileName, insts);
514 } else {
515 Write.au(score, "RenderedFile.au", insts);
516 audioName.setText("RenderedFile.au");
517 }
518 audioViewBtn.setEnabled(true);
519 audioPlayBtn.setEnabled(true);
520 //audioStopBtn.setEnabled(true);
521 }
522
523 /** Show the saved audio file in the wave viewer */
524 private void viewAudio() {
525 View.au(audioName.getText().trim(), this.getSize().width + 5, 0);
526 }
527
528 /** Playback the audio file using jMusic real time audio */
529 private void playAudio() {
530 Play.au(audioName.getText().trim(), false);
531 }
532
533 /** Stop playback of the audio file */
534 private void stopAudio() {
535 // stop playback if possible here!
536 }
537
538 public void adjustmentValueChanged(java.awt.event.AdjustmentEvent ae) {
539 if (ae.getSource() == sliderA) {
540 labelA.setText(" variableA = " + sliderA.getValue());
541 variableA = new Integer(sliderA.getValue()).intValue();
542 }
543 if (ae.getSource() == sliderB) {
544 labelB.setText(" variableB = " + sliderB.getValue());
545 variableB = new Integer(sliderB.getValue()).intValue();
546 }
547 if (ae.getSource() == sliderC) {
548 labelC.setText(" variableC = " + sliderC.getValue());
549 variableC = new Integer(sliderC.getValue()).intValue();
550 }
551 if (ae.getSource() == sliderD) {
552 labelD.setText(" variableD = " + sliderD.getValue());
553 variableD = new Integer(sliderD.getValue()).intValue();
554 }
555 if (ae.getSource() == sliderE) {
556 labelE.setText(" variableE = " + sliderE.getValue());
557 variableE = new Integer(sliderE.getValue()).intValue();
558 }
559 }
560
561 /*
562 * Save the current scare as a jMusic XML file.
563 */
564 private void xmlSave() {
565 FileDialog fd = new FileDialog(new Frame(),
566 "Save as a jMusic XML file...",
567 FileDialog.SAVE);
568 fd.show();
569 if (fd.getFile() != null) {
570 jm.util.Write.xml(score, fd.getDirectory() + fd.getFile());
571 }
572 }
573
574 /*
575 * Import a jMusic XML score to be the current score.
576 */
577 private void xmlOpen() {
578 Read.xml(score);
579 makeBtnsVisible();
580 }
581 }