All Downloads are FREE. Search and download functionalities are using the official Maven repository.

net.sf.fmj.ejmf.toolkit.util.SourcedTimer Maven / Gradle / Ivy

There is a newer version: 1.0.2-jitsi
Show newest version
package net.sf.fmj.ejmf.toolkit.util;

import java.awt.event.*;

import javax.swing.*;
import javax.swing.event.*;

/**
 * The SourcedTimer class implements a timer dependent on a named source. This
 * is a generalization of a timer simply dependent on a monotonically increasing
 * clock.
 *
 * An instance of SourcedTimer creates a java.swing.Timer and becomes a listener
 * on that timer. This timer is called the base timer. Every time the base timer
 * fires, the SourcedTimer object asks its source what time it is and then
 * notifies its listeners.
 *
 * This class is used by the TimerPlayer to track media time.
 *
 * From the book: Essential JMF, Gordon, Talley (ISBN 0130801046). Used with
 * permission.
 *
 * see java.awt.swing.Timer see ejmf.toolkit.TimeSource see
 * ejmf.examples.timerplayer.TimerPlayer
 *
 * @version 1.0
 * @author Rob Gordon & Steve Talley
 */
public class SourcedTimer implements ActionListener
{
    /**
     * How often in milliseconds the baseTimer triggers
     */
    protected static int _defaultGran = 1000;
    /**
     * The source from which the SourcedTimer gets its idea of time
     */
    private TimeSource source;
    /**
     * The base timer
     */
    private Timer baseTimer;
    /**
     * These are listeners on the SourcedTimer
     */
    private EventListenerList listenerList = null;
    /**
     * This event is sent to all of my listeners
     */
    private SourcedTimerEvent event;
    /**
     * Flag that tracks whether base timer is running.
     */
    private boolean started = false;

    // This needs to be global since it is used by inner class
    private Object[] listeners;

    /**
     * Create a SourcedTimer for the given source using default granularity.
     *
     * @param src
     *            An object that implements the TimeSource interface.
     */
    public SourcedTimer(TimeSource src)
    {
        this(src, _defaultGran);
    }

    /**
     * Create a SourcedTimer for the given source with the specified
     * granularity.
     *
     * @param src
     *            An object that implements the TimeSource interface.
     * @param granularity
     *            Periood in milliseconds that base timer should fire.
     */
    public SourcedTimer(TimeSource src, int granularity)
    {
        source = src;
        event = new SourcedTimerEvent(this, 0);
        baseTimer = new Timer(granularity, this);
        baseTimer.setInitialDelay(0);
    }

    /**
     * Create a SourcedTimer for the given source. Use the Timer passed as an
     * argument for the base timer.
     *
     * @param src
     *            An object that implements the TimeSource interface.
     * @param timer
     *            A java.swing.Timer object for use as base timer.
     */
    public SourcedTimer(TimeSource src, Timer timer)
    {
        source = src;
        event = new SourcedTimerEvent(this, 0);
        baseTimer = timer;
    }

    /**
     * Called in response to an ActionEvent from the associated base timer.
     * Nominally this method is called every granularity milliseconds.
     *
     * @param e
     *            ActionEvent from base timer.
     */
    public void actionPerformed(ActionEvent e)
    {
        runNotifyThread(source.getTime());
    }

    /**
     * Add a listener to this object.
     *
     * @param l
     *            An object that implements SourcedTimerListener interface.
     */
    public void addSourcedTimerListener(SourcedTimerListener l)
    {
        if (listenerList == null)
            listenerList = new EventListenerList();
        listenerList.add(SourcedTimerListener.class, l);
    }

    /**
     * A client of SourcedTimer may need to convert source timer time from raw
     * units to some other units for display purposes. This method is available
     * to listeners who have a reference to a SourcedTimer but not necessarily
     * the source itself. It simply delegates to the source and asks what number
     * are raw units divider by to arrive at seconds.
     *
     *
     * @return A number used to divide base timer time for conversion to
     *         seconds.
     */
    public long getConversionDivisor()
    {
        return source.getConversionDivisor();
    }

    /**
     * Starts a thread that is responsible for notifying any listeners on this
     * SourcedTimer. For each listener, its timerUpdate method is called.
     *
     * @param nsecs
     *            Time in nanoseconds from base timer.
     */
    private void runNotifyThread(long nsecs)
    {
        event.setTime(nsecs);
        listeners = listenerList.getListenerList();
        Thread nThread = new Thread("SourcedTimer Notify Thread")
        {
            @Override
            public void run()
            {
                // This is canonical means for traversing a
                // Listener list, notifying listeners
                for (int i = listeners.length - 2; i >= 0; i -= 2)
                    if (listeners[i] == SourcedTimerListener.class)
                        ((SourcedTimerListener) listeners[i + 1])
                                .timerUpdate(event);
            }
        };
        nThread.start();
    }

    /**
     * Start the timer. The associated base timer is started if it is not
     * already running.
     *
     */
    public void start()
    {
        if (started == false)
        {
            baseTimer.start();
            runNotifyThread(0);
        }
    }

    /**
     * Stop the timer. The associated base timer is stopped.
     *
     */
    public void stop()
    {
        started = false;
        baseTimer.stop();

        // Force one last notification. This call acts
        // like a 'flush' event and ensues a final event
        // occurs when stopping Timer. We do it after stop
        // in case it takes a while.
        runNotifyThread(source.getTime());
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy