1  /**
     2   * com.sekati.ui.FLVPlayer
     3   * @version 1.2.1
     4   * @author jason m horwitz | sekati.com
     5   * Copyright (C) 2007  jason m horwitz, Sekat LLC. All Rights Reserved.
     6   * Released under the MIT License: http://www.opensource.org/licenses/mit-license.php
     7   */
     8   
     9  import com.sekati.core.App;
    10  import com.sekati.core.FWDepth;
    11  import com.sekati.data.FLV;
    12  import com.sekati.display.CoreClip; 
    13  import com.sekati.utils.Delegate;
    14  
    15  /**
    16   * FLVPlayer controller to be used with {@link com.sekati.data.FLV}
    17   */
    18  class com.sekati.ui.FLVPlayer extends CoreClip {
    19  
    20  	private var _video:Object;
    21  	private var _playBtn:MovieClip;
    22  	private var _progBar:MovieClip;
    23  	private var _buffBar:MovieClip;
    24  	private var _guttBar:MovieClip;
    25  	private var _volBtn:MovieClip;
    26  	private var _audioContainer:MovieClip;
    27  	private var _movie:Object;
    28  	private var _isDrag:Boolean;
    29  	private var _isSeeking:Boolean;
    30  	private var _wasPlaying:Boolean;
    31  	private var _keyListener:Object;
    32  	private var _isKeyEnabled:Boolean;
    33  
    34  	/**
    35  	 * Constructor
    36  	 */
    37  	private function FLVPlayer() {
    38  	}
    39  
    40  	/**
    41  	 * init called via CoreClip onLoad event
    42  	 * @return Void
    43  	 */
    44  	private function configUI():Void {
    45  		_video = _this.video;
    46  		_playBtn = _this.playBtn;
    47  		_progBar = _this.progBar;
    48  		_buffBar = _this.buffBar;
    49  		_guttBar = _this.guttBar;
    50  		_volBtn = _this.volBtn;
    51  		_audioContainer = _this.createEmptyMovieClip( "audioContainer", FWDepth.FLVAudioContainer );
    52  		// general ui setup
    53  		App.bc.subscribe( _this );
    54  		_progBar._xscale = 0;
    55  		_buffBar._xscale = 0;
    56  		_isDrag = false;
    57  		_isSeeking = false;
    58  		_wasPlaying = false;
    59  		_isKeyEnabled = true;
    60  		// playBtn events
    61  		_playBtn.onRollOver = Delegate.create( _this, playBtn_onRollOver );
    62  		_playBtn.onRollOut = Delegate.create( _this, playBtn_onRollOut );
    63  		_playBtn.onDragOver = Delegate.create( _this, playBtn_onRollOver );
    64  		_playBtn.onDragOut = Delegate.create( _this, playBtn_onRollOut );
    65  		_playBtn.onPress = Delegate.create( _this, playBtn_onPress );
    66  		// volBtn events
    67  		_volBtn.onPress = Delegate.create( _this, volBtn_onPress );
    68  		_volBtn.onRelease = Delegate.create( _this, volBtn_onRelease );
    69  		_volBtn.onReleaseOutside = Delegate.create( _this, volBtn_onRelease );
    70  		_volBtn.onMouseMove = Delegate.create( _this, volBtn_onMouseMove );
    71  		// buffbar events
    72  		_buffBar.onPress = Delegate.create( _this, buffBar_onPress );
    73  		_buffBar.onRelease = Delegate.create( _this, buffBar_onRelease );
    74  		_buffBar.onReleaseOutside = Delegate.create( _this, buffBar_onRelease );
    75  		_buffBar.onMouseMove = Delegate.create( _this, buffBar_onMouseMove );
    76  		// key listener
    77  		_keyListener = new Object( );
    78  		_keyListener.onKeyDown = Delegate.create( _this, keyManager );
    79  		Key.addListener( _keyListener );
    80  	}
    81  
    82  	//--------------------------------------------------------------------------------------------------------------
    83  	// player init, events, controls
    84  	private function onAppConfigured():Void {
    85  		App.log.trace( this, "* initializing FLVPlayer" );
    86  		_this.init( App.db.data.flv.data );
    87  	}
    88  
    89  	private function onVideoComplete():Void {
    90  		App.log.trace( this, "... FLV playback complete." );
    91  		_movie.seekToPercent( 0 );
    92  		onPauseFLVPlayer( );
    93  	}
    94  
    95  	/**
    96  	 * load video and initialize FLVPlayer UI and FLVPlayer Core
    97  	 * @param url (String) flv url
    98  	 * @return Void
    99  	 */
   100  	public function init(url:String):Void {
   101  		removeMovie( );
   102  		_playBtn.gotoAndStop( 1 );
   103  		_movie = new FLV( );
   104  		_movie.onProgress = Delegate.create( _this, movie_onProgress );
   105  		_movie.onEvent = Delegate.create( _this, movie_onEvent );
   106  		_movie.load( url, _this.video, 320, 240, _this.audioContainer );
   107  		_movie.playVideo( );
   108  	}
   109  
   110  	/**
   111  	 * Remove the movie from player.
   112  	 * @return Void
   113  	 */
   114  	public function removeMovie():Void {
   115  		if (_movie) {
   116  			_video._visible = false;
   117  			_movie.stopVideo( );
   118  			_movie.clean( );
   119  			_movie = null;
   120  			resetUI( );
   121  		}
   122  	}
   123  
   124  	/**
   125  	 * Reset the Interface
   126  	 * @return Void
   127  	 */
   128  	public function resetUI():Void {
   129  		_buffBar._xscale = 0;
   130  		_progBar._xscale = 0;
   131  		_playBtn.gotoAndStop( 2 );
   132  		_video._visible = true;
   133  	}
   134  
   135  	/**
   136  	 * event for pausing video playback
   137  	 * @return Void
   138  	 */
   139  	public function onPauseFLVPlayer():Void {
   140  		if (_movie) {
   141  			_isKeyEnabled = false;
   142  			_playBtn.gotoAndStop( 2 );
   143  			_movie.pause( );
   144  		}
   145  	}
   146  
   147  	/**
   148  	 * event for resuming video playback
   149  	 * @return Void
   150  	 */
   151  	public function onResumeFLVPlayer():Void {
   152  		if (_movie) {
   153  			_isKeyEnabled = true;
   154  			_playBtn.gotoAndStop( 1 );
   155  			_movie.resume( );
   156  		}
   157  	}
   158  
   159  	private function movie_onProgress(loadPercent:Number, currentTimePercent:Number):Void {
   160  		var lp:Number = (loadPercent < 100) ? loadPercent : 100;
   161  		var cp:Number = (currentTimePercent < 100) ? currentTimePercent : 100;
   162  		_this._buffBar._xscale = lp;
   163  		if (!_isSeeking) {
   164  			_this._progBar._xscale = cp;
   165  		} else {
   166  			_movie.seekToPercent( _this._progBar._xscale );
   167  		}
   168  	}
   169  
   170  	private function movie_onEvent(info:String):Void {
   171  		switch (info) {
   172  			case "bufferEmpty" :
   173  				App.log.trace( this, "movieEvent: bufferEmpty" );
   174  				break;
   175  			case "bufferFull" :
   176  				App.log.trace( this, "movieEvent: bufferFull" );
   177  				break;
   178  			case "bufferFlush" :
   179  				App.log.trace( this, "movieEvent: bufferFlush" );
   180  				break;
   181  			case "start" :
   182  				App.log.trace( this, "movieEvent: start" );
   183  				break;
   184  			case "stop" :
   185  				App.log.trace( this, "movieEvent: stop" );
   186  				//removeMovie ();
   187  				App.bc.broadcast( "onVideoComplete" );
   188  				break;
   189  			case "play_streamNotFound" :
   190  				App.log.trace( this, "movieEvent: play_streamNotFound" );
   191  				App.bc.broadcast( "onStreamNotFound" );
   192  				break;
   193  			case "seek_InvalidTime" :
   194  				App.log.trace( this, "movieEvent: seek_invalidTime" );
   195  				_movie.rew( );
   196  				break;
   197  			case "seek_notify" :
   198  				App.log.trace( this, "movieEvent: seek_notify" );
   199  				break;
   200  			default :
   201  				App.log.trace( this, "movieEvent: unrecognized onStatus value: " + info );
   202  		}
   203  	}
   204  
   205  	private function pauseMemory():Void {
   206  		_wasPlaying = _movie.isPaused( );
   207  		_movie.pause( );
   208  	}
   209  
   210  	private function resumeMemory():Void {
   211  		if (!_wasPlaying) {
   212  			_movie.resume( );
   213  		}
   214  		_wasPlaying = null;
   215  	}
   216  
   217  	// volumeController
   218  	private function setVolumeControl(p:Number):Void {
   219  		// bust into orig/max/min check vars to help flash cope with quick keybound calls (bad flashplayer ... baaaddd)
   220  		var ov:Number = (p) ? p : int( _volBtn._xmouse * 100 / _volBtn._width );
   221  		var mv:Number = (ov >= 100) ? 100 : ov;
   222  		var v:Number = (mv <= 0) ? 0 : mv;
   223  		_volBtn.vbar._xscale = v;
   224  		_movie.setVolume( v );
   225  	}
   226  
   227  	private function seek_ui():Void {
   228  		if (_this._isSeeking) {
   229  			// use guttBar to prevent seek offset inaccuracy while still buffering
   230  			var percent:Number = int( (_guttBar._xmouse - 2) * 100 / (_guttBar._width - 2) );
   231  			percent = (percent >= _buffBar._xscale) ? _buffBar._xscale - 1 : percent;
   232  			percent = (percent <= 0) ? 1 : percent;
   233  			percent = (percent >= 95) ? 95 : percent;
   234  			_progBar._xscale = percent;
   235  			//trace ("@seek_ui: " + percent + "% | bufferPercent: " + _buffBar._xscale + "% | bufferBar._xmouse=" + _buffBar._xmouse + " | buffBar._width: " + _buffBar._width);
   236  		}
   237  	}
   238  
   239  	//--------------------------------------------------------------------------------------------------------------
   240  	// ui event controllers
   241  	private function keyManager():Void {
   242  		if (!App.KEY_ENABLE) {
   243  			return;
   244  		}
   245  		var v:Number;
   246  		if (Key.getCode( ) == Key.UP && _volBtn.vbar._xscale < 100) {
   247  			v = int( _volBtn.vbar._xscale + 10 );
   248  			_this.setVolumeControl( v );
   249  		}
   250  		if (Key.getCode( ) == Key.DOWN && _volBtn.vbar._xscale > 0) {
   251  			v = int( _volBtn.vbar._xscale - 10 );
   252  			_this.setVolumeControl( v );
   253  		}
   254  		if (Key.getCode( ) == Key.SPACE && _isKeyEnabled) {
   255  			_this.playBtn_onPress( );
   256  		}
   257  	}
   258  
   259  	private function buffBar_onPress():Void {
   260  		_isSeeking = true;
   261  		seek_ui( );
   262  		pauseMemory( );
   263  	}
   264  
   265  	private function buffBar_onRelease():Void {
   266  		_isSeeking = false;
   267  		resumeMemory( );
   268  	}
   269  
   270  	private function buffBar_onMouseMove():Void {
   271  		seek_ui( );
   272  	}
   273  
   274  	private function playBtn_onPress():Void {
   275  		if (_movie) {
   276  			if (_playBtn._currentframe == 1) {
   277  				_playBtn.gotoAndStop( 2 );
   278  				_movie.pause( );
   279  			} else {
   280  				_playBtn.gotoAndStop( 1 );
   281  				_movie.resume( );
   282  			}
   283  		}
   284  	}
   285  
   286  	private function playBtn_onRollOver():Void {
   287  	}
   288  
   289  	private function playBtn_onRollOut():Void {
   290  	}
   291  
   292  	private function volBtn_onPress():Void {
   293  		_this._isDrag = true;
   294  		_this.setVolumeControl( );
   295  	}
   296  
   297  	private function volBtn_onRelease():Void {
   298  		_this._isDrag = false;
   299  	}
   300  
   301  	private function volBtn_onMouseMove():Void {
   302  		if (_this._isDrag) {
   303  			_this.setVolumeControl( );
   304  		}
   305  	}
   306  }