How to stop a sound?

Because we wanted to play sound in our GUI based program we took this code:

















Now we’d like to also make it possible that the sound can be stopped. How can we do this?



Thanks in advance.

Hi,



stopAllSounds();



will stop all sounds in the movie.



button sound is just putting the sound on the appropriate keyframe in the button.



Object sound takes a bit of actionscript. You need to create a new sound object and then depending on how you want to load it… either attaching it from the library or using the loadSound method…

Code:



mySound = newSound();

mySound.attachSound(“soundtrack”);

mySound.start();

trace(“Soundtrack is " + mySound.duration/1000 + " seconds in length”);



This would require the sound to be in your library and exported for actionscript in the first frame with an export name of “soundtrack”



[irrelevant SEO link removed by admin, post left for amusement]

@royabryant



o_O wtf? wrong universe?

Sorry the code is right here:



[xml]<panel id="panel_bottom_sON" height="6%" width="80%" valign="bottom" backgroundImage="Interface/RedHeadGUI/Buttons/import1.png" childLayout="center" visibleToMouse="true">

<effect>

<onHover name="changeImage" active="Interface/RedHeadGUI/Buttons/import2.png" inactive="Interface/RedHeadGUI/Buttons/import1.png" />

<onClick name="playSound" sound="myclick"/>

</effect>

</panel>[/xml]

Well, if you wanna manage the sounds, it should be better you use AudioNode instead. I did an audio manager for my app, take a look:



AudioManager.java



[java]

/*

  • To change this template, choose Tools | Templates
  • and open the template in the editor.

    */

    package kinetrax.audio;



    import com.jme3.asset.AssetManager;

    import com.jme3.audio.AudioNode;

    import com.jme3.scene.Node;

    import com.jme3.scene.SceneGraphVisitor;

    import com.jme3.scene.Spatial;

    import java.util.ArrayList;

    import java.util.List;

    import java.util.logging.Level;

    import java.util.logging.Logger;

    import kinetrax.util.Stopwatch;



    /**

    *
  • @author Glauco Márdano

    /

    public class AudioManager {



    private static final Logger logger = Logger.getLogger(AudioManager.class.getName());

    private AssetManager assetManager;

    private Node rootNode;

    private List<Stopwatch> stopwatchList = new ArrayList<Stopwatch>();

    private float audioVolume = 1f;



    public AudioManager(AssetManager assetManager, Node rootNode) {

    this.assetManager = assetManager;

    this.rootNode = rootNode;

    rootNode.depthFirstTraversal(stopwatchVisitor);

    logger.info(“Audio Manager created!”);

    }



    public void playAudio(String name) {

    logger.log(Level.INFO, “Play audio {0}”, name);

    AudioNode ad = getAudio(name);

    Stopwatch sw = getStopwatch(ad);

    ad.play();

    sw.start();

    }



    public void resumeAudio(String name) {

    logger.log(Level.INFO, “Resume audio {0}”, name);

    AudioNode ad = getAudio(name);

    Stopwatch sw = getStopwatch(ad);

    ad.play();

    sw.resume();

    }



    public void pauseAudio(String name) {

    logger.log(Level.INFO, “Pause audio {0}”, name);

    AudioNode ad = getAudio(name);

    Stopwatch sw = getStopwatch(ad);

    // doesn’t work

    // ad.pause();

    ad.stop();

    sw.pause();

    ad.setTimeOffset(sw.elapsed() * 1f / 1000);

    }



    public void stopAudio(String name) {

    logger.log(Level.INFO, “Stop audio {0}”, name);

    AudioNode ad = getAudio(name);

    Stopwatch sw = getStopwatch(ad);

    ad.stop();

    sw.stop();

    ad.setTimeOffset(0);

    }



    public void setAudioElapsedTime(String name, long elapsed) {

    logger.log(Level.FINEST, “Set audio elapsed time {0}”, name);

    AudioNode ad = getAudio(name);

    Stopwatch sw = getStopwatch(ad);

    ad.setTimeOffset(elapsed * 1f / 1000);

    sw.reset(elapsed);

    }



    public Stopwatch getStopwatch(AudioNode ad) {

    return stopwatchList.get(ad.getParent().getChildIndex(ad));

    }



    public AudioNode getAudio(String name) {

    return (AudioNode) rootNode.getChild(name);

    }



    public void setAudioVolume(float volume) {

    audioVolume = volume;

    rootNode.depthFirstTraversal(volumeVisitor);

    }

    private final SceneGraphVisitor volumeVisitor = new SceneGraphVisitor() {



    public void visit(Spatial spatial) {

    if (spatial instanceof AudioNode) {

    ((AudioNode) spatial).setVolume(audioVolume);

    }

    }

    };

    private final SceneGraphVisitor stopwatchVisitor = new SceneGraphVisitor() {



    public void visit(Spatial spatial) {

    if (spatial instanceof AudioNode) {

    AudioNode ad = (AudioNode) spatial;

    ad.setVolume(audioVolume);

    stopwatchList.add(new Stopwatch());

    }

    }

    };

    }

    [/java]



    Stopwatch.java



    [java]

    /


* Antelmann.com Java Framework by Holger Antelmann
* Copyright (c) 2005 Holger Antelmann <info@antelmann.com>
* For details, see also http://www.antelmann.com/developer/
*
*/
package kinetrax.util;

