Package ejmf.toolkit.multiplayer

Source Code of ejmf.toolkit.multiplayer.MultiPlayer

package ejmf.toolkit.multiplayer;

import java.io.File;

import javax.media.ControllerErrorEvent;
import javax.media.ControllerEvent;
import javax.media.ControllerListener;
import javax.media.Manager;
import javax.media.MediaLocator;
import javax.media.Player;
import javax.media.RestartingEvent;
import javax.media.StartEvent;
import javax.media.StopEvent;
import javax.media.TimeBase;
import javax.swing.event.EventListenerList;

import ejmf.toolkit.gui.ViewingPanel;
import ejmf.toolkit.util.Debug;
import ejmf.toolkit.util.Utility;

/**
* Plays multiple players. The MultiPlayerControl strategy
* associated with the MutliPlayer determines how the Players
* are operated.
*
* A MultiPlayer has a TrackList. Each member of the TrackList
* can be thought of as a media track in the sense of an a/v
* mixing board. Each track is a Track object and maintains
* the Player reference, its start time and stop time.
*
* If a MultiPlayer has a ViewingPanel associated with it,
* a Player's GUI components are displayed.
*
* A MultiPlayer can be used in conjunction with a TrackModel
* and implements the TrackModelListener interface to listen
* to changes to the TrackModel.
*
* A MultiPlayer has one of four states: NOTINITIALIZED, INITIALIZED,
* STARTED, STOPPED.
*
* @see ejmf.toolkit.multiplayer.TrackList
* @see ejmf.toolkit.multiplayer.Track
* @see ejmf.toolkit.multiplayer.MultiPlayerControl
*/

