JAVA - Boolean correction - Still going on when pressing Play - java

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.

Related

Audio not playing within thread Android

So i've got an audio file that i'd like to play within a thread, this is where i've left the comment // Tried playing audio here . But the even with the logic to make sure that it only plays once no audio is being played. Instead it seems like it's forcing the application to skip frames instead causing the game to have a few glitches because of the inconsistent frame rate.
Here's the code which i've been using.
while (isRunning) {
// Go back to the if statement and check if the surface still isn't valid
if (!mySurfaceHolder.getSurface().isValid())
continue;
// Lock the canvas for editing, make changes and unlock with new changes
final Canvas canvas = mySurfaceHolder.lockCanvas();
canvas.drawRect(0,0,canvas.getWidth(), canvas.getHeight(), pWhite);
// Create the block to check the answer
answerObject = new AnswerObject(canvas);
animalObject.move(canvas, tilt);
if(answerObject.onCollision(animalObject) != null){
// Inside of box else is outside of box
if (answerObject.onCollision(animalObject)) {
// If the animal is part of that enviroment
if (verifyEnviroment(enviromentObject.getAnimals())){
isCorrect = true;
} else {
isCorrect = false;
}
} else {
// If the animal is part of that enviroment
if (!verifyEnviroment(enviromentObject.getAnimals())){
// Tried playing audio here
isCorrect = true;
} else {
// Tried playing audio here
isCorrect = false;
}
}
gameActivity.runOnUiThread(new Runnable() {
#Override
public void run() {
if (isCorrect){
scoreObject.setScore(10);
} else {
healthObject.setHealth(10);
healthObject.setHealthImgs(healthObject.getHealth());
if (healthObject.getHealth() <= 0){
isRunning = false;
}
}
resetGameObjects();
}
});
}
mySurfaceHolder.unlockCanvasAndPost(canvas);
}

Automatically enable button after playing music

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);

How to delay a board game between moves so a sound can play

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);

AudioInputStream() does not stop

I have inserted a background audio into my program using AudioInputStream.
When I press the On, the background audio will play, and Off will stop playing the background audio.
Here is the part of my code for the audio playing part :
public void playSound(int i)
{
try
{
. //Others buttons sound
. //Others buttons sound
if(i == 3 || i == 4)
{
AudioInputStream audioInputStream = AudioSystem.getAudioInputStream(new File("Background.wav"));
Clip clip3 = AudioSystem.getClip( );
clip3.open(audioInputStream);
if(i == 3)
{
clip3.loop(Clip.LOOP_CONTINUOUSLY);
clip3.start();
settingSubMenuItem3.setEnabled(false);
settingSubMenuItem4.setEnabled(true);
}
if(i == 4)
{
clip3.stop();
settingSubMenuItem3.setEnabled(true);
settingSubMenuItem4.setEnabled(false);
}
}
catch(Exception e)
{
System.out.println("Error with playing sound.");
e.printStackTrace();
}
}
And here is the ButtonListener part :
private class MenuItemListener implements ActionListener
{
public void actionPerformed(ActionEvent e)
{
if(e.getSource() == settingSubMenuItem3)
{
playSound(3);
}
if(e.getSource() == settingSubMenuItem4)
{
playSound(4);
}
}
}
My code can play the audio when I press On button, but when I press Off button, it does not work.
There is no error during compile and run.
What is the error of my code?
Your AudioInputStream variable, audioInputStream, and Clip variable, clip3, are local to the method. The object you are trying to stop is not the same as the one that's playing currently.
Make them class fields, check that they're not null before calling methods on them, don't create a new object if you're trying to stop the currently playing object, and you should be OK.
Something like:
public void playSound(int i) {
try {
// ...
if (i == 3 || i == 4) {
if (i == 3) {
audioInputStream = AudioSystem
.getAudioInputStream(new File("Background.wav"));
clip3 = AudioSystem.getClip();
clip3.open(audioInputStream);
clip3.loop(Clip.LOOP_CONTINUOUSLY);
clip3.start();
settingSubMenuItem3.setEnabled(false);
settingSubMenuItem4.setEnabled(true);
}
if (i == 4) {
if (clip3 != null && clip3.isActive()) {
clip3.stop();
settingSubMenuItem3.setEnabled(true);
settingSubMenuItem4.setEnabled(false);
}
}
}
} catch (Exception e) {
System.out.println("Error with playing sound.");
e.printStackTrace();
}
}
Again, making audioInputStream and clip3 non-static class fields.
As an aside, I would avoid using "magic" numbers such as 3 and 4 as you are doing as this may become a devil to debug 6 months from now. Instead give each JButton its own Action. It deserves no less.

File saved with JFileChooser showSaveDialog even on 'Cancel'

I have a file saved that works fine apart from one problem. When the cancel button is pressed a copy of the file is saved in the java directory. This only happens when the cancel button is pressed, if the save button is used the file ends up where the user selects. How can I stop this happening so when the cancel button is pressed nothing is saved anywhere?
My code is below, all help appreciated. Thanks
// Save dialog
private void savePlaylist() {
JFileChooser savePlaylistDialog = new JFileChooser();
savePlaylistDialog.setSelectedFile(new File(newPlaylistNameTxt.getText() + ".txt"));
savePlaylistDialog.showSaveDialog(playlistDialogs);
File savePlaylist = savePlaylistDialog.getSelectedFile();
try {
outFile = new PrintWriter(new FileWriter(savePlaylist));
outFile.println(newPlaylistInformationTxt.getText());
outFile.close();
// Plays a sound when play() is called (edited from Bombard)
try {
Clip saveButtonSound = AudioSystem.getClip();
AudioInputStream ais = AudioSystem.getAudioInputStream(new File("Tri-tone.wav"));
saveButtonSound.open(ais);
saveButtonSound.start();
} catch (Exception ex) {
ex.printStackTrace();
}
} catch (Exception ex) {
JOptionPane.showMessageDialog(null, "File could not be written, try again.");
}
}
savePlaylistDialog.showSaveDialog(playlistDialogs);
That method call above returns an int. You need to check its value - if the user clicked on the Save button, it would return JFileChooser.ACCEPTED_OPTION. In this case, you are taking the return value (which could be accepted/save or cancel), ignoring it, and proceeding to write the data to disk anyway.
Here is the fixed code I used:
// Save dialog
private void savePlaylist() {
JFileChooser savePlaylistDialog = new JFileChooser();
savePlaylistDialog.setSelectedFile(new File(newPlaylistNameTxt.getText() + ".txt"));
int status = savePlaylistDialog.showSaveDialog(playlistDialogs);
try {
if (status == JFileChooser.APPROVE_OPTION) {
//User has pressed save button
File savePlaylist = savePlaylistDialog.getSelectedFile();
outFile = new PrintWriter(new FileWriter(savePlaylist));
outFile.println(newPlaylistInformationTxt.getText());
outFile.close();
// Plays a sound when play() is called (edited from Bombard)
try {
Clip saveButtonSound = AudioSystem.getClip();
AudioInputStream ais = AudioSystem.getAudioInputStream(new File("Tri-tone.wav"));
saveButtonSound.open(ais);
saveButtonSound.start();
} catch (Exception ex) {
ex.printStackTrace();
}
} else if (status == JFileChooser.CANCEL_OPTION) {
// User has pressed cancel button
}
} catch (Exception ex) {
JOptionPane.showMessageDialog(null, "File could not be written, try again.");
}
}
showSaveDialog should return whether the user canceled or not and you code shoul act accordingly. At the moment you save no matter what the user did in the save dialog.

Categories