import java.io.Serializable;
import java.util.Date;

/**
* Stopwatch is a convenient implementation to bench just about anything.
* Todo: provide support for internationalization
*
* @author Holger Antelmann
*/
public class Stopwatch implements Serializable {

private static final long serialVersionUID = -6958796021257440232L;
private long start;
private boolean paused;
private long halted;
private long end;

/**
* initializes a running Stopwatch starting now
*/
public Stopwatch() {
start = System.currentTimeMillis();
}

/**
* This constructor starts a Stopwatch starting at the current time
* minus the milliseconds given. I.e. a negative value would mean that
* the StopWach counts towards zero until zero is reached and then
* continues to count forward.
*/
public Stopwatch(long milliseconds) {
start = System.currentTimeMillis() - milliseconds;
}

/**
* This constructor starts a Stopwatch starting at the given point in time.
* I.e. a time in the future would mean that the StopWach counts towards
* zero until zero is reached and then continues to count forward.
*/
public Stopwatch(Date time) {
start = time.getTime();
}

/**
* This constructor generates a new Stopwatch synchronized
* with the given timer
*/
public Stopwatch(Stopwatch timer) {
synchronize(timer);
}

/**
* If the boolean parameter is true, this call is equivalent
* to the default constructor; if the parameter is false,
* the StopWach will be initialized but is halted with
* no elapsed time so far.
*/
public Stopwatch(boolean isRunning) {
this();
if (!isRunning) {
pause();
reset();
}
}

public Stopwatch(long milliseconds, boolean isRunning) {
if (isRunning) {
start = System.currentTimeMillis() - milliseconds;
} else {
end = System.currentTimeMillis();
start = end - milliseconds;
paused = true;
}
}

/**
* synchronize() will make this Stopwatch equivalent
* to the passed timer
*/
public synchronized void synchronize(Stopwatch timer) {
synchronized (timer) {
start = timer.getStartTime();
paused = timer.isPaused();
end = timer.getEnd();
halted = timer.getHalted();
}
}

/**
* returns the time this Stopwatch was constructed or when any of
* the reset() or restart() methods were called last
*/
public long getStartTime() {
return start;
}

/**
* returns the initial start time of the Stopwatch.
* This time may have been changed through synchronize() or restart().
*/
public Date getStartDate() {
return new Date(start);
}

/**
* returns true if Stopwatch is paused.
* isPaused() <==> !isRunning()
*/
public boolean isPaused() {
return (paused);
}

/**
* returns true if Stopwatch is running.
* isPaused() <==> !isRunning()
*/
public boolean isRunning() {
return (!paused);
}

/**
* pause() stops the timer and maintains the elapsed time;
* it does nothing if the timer is already paused.
*/
public synchronized void pause() {
if (!paused) {
end = System.currentTimeMillis();
paused = true;
}
}

/**
* resume() will reactivate a suspended timer (suspended through
* either stop() or pause()). The beginning time as well as the
* suspended time is maintained, so that the elapsed time remains
* accurate. If the StopWach is currently running, the function doesn't
* do anything.
*/
public synchronized void resume() {
if (paused) {
halted = halted + (System.currentTimeMillis() - end);
end = 0;
paused = false;
}
}

/**
* start() maintains the beginning time and sets
* the elapsed time to zero (through halted time);
* time will be running.
*/
public synchronized void start() {
halted = (System.currentTimeMillis() - start);
paused = false;
end = 0;
}

/**
* stop() returns the elapsed time and also performs
* a reset().
*/
public synchronized long stop() {
long t = elapsed();
pause();
reset();
return t;
}

/**
* reset() will set the start to the current time and set
* the halted time to zero. The running status (paused or not)
* of the timer is maintained.
*/
public synchronized void reset() {
start = System.currentTimeMillis();
if (paused) {
end = start;
}
halted = 0;
}

/**
* sets the given time as elapsed time; run/pause status remains
* and halted time is reset
*/
public synchronized void reset(long milliseconds) {
if (paused) {
start = System.currentTimeMillis() - milliseconds;
end = start + milliseconds;
halted = 0;
} else {
restart(milliseconds);
}
}

/**
* restart() reinitializes the timer equivalent to it
* just being construced with the default constructor (time is running).
*/
public synchronized void restart() {
start = System.currentTimeMillis();
halted = 0;
end = 0;
paused = false;
}

/**
* restart() reinitializes the timer with the passed
* milliseconds interpreted as already elapsed time.
*/
public synchronized void restart(long milliseconds) {
start = System.currentTimeMillis();
halted = -milliseconds;
end = 0;
paused = false;
}

/**
* returns the elapsed time in milliseconds
*/
public synchronized long elapsed() {
if (paused) {
return ((end - start) - halted);
} else {
return ((System.currentTimeMillis() - start) - halted);
}
}

/**
* returns a string representing the elapsed time with
* - if applicable - days, hours, minutes and seconds
* (down to the milliseconds).
*/
public String elapsedAsString() {
return timeAsString(elapsed());
}

/**
* displays the elapsed time as timeAsStringShort(elapsed())
*
* @see #timeAsStringShort(long)
*/
public String display() {
return timeAsStringShort(elapsed());
}

/**
* takes milliseconds and converts them into a String
* using all relevant time measures up to days
*/
public static String timeAsString(long milliSecs) {
String s = "";
int days = (int) (milliSecs / (1000 * 60 * 60 * 24));
int hours = (int) (milliSecs % (1000 * 60 * 60 * 24)) / 3600000;
int minutes = (int) (milliSecs % 3600000) / 60000;
double seconds = (double) (milliSecs % 60000) / 1000;
if (days != 0) {
s += days + " days, ";
}
if (hours != 0) {
s += hours + " h, ";
}
if (minutes != 0) {
s += minutes + " min, ";
}
s += seconds + " sec";
return s;
}

/**
* takes milliseconds and converts them into a short String.
* The format is <pre>h:mm:ss</pre>.
*/
public static String timeAsStringShort(long milliSecs) {
int hours = Math.abs((int) milliSecs / 3600000);
int minutes = Math.abs((int) (milliSecs % 3600000) / 60000);
int seconds = Math.abs((int) (milliSecs % 60000) / 1000);
String s = hours + ":";
s += ((minutes < 10) ? ("0" + minutes) : String.valueOf(minutes));
s += ":";
s += ((seconds < 10) ? ("0" + seconds) : String.valueOf(seconds));
if (milliSecs < 0) {
s = "-" + s;
}
return s;
}

/**
* returns the elapsed time in a convenient format
* including elapsedAsString() and tells
* whether the Stopwatch is currently running or not
*/
public String toString() {
String s = "elapsed time: ";
s += elapsedAsString();
if (paused) {
s += " (time paused)";
} else {
s += " (time running)";
}
return (s);
}

protected long getHalted() {
return halted;
}

protected long getEnd() {
return end;
}
}
[/java]

