jmri.jmrit.vsdecoder.Diesel2Sound.java Source code

Java tutorial

Introduction

Here is the source code for jmri.jmrit.vsdecoder.Diesel2Sound.java

Source

package jmri.jmrit.vsdecoder;

/*
 * <hr>
 * This file is part of JMRI.
 * <P>
 * JMRI is free software; you can redistribute it and/or modify it under 
 * the terms of version 2 of the GNU General Public License as published 
 * by the Free Software Foundation. See the "COPYING" file for a copy
 * of this license.
 * <P>
 * JMRI is distributed in the hope that it will be useful, but WITHOUT 
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License 
 * for more details.
 * <P>
 *
 * @author         Mark Underwood Copyright (C) 2011
 * @version         $Revision: 18481 $
 */
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.HashMap;
import java.util.Iterator;
import jmri.util.PhysicalLocation;
import org.jdom2.Element;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

// Usage:
// EngineSound() : constructor
// play() : plays short horn pop
// loop() : starts extended sustain horn
// stop() : ends extended sustain horn (plays end sound)
class Diesel2Sound extends EngineSound {

    // Engine Sounds
    HashMap<Integer, NotchSound> notch_sounds;
    SoundBite start_sound;
    SoundBite shutdown_sound;
    SoundBite notch_transition; // used for changing notches
    Float throttle_setting;
    EnginePane engine_pane;

    int current_notch = 1;
    boolean changing_speed = false;

    public Diesel2Sound(String name) {
        super(name);
    }

    // Note:  Play and Loop do the same thing, since all of the notch sounds are set to loop.
    @Override
    public void play() {
        log.debug("EngineSound Play: current_notch = " + current_notch);
        if (notch_sounds.containsKey(current_notch) && (engine_started || auto_start_engine)) {
            notch_sounds.get(current_notch).play();
            is_playing = true;
        }
    }

    // Note:  Play and Loop do the same thing, since all of the notch sounds are set to loop.
    @Override
    public void loop() {
        if (notch_sounds.containsKey(current_notch) && (engine_started || auto_start_engine)) {
            notch_sounds.get(current_notch).play();
            is_playing = true;
        }
    }

    @Override
    public void stop() {
        if (notch_sounds.containsKey(current_notch)) {
            notch_sounds.get(current_notch).stop();
        }
        is_playing = false;
    }

    @Override
    public void handleSpeedChange(Float s, EnginePane e) {
        throttle_setting = s;
        if (!changing_speed) {
            changeSpeed(s, e);
        }
    }

