Hi all,
I'm pretty new to programming and I've become completely stumped at the error I'm getting. I searched the forums and found a few people with similar errors, but I don't think that mine is related.
The program displays a GUI where a text string can be entered. The string is notation for hand drumming, like: D-T-kkT-D-kkT-kk Each character indicates a quarter of a beat. The program steps through the string playing everything back at the proper tempo. This program was working fine until I tried to make it threaded. It does play back and it even accepts edits while its being played back. But once I stop the playback and try to play it again, it gives me the following error:
Where it says "Play" below "Jun 5" is when the button press controlEvent triggers a println. It's not actually part of the error message.
For implementing threading I am using the example code from the wiki, modified so that the thread doesn't recur at intervals. Threading and overrides are not something that I fully understand at this time, so I wonder if its something in that section that is clashing with controlP5.
I'm sorry if this ends up being a simple fix, but I've been unable to figure out what is wrong. I greatly appreciate any help you can offer!
Here is the code:
I'm pretty new to programming and I've become completely stumped at the error I'm getting. I searched the forums and found a few people with similar errors, but I don't think that mine is related.
The program displays a GUI where a text string can be entered. The string is notation for hand drumming, like: D-T-kkT-D-kkT-kk Each character indicates a quarter of a beat. The program steps through the string playing everything back at the proper tempo. This program was working fine until I tried to make it threaded. It does play back and it even accepts edits while its being played back. But once I stop the playback and try to play it again, it gives me the following error:
Jun 5, 2011 3:22:47 PM controlP5.ControlBroadcaster printMethodError
Play
SEVERE: An error occured while forwarding a Controller value
to a method in your program. Please check your code for any
possible errors that might occur in this method .
e.g. check for casting errors, possible nullpointers, array overflows ... .
method: Play
exception: java.lang.reflect.InvocationTargetException
Where it says "Play" below "Jun 5" is when the button press controlEvent triggers a println. It's not actually part of the error message.
For implementing threading I am using the example code from the wiki, modified so that the thread doesn't recur at intervals. Threading and overrides are not something that I fully understand at this time, so I wonder if its something in that section that is clashing with controlP5.
I'm sorry if this ends up being a simple fix, but I've been unable to figure out what is wrong. I greatly appreciate any help you can offer!
Here is the code:
// beats - Play back text formatted drum beats. Now theaded to allow looping and realtime editing while looping.
// Note: Minim's AudioSample launches a new thread per sound played. The beta has a new way to handle this, but for one drum part this isn't a big deal. For an ensemble, it'll be a problem.
import controlP5.*;
import ddf.minim.*;
ControlP5 controlP5;
Minim minim;
AudioSample doumbekD;
AudioSample doumbekT;
AudioSample doumbekk;
AudioSample doumbekS;
AudioSample doumbekP;
Textfield Doumbek;
Textfield Tempo;
Textarea Instructions;
SimpleThread playbackThread;
void setup()
{
size(600, 180);
frameRate(25);
controlP5 = new ControlP5(this);
minim = new Minim(this);
playbackThread = new SimpleThread("n");
doumbekD = minim.loadSample("D.wav");
doumbekT = minim.loadSample("T.wav");
doumbekk = minim.loadSample("k.wav");
doumbekS = minim.loadSample("S.wav");
doumbekP = minim.loadSample("P.wav");
Doumbek = controlP5.addTextfield("doumbek",60,50,480,20);
Doumbek.setFocus(true);
Doumbek.setAutoClear(false);
Doumbek.setText("D-T-kkT-D-kkT-kk D-S-kkS-D-kkP-kk");
controlP5.addButton("Play",0,60,100,70,20);
controlP5.addButton("StopPlayback",0,190,100,70,20);
Tempo = controlP5.addTextfield("tempo",320,100,70,20);
Tempo.setAutoClear(false);
Tempo.setText("120");
controlP5.addButton("Clear",0,470,100,70,20);
Instructions=controlP5.addTextarea(
"Instructions",
"Play back text hand percussion notation.\nD=Doum T=Tek K=Ka k=quieter Ka S=Slap P=Pop -=Rest",
10,10,400,30);
}
void draw()
{
background(0);
}
public void controlEvent(ControlEvent theEvent) {
// outputs events to console for debugging
println(theEvent.controller().name());
}
public void Clear(int theValue) {
Doumbek.clear();
}
public void Play(int theValue) {
playbackThread.start();
}
public void StopPlayback(int theValue) {
playbackThread.quit();
}
public float calculateDelay()
{
// figure out the delay between each beat in milliseconds
float msperbeat = 60000 / Integer.parseInt(Tempo.getText());
// since we are using 16th note resolution, divide by 4 to find out the delay between each note
float delaybetween = msperbeat / 4;
return delaybetween;
}
public int lengthofloop()
{
// find out how long our loop is.
String beatloop = Doumbek.getText();
int looplength = beatloop.length();
return looplength;
}
void stop()
{
// close the loaded wav files
doumbekD.close();
doumbekT.close();
doumbekk.close();
doumbekS.close();
doumbekP.close();
// stop audio
minim.stop();
// this calls the stop method that
// you are overriding by defining your own
// it must be called so that your application
// can do all the cleanup it would normally do
super.stop();
}
class SimpleThread extends Thread {
boolean running; // Is the thread running? Yes or no?
String id; // Thread name
// Constructor, create the thread
// It is not running by default
SimpleThread (String s) {
running = false;
id = s;
}
// Overriding "start()"
void start () {
// Set running equal to true
running = true;
// Do whatever start does in Thread, don't forget this!
super.start();
}
// We must implement run, this gets triggered by start()
void run () {
while (running) {
int skip = 0;
for (int i = 0; (i < lengthofloop()) && running; i++) {
switch(Doumbek.getText().charAt(i)) {
case 'D':
doumbekD.trigger();
println("D");
break;
case 'T':
doumbekT.trigger();
println("T");
break;
case 'K':
doumbekT.trigger(); // T and K should have the same sound; difference indicates what hand
println("K");
break;
case 'k':
doumbekk.trigger(); // softer than a normal K
println("k");
break;
case 'S':
doumbekS.trigger();
println("S");
break;
case 'P':
doumbekP.trigger();
println("P");
break;
case '-':
println("-");
break;
default:
skip = 1;
break;
}
// delay until the next note, unless told to skip (this is so that the user can use spaces to make the music more readable without affecting playback)
if (skip == 1) {
skip = 0;
}
else {
delay(int(calculateDelay()));
}
}
} // end while(running)
System.out.println(id + " thread is done!"); // The thread is done when we get to the end of run()
} // end run()
// Our method that quits the thread
void quit() {
System.out.println("Quitting.");
running = false; // Setting running to false ends the loop in run()
// In case the thread is waiting. . .
interrupt();
}
} // end SimpleThread
1