Why is this throwing an exception?
Hi everybody,
To anyone who looked at my earlier post, ignore it; I decided to try a different way of implementing what I was trying to do. Unfortunately, I ran into some problems that way too, so I was hoping someone could help me out.
I'm trying to play a list of songs in order. So far, I can play the first song. However, when I play it, it throws an Illegal Monitor State Exception and never gets to the second song. I'm really not sure why this is happening. Can anyone help me out?
The code is:
// The song title and its length in milliseconds (from 3:15 and 4:12)
String[][] songs ={{"Dark Matter","195000"},{"Golden","252000"}};
for(int i = 0; i < songs.length; i++ ){
in =new FileInputStream("D:\\Musica\\" + songs[i][0] + ".wav");
audioStream =new AudioStream(in);
AudioPlayer.player.start(audioStream);
int milli = Integer.parseInt( songs[i][1] );
Object waitObject =new Object();
waitObject.wait( milli );
// Throws exception at this line
}
Any help would be great, and sorry if the (sort of) repeat post is annoying.
Thanks!
Jezzica8t
Message was edited by:
jezzica85
[1836 byte] By [
jezzica85a] at [2007-11-27 11:28:58]

What's the wait() for? Try Thread.sleep(). If you call x.wait() for any x you have to be synchronized on x.
ejpa at 2007-7-29 16:25:08 >

I tried Thread.sleep(), but then it wouldn't let me do anything else while the music was playing. I tried to say:
synchronized waitObject
but it wouldn't let me do that either. Do you know what I could be missing?
Jezzica85
Of course you can't do anything, you're asleep. Why wait or sleep at all? What's the purpose?
ejpa at 2007-7-29 16:25:08 >

If I don't have anything else in the loop, the program plays both of my files simultaneously. I'd like to play them one after the other, and putting in a wait was the only way I could think of to pause the loop until a song finished playing. Is there something else I could do?
So I don't understand what's wrong with Thread.sleep().
ejpa at 2007-7-29 16:25:08 >

I'm trying to play music in the background of a GUI, and I want the functionality of the GUI to remain while the music is playing.
Try putting it in a Thread
Thanks Airplane,
Can you give me an example in the for loop? I really don't understand how, and threads are confusing to me.
Jezzica85
Hehe, give me a few minutes to toy around with it :)
-Airplane
Here would be your main, or where ever you want to launch the thread from:
public class TestMain{
public static void main(String [] args){
Thread thread = new Thread1();
thread.run();
}
}
Heres the thread:
public class Thread1 extends Thread{
public Thread1(){
}
public void run(){
// The song title and its length in milliseconds (from 3:15 and 4:12)
String[][] songs = {{"Dark Matter", "195000"}, {"Golden", "252000"}};
for( int i = 0; i < songs.length; i++ ) {
in = new FileInputStream("D:\\Musica\\" + songs[i][0] + ".wav");
audioStream = new AudioStream(in);
AudioPlayer.player.start(audioStream);
int milli = Integer.parseInt( songs[i][1] );
//Object waitObject = new Object();
//waitObject.wait( milli );
//--Now instead of using wait^^ use sleep--
// Throws exception at this line
}
}
}
> AudioPlayer.player.start(audioStream);
new Thread(new Runnable()
{
public void run()
{
AudioPlayer.player.start(audioStream);
}
}).start();
You will also have to declare 'audioStream' as final.
ejpa at 2007-7-29 16:25:08 >

Thanks Airplane,
That's almost it, but Thread.sleep stops my GUI from responding too. Should I not have put it in the for loop?
Oh, and sorry ejp, I didn't see your reply. Your solution skips the first element in my array, or at least that's what it looks like, and if I make the AudioStream final, I can't make a new one for every file. I'll keep trying to tweak it though.
Message was edited by:
jezzica85
> Your solution skips the first element in my array, or at least that's what it looks like
The code I provided doesn't deal in elements or arrays at all so it can't be my solution that's at fault here.
ejpa at 2007-7-29 16:25:08 >

I know, it's probably something I'm doing. The second song plays fine; I think it might be because I haven't called Thread.sleep or something, but every time I call Thread.sleep it stops the GUI from being functional. This is what I have right now:
// The second string is length in milliseconds
String[][] songs = {{"Dark Matter", "195000"}, {"Golden", "252000"}};
for( int i = 0; i < songs.length; i++ ) {
in = new FileInputStream( "D:\\Musica\\" + songs[i][0] + ".wav" );
audioStream = new AudioStream(in);
new Thread(new Runnable() {
public void run() {
AudioPlayer.player.start(audioStream);
}
}).start();
}
Maybe you can see something I don't.
Jezzica85
Message was edited by:
jezzica85
Actually I think the run() should be around the loop otherwise you just have the same problem without the GUI freeze. There must be something in AudioPlayer that can tell you when the clip is finished playing.
ejpa at 2007-7-29 16:25:16 >

Is this the ancient sun.audio package?
I sincerely hope not. There are a couple of other things out there called AudioPlayer, unsurprisingly.
ejpa at 2007-7-29 16:25:16 >

Yes, this is sun.audio AudioPlayer. I haven't seen anything in it that tells when something has stopped playing.
Wouldn't going outside the for loop with run() have the same problem happen? The threads would still start almost concurrently.
What other AudioPlayers are you referring to?
Jezzica85
The ones I found on Google when I researched your question.
See the following note about using sun.* packages:
http://java.sun.com/products/jdk/faq/faq-sun-packages.html.
Basically you should be using javax.sound.sampled.AudioSystem and friends. See the. first example at http://mindprod.com/jgloss/sound.html. NB this website is not generally the most reliable resource.
ejpa at 2007-7-29 16:25:16 >

Thanks, I guess I'll see what I can do with those other classes.
Jezzica85
if the audio/gui are blocking one another that means
you are either processing in the gui thread or you failed to spawn off
your audio thread.
One other unrelated question: Why are you using a 2-D array of unrelated items (song name and time) rather than using a more natural-seeming 1-D array of object that combines song name, time (and anything else you want to ad)?
Something like this:
public class Song
{
private String name;
private int time;
public Song(String name, int time)
{
this.name = name;
this.time = time;
}
public String getName()
{
return name;
}
public int getTime()
{
return time;
}
}
and........
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import sun.audio.AudioPlayer;
import sun.audio.AudioStream;
public class UseSongs
{
private List<Song> songs = new ArrayList<Song>();
private FileInputStream in;
private AudioStream audioStream;
public UseSongs()
{
initSongList();
playSongList();
}
private void initSongList()
{
songs.add(new Song("Dark Matter", 195000));
songs.add(new Song("Golden", 252000));
}
private void playSongList()
{
for (int i = 0; i < songs.size(); i++)
{
Song mySong = songs.get(i);
try
{
in = new FileInputStream("D:\\Musica\\" + mySong.getName() + ".wav");
audioStream = new AudioStream(in);
AudioPlayer.player.start(audioStream);
int milli = mySong.getTime();
// TODO complete rest of code
}
catch (FileNotFoundException e)
{
e.printStackTrace();
}
catch (IOException ioe)
{
ioe.printStackTrace();
}
}
}
}
Or you could put a songPlay method in the Song class so the song "knows" how to play itself...
Calm down, this is not the issue, and not the classes to be using either.
ejpa at 2007-7-29 16:25:16 >
