MediaPlayerLatch.java :  » Media » vlcj » uk » co » caprica » vlcj » player » Java Open Source

Java Open Source » Media » vlcj 
vlcj » uk » co » caprica » vlcj » player » MediaPlayerLatch.java
/*
 * This file is part of VLCJ.
 *
 * VLCJ is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * VLCJ 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.
 *
 * You should have received a copy of the GNU General Public License
 * along with VLCJ.  If not, see <http://www.gnu.org/licenses/>.
 * 
 * Copyright 2009, 2010, 2011 Caprica Software Limited.
 */

package uk.co.caprica.vlcj.player;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicBoolean;

import uk.co.caprica.vlcj.logger.Logger;

/**
 * This class implements a mechanism to play a media item and wait for it to
 * start (or wait for it to raise an error instead of starting).
 * <p>
 * Ordinarily a call to play new media returns immediately and the native media
 * player attempts to open and start playing the media asynchronously. This can
 * make it a little difficult for application code to know if the media 
 * successfully started or failed to start because of an error.
 * <p>
 * It is possible for application code to respond to media player events to
 * determine whether the media started successfully or failed because of an 
 * error but this class serves as a convenient encapsulation of that 
 * functionality.
 * <p>
 * The strategy is simply to block the play call until a media player "playing" 
 * or "error" event is received.
 * <p>
 * Example usage:
 * <pre>
 *   mediaPlayer.prepareMedia(mrl, options);
 *   boolean definitelyStarted = new MediaPlayerLatch(mediaPlayer).play();
 * </pre>
 * The {@link DefaultMediaPlayer} uses this class for the "play and wait..."
 * implementation, see {@link MediaPlayer#startMedia(String, String...)}.
 * <p> 
 * Most applications are not expected to need this class and use the "start 
 * media" functionality on the media player instead.
 */
public class MediaPlayerLatch {

  /**
   * Media player instance.
   */
  private final MediaPlayer mediaPlayer;
  
  /**
   * Create a new media player latch.
   * 
   * @param mediaPlayer media player instance
   */
  public MediaPlayerLatch(MediaPlayer mediaPlayer) {
    this.mediaPlayer = mediaPlayer;
  }
  
  /**
   * Play the media and wait for it to either start playing or error.
   * 
   * @return true if the media definitely started playing and false if it 
   *         did not or the thread was interrupted while waiting (unlikely, but
   *         in which case the media player <em>might</em> still start)   
   */
  public boolean play() { 
    Logger.debug("play()");
    CountDownLatch latch = new CountDownLatch(1);
    LatchListener listener = new LatchListener(latch);
    mediaPlayer.addMediaPlayerEventListener(listener);
    mediaPlayer.play();
    try {
      Logger.debug("Waiting for media playing or error...");
      latch.await();
      Logger.debug("Finished waiting.");
      boolean started = listener.playing.get();
      Logger.debug("started={}", started);
      return started;
    }
    catch(InterruptedException e) {
      Logger.debug("Interrupted while waiting for media player", e);
      return false;
    }
    finally {
      mediaPlayer.removeMediaPlayerEventListener(listener);
    }
  }
  
  /**
   * Short-lived listener to wait for playing/error events. 
   */
  private final class LatchListener extends MediaPlayerEventAdapter {

    /**
     * Synchronisation latch.
     */
    private final CountDownLatch latch;
    
    /**
     * True if the media started, otherwise false.
     */
    private AtomicBoolean playing = new AtomicBoolean();
    
    /**
     * Create a new listener.
     * 
     * @param latch synchronisation latch.
     */
    private LatchListener(CountDownLatch latch) {
      this.latch = latch;
    }
    
    @Override
    public void playing(MediaPlayer mediaPlayer) {
      playing.set(true);
      latch.countDown();
    }

    @Override
    public void error(MediaPlayer mediaPlayer) {
      playing.set(false);
      latch.countDown();
    }
  }
}
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.