Stop one thread and start the other? - java

I am having trouble stopping one thread and starting another one. I have created two threads. One of them is first run from the main method. It then takes user input and if the desired input is provided, thread one (sound) is supposed to stop and start thread two (sound2). From the code below, thread two does start playing after the correct input is provided during thread one. But thread one does not stop. I can hear audio files from both thread one and thread two playing. Please help.
public class crytask {
public static void main(String args[]) throws InterruptedException {
Runnable sound = new sound();
final Thread soundthread = new Thread(sound);
soundthread.start();
int count = 0;
System.out.println("Enter");
Scanner reader = new Scanner(System.in);
int a = reader.nextInt();
if (a==12)
soundthread.interrupt();
System.out.println("this thread is cancelled");
Runnable sound2 = new sound2();
final Thread soundthread2 = new Thread(sound2);
soundthread2.start();
int count2 = 0;
System.out.println("Enter");
Scanner reader2 = new Scanner(System.in);
int b = reader2.nextInt();
if (b==12)
soundthread2.interrupt();
}}
class sound implements Runnable {
#Override
public void run() {
try {
AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(new File("/Users/babe/Desktop/Con1.wav").getAbsoluteFile());
Clip clip = AudioSystem.getClip();
clip.open(audioInputStream);
clip.start();
Thread.sleep(clip.getMicrosecondLength() / 1000);
} catch(InterruptedException ex) {
System.out.println("Cancelled 1!");
} catch (Exception ex) {
System.out.println("Error with playing sound.");
ex.printStackTrace();
}
}
}
class sound2 implements Runnable {
#Override
public void run() {
try {
AudioInputStream audioInputStream2 = AudioSystem.getAudioInputStream(new File("/Users/babe/Desktop/Con1.wav").getAbsoluteFile());
Clip clip = AudioSystem.getClip();
clip.open(audioInputStream2);
clip.start();
Thread.sleep(clip.getMicrosecondLength() / 1000);
} catch(InterruptedException ex) {
System.out.println("Cancelled 2!");
} catch (Exception ex) {
System.out.println("Error with playing sound.");
ex.printStackTrace();
}
}
}

Try stopping the clip when the thread is interrupted, adding clip.close() to the catch clause that catches the interruptedException, like this:
class sound implements Runnable {
#Override
public void run() {
Clip clip = null; // take the declaration of the clip variable out of the try - catch
try {
AudioInputStream audioInputStream =
AudioSystem.getAudioInputStream(new File("/Users/babe/Desktop/Con1.wav").getAbsoluteFile());
clip = AudioSystem.getClip();
clip.open(audioInputStream);
clip.start();
Thread.sleep(clip.getMicrosecondLength() / 1000);
} catch(InterruptedException ex) {
clip.stop(); // <--- ADD THIS LINE
System.out.println("Cancelled 1!");
} catch (Exception ex) {
System.out.println("Error with playing sound.");
ex.printStackTrace();
}
}
}

Related

How I can check when music has ended

I have a JFrame with 2 buttons: Turn On and Turn Off
My problem is when a song has ended, I can't check that it ended and to play it again
How can I check it? Thank you so much
Below is the way that I play sound on Swing
class MP3 {
private Player player;
private String filename;
public MP3(String filename) {
this.filename = filename;
}
public void stop() {
if (player != null)
player.close();
}
public void play() {
try {
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(filename));
player = new Player(bis);
} catch (FileNotFoundException | JavaLayerException ex) {
System.out.println(ex);
}
new Thread(new Runnable() {
#Override
public void run() {
try {
player.play();
} catch (Exception ex) {
System.out.println(ex);
}
}
}).start();
}
}
And Event when I click buttons
private void btnPlayActionPerformed(java.awt.event.ActionEvent evt) {
sound = new MP3("src/Sound/02 - Cold Pizza.mp3");
sound.play();
btnPlay.setVisible(false);
btnStop.setVisible(true);
}
private void btnStopActionPerformed(java.awt.event.ActionEvent evt) {
sound.stop();
btnStop.setVisible(false);
btnPlay.setVisible(true);
}
sound is a instance of MP3 class in main class
I did it this way. I made the mp3 file a wav file. Then I made two objects
AudioInputStream songReader;
Clip song;
try{
songReader =
AudioSystem.getAudioInputStream(
getClass().getResource("wally.wav"));
song = AudioSystem.getClip();
song.open(songReader);
}catch (Exception e){
System.out.println("won't work");
}
try{
song.stop();
song.setFramePosition(0);
}catch(Exception e){
System.out.println("Error playing your music");
}
try{
song.start();
song.loop(song.LOOP_CONTINUOUSLY);
}catch(Exception e){
System.out.println("Won't work");
}
This makes it play infinitely, but if you need you can stop it at any point with song.stop(). Hopefully, that will work for you.