The “FadeSound” effect should stop the sound when this effect ends.



Or you should be able to stop sounds directly like so:



[java]SoundHandle soundHandle = nifty.getSoundSystem().getSound(“soundId”);

soundHandle.stop()[/java]

1 Like

Unfortunately it doesn’t work with the StopHandle-thing.



MyScreen.java:

[java]public void stopSound(String soundId) {

SoundHandle soundHandle = nifty.getSoundSystem().getSound(“soundId”);

soundHandle.stop();

}[/java]



And in the XML:

[xml]<panel id=“panel_bottom_sON” height=“6%” width=“20%” valign=“bottom” backgroundImage=“Interface/RedHeadGUI/Buttons/music.png” childLayout=“center” visibleToMouse=“true”>

<effect>

<onClick name=“playSound” sound=“myclick”/>

</effect>

<interact onSecondaryClick=“stopSound(myclick)” />

</panel>[/xml]



Unfortunately this doesn’t work. Does anyone have an idea how I can realize it so that it works? (when you click the button the first time, the music should play and by clicking it the second time it should stop the music)

Any ideas? :frowning:

Works fine for me!



When you access the sound from Java with:



[java]SoundHandle soundHandle = nifty.getSoundSystem().getSound(“soundId”);[/java]



You need to use the id of the sound. Since you’ve started the sound with the id “myclick” in your XML you should use:



