I am trying to implement a looped sound (testing only at the moment) the following way (there may be a better way, but this is not the point for me now):
a task (check-task) is running every 500 ms checking if the sound is still running. If it checks that the sound is about to finish within these 500ms it cancels itself and schedules another task (play-task) to start the other sound once this sound has finished (I am doing this more complicated, in order to tackle issues which could occur if the device is busy or does not finish right on time). This play-task is just running once and after starting the sound to play it starts the timer to schedule the check-task (every 500 ms). This goes on forever.
The problem is, that while debugging I can see that every time when scheduling the play-task and the loop starts again, a timer object is added, a thread object is added and a "JFXMedia Player EventQueueThread" is running. I have tested this for 10 minutes and had hundreds of objects shown in the debugger.
Is this a problem? Is this something which has to do with Netbeans? With the way Codename One implements Timer? Or is this my code? I have tried this code (without playing stuff) in a normal java application and there is just one timer running all the time.
Here is my code (I have tried to add only the vital parts). If someone could help me with this issue this would be great!
class MyMedia{
private Media m_Media;
private InputStream m_InputStream;
private Runnable m_Callback;
private String m_Mimetype;
public MyMedia(String name, String mimetype) throws Exception{
m_InputStream = theme.getData(name);
m_Callback = new SoundFinished(this);
m_Mimetype = mimetype;
m_Media = create();
}
public int getDuration(){
return m_Media.getDuration();
}
public int getTime(){
return m_Media.getTime();
}
public boolean isPlaying(){
return m_Media.isPlaying();
}
Media create() throws Exception{
return MediaManager.createMedia(m_InputStream, m_Mimetype, m_Callback);
}
public Media getMedia(){
return m_Media;
}
public void reload() throws Exception{
m_InputStream.reset();
m_Media = create();
}
}
//called once the sound is finished, reloads it to play it again later
class SoundFinished implements Runnable{
MyMedia m_Media;
public SoundFinished(MyMedia m) {
m_Media = m;
}
public void run() {
try{
m_Media.reload();
}
catch(Exception ex){
}
}
}
//plays a sound reschedules the timer to check
class PlaySoundTask extends TimerTask{
MyMedia toPlay;
MyMedia playNext;
public PlaySoundTask(MyMedia play, MyMedia playnext){
toPlay = play;
playNext = playnext;
}
@Override
public void run() {
try{
toPlay.getMedia().play();
if (add > 0)
toPlay.getMedia().setTime(add);
this.cancel();
m_Timer.schedule(new CheckSoundTask(toPlay, playNext), CheckInterval, CheckInterval);
toPlay = playNext = null;
}
catch(Exception ex){
}
}
}
//checks if sound is still playing, if almost finished schedules PlaySoundTask and cancels itself
class CheckSoundTask extends TimerTask{
MyMedia m_Media;
MyMedia m_Other;
public CheckSoundTask(MyMedia m, MyMedia other){
m_Media = m;
m_Other = other;
}
@Override
public void run() {
int timeForNextAction = getTimeForNextAction(m_Media);
if (timeForNextAction != CheckInterval){
this.cancel();
m_Timer.schedule(new PlaySoundTask(m_Other, m_Media), timeForNextAction);
m_Media = m_Other = null;
}
}
}
int getMediaTimeToPlay(MyMedia m){
if (!m.isPlaying()){
return 0;
}
return Math.max(0, m.getDuration() - m.getTime());
}
int getTimeForNextAction(MyMedia m){
int mTimeToPlay = getMediaTimeToPlay(m);
if (mTimeToPlay < CheckInterval)
return mTimeToPlay;
return CheckInterval;
}
//called when hitting a button in the application
public void actionPerformed(ActionEvent evt) {
try
{
m_1 = new MyMedia(filename,mimetype);
m_2 = new MyMedia(filename,mimetype);
m_1.getMedia().play();
m_Timer.schedule(new CheckSoundTask(m_1, m_2), CheckInterval, CheckInterval);
//timer.schedule(new MyTimerTask(), );
}
catch(Exception ex){
Dialog.show("Warning", "Load failed", "okay", null);
}
}