It’s a small case, look like easy but in the end it’s a really big headache to me:
I got a heartbeat sound declare in the nifty XML:
[xml]<registerSound id=“heartbeatSpeedUp” filename=“Sounds/heartbeat/Heartbeat speeds up 2.ogg” />[/xml]
I triggered it with the onStartScreen trigger:
[xml]
<screen id=“hello_logo” controller=“mygame.GameGUIManager”>
<layer id=“layer” childLayout=“center”>
<effect>
<onStartScreen name=“playSound” sound=“heartbeatSpeedUp”/>
</effect> [/xml]
Then when the screen change I want to shut the sound up…
I 've tried a few way but all failed:
[java]
// Way1
SoundHandle sound1 = nifty.getSoundSystem().getSound(“heartbeatSpeedUp”);
sound1.stop(); // Won’t work?
// Way2
Element layer = getElementByPath(“hello_logo/layer”);
EffectManager efM = layer.getEffectManager();
efM.stopEffect(EffectEventId.onStartScreen);
efM.removeAllEffects(
// Won’t work?
// Way3
for (Effect ef : efM.getEffects(EffectEventId.onStartScreen, PlaySound.class)) {
EffectImpl efI = ef.getEffectImpl(PlaySound.class);
efI.deactivate(); // Won’t work?
}
[/java]
So how can I control that sound effect, I’ve read through Nifty’s source code but hardly to see how?
[java]public class PlaySound implements EffectImpl {
private boolean done;
private boolean repeat;
private SoundHandle soundHandle;
private Nifty nifty;
public void activate(final Nifty nifty, final Element element, final EffectProperties parameter) {
this.nifty = nifty;
soundHandle = nifty.getSoundSystem().getSound(parameter.getProperty(“sound”));
repeat = Boolean.valueOf(parameter.getProperty(“repeat”, “false”));
done = false;
}
public void execute(
final Element element,
final float normalizedTime,
final Falloff falloff,
final NiftyRenderEngine r) {
if (normalizedTime > 0.0f) {
if (soundHandle != null) {
if (!done) {
playSound();
done = true;
} else {
// in repeat mode, when the sound is not playing anymore we’ll simply start it again
if (repeat) {
if (!soundHandle.isPlaying()) {
playSound();
}
}
}
}
}
}
private void playSound() {
soundHandle.play();
soundHandle.setVolume(nifty.getSoundSystem().getMusicVolume());
}
public void deactivate() {
}
}[/java]
OMFG, just found this in the Nifty source code…
the deactivate method is not implemented yet Y_Y …
BTW, Effect is only for visual effects.
A different solution would be to use the engine to play that sound while you’re on that first screen and switch to other sounds (or stop the first) instead of using Nifty.
ok, time to set some things straight:
- effects are NOT for visual effects only! There are effects to play sounds or music and you should use them!
- the deactivate() method is not implemented because this method is called when the effect lifetime ends! If you would use playSound on “onStartScreen” and onStartScreen ends then stopping the sound in deactivate() would stop the sound playing immediatly
Certainly not what you want or expect I suppose. So playSound will simply continue playing.
- The SoundHandle implementation you got from Nifty when using the SoundDeviceJme is actually using the JME stuff to play sound. So this is really the right way to play sounds
The first way you’ve tried to stop the sound playing is the correct solution:
[java]// Way1
SoundHandle sound1 = nifty.getSoundSystem().getSound(“heartbeatSpeedUp”);
sound1.stop(); // Won’t work?[/java]
I don’t know why this doesn’t work thoLooking at the source for SoundHandleJme.java it looks like it should work:
[java] private AudioRenderer ar;
…
public void stop() {
if (fileName != null){
ar.stopSource(node);
node = null;
}
}[/java]
Sadly I’m not familar with the JME-Soundsystem. Any JME-SoundSystem gurus reading this? Why does calling AudioRenderer.stopSource(node) does not stop the playing?
PS: There is an effect you can use to stop playing the sound which has the additional benefit of fading out the sound. The effect is called “fadeSound” and “fadeMusic” and you give the sound id in the “sound” parameter. The effects will fade the sound/music over the lifetime of the effect and finally will call soundHandle.stop() internally too. So this SHOULD work too but it won’t because of some issue with the jme soundsystem maybe?
Ah my bad.
My case is I want to shut the sound immediately to go to another Screen… But since I trigger it with onStartScreen is continue playing.
The same situation when I want to go immediately straight to test the game ( I called QuickMode) so every waiting in Nifty must be suspend when I push F1 for example. But my Nifty start screen have some effect with delay time = 3000 or more… Then I got:
gotoScreen aborted because still in gotoScreenInProgress phase
[java] public void gotoScreen(final String id) {
if (gotoScreenInProgess) {
log.info("gotoScreen [" + id + "] aborted because still in gotoScreenInProgress phase");
return;
}
log.info("gotoScreen [" + id + "]");
gotoScreenInProgess = true;
if (currentScreen.isNull()) {
gotoScreenInternal(id);
} else {
// end current screen
currentScreen.endScreen(
new EndNotify() {
public void perform() {
gotoScreenInternal(id);
}
});
}
}[/java]
So my point is maybe we need a way to suspend everything right away on user demand... !
I used debugger and found that JmeSoundHandle is not “null” but the filename is “null” … Seems like an mistaken code line hidden somewhere… I will take a deeper look Y_Y . Now I’m nearly mute all my sound file due to that issue
@void256
I think I smell a rat here
Can you tell me the logic of these line :
[java]
//package de.lessvoid.nifty.sound;
// SoundSystem class
public boolean addSound(final String name, final String filename) {
log.fine(“register sound [” + name + “] for file '” + filename + “’”);
SoundHandle sound = soundDevice.loadSound(this, filename);
if (sound == null) {
return false;
}
soundLookup.put(name, sound);
return true;
}
[/java]
[java]
//package com.jme3.niftygui;
// class SoundDeviceJme implements SoundDevice
public SoundHandle loadSound(SoundSystem soundSystem, String filename) {
AudioNode an = new AudioNode(ar, assetManager, filename, false);
an.setPositional(false);
return new SoundHandleJme(ar, an);
}
[/java]
So , SoundHandle sound = soundDevice.loadSound(this, filename);
but loadSound don’t care about the filename and create a new SoundHandleJme(ar, an); ???
So the filename is “null” due to this problem…
You can see in this picture of the watched “soundLookup” , the handle is not “null” but the filename is null!!!
http://farm7.static.flickr.com/6138/6015215559_fd2b06ca54_z.jpg
OK, I fixed it in SVN. Thanks