I'm making a demo to play WAV file and stuck with this. When I begin to play the music, I disable the btnPlay. Now I want when the music finish playing, the btnPlay must be enable automatically. But I can't do this. I can get the file duration in microsecond but I don't know what to do next. Here is the code.
public void playmusic(){
try{
btnClose.setEnabled(true);
btnShuffle.setEnabled(true);
btnRepeat.setEnabled(true);
btnPause.setEnabled(true);
btnStop.setEnabled(true);
btnPlay.setEnabled(false);
if(isPausing==false){
AudioInputStream ais = AudioSystem.getAudioInputStream(f);
clip = AudioSystem.getClip();
clip.open(ais);
clip.start();
}
else{
isPausing=false;
clip.start();
}
}
catch(Exception ex){}
}
Could you give me a solution for this? Thank you very much!
You can add a LineListener to the clip and re-enable the button when the LineEvent.Type Stop fires.
You can find more information on the Line interface here. The code might look something like this:
LineListener listener = new LineListener() {
public void update(LineEvent event) {
if (event.getType() == Type.STOP) {
btnPlay.setEnabled(true);
}
}
};
clip.addLineListener(listener);
Related
I am developing an alarm clock program that plays an audio clip as an alarm. I can successfully play an audio clip, and terminate an inactive alarm. However, when I try to terminate an alarm that is currently playing, the audio keeps playing. Solutions I've tried were setting the clip to null, clip.stop(); and
public void stopSound(Clip clip){
clip.stop();
clip.flush();
clip.close();
}
Is there a way to end a clip at any percentage through a clip?
This works for me. It stops after 5 seconds of playing.
import javax.sound.sampled.*;
import java.io.File;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
public class Main {
public static void main(String[] args) {
playMusic("<Type your path to music here>");
}
static void playMusic(String musicLocation) {
new Thread(() -> {
try {
File musicPath = new File(musicLocation);
if (musicPath.exists()) {
AudioInputStream audioInput = AudioSystem.getAudioInputStream(musicPath);
Clip clip = AudioSystem.getClip();
clip.open(audioInput);
clip.start();
TimeUnit.SECONDS.sleep(5);
clip.stop();
} else {
System.out.println("Can't find file");
}
} catch (IOException | UnsupportedAudioFileException | LineUnavailableException | InterruptedException e) {
throw new RuntimeException(e);
}
}).start();
}
}
I'm using java to try and make an alarm of sorts. I want to input a time and then when it hits zero, play a specific .mp3. The countdown works fine, but when it hits zero and tries to play the mp3, it can't find the file. Advice? I've already searched the site and can't find anything simple enough for me to use (I'm a beginner). Here's what I got so far:
public static void main(String[] args) {
int timer;
File song = new File("C:/Users/N/Documents/Random/Handies/Proj/Song.mp3");
timer = 1;
timer*=1;
while (timer != 0)
{
try
{
Thread.sleep(1000);
} catch (InterruptedException e) {}
timer -= 1;
System.out.println(timer);
}
if (timer == 0)
Play(song);
}
public static void Play(File song)
{
try
{
Clip clip = AudioSystem.getClip();
clip.open(AudioSystem.getAudioInputStream(song));
clip.start();
}
catch (Exception exc)
{
exc.printStackTrace(System.out);
}
}
With JavaFX you can easily play the MP3 like this:
public class Test extends javafx.application.Application {
#Override
public void start(Stage primaryStage) throws Exception {
File file = new File("/path/test.mp3");
Media media = new Media(file.toURI().toString());
MediaPlayer mediaPlayer = new MediaPlayer(media);
mediaPlayer.play();
}
}
I usually find it hard using AudioSystem for this kind of thing.
So im pretty close to my end and I can't figure out why its doing like this. Maybe because im stupid right now after coding a while. however. So I have two files that should be allowed to my program. The first one is a MP3 and the Other one is Wav. I got them to work. By that I mean if I choose Wav file, the sound comes, if I choose the mp3 it works so there is no problem with that but the problem is right now is when pressing Open (-> browersing a file) and then press play, the sound should come, and yes it does. so when I open a another file for exemple a new song. then press play. the song is playing with the first song which makes it two tracks at the same time and I want it to make -> when one song is playing then play. and if I choose new song and press play, then the first song should go away. I think im pretty close but yeah. However I have done this
static boolean status = true;
btnPlay.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if (e.getSource() == btnPlay) {
if(!status) {
clip.start();
lblPlaying.setText("Enjoy the music!");
} else if(status == true) {
mp3_player.play();
lblPlaying.setText("Enjoy the music!");
}
}
}
});
public void Choose() throws IOException {
String userDir = System.getProperty("user.home");
JFileChooser fileChooser = new JFileChooser(userDir +"/Desktop");
int returnValue = fileChooser.showOpenDialog(null);
if (returnValue == JFileChooser.APPROVE_OPTION) {
File selectedFile = fileChooser.getSelectedFile();
System.out.println(selectedFile.getName());
String ext = selectedFile.getPath();
if(ext.endsWith(".mp3")) { // For mp3
status = true;
mp3_player = new MP3Player(selectedFile);
lblPlayURL.setText(selectedFile.getName());
}
else if(ext.endsWith(".wav")) {
status = false; //For .Wav
try {
AudioInputStream stream;
AudioFormat format;
DataLine.Info info;
clip = clip;
stream = AudioSystem.getAudioInputStream(selectedFile);
format = stream.getFormat();
info = new DataLine.Info(Clip.class, format);
clip = (Clip) AudioSystem.getLine(info);
clip.open(stream);
lblPlayURL.setText(selectedFile.getName());
}
catch(Exception e) {
//whatevers
}
}
}
}
}
To make the story shorter so what I have done is I have a variable that is set boolean to false. so whenever False is running it takes the Wav. when True its mp3. but as I said. the problem is sitting when.
Choose a song
Press play for the song
Choose new song
Press play for the new song (and here is where the 1st one song still going on which I don't want to)
Have I done something wrong with booleans?
EDIT: Forgot to add the open button:
btnOpen.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if(e.getSource() == btnOpen) {
try {
Choose();
}
catch (IOException e1) {
e1.printStackTrace();
}
}
}
});
}
edit : Stop method
,
btnStop.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
if(e.getSource() == btnStop) {
if(!status) {
clip.stop();
lblPlaying.setText("Nothing plays right now!");
} else if(status == true) {
mp3_player.stop();
lblPlaying.setText("Nothing plays right now!");
}
}
}
});
You need to have another flag which tells you if it's playing or not. Then before you start the song, check the flag, then STOP any music if it's true, then start the new one.
You essentially have a design flaw. The system is capable of playing multiple songs at once, it didn't know you wanted to stop one of them.
In the board game I am designing, each user has a grid with 100 cells. The user clicks a cell in the computer's grid, which makes a sound and changes to a different colour. The computer then automatically clicks a cell in the user's grid, which makes a sound and changes to a different colour.
The user's clicks are dealt with via the MouseListener (and the MouseClicked method). Currently, the last thing the method does is call the computerMove() method. This method executes and performs the computer move before giving changing the current player back to human. The game proceeds when the human makes another mouse click.
Ideally, I'd like to have a pause (perhaps a second) between each player move. However, due to the fact the computerMove method is being called inside the MouseClicked method, this is proving troublesome. By using Thread.sleep and even a TimerTask, the best I can do is to slow the human player's move down. However, as soon as the player makes a mouse click, the computer instantaneously responds.
Does anybody have any suggestions as to how I could implement a delay? Do I need to change how I am calling the methods?
ComputerMove method:
public void computerMove() {
if (currentTurn == computer) {
int xPos = randomGenerator.nextInt(10);
int yPos = randomGenerator.nextInt(10);
LogicCell attackedCell = new LogicCell(xPos, yPos);
playerGridLogic.addCellsThatHaveBeenAttacked(attackedCell);
if (playerGridLogic.getCellsWithShips().contains(attackedCell)) {
playerGrid.getCellArray()[xPos][yPos].setBackground(Color.ORANGE);
hitSound();
}
else {
playerGrid.getCellArray()[xPos][yPos].setBackground(Color.MAGENTA);
missSound();
}
nextTurn();
}
}
Corresponding MouseClick method:
#Override
public void mouseClicked(MouseEvent e) {
if (allComputerShipsPlaced && currentTurn == human) {
ViewCell currentCell = (ViewCell) e.getSource();
xPos = currentCell.getXPos();
yPos = currentCell.getYPos();
LogicCell attackedCell = new LogicCell(xPos, yPos);
computerGridLogic.addCellsThatHaveBeenAttacked(attackedCell);
if (computerGridLogic.getCellsWithShips().contains(attackedCell)) {
cellArray[xPos][yPos].setBackground(Color.ORANGE);
hitSound();
}
else {
cellArray[xPos][yPos].setBackground(Color.MAGENTA);
missSound();
}
nextTurn();
computerMove();
}
}
missSound method() (hitSound is very similar):
public static void missSound() {
try {
Clip clip = AudioSystem.getClip();
clip.open(AudioSystem.getAudioInputStream(new File("water-splash.wav")));
clip.start();
}
catch (Exception exc)
{
exc.printStackTrace(System.out);
}
}
Edit: I've tried changing the sound classes to this, but to no avail:
public static void hitSound()
{
try
{
Clip clip = AudioSystem.getClip();
clip.open(AudioSystem.getAudioInputStream(new File("bomb-explosion.wav")));
clip.start();
LineListener listener = new LineListener() {
public void update(LineEvent event) {
if (event.getType() != Type.STOP) {
return;
}
try {
queue.take();
} catch (InterruptedException e) {
//ignore this
}
}
};
clip.addLineListener(listener);
}
catch (Exception exc)
{
exc.printStackTrace(System.out);
}
}
You should be able to add a listener and react to the end of the sound.
See this question: how can I wait for a java sound clip to finish playing back?
This works for me:
public class Test {
public static void main(String[] args) {
final Object foo = new Object();
Clip clip;
try {
clip = AudioSystem.getClip();
clip.open(AudioSystem.getAudioInputStream(new File("go.wav")));
clip.addLineListener(new LineListener() {
public void update(LineEvent event) {
if(event.getType() == LineEvent.Type.STOP){
System.out.println("done playing");
synchronized(foo) {
foo.notify();
}
}
}
});
clip.start();
} catch (Exception e) {
e.printStackTrace();
}
synchronized(foo) {
try {
foo.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
I would consider calling computerMove inside nextTurn, and do the waiting inside nextTurn.
You could use Thread.sleep in computerMove() to pause the execution. You can use clip.getMicrosecondsLength to get the length of the sound effect in microseconds. Multiply it with 1000 and pass it to sleep to wait for the sound effect to finish.
Clip clip = AudioSystem.getClip();
clip.open(AudioSystem.getAudioInputStream(new File("water-splash.wav")));
clip.start();
int lengthInMilliseconds = clip.getMicrosecondLength() * 1000;
Thread.sleep(lengthInMilliseconds);
I have created a class to play the sound when I click the buttons.
Here is the code :
public void playSound()
{
try
{
AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(new File("beep-1.wav"));
Clip clip = AudioSystem.getClip( );
clip.open(audioInputStream);
clip.start( );
}
catch(Exception e)
{
System.out.println("Error with playing sound.");
}
}
When I want to implement it into the the ButtonListener method, it's seem like no sound is played.
Here the ButtonListener code :
private class ButtonListener implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
if (replayButton == e.getSource())
{
playSound();
}
}
}
What's wrong with the code?
EDIT :
Basically I'm trying to create a simple memory game, and I want to add sound to the buttons when clicked.
SOLVED :
Seems like the audio file I downloaded from Soundjay got problem, and hence, the audio file can't be played. #_#
Use
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
playSound();
}
});
This should work:
public class Test extends JFrame {
public static void main(String[] args) {
new Test();
}
public Test() {
JButton button = new JButton("play");
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
playSound();
}});
this.getContentPane().add(button);
this.setVisible(true);
}
public void playSound() {
try {
AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(new File("beep.wav"));
Clip clip = AudioSystem.getClip( );
clip.open(audioInputStream);
clip.start( );
}
catch(Exception e) {
e.printStackTrace( );
}
}
}
Note that during the play of your file, the GUI will be not responsable. Use the approach from Joop Eggen in your listener to correct this. It will play the file asynchronous.
SwingUtilities.invokeLater(new Runnable() {
public void run() {
playSound();
}
});
Any stacktrace, please??? did you add listener to the button???
Anyway the standart way have some bugs when targeting cross-platform. Use Java Media Framework at http://www.oracle.com/technetwork/java/javase/tech/index-jsp-140239.html.