[java]SoundHandle soundHandle = nifty.getSoundSystem().getSound(“myclick”);[/java]



And “onSecondaryClick” does not mean second click on this element but instead it means “click with the second mouse button”. In most cases this means a click with the right mouse button!



So now I can click with the left mouse button on the panel and the sound starts playing and when I press with the right mouse button on the panel the sound stops playing! Everything works as expected.



If you really need to toggle the sound playing with the left mouse button you could add a single “interact onClick” event handler and toggle the sound playing in the eventhandler directly (without using the onClick playSound effect - just start and stop the sound playing from Java in this case).

Yeah I know that it has to work like this, but it just doesn’t work! I just don’t know why…I post the complete Gui.java and the XML right here, so you can see how it looks like:



[java]package RedHeadGUI;



import RedHead.Main;



import com.jme3.niftygui.SoundHandleJme;

import com.jme3.app.Application;

import com.jme3.app.state.AbstractAppState;

import com.jme3.app.state.AppState;

import com.jme3.app.state.AppStateManager;

import com.jme3.audio.AudioNode;

import com.jme3.input.controls.ActionListener;

import com.jme3.input.controls.MouseButtonTrigger;

import com.jme3.material.Material;

import com.jme3.renderer.RenderManager;

import com.jme3.scene.shape.Box;

import de.lessvoid.nifty.Nifty;

import de.lessvoid.nifty.controls.Menu;

import de.lessvoid.nifty.controls.MenuItemActivatedEvent;

import de.lessvoid.nifty.elements.Element;

import de.lessvoid.nifty.elements.render.TextRenderer;

import de.lessvoid.nifty.screen.Screen;

import de.lessvoid.nifty.screen.ScreenController;

import de.lessvoid.nifty.spi.sound.SoundHandle;

import de.lessvoid.nifty.tools.SizeValue;

import java.io.IOException;

import java.net.URI;

import java.awt.Desktop;



public class Gui extends Main implements ScreenController, AppState{



private Nifty nifty;

private Element popup;



/** custom methods /

public Gui() {



/
* You custom constructor, can accept arguments /

}



public void startGame(String nextScreen) {

nifty.gotoScreen(nextScreen); // switch to another screen

}



/
* Nifty GUI ScreenControl methods */

public void bind(Nifty nifty, Screen screen) {

this.nifty = nifty;

}



public void backToStart(String prevScreen) {

nifty.gotoScreen(prevScreen); // switch to another screen

}



public void goToNext(String nextScreen) {

nifty.gotoScreen(nextScreen); // switch to another screen

}



public void onStartScreen() {

}



public void onEndScreen() {

}

public void linkHelp() throws IOException {

String url = “http://redheadsim.re.funpic.de/help2.html”;

java.awt.Desktop.getDesktop().browse(java.net.URI.create(url));

}





public void startSound(String myclick) {

SoundHandle soundHandle = nifty.getSoundSystem().getSound(myclick);

soundHandle.play();

}



public void stopSound(String myclick) {

SoundHandle soundHandle = nifty.getSoundSystem().getSound(myclick);

soundHandle.stop();

}



@Override

public void cleanup() {

// TODO Auto-generated method stub



}



@Override

public boolean isEnabled() {

// TODO Auto-generated method stub

return false;

}



@Override

public boolean isInitialized() {

// TODO Auto-generated method stub

return false;

}



@Override

public void postRender() {

// TODO Auto-generated method stub



}



@Override

public void render(RenderManager arg0) {

// TODO Auto-generated method stub



}



@Override

public void setEnabled(boolean arg0) {

// TODO Auto-generated method stub



}



@Override

public void stateAttached(AppStateManager arg0) {

// TODO Auto-generated method stub



}



@Override

public void stateDetached(AppStateManager arg0) {

// TODO Auto-generated method stub



}



@Override

public void update(float arg0) {

// TODO Auto-generated method stub



}









}[/java]





[xml]<?xml version=“1.0” encoding=“UTF-8”?>

<nifty xmlns=“http://nifty-gui.sourceforge.net/nifty-1.3.xsd” xmlns:xsi=“http://www.w3.org/2001/XMLSchema-instance