public class MultiPlayer
  implements TrackModelListener, ControllerListener {


  /** No control strategy associated with MultiPlayer */
    final public static int  NOTINITIALIZED = -1;
  /** Control strategy has been associated with MultiPlayer */
    final public static int  INITIALIZED = 1;
  /** At least one of associated Players is started */
    final public static int  STARTED = 2;
  /** All Players have stopped. */
    final public static int  STOPPED = 3;

    private int      state = NOTINITIALIZED;

    private TrackList    tracks;
    private TrackModel    trackModel = null;
    private int      nActiveTracks;
    private int      startedCount;
    private int      totalToStart;

    private ViewingPanel  viewingPanel = null;

    private EventListenerList  listeners = null;
 
    // This is the Player whose TimeBase is used by all others.
    private Player    master;
    private TimeBase    masterTimeBase = null;

    // Reference to control strategy
    private MultiPlayerControl  mpc;
 
    /**
     * Create a MultiPlayer from an array of media file names.
  * @param mediaFiles An array of media file names   
  * @param mpc A MultiPlayerControl strategy.
     */

    public MultiPlayer(String[] mediaFiles, MultiPlayerControl mpc) {
  tracks = new TrackList(mediaFiles.length);
  for (int i = 0; i < mediaFiles.length; i++) {
      try {
          String path = new File(mediaFiles[i]).getCanonicalPath();
          MediaLocator ml = Utility.appArgToMediaLocator(path);
          Player player = Manager.createPlayer(ml);
          tracks.addElement(new Track(i, ml, player));
      } catch (Exception e) {
    System.err.println(
        "Unable to create Player from " + mediaFiles[i]);
    continue;
       }
  }
  nActiveTracks = addAsListener(tracks);
  setControlStrategy(mpc);
    }

    /**
     * Create a MultiPlayer from an array of MediaLocators
  * @param mls An array of MediaLocators
  * @param mpc A MultiPlayerControl strategy.
     */
    public MultiPlayer(MediaLocator[] mls, MultiPlayerControl mpc) {
  tracks = new TrackList(mls.length);
  for (int i = 0; i < mls.length; i++) {
      try {
          Player player = Manager.createPlayer(mls[i]);
          tracks.addElement(new Track(i, mls[i], player));
      } catch (Exception e) {
    System.err.println("Unable to create Player from " +
      mls[i].toString());
    continue;
      }
  }
  nActiveTracks = addAsListener(tracks);
  setControlStrategy(mpc);
    }

    /** Create a MultiPlayer from a TrackModel. This
     *  constructor adds the MultiPlayer as a TrackModelListener.
     *  The MultiPlayer's TackList is obtained from the TrackModel.
  * @param tm A TrackModel
  * @param mpc A MultiPlayerControl strategy.
     */
    public MultiPlayer(TrackModel tm, MultiPlayerControl mpc) {
  tracks = tm.getTrackList();
  tm.addTrackModelListener(this);
  trackModel = tm;
  nActiveTracks = addAsListener(tracks);
  setControlStrategy(mpc);
    }

    /**
     * Create a MultiPlayer from a TrackList.
  * @param tracks A TrackList
  * @param mpc A MultiPlayerControl strategy.
     */
    public MultiPlayer(TrackList tracks, MultiPlayerControl mpc) {
  this.tracks = tracks;
  nActiveTracks = addAsListener(tracks);
  setControlStrategy(mpc);
    }
 

    /** 
      * Return the TrackList associated with MultiPlayer.
  * @return TrackList associated with this MultiPlayer.
      */
    public TrackList getTrackList() {
  return tracks;
    }

    /**
     * Associate a ViewingPanel with this MultiPlayer for
     * display of Player GUI Components.
     * @param a ejmf.toolkit.gui.ViewingPanel in which 
  * player visual components are displayed.
     */
    public void setViewingPanel(ViewingPanel viewingPanel) {
  this.viewingPanel = viewingPanel;
    }

    /**
      * Return the ViewingPanel associated with this MultiPlayer.
      *
      * @return ejmf.toolkit.gui.ViewPanel used for display of Players.
      */
    public ViewingPanel getViewingPanel() {
  return viewingPanel;
    }

    /** 
      * Get current state of MultiPlayer.
      * @return current state of MultiPlayer
      */
    public int getState() {
  return state;
    }

    /**
     * Shutdown all Players.
     */
    public synchronized void close() {
  if (state < INITIALIZED)
      return;
  if (state == STARTED)
      mpc.stop();
  mpc.close();
    }
    
    /** Stop all Players
     *
     */
    public synchronized void stop() {
  totalToStart = 0;
  mpc.stop();
    }

    /** 
      * Rewind the MultiPlayer, settings the media time of all its
      * Player to zero.
      *
      * @exception MultiPlayerStateException
      * If the MultiPlayer is in the STARTED state
      * or has not been initialized, a MultiPlayerStateException is thrown.
      */
    public synchronized void rewind() throws MultiPlayerStateException {
  if (state == STARTED || state == INITIALIZED)
      throw new MultiPlayerStateException(
    "Illegal state for rewind. MultiPlayer is " +
    stateToString(state) + ".");

  mpc.rewind();
    }

    /**
      * Start all Players.
     */

    public synchronized void start()  {
  // Assumption 1: All Players are prefetched
  // Assumption 2: All Players share TimeBase

  if (state == STARTED) {
      return;
  }

  // Reset number of Tracks started.
  startedCount = 0;

  // Set total number of Tracks to be started.
  totalToStart = nActiveTracks;

  mpc.start();

  state = STARTED;
  fireMultiPlayerUpdate(STARTED);
    }

     /* Set the control strategy for this MultiPlayer.
      *  A control stategy can only be set once.
      *  MultiPlayer update event is posted and,
      *  upon return, the MultiPlayer state has been set to
      *  INITIALIZED.
      */
     private void setControlStrategy(MultiPlayerControl mpc) {

  this.mpc = mpc;
        if (mpc.init() == true) {
      state = INITIALIZED;
      fireMultiPlayerUpdate(INITIALIZED);
  }
     }

    /** Display all Player ViewScreens
     *
     */
     public void displayPlayers() {
  if (viewingPanel == null)
      return;

        for (int i = 0; i < tracks.getNumberOfTracks(); i++) {
      Track track = tracks.getTrack(i);
      if (track.isAvailable())
    continue;
      Player player = track.getPlayer();
      String path = track.getMediaLocator().toString();
      viewingPanel.addScreen(new File(path).getName(),
        player,
        ViewingPanel.DISPLAY_BOTH);
  }
     }

    ////////// Listener/notification code ////////////////

    /** Inform listeners of a state change to MultiPlayer
  * @param The current state of the MultiPlayer.
     */
    protected void fireMultiPlayerUpdate(int state) {
  if (listeners == null)
      return;
  Object[] l = listeners.getListenerList();
  for (int i = l.length-2; i>=0; i-=2) {
      if (l[i]== MultiPlayerListener.class)
    ((MultiPlayerListener)l[i+1]).multiPlayerUpdate(state);
  }
    }

    /** Add a MultiPlayerListener
     * @param a MultiPlayerListener
     *
     * @see ejmf.toolkit.multiplayer.MultiPlayerListener
     */
    public void addMultiPlayerListener(MultiPlayerListener mpl) {
  if (listeners == null)
      listeners = new EventListenerList();

  listeners.add(MultiPlayerListener.class, mpl);
    }

    /** Remove a MultiPlayerListener
     *
     * @see ejmf.toolkit.multiplayer.MultiPlayerListener
     */
    public void removeMultiPlayerListener(MultiPlayerListener mpl) {
  if (listeners != null)
      listeners.remove(MultiPlayerListener.class, mpl);
    }

    /**
      * A debugging hook for dumping contents of each Track
      * to the file.dbg.out.
      */
    public void query() {
  for (int i = 0; i < tracks.getNumberOfTracks(); i++) {
      Track track = tracks.getTrack(i);
      Player p = track.getPlayer();

      System.out.println("++++++++++++++++++++");

      if (track.isAvailable()) {
    System.out.println("Track " + i +  " not assigned");
     continue;
            }
      System.out.println("player = " + track.getMediaLocator().toString());
            System.out.println("state = " + Utility.stateToString(p.getState()));
            System.out.println("media time = " + p.getMediaTime().getSeconds());
            System.out.println("stop time = " + p.getStopTime().getSeconds());
            System.out.println("duration = " + p.getDuration().getSeconds());
  }
    }

    /** Listen for changes to TrackModel
     *  In response to every update, the MultiPlayerControl's
     *  update method is called with a TrackModelEvent as an argument.
     *  <p>
     @param tme A TrackModelEvent
     * @see ejmf.toolkit.multiplayer.TrackModelEvent
     */
    public void trackModelUpdate(TrackModelEvent tme) {
  TrackModel tm = tme.getTrackModel();
  tracks = tm.getTrackList();
  int index = tme.getIndex();
  if (tme instanceof TrackModelDeassignEvent) {
      uninstallPlayer(tm, index);
  } else if (tme instanceof TrackModelAssignEvent) {
      installPlayer(tm, index);
  }
  if (tm.getNumberOfAssignedTracks() > 0) {
      mpc.update(tracks);
  }
    }

    //////////// Track management //////////////
    //  Addition and deletion of new Player
    //  The following two methods are invoked by trackModelUpdate

    /** In response to TrackModelEvent, remove a Player  
     *   and its screen from desktop.
     *
     *  @param tm TrackModel from which Player is being removed.
     *   @param index Index of Player in TrackList
     *  @see ejmf.toolkit.multiplayer.TrackList
     *  @see ejmf.toolkit.multiplayer.TrackModel
     */
    private void uninstallPlayer(TrackModel tm, int index) {
  Player player = tracks.getTrack(index).getPlayer();

  if (viewingPanel != null) {
      viewingPanel.removeScreen(player);
      Debug.printObject("uninstallPlayer : after remove screen");
  }
     player.removeControllerListener(this)
  synchronized (this) {
      nActiveTracks--;
  }
  Debug.printObject("exit uninstallPlayer : " + index);
    }

    /** In response to TrackModelEvent, add a Player.
     *  initPlayer is called to bring Player to prefetched
     *  state. If a ViewingPanel exists, the Player screen
     *  is displayed. Newly added Player adopts TimeBase
     *  of current master Player.
     *
     *  @param tm TrackModel to which Player is being added.
     *  @param index which track is getting a new Player
     *  @see javax.media.TimeBase
     *  @see ejmf.toolkit.multiplayer.TrackModelAssignEvent
     *  @see ejmf.toolkit.multiplayer.TrackModel
     *  @see ejmf.toolkit.gui.ViewingPanel
     *  @see ejmf.toolkit.gui.ViewScreen
     *  
     */
    private void installPlayer(TrackModel tm, int index)  {
  Debug.printObject("enter installPlayer : " + index);
  Track  track = tracks.getTrack(index);
  Player   player = track.getPlayer();

  player.addControllerListener(this);
  synchronized (this) {
      nActiveTracks++;
  }
  if (viewingPanel != null)
      viewingPanel.addScreen(track.getMediaLocator().toString(),
        player,
        ViewingPanel.DISPLAY_BOTH);
  Debug.printObject("exit installPlayer : " + index);
    }

    /** Track number of started Players, number of stopped
     * Players and fire a MultiPlayerUpdate event when all tracks
     * have been stopped or an error has occurred.
     *
     * @param event A ControllerEvent
     */
    public synchronized void controllerUpdate(ControllerEvent event) {
  Player p = (Player)event.getSourceController();
  Track track = tracks.findTrack(p);

  if (event instanceof StartEvent) {
      startedCount++;
      totalToStart--;
      track.setState(STARTED);
        }

  if (event instanceof StopEvent &&
      !(event instanceof RestartingEvent))
  {
      // It is possible that multiple StopEvents come for
      // one Player. Eg. if end of media is reached before
            // stop() request. A stop() call always generates a
      // StopByRequestEvent even if Controller is already stopped.
      // For this reason, we test state value in Track associated
      // with Player object.

      if (track.getState() == STARTED) {
          startedCount--;
    track.setState(STOPPED);
      }
      if (startedCount == 0 &&  totalToStart == 0) {
    state = STOPPED;
    mpc.rewind();
    fireMultiPlayerUpdate(STOPPED);
      }
  }
  if (event instanceof ControllerErrorEvent) {
      // If this Player was part of TrackModel
      // close it down in response to error.
      if (trackModel != null) {
    trackModel.deassignTrack(p);
      }
  }
    }

  /////////////// Helper Methods ////////////////////

     /*
      * Add MultiPlayer as listener on each Player.
      * Return how many Players.
      */
     private int addAsListener(TrackList tracks) {
  int count = 0;
  for (int i = 0; i < tracks.getNumberOfTracks(); i++) {
      Track track = tracks.getTrack(i);
      if (!track.isAvailable()) {
    track.getPlayer().addControllerListener(this);
    count++;
      }
  }
  return count;
     }

   /**
  * Convert MultiPlayer state to a string.
  * @param The current state of the MultiPlayer
  * @return A String representing current state of MultiPlayer.
  */
     public static String stateToString(int state) {
  if (state == INITIALIZED)
      return "Initialized";
        else if (state == STARTED)
      return "Started";
  else if (state == STOPPED)
      return "Stopped";
        return null;
     }
}
TOP

Related Classes of ejmf.toolkit.multiplayer.MultiPlayer

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.