Java music not working

I made a java program and wanted a background music so I used this function
public static void playSound(final String url) {
new Thread(new Runnable() {
public void run() {
try {
Clip clip = AudioSystem.getClip();
AudioInputStream inputStream = AudioSystem
.getAudioInputStream(getClass().getResourceAsStream("/" + url));
clip.open(inputStream);
clip.start();
} catch (Exception e) {
System.err.println(e.getMessage());
}
}
}).start();
}
only problem is when I try to run the 27 minute wav file, it speeds it up really fast

AudioClip Issues when trying to play sounds on JFrame

I've been trying to play sound1 and sound2 using AudioClips. This is my code:
import javax.sound.sampled.*;
public class Sound {
private Clip clip;
public static final Sound sound1 = new Sound("src/Sounds/Classic_Horror_2.wav");
public static final Sound sound2 = new Sound("src/Sounds/Classic Horror 3.mp3");
public Sound (String fileName) {
try {
AudioInputStream ais = AudioSystem.getAudioInputStream(Sound.class.getResource(fileName));
clip = AudioSystem.getClip();
clip.open(ais);
} catch (Exception e) {
e.printStackTrace();
}
}
public void play() {
try {
if (clip != null) {
new Thread() {
public void run() {
synchronized (clip) {
clip.stop();
clip.setFramePosition(0);
clip.start();
}
}
}.start();
}
} catch (Exception e) {
e.printStackTrace();
}
}
public void stop(){
if(clip == null) return;
clip.stop();
}
public void loop() {
try {
if (clip != null) {
new Thread() {
public void run() {
synchronized (clip) {
clip.stop();
clip.setFramePosition(0);
clip.loop(Clip.LOOP_CONTINUOUSLY);
}
}
}.start();
}
} catch (Exception e) {
e.printStackTrace();
}
}
public boolean isActive(){
return clip.isActive();
}
}
When I try to do Sound.sound1.loop(); or Sound.sound1.play(); I get a null pointer exception. Same goes for sound2. Here are the exact errors messages:
java.lang.NullPointerException
at com.sun.media.sound.StandardMidiFileReader.getSequence(StandardMidiFileReader.java:207)
at javax.sound.midi.MidiSystem.getSequence(MidiSystem.java:841)
at com.sun.media.sound.SoftMidiAudioFileReader.getAudioInputStream(SoftMidiAudioFileReader.java:178)
at javax.sound.sampled.AudioSystem.getAudioInputStream(AudioSystem.java:1147)
at Sound.<init>(Sound.java:12)
at Sound.<clinit>(Sound.java:7)
at IntroductionComponent.<init>(IntroductionComponent.java:54)
at IntroductionGUI.main(IntroductionGUI.java:9)
java.lang.NullPointerException
at com.sun.media.sound.StandardMidiFileReader.getSequence(StandardMidiFileReader.java:207)
at javax.sound.midi.MidiSystem.getSequence(MidiSystem.java:841)
at com.sun.media.sound.SoftMidiAudioFileReader.getAudioInputStream(SoftMidiAudioFileReader.java:178)
at javax.sound.sampled.AudioSystem.getAudioInputStream(AudioSystem.java:1147)
at Sound.<init>(Sound.java:12)
at Sound.<clinit>(Sound.java:8)
at IntroductionComponent.<init>(IntroductionComponent.java:54)
at IntroductionGUI.main(IntroductionGUI.java:9)
I have repeatedly browsed stackoverflow to look for possible fixes, however it may be that fileName returns null constantly, or that my URL's are somehow incorrect. That said, for all I know it could be anything. Any suggestions on how to fix this?
The inclusion of src in your paths...
public static final Sound sound1 = new Sound("src/Sounds/Classic_Horror_2.wav");
public static final Sound sound2 = new Sound("src/Sounds/Classic Horror 3.mp3");
is your key problem, src won't exist once the application is build and package, you should never refer to src ever.
You should probably be using something more like...
public static final Sound sound1 = new Sound("/Sounds/Classic_Horror_2.wav");
public static final Sound sound2 = new Sound("/Sounds/Classic Horror 3.mp3");
public Sound (String fileName) {
try {
AudioInputStream ais = AudioSystem.getAudioInputStream(getClass().getResource(fileName));
clip = AudioSystem.getClip();
clip.open(ais);
} catch (Exception e) {
e.printStackTrace();
}
}
Personally, I'd make Sound require a URL...
public Sound (URL url) {
try {
AudioInputStream ais = AudioSystem.getAudioInputStream(url);
clip = AudioSystem.getClip();
clip.open(ais);
} catch (Exception e) {
e.printStackTrace();
}
}
This way there's no confusion over what String means and you can pass a reference from embedded resources, file references or even from the net
Also from memory, clip.start() creates it's own thread, so there's no need to create your own

Sound loading working in ubuntu but not working in windows

I have written a method in java to play a sound. It works fine on my ubuntu laptop but doesnt work on windows. There is no error but i think it might be bypassing the drain method on windows for some reason.
public static void runOnce(final String location) {
new Thread(new Runnable() {
public void run() {
try {
File audioFile = new File(Game.gameFolder + "/sounds/" + location);
final AudioInputStream audioStream = AudioSystem.getAudioInputStream(audioFile);
AudioFormat format = audioStream.getFormat();
DataLine.Info info = new DataLine.Info(Clip.class, format);
final Clip audioClip = (Clip) AudioSystem.getLine(info);
audioClip.open(audioStream);
audioClip.start();
audioClip.drain();
try {
audioClip.close();
audioStream.close();
} catch (Exception e) {
System.out.println("heyeyeyeyye");
}
System.out.println("sound method ran");
} catch(Exception e) {}
}
}).start();
}
thanks -Tyler
EDIT:
i remember actually it worked on windows before i used drain but after a certain amount of time it wouldnt load anymore so i switched to drain
I suggest you use try-with-resources and that you join() the Thread you start and never swallow the message from your Exception. Something like,
public static void runOnce(final String location) {
File audioFile = new File(Game.gameFolder + "/sounds/" + location);
Thread t = new Thread(new Runnable() {
public void run() {
try (AudioInputStream audioStream = AudioSystem
.getAudioInputStream(audioFile);) {
AudioFormat format = audioStream.getFormat();
DataLine.Info info = new DataLine.Info(Clip.class, format);
try (Clip audioClip = (Clip) AudioSystem.getLine(info);) {
audioClip.open(audioStream);
audioClip.start();
audioClip.drain();
}
System.out.println("heyeyeyeyye");
System.out.println("sound method ran");
} catch (Exception e) {
e.printStackTrace();
}
}
});
t.start();
t.join();
}

LineUnavailableException while playing sound in java

I have this slightly altered a sound manager from another question How can I play sound in Java?. Here it is:
public static synchronized void playSound(final String url)
{
new Thread(new Runnable()
{
public void run()
{
try
{
Clip clip = AudioSystem.getClip();
AudioInputStream inputStream = AudioSystem.getAudioInputStream(new File("sound/" + url));
clip.open(inputStream);
clip.start();
}
catch (Exception e)
{
e.printStackTrace();
}
}
}).start();
}
Whenever I call this method I get a javax.sound.sampled.LineUnavailableException in the clip.open(inputStream);. What can I do to repair it? Why does it not work?

Categories