xsi:schemaLocation=“http://nifty-gui.sourceforge.net/nifty-1.3.xsd http://nifty-gui.sourceforge.net/nifty-1.3.xsd”>

<useStyles filename=“nifty-default-styles.xml” />

<useControls filename=“nifty-default-controls.xml” />

<registerSound id=“myclick” filename=“Interface/RedHeadGUI/sound/walkgeloopt.ogg” />

<!-- USER INTERFACE von Frederik und Daniel–>





<!-- +++++++++++++++++++++++++++++++++++++++ -->

<!-- Startscreen Viewer–>

<!-- +++++++++++++++++++++++++++++++++++++++ -->



<screen id=“start” controller=“RedHeadGUI.Gui”>

<layer id=“background” childLayout=“center”>

<image filename=“Interface/RedHeadGUI/rh-hud-v2.png”></image>

</layer>

<layer id=“foreground” childLayout=“horizontal”>

<panel id=“panel_left” width=“80%” height=“100%” childLayout=“horizontal” >

<panel id=“space” width=“0.5%” height=“6%”></panel>

<!-- Linkes kleineres Panel im linken Panel–>

<panel id=“panel_left_left” width=“18%” height=“80%” childLayout=“vertical” >

<panel id=“space” width=“0.5%” height=“1%”></panel>



<!-- Help Button PopUp–>

<panel id=“help” height=“6%” width=“20%” valign=“bottom” backgroundImage=“Interface/RedHeadGUI/Buttons/help.png” childLayout=“center” visibleToMouse=“true”>

<!–<effect>

<onHover name=“changeImage” active=“Interface/RedHeadGUI/Buttons/help2.png” inactive=“Interface/RedHeadGUI/Buttons/help1.png” />

</effect>–>

<interact onClick=“linkHelp2()” />

</panel>



<panel id=“luecke_left” height=“100%” width=“22%” valign=“bottom” childLayout=“center” ></panel>



<!-- Musik Button On–>

<panel id=“panel_bottom_sON” height=“6%” width=“20%” valign=“bottom” backgroundImage=“Interface/RedHeadGUI/Buttons/music.png” childLayout=“center” visibleToMouse=“true”>

<!–<effect>

<onClick name=“playSound” sound=“myclick”/>

</effect>–>

<interact onClick=“startSound(myclick)” />

</panel>



<!-- Musik Button OFF–>

<panel id=“panel_bottom_sOFF” height=“6%” width=“20%” valign=“bottom” backgroundImage=“Interface/RedHeadGUI/Buttons/music.png” childLayout=“center” visibleToMouse=“true”>

<interact onClick=“stopSound(myclick)” />

</panel>





</panel>

</panel>



<!-- Rechtes Panel–>

<panel id=“panel_right” width=“18%” height=“80%” childLayout=“vertical” >







<!-- <panel id=“panel_right” height=“20%” width=“0%” align=“center” childLayout=“vertical”>–>



<!-- Menue Bild auf der rechten Seite–>

<panel id=“panel_menue” height=“90%” width=“80%” valign=“bottom” childLayout=“center” visibleToMouse=“true”></panel>



<!–Quit Button–>



<panel id=“panel_bottom_quit” height=“6%” width=“80%” valign=“bottom” backgroundImage=“Interface/RedHeadGUI/Buttons/quit1.png” childLayout=“center” visibleToMouse=“true”>

<interact onClick=“quitGame()” />

<effect>

<onHover name=“changeImage” active=“Interface/RedHeadGUI/Buttons/quit2.png” inactive=“Interface/RedHeadGUI/Buttons/quit1.png” />

</effect>

</panel>



</panel>



</layer>



</screen>







</nifty>[/xml]

Alright, I could finally reproduce this issue. Seems like there is some issue in SoundHandleJme which prevents it to be played again after being stopped. I’ve posted a bug report for this http://code.google.com/p/jmonkeyengine/issues/detail?id=511. Please keep an eye on the issue to see when it will be fixed.



As a workaround you could change:



[xml]<registerSound id=“myclick” filename=“Interface/RedHeadGUI/sound/walkgeloopt.ogg” />[/xml]



to



[xml]<registerMusic id=“myclick” filename=“Interface/RedHeadGUI/sound/walkgeloopt.ogg” />[/xml]



and keep the Java Code as is. The issue with stop() and play() only occurs when the sound is a “sound” instead of a “music” because a “sound” is handled slightly differently inside of SoundHandleJme :slight_smile:

1 Like

Hahahaha great sense of humour. I like!