    // Responds to "CHANGE" trigger
    public void changeThrottle(float s) {
        NotchSound cn = notch_sounds.get(current_notch);
        log.debug("Change Throttle: " + s + " Accel Limit = " + cn.getAccelLimit() + " Decel Limit = "
                + cn.getDecelLimit());
        throttle_setting = s;
        // Really first, is this a "Panic Stop"?
        if (s < 0) {
            // DO something to shut down
            this.shutdown();
            return;
        }
        // First, am I too fast or too slow for the current notch?
        if ((s <= cn.getAccelLimit()) && (s >= cn.getDecelLimit())) {
            // Still (or now) in this notch.  Nothing to do.
            changing_speed = false;
            log.debug("No Change");
            cn.fadeIn();
            //cn.play();
            return;
        } else if (s > cn.getAccelLimit()) {
            // Too fast. Need to go to next notch up.
            changing_speed = true;
            notch_transition = cn.getAccelSound();
            current_notch = cn.getNextNotch();
            log.debug("Change up. notch=" + current_notch);
        } else if (s < cn.getDecelLimit()) {
            // Too slow.  Need to go to next notch down.
            changing_speed = true;
            notch_transition = cn.getDecelSound();
            current_notch = cn.getPrevNotch();
            log.debug("Change down. notch=" + current_notch);
        }
        // Now, regardless of whether we're going up or down, set the timer,
        // fade the current sound, and move on.
        if (notch_transition == null) {
            // No transition sound to play.  Skip the timer bit.
            // Recurse directly to try the next notch.
            //cn.fadeOut();
            cn.play();
            changeThrottle(s);
            log.debug("No transition sound defined.");
            return;
        }
        t = newTimer(notch_transition.getLengthAsInt() - this.getFadeInTime(), false, new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                handleNotchTimerPop(e);
            }
        });
        t.start();
        //cn.fadeOut();
        cn.stop();
        //notch_transition.fadeIn();
        notch_transition.play();
        // Regardless, set the throttle to the (possibly new) current notch.
    }

    protected void changeSpeed(Float s, EnginePane e) {
        engine_pane = e; // this should probably be cleaned up.  It's here for the recursion.
        changeThrottle(s);
    }

    protected void handleNotchTimerPop(ActionEvent e) {
        // semi-Recursively call the speed change handler until it quits setting up timers.
        notch_transition.fadeOut();
        changeSpeed(throttle_setting, engine_pane);
    }

    @Override
    public void startEngine() {
        start_sound.play();
        current_notch = calcEngineNotch(0.0f);
        t = newTimer(start_sound.getLengthAsInt() - start_sound.getFadeOutTime(), false, new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                startToIdleAction(e);
            }
        });
        t.setInitialDelay(start_sound.getLengthAsInt() - start_sound.getFadeOutTime());
        t.setRepeats(false);
        log.debug("Starting Engine");
        t.start();
    }

    @Override
    public void stopEngine() {
        notch_sounds.get(current_notch).fadeOut();
        shutdown_sound.play();
        engine_started = false;
    }

    private void startToIdleAction(ActionEvent e) {
        log.debug("Starting idle sound notch = " + current_notch + " sound = " + notch_sounds.get(current_notch));
        notch_sounds.get(current_notch).loop();
        engine_started = true;
    }

    @Override
    public void shutdown() {
        for (NotchSound ns : notch_sounds.values()) {
            ns.stop();
        }
        if (start_sound != null) {
            start_sound.stop();
        }
        if (shutdown_sound != null) {
            shutdown_sound.stop();
        }
    }

    @Override
    public void mute(boolean m) {
        for (NotchSound ns : notch_sounds.values()) {
            ns.mute(m);
        }
        if (start_sound != null) {
            start_sound.mute(m);
        }
        if (shutdown_sound != null) {
            shutdown_sound.mute(m);
        }
    }

    @Override
    public void setVolume(float v) {
        for (NotchSound ns : notch_sounds.values()) {
            ns.setVolume(v);
        }
        if (start_sound != null) {
            start_sound.setVolume(v);
        }
        if (shutdown_sound != null) {
            shutdown_sound.setVolume(v);
        }
    }

    @Override
    public void setPosition(PhysicalLocation p) {
        for (NotchSound ns : notch_sounds.values()) {
            ns.setPosition(p);
        }
        if (start_sound != null) {
            start_sound.setPosition(p);
        }
        if (shutdown_sound != null) {
            shutdown_sound.setPosition(p);
        }
    }

    @Override
    public Element getXml() {
        Element me = new Element("sound");
        me.setAttribute("name", this.getName());
        me.setAttribute("type", "engine");
        // Do something, eventually...
        return (me);
    }

    @Override
    public void setXml(Element e, VSDFile vf) {
        Element el;
        String fn;
        NotchSound sb;

        // Handle the common stuff.
        super.setXml(e, vf);

        log.debug("Diesel EngineSound: " + e.getAttribute("name").getValue());
        notch_sounds = new HashMap<Integer, NotchSound>();

        // Get the notch sounds
        Iterator<Element> itr = (e.getChildren("notch-sound")).iterator();
        int i = 0;
        while (itr.hasNext()) {
            el = itr.next();
            fn = el.getChildText("file");
            int nn = Integer.parseInt(el.getChildText("notch"));
            //log.debug("Notch: " + nn + " File: " + fn);
            sb = new NotchSound(vf, fn, "Engine_n" + i, "Engine_" + i);
            sb.setLooped(true);
            sb.setFadeTimes(this.getFadeInTime(), this.getFadeOutTime());
            sb.setGain(setXMLGain(el));
            sb.setNextNotch(el.getChildText("next-notch"));
            sb.setPrevNotch(el.getChildText("prev-notch"));
            sb.setAccelLimit(el.getChildText("accel-limit"));
            sb.setDecelLimit(el.getChildText("decel-limit"));
            if (el.getChildText("accel-file") != null) {
                sb.setAccelSound(
                        new SoundBite(vf, el.getChildText("accel-file"), "Engine_na" + i, "Engine_na" + i));
            } else {
                sb.setAccelSound(null);
            }
            if (el.getChildText("decel-file") != null) {
                sb.setDecelSound(
                        new SoundBite(vf, el.getChildText("decel-file"), "Engine_nd" + i, "Engine_nd" + i));
            } else {
                sb.setDecelSound(null);
            }
            // Store in the list.
            notch_sounds.put(nn, sb);
            i++;
        }

        // Get the start and stop sounds
        el = e.getChild("start-sound");
        if (el != null) {
            fn = el.getChild("file").getValue();
            //log.debug("Start sound: " + fn);
            start_sound = new SoundBite(vf, fn, "Engine_start", "Engine_Start");
            // Handle gain
            start_sound.setGain(setXMLGain(el));
            start_sound.setFadeTimes(this.getFadeInTime(), this.getFadeOutTime());
            start_sound.setLooped(false);
        }
        el = e.getChild("shutdown-sound");
        if (el != null) {
            fn = el.getChild("file").getValue();
            //log.debug("Shutdown sound: " + fn);
            shutdown_sound = new SoundBite(vf, fn, "Engine_shutdown", "Engine_Shutdown");
            shutdown_sound.setLooped(false);
            // Handle gain
            shutdown_sound.setGain(setXMLGain(el));
            shutdown_sound.setFadeTimes(this.getFadeInTime(), this.getFadeOutTime());
        }

    }

    private static final Logger log = LoggerFactory.getLogger(EngineSound.class.getName());

}