[Pkg-javascript-commits] [jarisplayer] 55/80: RTMP fixes.
Jonas Smedegaard
dr at jones.dk
Tue May 10 08:45:36 UTC 2016
This is an automated email from the git hooks/post-receive script.
js pushed a commit to branch master
in repository jarisplayer.
commit 9a2b82b588b7c61645c89d8187698d85509c5a4b
Author: jgmdev <jgmdev at gmail.com>
Date: Sun Nov 22 02:05:34 2015 -0400
RTMP fixes.
---
bin/JarisFLVPlayer.swf | Bin 24713 -> 24962 bytes
changes.txt | 24 +-
documentation.txt | 243 ++--
src/jaris/Version.hx | 24 +-
src/jaris/player/Player.hx | 3477 ++++++++++++++++++++++----------------------
5 files changed, 1907 insertions(+), 1861 deletions(-)
diff --git a/bin/JarisFLVPlayer.swf b/bin/JarisFLVPlayer.swf
index 29ca65c..493f8bd 100644
Binary files a/bin/JarisFLVPlayer.swf and b/bin/JarisFLVPlayer.swf differ
diff --git a/changes.txt b/changes.txt
index f6fb7c6..6bd35ce 100644
--- a/changes.txt
+++ b/changes.txt
@@ -1,10 +1,16 @@
-Jaris FLV Player v2.0.16 - 11/09/2014
+Jaris FLV Player v2.0.17 - 22/11/2015
+
+ * Disabled second parameter when calling play() on a rtmp source.
+ * Disabled rtmpSourceParser() because it is causing issues.
+ * Added rtmp notes to documentation.txt
+
+Jaris FLV Player v2.0.16 - 11/09/2014
* Fixes in order to compile with new haxe v3 thanks to jonassmedegaard
* Fix the AsyncErrorEvent exception thrown by player thanks to lcb931023
* Added loadVideo() JsAPI call, call from JS new video thanks to Spiritdude
* Added build.hxml
-
+
Jaris FLV Player v2.0.15 beta - 27/08/2011
* New player controls
@@ -24,19 +30,19 @@ Jaris FLV Player v2.0.13 beta - 6/03/2011
* Implemented loop class
* Added loop functionality by passing loop=true or loop=1 as parameter
* Fixed reported bug "slider will show wrong position" on pseudostreaming seek (Thanks to Adam)
-
+
Jaris FLV Player v2.0.12 beta - 06/11/2010
* Java Script Api to listen for events and control the player.
* More player events added to use on JSApi.
* All this changes thanks to Sascha Kluger from http://projekktor.com
-
+
Jaris FLV Player v2.0.11 beta - 03/10/2010
- * Removed togglePlay of onFullscreen event since it seems that new flash versions doesnt emits
+ * Removed togglePlay of onFullscreen event since it seems that new flash versions doesnt emits
the space keydown anymore that affected playback on fullcreen switching.
* Added class to store user settings as volume and aspect ratio to load them next time player is load.
-
+
Jaris FLV Player v2.0.10 beta - 29/09/2010
* Added flashvar aspectratio option to initially tell on wich aspect ratio to play the video
@@ -85,7 +91,7 @@ Jaris FLV Player v2.0.2 beta - 03/09/2010
* Some more improvements to controls on short heights
* Other improvements and code refactoring
* added id3 info to player events
-
+
Jaris FLV Player v2.0.1 beta - 03/08/2010
* Toggle Quality on Context Menu
@@ -95,7 +101,7 @@ Jaris FLV Player v2.0.1 beta - 03/08/2010
* Controls fixes
* Other refinements and fixes
* Duration parameter to indicate how much total time takes input media
-
+
Jaris FLV Player v2.0.0 beta - 03/05/2010
* Moved from swishmax 2 to haxe and flashdevelop
@@ -110,7 +116,7 @@ Jaris FLV Player v2.0.0 beta - 03/05/2010
* Video smoothing enabled by default
* Added custom context menu
* Other refinements and fixes
-
+
Jaris FLV Player v1.0 - 05/21/2008
* Calculates video aspect ratio on player load.
diff --git a/documentation.txt b/documentation.txt
index dfa8f53..7ae4687 100644
--- a/documentation.txt
+++ b/documentation.txt
@@ -2,7 +2,8 @@
How To!
==================
-The above example is one of the ways to embed the player to your html files. Just copy and paste.
+The above example is one of the ways to embed the player to your html
+files. Just copy and paste.
---------------------------------------Code------------------------------------------
<object
@@ -10,36 +11,74 @@ The above example is one of the ways to embed the player to your html files. Jus
codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=10,0,45,2"
width="640" height="360"
>
- <param name="allowFullscreen" value="true">
- <param name="allowScriptAccess" value="always">
- <param name="movie" value="JarisFLVPlayer.swf">
- <param name="bgcolor" value="#000000">
- <param name="quality" value="high">
- <param name="scale" value="noscale">
- <param name="wmode" value="opaque">
- <param name="flashvars" value="source=jaris-intro.mp4&type=video&streamtype=file&poster=poster.png&autostart=false&logo=logo.png&logoposition=top left&logoalpha=30&logowidth=130&logolink=http://jaris.sourceforge.net&hardwarescaling=false&darkcolor=000000&brightcolor=4c4c4c&controlcolor=FFFFFF&hovercolor=67A8C1">
- <param name="seamlesstabbing" value="false">
- <embed
- type="application/x-shockwave-flash"
- pluginspage="http://www.adobe.com/shockwave/download/index.cgi?P1_Prod_Version=ShockwaveFlash"
- width="640" height="360"
- src="JarisFLVPlayer.swf"
- allowfullscreen="true"
- allowscriptaccess="always"
- bgcolor="#000000"
- quality="high"
- scale="noscale"
- wmode="opaque"
- flashvars="source=jaris-intro.mp4&type=video&streamtype=file&poster=poster.png&autostart=false&logo=logo.png&logoposition=top left&logoalpha=30&logowidth=130&logolink=http://jaris.sourceforge.net&hardwarescaling=false&darkcolor=000000&brightcolor=4c4c4c&controlcolor=FFFFFF&hovercolor=67A8C1"
- seamlesstabbing="false"
- >
- <noembed>
- </noembed>
- </embed>
+ <param name="allowFullscreen" value="true">
+ <param name="allowScriptAccess" value="always">
+ <param name="movie" value="JarisFLVPlayer.swf">
+ <param name="bgcolor" value="#000000">
+ <param name="quality" value="high">
+ <param name="scale" value="noscale">
+ <param name="wmode" value="opaque">
+ <param name="flashvars" value="source=jaris-intro.mp4&type=video&streamtype=file&poster=poster.png&autostart=false&logo=logo.png&logoposition=top left&logoalpha=30&logowidth=130&logolink=http://jaris.sourceforge.net&hardwarescaling=false&darkcolor=000000&brightcolor=4c4c4c&controlcolor=FFFFFF&hovercolor=67A8C1">
+ <param name="seamlesstabbing" value="false">
+ <embed
+ type="application/x-shockwave-flash"
+ pluginspage="http://www.adobe.com/shockwave/download/index.cgi?P1_Prod_Version=ShockwaveFlash"
+ width="640" height="360"
+ src="JarisFLVPlayer.swf"
+ allowfullscreen="true"
+ allowscriptaccess="always"
+ bgcolor="#000000"
+ quality="high"
+ scale="noscale"
+ wmode="opaque"
+ flashvars="source=jaris-intro.mp4&type=video&streamtype=file&poster=poster.png&autostart=false&logo=logo.png&logoposition=top left&logoalpha=30&logowidth=130&logolink=http://jaris.sourceforge.net&hardwarescaling=false&darkcolor=000000&brightcolor=4c4c4c&controlcolor=FFFFFF&hovercolor=67A8C1"
+ seamlesstabbing="false"
+ >
+ <noembed>
+ </noembed>
+ </embed>
</object>
--------------------------------------End-Code---------------------------------------
==================
+RTMP Playback
+==================
+
+In order to play from RTMP servers set the following parameters
+as follow:
+
+ streamtype=rtmp
+ server=rtmp://server/application/
+ source=streamkey
+
+Some rtmp streaming servers support a source syntax as follows:
+
+ * source=mp4:channel
+ * source=mp3:channel
+
+This is to tell the server in which format to stream the content.
+
+==================
+RTMPD Example
+==================
+
+An example of rtmp streaming using crtmpserver:
+
+1. First, in order to stream from your pc you can use ffmpeg as follows:
+
+ * ffmpeg -i file.avi -vcodec libx264 -f flv -metadata \
+ streamName="test" tcp://127.0.0.1:6666
+
+2. To play this stream on jarisplayer set the flashvars as follow:
+
+ streamtype=rtmp
+ server=rtmp://127.0.0.1/live/
+ source=test
+
+In the example 'live' is an alias of 'flvplayback' and 'test' is
+the streamName.
+
+==================
Flash Variables
==================
@@ -47,83 +86,83 @@ Here is the list of variables that you can pass to the player.
* source:
This is the actual path of the media that is going to be played.
-
- * type:
+
+ * type:
The type of file to play, allowable values are: audio, video.
-
+
* streamtype:
The stream type of the file, allowable values are: file, http, rmtp, youtube.
-
- * server:
- Used in coordination with rtmp stream servers
-
- * duration:
+
+ * server:
+ Used in coordination with rtmp stream servers
+
+ * duration:
Total times in seconds for input media or formatted string in the format hh:mm:ss
-
- * poster:
+
+ * poster:
Screenshot of the video that is displayed before playing in png, jpg or gif format.
-
- * autostart:
+
+ * autostart:
A true or false value that indicates to the player if it should auto play the video on load.
-
- * logo:
+
+ * logo:
The path to the image of your logo.
-
- * logoposition:
+
+ * logoposition:
The position of the logo in the player, permitted values are: top left, top right, bottom left and bottom right
-
- * logoalpha:
+
+ * logoalpha:
The transparency percent. values permitted 0 to 100, while more higher the vale less transparency is applied.
-
- * logowidth:
+
+ * logowidth:
The width in pixels of the logo.
-
- * logolink:
+
+ * logolink:
A link to a webpage when the logo is clicked.
-
- * hardwarescaling:
+
+ * hardwarescaling:
Enable or disable hardware scaling on fullscreen mode, values: false or true
-
- * logoalpha:
+
+ * logoalpha:
The transparency percent. values permitted 1 to 100
-
- * controls:
- To disable the displaying of controls, values: false to hide otherwise defaults to show
-
- * controltype
- Choose which controls to displa. 0 = old controls, 1 = new controls
-
- * controlsize
- Changes the height of the new controllers, the default value is 40
-
- * seekcolor
- Change the seekbar color (new controls only)
-
- * darkcolor:
+
+ * controls:
+ To disable the displaying of controls, values: false to hide otherwise defaults to show
+
+ * controltype
+ Choose which controls to displa. 0 = old controls, 1 = new controls
+
+ * controlsize
+ Changes the height of the new controllers, the default value is 40
+
+ * seekcolor
+ Change the seekbar color (new controls only)
+
+ * darkcolor:
The darker color of player controls in html hexadecimal format
-
- * brightcolor:
+
+ * brightcolor:
The bright color of player controls in html hexadecimal format
-
- * controlcolor:
+
+ * controlcolor:
The face color of controls in html hexadecimal format
-
- * hovercolor:
+
+ * hovercolor:
On mouse hover color for controls in html hexadecimal format
-
- * aspectratio:
+
+ * aspectratio:
To override original aspect ratio on first time player load. Allowable values: 1:1, 3:2, 4:3, 5:4, 14:9, 14:10, 16:9, 16:10
-
- * jsapi:
- Expose events to javascript functions and enable controlling the player from the outside. Set to any value to enable.
-
- * loop:
- As the variable says this keeps looping the video. Set to any value to enable.
-
- * buffertime
- To change the default 10 seconds buffer time for local/pseudo streaming
-
-==================
+
+ * jsapi:
+ Expose events to javascript functions and enable controlling the player from the outside. Set to any value to enable.
+
+ * loop:
+ As the variable says this keeps looping the video. Set to any value to enable.
+
+ * buffertime
+ To change the default 10 seconds buffer time for local/pseudo streaming
+
+==================
Keyboard Shortcuts
==================
@@ -131,27 +170,27 @@ Here is the list of keyboard shortcuts to control Jaris Player.
* SPACE
Play or pause video.
-
+
* TAB
Switch between different aspect ratios.
-
- * UP
+
+ * UP
Raise volume
-
- * DOWN
+
+ * DOWN
Lower volume
-
- * LEFT
+
+ * LEFT
Rewind
-
- * RIGHT
+
+ * RIGHT
Forward
-
- * M
+
+ * M
Mute or unmute volume.
-
- * F
+
+ * F
Swtich to fullscreen mode.
-
- * X
- Stops and close current stream
\ No newline at end of file
+
+ * X
+ Stops and close current stream
diff --git a/src/jaris/Version.hx b/src/jaris/Version.hx
index ab14e0b..dc37f66 100644
--- a/src/jaris/Version.hx
+++ b/src/jaris/Version.hx
@@ -1,13 +1,13 @@
-/**
+/**
* @author Jefferson González
* @copyright 2010 Jefferson González
*
- * @license
+ * @license
* This file is part of Jaris FLV Player.
*
* Jaris FLV Player is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License or GNU LESSER GENERAL
- * PUBLIC LICENSE as published by the Free Software Foundation, either version
+ * it under the terms of the GNU General Public License or GNU LESSER GENERAL
+ * PUBLIC LICENSE as published by the Free Software Foundation, either version
* 3 of the License, or (at your option) any later version.
*
* Jaris FLV Player is distributed in the hope that it will be useful,
@@ -15,8 +15,8 @@
* 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 and
- * GNU LESSER GENERAL PUBLIC LICENSE along with Jaris FLV Player. If not,
+ * You should have received a copy of the GNU General Public License and
+ * GNU LESSER GENERAL PUBLIC LICENSE along with Jaris FLV Player. If not,
* see <http://www.gnu.org/licenses/>.
*/
@@ -25,11 +25,11 @@ package jaris;
/**
* Actual jaris flv player version and date
*/
-class Version
+class Version
{
- public static var NUMBER:String = "2.0.16";
- public static var STATUS:String = "stable";
- public static var DATE:String = "11";
- public static var MONTH:String = "09";
- public static var YEAR:String = "2014";
+ public static var NUMBER:String = "2.0.17";
+ public static var STATUS:String = "stable";
+ public static var DATE:String = "22";
+ public static var MONTH:String = "11";
+ public static var YEAR:String = "2015";
}
diff --git a/src/jaris/player/Player.hx b/src/jaris/player/Player.hx
index deff6e0..af35ef7 100644
--- a/src/jaris/player/Player.hx
+++ b/src/jaris/player/Player.hx
@@ -1,13 +1,13 @@
-/**
+/**
* @author Jefferson González
* @copyright 2010 Jefferson González
*
- * @license
+ * @license
* This file is part of Jaris FLV Player.
*
* Jaris FLV Player is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License or GNU LESSER GENERAL
- * PUBLIC LICENSE as published by the Free Software Foundation, either version
+ * it under the terms of the GNU General Public License or GNU LESSER GENERAL
+ * PUBLIC LICENSE as published by the Free Software Foundation, either version
* 3 of the License, or (at your option) any later version.
*
* Jaris FLV Player is distributed in the hope that it will be useful,
@@ -15,8 +15,8 @@
* 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 and
- * GNU LESSER GENERAL PUBLIC LICENSE along with Jaris FLV Player. If not,
+ * You should have received a copy of the GNU General Public License and
+ * GNU LESSER GENERAL PUBLIC LICENSE along with Jaris FLV Player. If not,
* see <http://www.gnu.org/licenses/>.
*/
@@ -62,1740 +62,1741 @@ import jaris.player.UserSettings;
*/
class Player extends EventDispatcher
{
- //{Member variables
- private var _stage:Stage;
- private var _movieClip:MovieClip;
- private var _connection:NetConnection;
- private var _stream:NetStream;
- private var _fullscreen:Bool;
- private var _soundMuted:Bool;
- private var _volume:Float;
- private var _bufferTime:Float;
- private var _mouseVisible:Bool;
- private var _mediaLoaded:Bool;
- private var _hideMouseTimer:Timer;
- private var _checkAudioTimer:Timer;
- private var _mediaSource:String;
- private var _type:String;
- private var _streamType:String;
- private var _server:String; //For future use on rtmp
- private var _sound:Sound;
- private var _soundChannel:SoundChannel;
- private var _id3Info:ID3Info;
- private var _video:Video;
- private var _videoWidth:Float;
- private var _videoHeight:Float;
- private var _videoMask:Sprite;
- private var _videoQualityHigh:Bool;
- private var _mediaDuration:Float;
- private var _lastTime:Float;
- private var _lastProgress:Float;
- private var _isPlaying:Bool;
- private var _aspectRatio:Float;
- private var _currentAspectRatio:String;
- private var _originalAspectRatio:Float;
- private var _mediaEndReached:Bool;
- private var _seekPoints:Array<Float>;
- private var _downloadCompleted:Bool;
- private var _startTime:Float;
- private var _firstLoad:Bool;
- private var _stopped:Bool;
- private var _useHardWareScaling:Bool;
- private var _youtubeLoader:Loader;
- private var _userSettings:UserSettings;
- //}
-
-
- //{Constructor
- public function new()
- {
- super();
-
- //{Main Variables Init
- _stage = Lib.current.stage;
- _movieClip = Lib.current;
- _mouseVisible = true;
- _soundMuted = false;
- _volume = 1.0;
- _bufferTime = 10;
- _fullscreen = false;
- _mediaLoaded = false;
- _hideMouseTimer = new Timer(1500);
- _checkAudioTimer = new Timer(100);
- _seekPoints = new Array();
- _downloadCompleted = false;
- _startTime = 0;
- _firstLoad = true;
- _stopped = false;
- _videoQualityHigh = false;
- _isPlaying = false;
- _streamType = StreamType.FILE;
- _type = InputType.VIDEO;
- _server = "";
- _currentAspectRatio = "original";
- _aspectRatio = 0;
- _lastTime = 0;
- _lastProgress = 0;
- _userSettings = new UserSettings();
- //}
-
- //{Initialize sound object
- _sound = new Sound();
- _sound.addEventListener(Event.COMPLETE, onSoundComplete);
+ //{Member variables
+ private var _stage:Stage;
+ private var _movieClip:MovieClip;
+ private var _connection:NetConnection;
+ private var _stream:NetStream;
+ private var _fullscreen:Bool;
+ private var _soundMuted:Bool;
+ private var _volume:Float;
+ private var _bufferTime:Float;
+ private var _mouseVisible:Bool;
+ private var _mediaLoaded:Bool;
+ private var _hideMouseTimer:Timer;
+ private var _checkAudioTimer:Timer;
+ private var _mediaSource:String;
+ private var _type:String;
+ private var _streamType:String;
+ private var _server:String; //For future use on rtmp
+ private var _sound:Sound;
+ private var _soundChannel:SoundChannel;
+ private var _id3Info:ID3Info;
+ private var _video:Video;
+ private var _videoWidth:Float;
+ private var _videoHeight:Float;
+ private var _videoMask:Sprite;
+ private var _videoQualityHigh:Bool;
+ private var _mediaDuration:Float;
+ private var _lastTime:Float;
+ private var _lastProgress:Float;
+ private var _isPlaying:Bool;
+ private var _aspectRatio:Float;
+ private var _currentAspectRatio:String;
+ private var _originalAspectRatio:Float;
+ private var _mediaEndReached:Bool;
+ private var _seekPoints:Array<Float>;
+ private var _downloadCompleted:Bool;
+ private var _startTime:Float;
+ private var _firstLoad:Bool;
+ private var _stopped:Bool;
+ private var _useHardWareScaling:Bool;
+ private var _youtubeLoader:Loader;
+ private var _userSettings:UserSettings;
+ //}
+
+
+ //{Constructor
+ public function new()
+ {
+ super();
+
+ //{Main Variables Init
+ _stage = Lib.current.stage;
+ _movieClip = Lib.current;
+ _mouseVisible = true;
+ _soundMuted = false;
+ _volume = 1.0;
+ _bufferTime = 10;
+ _fullscreen = false;
+ _mediaLoaded = false;
+ _hideMouseTimer = new Timer(1500);
+ _checkAudioTimer = new Timer(100);
+ _seekPoints = new Array();
+ _downloadCompleted = false;
+ _startTime = 0;
+ _firstLoad = true;
+ _stopped = false;
+ _videoQualityHigh = false;
+ _isPlaying = false;
+ _streamType = StreamType.FILE;
+ _type = InputType.VIDEO;
+ _server = "";
+ _currentAspectRatio = "original";
+ _aspectRatio = 0;
+ _lastTime = 0;
+ _lastProgress = 0;
+ _userSettings = new UserSettings();
+ //}
+
+ //{Initialize sound object
+ _sound = new Sound();
+ _sound.addEventListener(Event.COMPLETE, onSoundComplete);
_sound.addEventListener(Event.ID3, onSoundID3);
_sound.addEventListener(IOErrorEvent.IO_ERROR, onSoundIOError);
_sound.addEventListener(ProgressEvent.PROGRESS, onSoundProgress);
- //}
-
- //{Initialize video and connection objects
- _connection = new NetConnection();
- _connection.client = this;
- _connection.connect(null);
- _stream = new NetStream(_connection);
-
- _video = new Video(_stage.stageWidth, _stage.stageHeight);
-
- _movieClip.addChild(_video);
- //}
-
- //Video mask so that custom menu items work
- _videoMask = new Sprite();
- _movieClip.addChild(_videoMask);
-
- //Set initial rendering to high quality
- toggleQuality();
-
- //{Initialize system event listeners
- _movieClip.addEventListener(Event.ENTER_FRAME, onEnterFrame);
- _stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);
- _stage.addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
- _stage.addEventListener(FullScreenEvent.FULL_SCREEN, onFullScreen);
- _stage.addEventListener(Event.RESIZE, onResize);
- _hideMouseTimer.addEventListener(TimerEvent.TIMER, hideMouseTimer);
- _checkAudioTimer.addEventListener(TimerEvent.TIMER, checkAudioTimer);
- _connection.addEventListener(NetStatusEvent.NET_STATUS, onNetStatus);
- _connection.addEventListener(AsyncErrorEvent.ASYNC_ERROR, onAsyncError);
- //}
- }
- //}
-
-
- //{Timers
- /**
- * Timer that hides the mouse pointer when it is idle and dispatch the PlayerEvents.MOUSE_HIDE
- * @param event
- */
- private function hideMouseTimer(event:TimerEvent):Void
- {
- if (_fullscreen)
- {
- if (_mouseVisible)
- {
- _mouseVisible = false;
- }
- else
- {
- Mouse.hide();
- callEvents(PlayerEvents.MOUSE_HIDE);
- _hideMouseTimer.stop();
- }
- }
- }
-
- /**
- * To check if the sound finished playing
- * @param event
- */
- private function checkAudioTimer(event:TimerEvent):Void
- {
- if (_soundChannel.position + 100 >= _sound.length)
- {
- _isPlaying = false;
- _mediaEndReached = true;
- callEvents(PlayerEvents.PLAYBACK_FINISHED);
-
- _checkAudioTimer.stop();
- }
- }
- //}
-
-
- //{Events
- /**
- * Callback after bandwidth calculation for rtmp streams
- */
- private function onBWDone():Void
- {
- //Need to study this more
- }
-
- /**
- * Triggers error event on rtmp connections
- * @param event
- */
- private function onAsyncError(event:AsyncErrorEvent):Void
- {
- //TODO: Should trigger event for controls to display error message
- trace(event.error);
- }
-
- /**
- * Checks if connection failed or succeed
- * @param event
- */
- private function onNetStatus(event:NetStatusEvent):Void
- {
- switch (event.info.code)
- {
- case "NetConnection.Connect.Success":
- if (_streamType == StreamType.RTMP)
- {
- _stream = new NetStream(_connection);
- _stream.addEventListener(NetStatusEvent.NET_STATUS, onNetStatus);
- _stream.bufferTime = 10;
- _stream.play(Utils.rtmpSourceParser(_mediaSource), true);
- _stream.client = this;
- if(_type == InputType.VIDEO) {_video.attachNetStream(_stream); }
- }
- callEvents(PlayerEvents.CONNECTION_SUCCESS);
-
- case "NetStream.Play.StreamNotFound":
- trace("Stream not found: " + _mediaSource); //Replace with a dispatch for error event
- callEvents(PlayerEvents.CONNECTION_FAILED);
-
- case "NetStream.Play.Stop":
- if (_streamType != StreamType.RTMP)
- {
- if (_isPlaying) { _stream.togglePause(); }
- _isPlaying = false;
- _mediaEndReached = true;
- callEvents(PlayerEvents.PLAYBACK_FINISHED);
- }
-
- case "NetStream.Play.Start":
- _isPlaying = true;
- _mediaEndReached = false;
- if (_stream.bytesLoaded != _stream.bytesTotal || _streamType == StreamType.RTMP)
- {
- callEvents(PlayerEvents.BUFFERING);
- }
-
- case "NetStream.Seek.Notify":
- _mediaEndReached = false;
- if (_streamType == StreamType.RTMP)
- {
- _isPlaying = true;
- callEvents(PlayerEvents.PLAY_PAUSE);
- callEvents(PlayerEvents.BUFFERING);
- }
-
- case "NetStream.Buffer.Empty":
- if (_stream.bytesLoaded != _stream.bytesTotal)
- {
- callEvents(PlayerEvents.BUFFERING);
- }
-
- case "NetStream.Buffer.Full":
- callEvents(PlayerEvents.NOT_BUFFERING);
-
- case "NetStream.Buffer.Flush":
- if (_stream.bytesLoaded == _stream.bytesTotal)
- {
- _downloadCompleted = true;
- }
- }
- }
-
- /**
- * Proccess keyboard shortcuts
- * @param event
- */
- private function onKeyDown(event:KeyboardEvent):Void
- {
- var F_KEY:UInt = 70;
- var M_KEY:UInt = 77;
- var X_KEY:UInt = 88;
-
- if(event.keyCode == Keyboard.TAB)
- {
- toggleAspectRatio();
- }
- else if(event.keyCode == F_KEY)
- {
- toggleFullscreen();
- }
- else if(event.keyCode == M_KEY)
- {
- toggleMute();
- }
- else if(event.keyCode == Keyboard.UP)
- {
- volumeUp();
- }
- else if(event.keyCode == Keyboard.DOWN)
- {
- volumeDown();
- }
- else if(event.keyCode == Keyboard.RIGHT)
- {
- forward();
- }
- else if(event.keyCode == Keyboard.LEFT)
- {
- rewind();
- }
- else if(event.keyCode == Keyboard.SPACE)
- {
- togglePlay();
- }
- else if(event.keyCode == X_KEY)
- {
- stopAndClose();
- }
- }
-
- /**
- * IF player is full screen shows the mouse when gets hide
- * @param event
- */
- private function onMouseMove(event:MouseEvent):Void
- {
- if (_fullscreen && !_mouseVisible)
- {
- if (!_hideMouseTimer.running)
- {
- _hideMouseTimer.start();
- }
-
- _mouseVisible = true;
- Mouse.show();
-
- callEvents(PlayerEvents.MOUSE_SHOW);
- }
- }
-
- /**
- * Resize video player
- * @param event
- */
- private function onResize(event:Event):Void
- {
- resizeAndCenterPlayer();
- }
-
- /**
- * Dispath a full screen event to listeners as redraw player an takes care of some other aspects
- * @param event
- */
- private function onFullScreen(event:FullScreenEvent):Void
- {
- _fullscreen = event.fullScreen;
-
- if (!event.fullScreen)
- {
- Mouse.show();
- callEvents(PlayerEvents.MOUSE_SHOW);
- _mouseVisible = true;
- }
- else
- {
- _mouseVisible = true;
- _hideMouseTimer.start();
- }
-
- resizeAndCenterPlayer();
-
- callEvents(PlayerEvents.FULLSCREEN);
- }
-
- /**
- * Sits for any cue points available
- * @param data
- * @note Planned future implementation
- */
- private function onCuePoint(data:Dynamic):Void
- {
-
- }
-
- /**
- * After a video is loaded this callback gets the video information at start and stores it on variables
- * @param data
- */
- private function onMetaData(data:Dynamic):Void
- {
- if (_firstLoad)
- {
- _isPlaying = true;
-
- _firstLoad = false;
- if (data.width)
- {
- _videoWidth = data.width;
- _videoHeight = data.height;
- }
- else
- {
- _videoWidth = _video.width;
- _videoHeight = _video.height;
- }
-
- //Store seekpoints times
- if (data.hasOwnProperty("seekpoints")) //MP4
- {
- for (position in Reflect.fields(data.seekpoints))
- {
- _seekPoints.push(Reflect.field(data.seekpoints, position).time);
- }
- }
- else if (data.hasOwnProperty("keyframes")) //FLV
- {
- for (position in Reflect.fields(data.keyframes.times))
- {
- _seekPoints.push(Reflect.field(data.keyframes.times, position));
- }
- }
-
- _mediaLoaded = true;
- _mediaDuration = data.duration;
- _originalAspectRatio = AspectRatio.getAspectRatio(_videoWidth, _videoHeight);
-
- if (_aspectRatio <= 0)
- {
- _aspectRatio = _originalAspectRatio;
- }
-
- callEvents(PlayerEvents.MEDIA_INITIALIZED);
-
- resizeAndCenterPlayer();
-
- //Retrieve the volume that user selected last time
- setVolume(_userSettings.getVolume());
- }
- }
-
- /**
- * Dummy function invoked for pseudostream servers
- * @param data
- */
- private function onLastSecond(data:Dynamic):Void
- {
- trace("last second pseudostream");
- }
-
- /**
- * Broadcast Timeupdate and Duration
- */
- private function onEnterFrame(event:Event):Void
- {
- if (getDuration() > 0 && _lastTime != getCurrentTime())
- {
- _lastTime = getCurrentTime();
- callEvents(PlayerEvents.TIME);
- }
-
- if (getBytesLoaded() > 0 && _lastProgress < getBytesLoaded())
- {
- _lastProgress = getBytesLoaded();
- callEvents(PlayerEvents.PROGRESS);
- }
-
- }
-
-
- /**
- * Triggers when playbacks end on rtmp streaming server
- */
- private function onPlayStatus(info:Dynamic):Void
- {
- _isPlaying = false;
- _mediaEndReached = true;
- callEvents(PlayerEvents.PLAYBACK_FINISHED);
- }
-
- /**
- * When sound finished downloading
- * @param event
- */
- private function onSoundComplete(event:Event)
- {
- _mediaDuration = _sound.length / 1000;
- _downloadCompleted = true;
-
- callEvents(PlayerEvents.MEDIA_INITIALIZED);
- }
-
- /**
- * Mimic stream onMetaData
- * @param event
- */
- private function onSoundID3(event:Event)
- {
- if (_firstLoad)
- {
- _soundChannel = _sound.play();
- _checkAudioTimer.start();
-
- _isPlaying = true;
-
- _firstLoad = false;
-
- _mediaLoaded = true;
- _mediaDuration = ((_sound.bytesTotal / _sound.bytesLoaded) * _sound.length) / 1000;
- _aspectRatio = AspectRatio.getAspectRatio(_videoWidth, _videoHeight);
- _originalAspectRatio = _aspectRatio;
- _id3Info = _sound.id3;
-
- callEvents(PlayerEvents.CONNECTION_SUCCESS);
- callEvents(PlayerEvents.MEDIA_INITIALIZED);
-
- resizeAndCenterPlayer();
-
- //Retrieve the volume that user selected last time
- setVolume(_userSettings.getVolume());
- }
- }
-
- /**
- * Dispatch connection failed event on error
- * @param event
- */
- private function onSoundIOError(event:IOErrorEvent)
- {
- callEvents(PlayerEvents.CONNECTION_FAILED);
- }
-
- /**
- * Monitor sound download progress
- * @param event
- */
- private function onSoundProgress(event:ProgressEvent)
- {
- if (_sound.isBuffering)
- {
- callEvents(PlayerEvents.BUFFERING);
- }
- else
- {
- callEvents(PlayerEvents.NOT_BUFFERING);
- }
-
- _mediaDuration = ((_sound.bytesTotal / _sound.bytesLoaded) * _sound.length) / 1000;
- callEvents(PlayerEvents.MEDIA_INITIALIZED);
- }
-
- /**
- * Initializes the youtube loader object
- * @param event
- */
- private function onYouTubeLoaderInit(event:Event):Void
- {
- _youtubeLoader.content.addEventListener("onReady", onYoutubeReady);
- _youtubeLoader.content.addEventListener("onError", onYoutubeError);
- _youtubeLoader.content.addEventListener("onStateChange", onYoutubeStateChange);
- _youtubeLoader.content.addEventListener("onPlaybackQualityChange", onYoutubePlaybackQualityChange);
-
- }
-
- /**
- * This event is fired when the player is loaded and initialized, meaning it is ready to receive API calls.
- */
- private function onYoutubeReady(event:Event):Void
- {
- _movieClip.addChild(_youtubeLoader.content);
- _movieClip.setChildIndex(_youtubeLoader.content, 0);
- Reflect.field(_youtubeLoader.content, "setSize")(_stage.stageWidth, _stage.stageHeight);
- Reflect.field(_youtubeLoader.content, "loadVideoByUrl")(Utils.youtubeSourceParse(_mediaSource));
- callEvents(PlayerEvents.BUFFERING);
- }
-
- /**
- * This event is fired whenever the player's state changes. Possible values are unstarted (-1), ended (0),
- * playing (1), paused (2), buffering (3), video cued (5). When the SWF is first loaded it will broadcast
- * an unstarted (-1) event. When the video is cued and ready to play it will broadcast a video cued event (5).
- * @param event
- */
- private function onYoutubeStateChange(event:Event):Void
- {
- var status:UInt = Std.parseInt(Reflect.field(event, "data"));
-
- switch(status)
- {
- case -1:
- callEvents(PlayerEvents.BUFFERING);
-
- case 0:
- _isPlaying = false;
- _mediaEndReached = true;
- callEvents(PlayerEvents.PLAYBACK_FINISHED);
-
- case 1:
- if (_firstLoad)
- {
- _isPlaying = true;
-
- _videoWidth = _stage.stageWidth;
- _videoHeight = _stage.stageHeight;
-
- _firstLoad = false;
-
- _mediaLoaded = true;
- _mediaDuration = Reflect.field(_youtubeLoader.content, "getDuration")();
- _aspectRatio = AspectRatio.getAspectRatio(_videoWidth, _videoHeight);
- _originalAspectRatio = _aspectRatio;
-
- callEvents(PlayerEvents.CONNECTION_SUCCESS);
- callEvents(PlayerEvents.MEDIA_INITIALIZED);
-
- resizeAndCenterPlayer();
-
- //Retrieve the volume that user selected last time
- setVolume(_userSettings.getVolume());
- }
- callEvents(PlayerEvents.NOT_BUFFERING);
-
- case 2:
- callEvents(PlayerEvents.NOT_BUFFERING);
-
- case 3:
- callEvents(PlayerEvents.BUFFERING);
-
- case 5:
- callEvents(PlayerEvents.NOT_BUFFERING);
- }
- }
-
- /**
- * This event is fired whenever the video playback quality changes. For example, if you call the
- * setPlaybackQuality(suggestedQuality) function, this event will fire if the playback quality actually
- * changes. Your code should respond to the event and should not assume that the quality will automatically
- * change when the setPlaybackQuality(suggestedQuality) function is called. Similarly, your code should not
- * assume that playback quality will only change as a result of an explicit call to setPlaybackQuality or any
- * other function that allows you to set a suggested playback quality.
- *
- * The value that the event broadcasts is the new playback quality. Possible values are "small", "medium",
- * "large" and "hd720".
- * @param event
- */
- private function onYoutubePlaybackQualityChange(event:Event):Void
- {
- //trace(Reflect.field(event, "data"));
- }
-
- /**
- * This event is fired when an error in the player occurs. The possible error codes are 100, 101,
- * and 150. The 100 error code is broadcast when the video requested is not found. This occurs when
- * a video has been removed (for any reason), or it has been marked as private. The 101 error code is
- * broadcast when the video requested does not allow playback in the embedded players. The error code
- * 150 is the same as 101, it's just 101 in disguise!
- * @param event
- */
- private function onYoutubeError(event:Event):Void
- {
- trace(Reflect.field(event, "data"));
- }
- //}
-
-
- //{Private Methods
- /**
- * Function used each time is needed to dispatch an event
- * @param type
- */
- private function callEvents(type:String):Void
- {
- var playerEvent:PlayerEvents = new PlayerEvents(type, true);
-
- playerEvent.aspectRatio = getAspectRatio();
- playerEvent.duration = getDuration();
- playerEvent.fullscreen = isFullscreen();
- playerEvent.mute = getMute();
- playerEvent.volume = getVolume();
- playerEvent.width = _video.width;
- playerEvent.height = _video.height;
- playerEvent.stream = getNetStream();
- playerEvent.sound = getSound();
- playerEvent.time = getCurrentTime();
- playerEvent.id3Info = getId3Info();
-
- dispatchEvent(playerEvent);
- }
-
- /**
- * Reposition and resizes the video player to fit on screen
- */
- private function resizeAndCenterPlayer():Void
- {
- if (_streamType != StreamType.YOUTUBE)
- {
- _video.height = _stage.stageHeight;
- _video.width = _video.height * _aspectRatio;
-
- _video.x = (_stage.stageWidth / 2) - (_video.width / 2);
- _video.y = 0;
-
- if (_video.width > _stage.stageWidth && _aspectRatio == _originalAspectRatio)
- {
- var aspectRatio:Float = _videoHeight / _videoWidth;
- _video.width = _stage.stageWidth;
- _video.height = aspectRatio * _video.width;
- _video.x = 0;
- _video.y = (_stage.stageHeight / 2) - (_video.height / 2);
- }
-
- _videoMask.graphics.clear();
- _videoMask.graphics.lineStyle();
- _videoMask.graphics.beginFill(0x000000, 0);
- _videoMask.graphics.drawRect(_video.x, _video.y, _video.width, _video.height);
- _videoMask.graphics.endFill();
- }
- else
- {
- Reflect.field(_youtubeLoader.content, "setSize")(_stage.stageWidth, _stage.stageHeight);
-
- _videoMask.graphics.clear();
- _videoMask.graphics.lineStyle();
- _videoMask.graphics.beginFill(0x000000, 0);
- _videoMask.graphics.drawRect(0, 0, _stage.stageWidth, _stage.stageHeight);
- _videoMask.graphics.endFill();
- }
-
- callEvents(PlayerEvents.RESIZE);
- }
-
- /**
- * Check the best seek point available if the seekpoints array is available
- * @param time time in seconds
- * @return best seek point in seconds or given one if no seekpoints array is available
- */
- private function getBestSeekPoint(time:Float):Float
- {
- if (_seekPoints.length > 0)
- {
- var timeOne:String="0";
- var timeTwo:String="0";
-
- for(prop in Reflect.fields(_seekPoints))
- {
- if(Reflect.field(_seekPoints,prop) < time)
- {
- timeOne = prop;
- }
- else
- {
- timeTwo = prop;
- break;
- }
- }
-
- if(time - _seekPoints[Std.parseInt(timeOne)] < _seekPoints[Std.parseInt(timeTwo)] - time)
- {
- return _seekPoints[Std.parseInt(timeOne)];
- }
- else
- {
- return _seekPoints[Std.parseInt(timeTwo)];
- }
- }
-
- return time;
- }
-
- /**
- * Checks if the given seek time is already buffered
- * @param time time in seconds
- * @return true if can seek false if not in buffer
- */
- private function canSeek(time:Float):Bool
- {
- if (_type == InputType.VIDEO)
- {
- time = getBestSeekPoint(time);
- }
-
- var cacheTotal = Math.floor((getDuration() - _startTime) * (getBytesLoaded() / getBytesTotal())) - 1;
-
- if(time >= _startTime && time < _startTime + cacheTotal)
- {
- return true;
- }
-
- return false;
- }
- //}
-
-
- //{Public methods
- /**
- * Loads a video and starts playing it
- * @param video video url to load
- */
- public function load(source:String, type:String="video", streamType:String="file", server:String=""):Void
- {
- stopAndClose();
-
- _type = type;
- _streamType = streamType;
- _mediaSource = source;
- _stopped = false;
- _mediaLoaded = false;
- _firstLoad = true;
- _startTime = 0;
- _downloadCompleted = false;
- _seekPoints = new Array();
- _server = server;
-
- callEvents(PlayerEvents.BUFFERING);
-
- if (_streamType == StreamType.YOUTUBE)
- {
- Security.allowDomain("*");
- Security.allowDomain("www.youtube.com");
- Security.allowDomain("youtube.com");
- Security.allowDomain("s.ytimg.com");
- Security.allowDomain("i.ytimg.com");
-
- _youtubeLoader = new Loader();
- _youtubeLoader.contentLoaderInfo.addEventListener(Event.INIT, onYouTubeLoaderInit);
- _youtubeLoader.load(new URLRequest("http://www.youtube.com/apiplayer?version=3"));
- }
- else if (_type == InputType.VIDEO && (_streamType == StreamType.FILE || _streamType == StreamType.PSEUDOSTREAM))
- {
- _connection.connect(null);
- _stream = new NetStream(_connection);
- _stream.addEventListener(NetStatusEvent.NET_STATUS, onNetStatus);
- _stream.addEventListener(AsyncErrorEvent.ASYNC_ERROR, doAsyncError);
- _stream.bufferTime = _bufferTime;
- _stream.play(source);
- _stream.client = this;
- _video.attachNetStream(_stream);
- }
- else if (_type == InputType.VIDEO && _streamType == StreamType.RTMP)
- {
- _connection.connect(_server);
- }
- else if (_type == InputType.AUDIO && _streamType == StreamType.RTMP)
- {
- _connection.connect(_server);
- }
- else if(_type == InputType.AUDIO && _streamType == StreamType.FILE)
- {
- _sound.load(new URLRequest(source));
- }
- }
-
- private function doAsyncError(e:AsyncErrorEvent) : Void
- {
- // Do nothing, to block the exception.
- }
-
- /**
- * Closes the connection and makes player available for another video
- */
- public function stopAndClose():Void
- {
- if (_mediaLoaded)
- {
- _mediaLoaded = false;
- _isPlaying = false;
- _stopped = true;
- _startTime = 0;
-
- if (_streamType == StreamType.YOUTUBE)
- {
- Reflect.field(_youtubeLoader.content, "destroy")();
- }
- else if (_type == InputType.VIDEO)
- {
- _stream.close();
- }
- else
- {
- _soundChannel.stop();
- _sound.close();
- }
- }
-
- callEvents(PlayerEvents.STOP_CLOSE);
- }
-
- /**
- * Seeks 8 seconds forward from the current position.
- * @return current play time after forward
- */
- public function forward():Float
- {
- var seekTime = (getCurrentTime() + 8) + _startTime;
-
- if (getDuration() > seekTime)
- {
- seekTime = seek(seekTime);
- }
-
- return seekTime;
- }
-
- /**
- * Seeks 8 seconds back from the current position.
- * @return current play time after rewind
- */
- public function rewind():Float
- {
- var seekTime = (getCurrentTime() - 8) + _startTime;
-
- if (seekTime >= _startTime)
- {
- seekTime = seek(seekTime);
- }
-
- return seekTime;
- }
-
- /**
- * Seeks video player to a given time in seconds
- * @param seekTime time in seconds to seek
- * @return current play time after seeking
- */
- public function seek(seekTime:Float):Float
- {
- if (_startTime <= 1 && _downloadCompleted)
- {
- if (_type == InputType.VIDEO || _streamType == StreamType.RTMP)
- {
- _stream.seek(seekTime);
- }
- else if (_type == InputType.AUDIO)
- {
- _soundChannel.stop();
- _soundChannel = _sound.play(seekTime * 1000);
- if (!_isPlaying)
- {
- _soundChannel.stop();
- }
-
- setVolume(_userSettings.getVolume());
- }
- }
- else if(_seekPoints.length > 0 && _streamType == StreamType.PSEUDOSTREAM)
- {
- seekTime = getBestSeekPoint(seekTime);
-
- if (canSeek(seekTime))
- {
- _stream.seek(seekTime - _startTime);
- }
- else if(seekTime != _startTime)
- {
- _startTime = seekTime;
-
- var url:String;
- if (_mediaSource.indexOf("?") != -1)
- {
- url = _mediaSource + "&start=" + seekTime;
- }
- else
- {
- url = _mediaSource + "?start=" + seekTime;
- }
- _stream.play(url);
- }
- }
- else if (_streamType == StreamType.YOUTUBE)
- {
- if (!canSeek(seekTime))
- {
- _startTime = seekTime;
- Reflect.field(_youtubeLoader.content, "seekTo")(seekTime);
- }
- else
- {
- Reflect.field(_youtubeLoader.content, "seekTo")(seekTime);
- }
-
- }
- else if (_streamType == StreamType.RTMP)
- {
- // seekTime = getBestSeekPoint(seekTime); //Not Needed?
- _stream.seek(seekTime);
- }
- else if(canSeek(seekTime))
- {
- if (_type == InputType.VIDEO || _streamType == StreamType.RTMP)
- {
- _stream.seek(seekTime);
- }
- else if (_type == InputType.AUDIO)
- {
- _soundChannel.stop();
- _soundChannel = _sound.play(seekTime * 1000);
- if (!_isPlaying)
- {
- _soundChannel.stop();
- }
-
- setVolume(_userSettings.getVolume());
- }
- }
- callEvents(PlayerEvents.SEEK);
- return seekTime;
- }
-
- /**
- * To check wheter the media is playing
- * @return true if is playing false otherwise
- */
- public function isPlaying():Bool
- {
- return _isPlaying;
- }
-
- /**
- * Cycle betewen aspect ratios
- * @return new aspect ratio in use
- */
- public function toggleAspectRatio():Float
- {
- switch(_currentAspectRatio)
- {
- case "original":
- _aspectRatio = AspectRatio._1_1;
- _currentAspectRatio = "1:1";
-
- case "1:1":
- _aspectRatio = AspectRatio._3_2;
- _currentAspectRatio = "3:2";
-
- case "3:2":
- _aspectRatio = AspectRatio._4_3;
- _currentAspectRatio = "4:3";
-
- case "4:3":
- _aspectRatio = AspectRatio._5_4;
- _currentAspectRatio = "5:4";
-
- case "5:4":
- _aspectRatio = AspectRatio._14_9;
- _currentAspectRatio = "14:9";
-
- case "14:9":
- _aspectRatio = AspectRatio._14_10;
- _currentAspectRatio = "14:10";
-
- case "14:10":
- _aspectRatio = AspectRatio._16_9;
- _currentAspectRatio = "16:9";
-
- case "16:9":
- _aspectRatio = AspectRatio._16_10;
- _currentAspectRatio = "16:10";
-
- case "16:10":
- _aspectRatio = _originalAspectRatio;
- _currentAspectRatio = "original";
-
- default:
- _aspectRatio = _originalAspectRatio;
- _currentAspectRatio = "original";
- }
-
- resizeAndCenterPlayer();
-
- callEvents(PlayerEvents.ASPECT_RATIO);
-
- //Store aspect ratio into user settings
- if (_aspectRatio == _originalAspectRatio)
- {
- _userSettings.setAspectRatio(0.0);
- }
- else
- {
- _userSettings.setAspectRatio(_aspectRatio);
- }
-
- return _aspectRatio;
- }
-
- /**
- * Swithces between play and pause
- */
- public function togglePlay():Bool
- {
- if (_mediaLoaded)
- {
- if (_mediaEndReached)
- {
- _mediaEndReached = false;
-
- if (_streamType == StreamType.YOUTUBE)
- {
- Reflect.field(_youtubeLoader.content, "seekTo")(0);
- Reflect.field(_youtubeLoader.content, "playVideo")();
- }
- else if (_type == InputType.VIDEO || _streamType == StreamType.RTMP)
- {
- _stream.seek(0);
- _stream.togglePause();
- }
- else if (_type == InputType.AUDIO)
- {
- _checkAudioTimer.start();
- _soundChannel = _sound.play();
- setVolume(_userSettings.getVolume());
- }
- }
- else if (_mediaLoaded)
- {
- if (_streamType == StreamType.YOUTUBE)
- {
- if (_isPlaying)
- {
- Reflect.field(_youtubeLoader.content, "pauseVideo")();
- }
- else
- {
- Reflect.field(_youtubeLoader.content, "playVideo")();
- }
- }
- else if (_type == InputType.VIDEO || _streamType == StreamType.RTMP)
- {
- _stream.togglePause();
- }
- else if (_type == InputType.AUDIO)
- {
- if (_isPlaying)
- {
- _soundChannel.stop();
- }
- else
- {
- //If end of audio reached start from beggining
- if (_soundChannel.position + 100 >= _sound.length)
- {
- _soundChannel = _sound.play();
- }
- else
- {
- _soundChannel = _sound.play(_soundChannel.position);
- }
-
- setVolume(_userSettings.getVolume());
- }
- }
- }
- else if (_stopped)
- {
- load(_mediaSource, _type, _streamType, _server);
- }
-
- _isPlaying = !_isPlaying;
- callEvents(PlayerEvents.PLAY_PAUSE);
- return _isPlaying;
- }
- else if(_mediaSource != "")
- {
- load(_mediaSource, _type, _streamType, _server);
- callEvents(PlayerEvents.BUFFERING);
- return true;
- }
- callEvents(PlayerEvents.PLAY_PAUSE);
- return false;
- }
-
- /**
- * Switches on or off fullscreen
- * @return true if fullscreen otherwise false
- */
- public function toggleFullscreen():Bool
- {
- if (_fullscreen)
- {
- _stage.displayState = StageDisplayState.NORMAL;
- _stage.focus = _stage;
- return false;
- }
- else
- {
- if (_useHardWareScaling)
- {
- //Match full screen aspec ratio to desktop
- var aspectRatio = Capabilities.screenResolutionY / Capabilities.screenResolutionX;
- _stage.fullScreenSourceRect = new Rectangle(0, 0, _videoWidth, _videoWidth * aspectRatio);
- }
- else
- {
- //Use desktop resolution
- _stage.fullScreenSourceRect = new Rectangle(0, 0, Capabilities.screenResolutionX ,Capabilities.screenResolutionY);
- }
-
- _stage.displayState = StageDisplayState.FULL_SCREEN;
- _stage.focus = _stage;
- return true;
- }
- }
-
- /**
- * Toggles betewen high and low quality image rendering
- * @return true if quality high false otherwise
- */
- public function toggleQuality():Bool
- {
- if (_videoQualityHigh)
- {
- _video.smoothing = false;
- _video.deblocking = 1;
- }
- else
- {
- _video.smoothing = true;
- _video.deblocking = 5;
- }
-
- _videoQualityHigh = _videoQualityHigh?false:true;
-
- return _videoQualityHigh;
- }
-
- /**
- * Mutes or unmutes the sound
- * @return true if muted false if unmuted
- */
- public function toggleMute():Bool
- {
- var soundTransform:SoundTransform = new SoundTransform();
- var isMute:Bool;
-
- //unmute sound
- if (_soundMuted)
- {
- _soundMuted = false;
-
- if (_volume > 0)
- {
- soundTransform.volume = _volume;
- }
- else
- {
- _volume = 1.0;
- soundTransform.volume = _volume;
- }
-
- isMute = false;
- }
-
- //mute sound
- else
- {
- _soundMuted = true;
- _volume = _stream.soundTransform.volume;
- soundTransform.volume = 0;
- _stream.soundTransform = soundTransform;
-
- isMute = true;
- }
-
- if (_streamType == StreamType.YOUTUBE)
- {
- Reflect.field(_youtubeLoader.content, "setVolume")(soundTransform.volume * 100);
- }
- else if (_type == InputType.VIDEO || _streamType == StreamType.RTMP)
- {
- _stream.soundTransform = soundTransform;
- }
- else if (_type == InputType.AUDIO)
- {
- _soundChannel.soundTransform = soundTransform;
- setVolume(_userSettings.getVolume());
- }
-
- callEvents(PlayerEvents.MUTE);
- return isMute;
- }
-
- /**
- * Check if player is running on fullscreen mode
- * @return true if fullscreen false if not
- */
- public function isFullscreen():Bool
- {
- return _stage.displayState == StageDisplayState.FULL_SCREEN;
- }
-
- /**
- * Raises the volume
- * @return volume value after raising
- */
- public function volumeUp():Float
- {
- var soundTransform:SoundTransform = new SoundTransform();
-
- if (_soundMuted)
- {
- _soundMuted = false;
- }
-
- //raise volume if not already at max
- if (_volume < 1)
- {
- if (_streamType == StreamType.YOUTUBE)
- {
- _volume = (Reflect.field(_youtubeLoader.content, "getVolume")() + 10) / 100;
- Reflect.field(_youtubeLoader.content, "setVolume")(_volume * 100);
- }
- else if (_type == InputType.VIDEO || _streamType == StreamType.RTMP)
- {
- _volume = _stream.soundTransform.volume + (10/100);
- soundTransform.volume = _volume;
- _stream.soundTransform = soundTransform;
- }
- else if (_type == InputType.AUDIO)
- {
- _volume = _soundChannel.soundTransform.volume + (10/100);
- soundTransform.volume = _volume;
- _soundChannel.soundTransform = soundTransform;
- }
- }
-
- //reset volume to 1.0 if already reached max
- if (_volume >= 1)
- {
- _volume = 1.0;
- }
-
- //Store volume into user settings
- _userSettings.setVolume(_volume);
-
- callEvents(PlayerEvents.VOLUME_UP);
- return _volume;
- }
-
- /**
- * Lower the volume
- * @return volume value after lowering
- */
- public function volumeDown():Float
- {
- var soundTransform:SoundTransform = new SoundTransform();
-
- //lower sound
- if(!_soundMuted)
- {
- if (_streamType == StreamType.YOUTUBE)
- {
- _volume = (Reflect.field(_youtubeLoader.content, "getVolume")() - 10) / 100;
- Reflect.field(_youtubeLoader.content, "setVolume")(_volume * 100);
- }
- else if (_type == InputType.VIDEO || _streamType == StreamType.RTMP)
- {
- _volume = _stream.soundTransform.volume - (10/100);
- soundTransform.volume = _volume;
- _stream.soundTransform = soundTransform;
- }
- else if (_type == InputType.AUDIO)
- {
- _volume = _soundChannel.soundTransform.volume - (10/100);
- soundTransform.volume = _volume;
- _soundChannel.soundTransform = soundTransform;
- }
-
- //if volume reached min is muted
- if (_volume <= 0)
- {
- _soundMuted = true;
- _volume = 0;
- }
- }
-
- //Store volume into user settings
- _userSettings.setVolume(_volume);
-
- callEvents(PlayerEvents.VOLUME_DOWN);
- return _volume;
- }
- //}
-
-
- //{Setters
- /**
- * Set input type
- * @param type Allowable values are audio, video
- */
- public function setType(type:String):Void
- {
- _type = type;
- }
-
- /**
- * Set streaming type
- * @param streamType Allowable values are file, http, rmtp
- */
- public function setStreamType(streamType:String):Void
- {
- _streamType = streamType;
- }
-
- /**
- * Sets the server url for rtmp streams
- * @param server
- */
- public function setServer(server:String):Void
- {
- _server = server;
- }
-
- /**
- * To set the video source in case we dont want to start downloading at first so when use tooglePlay the
- * media is loaded automatically
- * @param source
- */
- public function setSource(source):Void
- {
- _mediaSource = source;
- }
-
- /**
- * Changes the current volume
- * @param volume
- */
- public function setVolume(volume:Float):Void
- {
- var soundTransform:SoundTransform = new SoundTransform();
-
- if (volume > _volume) {
- callEvents(PlayerEvents.VOLUME_UP);
- }
-
- if (volume < _volume) {
- callEvents(PlayerEvents.VOLUME_DOWN);
- }
-
- if (volume > 0)
- {
- _soundMuted = false;
- _volume = volume;
- }
- else
- {
- _soundMuted = true;
- _volume = 1.0;
- }
-
- soundTransform.volume = volume;
-
- if (!_firstLoad) //To prevent errors if objects aren't initialized
- {
- if (_streamType == StreamType.YOUTUBE)
- {
- Reflect.field(_youtubeLoader.content, "setVolume")(soundTransform.volume * 100);
- }
- else if (_type == InputType.VIDEO || _streamType == StreamType.RTMP)
- {
- _stream.soundTransform = soundTransform;
- }
- else if (_type == InputType.AUDIO)
- {
- _soundChannel.soundTransform = soundTransform;
- }
- }
-
- //Store volume into user settings
- _userSettings.setVolume(_volume);
-
- callEvents(PlayerEvents.VOLUME_CHANGE);
- }
-
- /**
- * Changes the buffer time for local and pseudo streaming
- * @param time in seconds
- */
- public function setBufferTime(time:Float):Void
- {
- if (time > 0)
- {
- _bufferTime = time;
- }
- }
-
- /**
- * Changes the aspec ratio of current playing media and resizes video player
- * @param aspectRatio new aspect ratio value
- */
- public function setAspectRatio(aspectRatio:Float):Void
- {
- _aspectRatio = aspectRatio;
-
- switch(_aspectRatio)
- {
- case 0.0:
- _currentAspectRatio = "original";
-
- case AspectRatio._1_1:
- _currentAspectRatio = "1:1";
-
- case AspectRatio._3_2:
- _currentAspectRatio = "3:2";
-
- case AspectRatio._4_3:
- _currentAspectRatio = "4:3";
-
- case AspectRatio._5_4:
- _currentAspectRatio = "5:4";
-
- case AspectRatio._14_9:
- _currentAspectRatio = "14:9";
-
- case AspectRatio._14_10:
- _currentAspectRatio = "14:10";
-
- case AspectRatio._16_9:
- _currentAspectRatio = "16:9";
-
- case AspectRatio._16_10:
- _currentAspectRatio = "16:10";
- }
-
- resizeAndCenterPlayer();
-
- //Store aspect ratio into user settings
- _userSettings.setAspectRatio(_aspectRatio);
- }
-
- /**
- * Enable or disable hardware scaling
- * @param value true to enable false to disable
- */
- public function setHardwareScaling(value:Bool):Void
- {
- _useHardWareScaling = value;
- }
- //}
-
-
- //{Getters
- /**
- * Gets the volume amount 0.0 to 1.0
- * @return
- */
- public function getVolume():Float
- {
- return _volume;
- }
-
- /**
- * The current aspect ratio of the loaded Player
- * @return
- */
- public function getAspectRatio():Float
- {
- return _aspectRatio;
- }
-
- /**
- * The current aspect ratio of the loaded Player in string format
- * @return
- */
- public function getAspectRatioString():String
- {
- return _currentAspectRatio;
- }
-
- /**
- * Original aspect ratio of the video
- * @return original aspect ratio
- */
- public function getOriginalAspectRatio():Float
- {
- return _originalAspectRatio;
- }
-
- /**
- * Total duration time of the loaded media
- * @return time in seconds
- */
- public function getDuration():Float
- {
- return _mediaDuration;
- }
-
- /**
- * The time in seconds where the player started downloading
- * @return time in seconds
- */
- public function getStartTime():Float
- {
- return _startTime;
- }
-
- /**
- * The stream associated with the player
- * @return netstream object
- */
- public function getNetStream():NetStream
- {
- return _stream;
- }
-
- /**
- * Video object associated to the player
- * @return video object for further manipulation
- */
- public function getVideo():Video
- {
- return _video;
- }
-
- /**
- * Sound object associated to the player
- * @return sound object for further manipulation
- */
- public function getSound():Sound
- {
- return _sound;
- }
-
- /**
- * The id3 info of sound object
- * @return
- */
- public function getId3Info():ID3Info
- {
- return _id3Info;
- }
-
- /**
- * The current sound state
- * @return true if mute otherwise false
- */
- public function getMute():Bool
- {
- return _soundMuted;
- }
-
- /**
- * The amount of total bytes
- * @return amount of bytes
- */
- public function getBytesTotal():Float
- {
- var bytesTotal:Float = 0;
-
- if (_streamType == StreamType.YOUTUBE)
- {
- if(_youtubeLoader != null && _mediaLoaded)
- bytesTotal = Reflect.field(_youtubeLoader.content, "getVideoBytesTotal")();
- }
- else if (_type == InputType.VIDEO || _streamType == StreamType.RTMP)
- {
- bytesTotal = _stream.bytesTotal;
- }
- else if (_type == InputType.AUDIO)
- {
- bytesTotal = _sound.bytesTotal;
- }
-
- return bytesTotal;
- }
-
- /**
- * The amount of bytes loaded
- * @return amount of bytes
- */
- public function getBytesLoaded():Float
- {
- var bytesLoaded:Float = 0;
-
- if (_streamType == StreamType.YOUTUBE)
- {
- if(_youtubeLoader != null && _mediaLoaded)
- bytesLoaded = Reflect.field(_youtubeLoader.content, "getVideoBytesLoaded")();
- }
- else if (_type == InputType.VIDEO || _streamType == StreamType.RTMP)
- {
- bytesLoaded = _stream.bytesLoaded;
- }
- else if (_type == InputType.AUDIO)
- {
- bytesLoaded = _sound.bytesLoaded;
- }
-
- return bytesLoaded;
- }
-
- /**
- * Current playing file type
- * @return audio or video
- */
- public function getType():String
- {
- return _type;
- }
-
- /**
- * The stream method for the current playing media
- * @return
- */
- public function getStreamType():String
- {
- return _streamType;
- }
-
- /**
- * The server url for current rtmp stream
- * @return
- */
- public function getServer():String
- {
- return _server;
- }
-
- /**
- * To check current quality mode
- * @return true if high quality false if low
- */
- public function getQuality():Bool
- {
- return _videoQualityHigh;
- }
-
- /**
- * The current playing time
- * @return current playing time in seconds
- */
- public function getCurrentTime():Float
- {
- var time:Float = 0;
- if (_streamType == StreamType.YOUTUBE)
- {
- if(_youtubeLoader != null)
- {
- time = Reflect.field(_youtubeLoader.content, "getCurrentTime")();
- }
- else
- {
- time = 0;
- }
- }
- else if (_streamType == StreamType.PSEUDOSTREAM)
- {
- time = getStartTime() + _stream.time;
- }
- else if (_type == InputType.VIDEO || _streamType == StreamType.RTMP)
- {
- time = _stream.time;
- }
- else if (_type == InputType.AUDIO)
- {
- if(_soundChannel != null)
- {
- time = _soundChannel.position / 1000;
- }
- else
- {
- time = 0;
- }
- }
-
- return time;
- }
- //}
+ //}
+
+ //{Initialize video and connection objects
+ _connection = new NetConnection();
+ _connection.client = this;
+ _connection.connect(null);
+ _stream = new NetStream(_connection);
+
+ _video = new Video(_stage.stageWidth, _stage.stageHeight);
+
+ _movieClip.addChild(_video);
+ //}
+
+ //Video mask so that custom menu items work
+ _videoMask = new Sprite();
+ _movieClip.addChild(_videoMask);
+
+ //Set initial rendering to high quality
+ toggleQuality();
+
+ //{Initialize system event listeners
+ _movieClip.addEventListener(Event.ENTER_FRAME, onEnterFrame);
+ _stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);
+ _stage.addEventListener(MouseEvent.MOUSE_MOVE, onMouseMove);
+ _stage.addEventListener(FullScreenEvent.FULL_SCREEN, onFullScreen);
+ _stage.addEventListener(Event.RESIZE, onResize);
+ _hideMouseTimer.addEventListener(TimerEvent.TIMER, hideMouseTimer);
+ _checkAudioTimer.addEventListener(TimerEvent.TIMER, checkAudioTimer);
+ _connection.addEventListener(NetStatusEvent.NET_STATUS, onNetStatus);
+ _connection.addEventListener(AsyncErrorEvent.ASYNC_ERROR, onAsyncError);
+ //}
+ }
+ //}
+
+
+ //{Timers
+ /**
+ * Timer that hides the mouse pointer when it is idle and dispatch the PlayerEvents.MOUSE_HIDE
+ * @param event
+ */
+ private function hideMouseTimer(event:TimerEvent):Void
+ {
+ if (_fullscreen)
+ {
+ if (_mouseVisible)
+ {
+ _mouseVisible = false;
+ }
+ else
+ {
+ Mouse.hide();
+ callEvents(PlayerEvents.MOUSE_HIDE);
+ _hideMouseTimer.stop();
+ }
+ }
+ }
+
+ /**
+ * To check if the sound finished playing
+ * @param event
+ */
+ private function checkAudioTimer(event:TimerEvent):Void
+ {
+ if (_soundChannel.position + 100 >= _sound.length)
+ {
+ _isPlaying = false;
+ _mediaEndReached = true;
+ callEvents(PlayerEvents.PLAYBACK_FINISHED);
+
+ _checkAudioTimer.stop();
+ }
+ }
+ //}
+
+
+ //{Events
+ /**
+ * Callback after bandwidth calculation for rtmp streams
+ */
+ private function onBWDone():Void
+ {
+ //Need to study this more
+ }
+
+ /**
+ * Triggers error event on rtmp connections
+ * @param event
+ */
+ private function onAsyncError(event:AsyncErrorEvent):Void
+ {
+ //TODO: Should trigger event for controls to display error message
+ //trace(event.error);
+ }
+
+ /**
+ * Checks if connection failed or succeed
+ * @param event
+ */
+ private function onNetStatus(event:NetStatusEvent):Void
+ {
+ switch (event.info.code)
+ {
+ case "NetConnection.Connect.Success":
+ if (_streamType == StreamType.RTMP)
+ {
+ _stream = new NetStream(_connection);
+ _stream.addEventListener(NetStatusEvent.NET_STATUS, onNetStatus);
+ _stream.bufferTime = 10;
+ //_stream.play(Utils.rtmpSourceParser(_mediaSource), true);
+ _stream.play(_mediaSource);
+ _stream.client = this;
+ if(_type == InputType.VIDEO) {_video.attachNetStream(_stream); }
+ }
+ callEvents(PlayerEvents.CONNECTION_SUCCESS);
+
+ case "NetStream.Play.StreamNotFound":
+ trace("Stream not found: " + _mediaSource); //Replace with a dispatch for error event
+ callEvents(PlayerEvents.CONNECTION_FAILED);
+
+ case "NetStream.Play.Stop":
+ if (_streamType != StreamType.RTMP)
+ {
+ if (_isPlaying) { _stream.togglePause(); }
+ _isPlaying = false;
+ _mediaEndReached = true;
+ callEvents(PlayerEvents.PLAYBACK_FINISHED);
+ }
+
+ case "NetStream.Play.Start":
+ _isPlaying = true;
+ _mediaEndReached = false;
+ if (_stream.bytesLoaded != _stream.bytesTotal || _streamType == StreamType.RTMP)
+ {
+ callEvents(PlayerEvents.BUFFERING);
+ }
+
+ case "NetStream.Seek.Notify":
+ _mediaEndReached = false;
+ if (_streamType == StreamType.RTMP)
+ {
+ _isPlaying = true;
+ callEvents(PlayerEvents.PLAY_PAUSE);
+ callEvents(PlayerEvents.BUFFERING);
+ }
+
+ case "NetStream.Buffer.Empty":
+ if (_stream.bytesLoaded != _stream.bytesTotal)
+ {
+ callEvents(PlayerEvents.BUFFERING);
+ }
+
+ case "NetStream.Buffer.Full":
+ callEvents(PlayerEvents.NOT_BUFFERING);
+
+ case "NetStream.Buffer.Flush":
+ if (_stream.bytesLoaded == _stream.bytesTotal)
+ {
+ _downloadCompleted = true;
+ }
+ }
+ }
+
+ /**
+ * Proccess keyboard shortcuts
+ * @param event
+ */
+ private function onKeyDown(event:KeyboardEvent):Void
+ {
+ var F_KEY:UInt = 70;
+ var M_KEY:UInt = 77;
+ var X_KEY:UInt = 88;
+
+ if(event.keyCode == Keyboard.TAB)
+ {
+ toggleAspectRatio();
+ }
+ else if(event.keyCode == F_KEY)
+ {
+ toggleFullscreen();
+ }
+ else if(event.keyCode == M_KEY)
+ {
+ toggleMute();
+ }
+ else if(event.keyCode == Keyboard.UP)
+ {
+ volumeUp();
+ }
+ else if(event.keyCode == Keyboard.DOWN)
+ {
+ volumeDown();
+ }
+ else if(event.keyCode == Keyboard.RIGHT)
+ {
+ forward();
+ }
+ else if(event.keyCode == Keyboard.LEFT)
+ {
+ rewind();
+ }
+ else if(event.keyCode == Keyboard.SPACE)
+ {
+ togglePlay();
+ }
+ else if(event.keyCode == X_KEY)
+ {
+ stopAndClose();
+ }
+ }
+
+ /**
+ * IF player is full screen shows the mouse when gets hide
+ * @param event
+ */
+ private function onMouseMove(event:MouseEvent):Void
+ {
+ if (_fullscreen && !_mouseVisible)
+ {
+ if (!_hideMouseTimer.running)
+ {
+ _hideMouseTimer.start();
+ }
+
+ _mouseVisible = true;
+ Mouse.show();
+
+ callEvents(PlayerEvents.MOUSE_SHOW);
+ }
+ }
+
+ /**
+ * Resize video player
+ * @param event
+ */
+ private function onResize(event:Event):Void
+ {
+ resizeAndCenterPlayer();
+ }
+
+ /**
+ * Dispath a full screen event to listeners as redraw player an takes care of some other aspects
+ * @param event
+ */
+ private function onFullScreen(event:FullScreenEvent):Void
+ {
+ _fullscreen = event.fullScreen;
+
+ if (!event.fullScreen)
+ {
+ Mouse.show();
+ callEvents(PlayerEvents.MOUSE_SHOW);
+ _mouseVisible = true;
+ }
+ else
+ {
+ _mouseVisible = true;
+ _hideMouseTimer.start();
+ }
+
+ resizeAndCenterPlayer();
+
+ callEvents(PlayerEvents.FULLSCREEN);
+ }
+
+ /**
+ * Sits for any cue points available
+ * @param data
+ * @note Planned future implementation
+ */
+ private function onCuePoint(data:Dynamic):Void
+ {
+
+ }
+
+ /**
+ * After a video is loaded this callback gets the video information at start and stores it on variables
+ * @param data
+ */
+ private function onMetaData(data:Dynamic):Void
+ {
+ if (_firstLoad)
+ {
+ _isPlaying = true;
+
+ _firstLoad = false;
+ if (data.width)
+ {
+ _videoWidth = data.width;
+ _videoHeight = data.height;
+ }
+ else
+ {
+ _videoWidth = _video.width;
+ _videoHeight = _video.height;
+ }
+
+ //Store seekpoints times
+ if (data.hasOwnProperty("seekpoints")) //MP4
+ {
+ for (position in Reflect.fields(data.seekpoints))
+ {
+ _seekPoints.push(Reflect.field(data.seekpoints, position).time);
+ }
+ }
+ else if (data.hasOwnProperty("keyframes")) //FLV
+ {
+ for (position in Reflect.fields(data.keyframes.times))
+ {
+ _seekPoints.push(Reflect.field(data.keyframes.times, position));
+ }
+ }
+
+ _mediaLoaded = true;
+ _mediaDuration = data.duration;
+ _originalAspectRatio = AspectRatio.getAspectRatio(_videoWidth, _videoHeight);
+
+ if (_aspectRatio <= 0)
+ {
+ _aspectRatio = _originalAspectRatio;
+ }
+
+ callEvents(PlayerEvents.MEDIA_INITIALIZED);
+
+ resizeAndCenterPlayer();
+
+ //Retrieve the volume that user selected last time
+ setVolume(_userSettings.getVolume());
+ }
+ }
+
+ /**
+ * Dummy function invoked for pseudostream servers
+ * @param data
+ */
+ private function onLastSecond(data:Dynamic):Void
+ {
+ trace("last second pseudostream");
+ }
+
+ /**
+ * Broadcast Timeupdate and Duration
+ */
+ private function onEnterFrame(event:Event):Void
+ {
+ if (getDuration() > 0 && _lastTime != getCurrentTime())
+ {
+ _lastTime = getCurrentTime();
+ callEvents(PlayerEvents.TIME);
+ }
+
+ if (getBytesLoaded() > 0 && _lastProgress < getBytesLoaded())
+ {
+ _lastProgress = getBytesLoaded();
+ callEvents(PlayerEvents.PROGRESS);
+ }
+
+ }
+
+
+ /**
+ * Triggers when playbacks end on rtmp streaming server
+ */
+ private function onPlayStatus(info:Dynamic):Void
+ {
+ _isPlaying = false;
+ _mediaEndReached = true;
+ callEvents(PlayerEvents.PLAYBACK_FINISHED);
+ }
+
+ /**
+ * When sound finished downloading
+ * @param event
+ */
+ private function onSoundComplete(event:Event)
+ {
+ _mediaDuration = _sound.length / 1000;
+ _downloadCompleted = true;
+
+ callEvents(PlayerEvents.MEDIA_INITIALIZED);
+ }
+
+ /**
+ * Mimic stream onMetaData
+ * @param event
+ */
+ private function onSoundID3(event:Event)
+ {
+ if (_firstLoad)
+ {
+ _soundChannel = _sound.play();
+ _checkAudioTimer.start();
+
+ _isPlaying = true;
+
+ _firstLoad = false;
+
+ _mediaLoaded = true;
+ _mediaDuration = ((_sound.bytesTotal / _sound.bytesLoaded) * _sound.length) / 1000;
+ _aspectRatio = AspectRatio.getAspectRatio(_videoWidth, _videoHeight);
+ _originalAspectRatio = _aspectRatio;
+ _id3Info = _sound.id3;
+
+ callEvents(PlayerEvents.CONNECTION_SUCCESS);
+ callEvents(PlayerEvents.MEDIA_INITIALIZED);
+
+ resizeAndCenterPlayer();
+
+ //Retrieve the volume that user selected last time
+ setVolume(_userSettings.getVolume());
+ }
+ }
+
+ /**
+ * Dispatch connection failed event on error
+ * @param event
+ */
+ private function onSoundIOError(event:IOErrorEvent)
+ {
+ callEvents(PlayerEvents.CONNECTION_FAILED);
+ }
+
+ /**
+ * Monitor sound download progress
+ * @param event
+ */
+ private function onSoundProgress(event:ProgressEvent)
+ {
+ if (_sound.isBuffering)
+ {
+ callEvents(PlayerEvents.BUFFERING);
+ }
+ else
+ {
+ callEvents(PlayerEvents.NOT_BUFFERING);
+ }
+
+ _mediaDuration = ((_sound.bytesTotal / _sound.bytesLoaded) * _sound.length) / 1000;
+ callEvents(PlayerEvents.MEDIA_INITIALIZED);
+ }
+
+ /**
+ * Initializes the youtube loader object
+ * @param event
+ */
+ private function onYouTubeLoaderInit(event:Event):Void
+ {
+ _youtubeLoader.content.addEventListener("onReady", onYoutubeReady);
+ _youtubeLoader.content.addEventListener("onError", onYoutubeError);
+ _youtubeLoader.content.addEventListener("onStateChange", onYoutubeStateChange);
+ _youtubeLoader.content.addEventListener("onPlaybackQualityChange", onYoutubePlaybackQualityChange);
+
+ }
+
+ /**
+ * This event is fired when the player is loaded and initialized, meaning it is ready to receive API calls.
+ */
+ private function onYoutubeReady(event:Event):Void
+ {
+ _movieClip.addChild(_youtubeLoader.content);
+ _movieClip.setChildIndex(_youtubeLoader.content, 0);
+ Reflect.field(_youtubeLoader.content, "setSize")(_stage.stageWidth, _stage.stageHeight);
+ Reflect.field(_youtubeLoader.content, "loadVideoByUrl")(Utils.youtubeSourceParse(_mediaSource));
+ callEvents(PlayerEvents.BUFFERING);
+ }
+
+ /**
+ * This event is fired whenever the player's state changes. Possible values are unstarted (-1), ended (0),
+ * playing (1), paused (2), buffering (3), video cued (5). When the SWF is first loaded it will broadcast
+ * an unstarted (-1) event. When the video is cued and ready to play it will broadcast a video cued event (5).
+ * @param event
+ */
+ private function onYoutubeStateChange(event:Event):Void
+ {
+ var status:UInt = Std.parseInt(Reflect.field(event, "data"));
+
+ switch(status)
+ {
+ case -1:
+ callEvents(PlayerEvents.BUFFERING);
+
+ case 0:
+ _isPlaying = false;
+ _mediaEndReached = true;
+ callEvents(PlayerEvents.PLAYBACK_FINISHED);
+
+ case 1:
+ if (_firstLoad)
+ {
+ _isPlaying = true;
+
+ _videoWidth = _stage.stageWidth;
+ _videoHeight = _stage.stageHeight;
+
+ _firstLoad = false;
+
+ _mediaLoaded = true;
+ _mediaDuration = Reflect.field(_youtubeLoader.content, "getDuration")();
+ _aspectRatio = AspectRatio.getAspectRatio(_videoWidth, _videoHeight);
+ _originalAspectRatio = _aspectRatio;
+
+ callEvents(PlayerEvents.CONNECTION_SUCCESS);
+ callEvents(PlayerEvents.MEDIA_INITIALIZED);
+
+ resizeAndCenterPlayer();
+
+ //Retrieve the volume that user selected last time
+ setVolume(_userSettings.getVolume());
+ }
+ callEvents(PlayerEvents.NOT_BUFFERING);
+
+ case 2:
+ callEvents(PlayerEvents.NOT_BUFFERING);
+
+ case 3:
+ callEvents(PlayerEvents.BUFFERING);
+
+ case 5:
+ callEvents(PlayerEvents.NOT_BUFFERING);
+ }
+ }
+
+ /**
+ * This event is fired whenever the video playback quality changes. For example, if you call the
+ * setPlaybackQuality(suggestedQuality) function, this event will fire if the playback quality actually
+ * changes. Your code should respond to the event and should not assume that the quality will automatically
+ * change when the setPlaybackQuality(suggestedQuality) function is called. Similarly, your code should not
+ * assume that playback quality will only change as a result of an explicit call to setPlaybackQuality or any
+ * other function that allows you to set a suggested playback quality.
+ *
+ * The value that the event broadcasts is the new playback quality. Possible values are "small", "medium",
+ * "large" and "hd720".
+ * @param event
+ */
+ private function onYoutubePlaybackQualityChange(event:Event):Void
+ {
+ //trace(Reflect.field(event, "data"));
+ }
+
+ /**
+ * This event is fired when an error in the player occurs. The possible error codes are 100, 101,
+ * and 150. The 100 error code is broadcast when the video requested is not found. This occurs when
+ * a video has been removed (for any reason), or it has been marked as private. The 101 error code is
+ * broadcast when the video requested does not allow playback in the embedded players. The error code
+ * 150 is the same as 101, it's just 101 in disguise!
+ * @param event
+ */
+ private function onYoutubeError(event:Event):Void
+ {
+ trace(Reflect.field(event, "data"));
+ }
+ //}
+
+
+ //{Private Methods
+ /**
+ * Function used each time is needed to dispatch an event
+ * @param type
+ */
+ private function callEvents(type:String):Void
+ {
+ var playerEvent:PlayerEvents = new PlayerEvents(type, true);
+
+ playerEvent.aspectRatio = getAspectRatio();
+ playerEvent.duration = getDuration();
+ playerEvent.fullscreen = isFullscreen();
+ playerEvent.mute = getMute();
+ playerEvent.volume = getVolume();
+ playerEvent.width = _video.width;
+ playerEvent.height = _video.height;
+ playerEvent.stream = getNetStream();
+ playerEvent.sound = getSound();
+ playerEvent.time = getCurrentTime();
+ playerEvent.id3Info = getId3Info();
+
+ dispatchEvent(playerEvent);
+ }
+
+ /**
+ * Reposition and resizes the video player to fit on screen
+ */
+ private function resizeAndCenterPlayer():Void
+ {
+ if (_streamType != StreamType.YOUTUBE)
+ {
+ _video.height = _stage.stageHeight;
+ _video.width = _video.height * _aspectRatio;
+
+ _video.x = (_stage.stageWidth / 2) - (_video.width / 2);
+ _video.y = 0;
+
+ if (_video.width > _stage.stageWidth && _aspectRatio == _originalAspectRatio)
+ {
+ var aspectRatio:Float = _videoHeight / _videoWidth;
+ _video.width = _stage.stageWidth;
+ _video.height = aspectRatio * _video.width;
+ _video.x = 0;
+ _video.y = (_stage.stageHeight / 2) - (_video.height / 2);
+ }
+
+ _videoMask.graphics.clear();
+ _videoMask.graphics.lineStyle();
+ _videoMask.graphics.beginFill(0x000000, 0);
+ _videoMask.graphics.drawRect(_video.x, _video.y, _video.width, _video.height);
+ _videoMask.graphics.endFill();
+ }
+ else
+ {
+ Reflect.field(_youtubeLoader.content, "setSize")(_stage.stageWidth, _stage.stageHeight);
+
+ _videoMask.graphics.clear();
+ _videoMask.graphics.lineStyle();
+ _videoMask.graphics.beginFill(0x000000, 0);
+ _videoMask.graphics.drawRect(0, 0, _stage.stageWidth, _stage.stageHeight);
+ _videoMask.graphics.endFill();
+ }
+
+ callEvents(PlayerEvents.RESIZE);
+ }
+
+ /**
+ * Check the best seek point available if the seekpoints array is available
+ * @param time time in seconds
+ * @return best seek point in seconds or given one if no seekpoints array is available
+ */
+ private function getBestSeekPoint(time:Float):Float
+ {
+ if (_seekPoints.length > 0)
+ {
+ var timeOne:String="0";
+ var timeTwo:String="0";
+
+ for(prop in Reflect.fields(_seekPoints))
+ {
+ if(Reflect.field(_seekPoints,prop) < time)
+ {
+ timeOne = prop;
+ }
+ else
+ {
+ timeTwo = prop;
+ break;
+ }
+ }
+
+ if(time - _seekPoints[Std.parseInt(timeOne)] < _seekPoints[Std.parseInt(timeTwo)] - time)
+ {
+ return _seekPoints[Std.parseInt(timeOne)];
+ }
+ else
+ {
+ return _seekPoints[Std.parseInt(timeTwo)];
+ }
+ }
+
+ return time;
+ }
+
+ /**
+ * Checks if the given seek time is already buffered
+ * @param time time in seconds
+ * @return true if can seek false if not in buffer
+ */
+ private function canSeek(time:Float):Bool
+ {
+ if (_type == InputType.VIDEO)
+ {
+ time = getBestSeekPoint(time);
+ }
+
+ var cacheTotal = Math.floor((getDuration() - _startTime) * (getBytesLoaded() / getBytesTotal())) - 1;
+
+ if(time >= _startTime && time < _startTime + cacheTotal)
+ {
+ return true;
+ }
+
+ return false;
+ }
+ //}
+
+
+ //{Public methods
+ /**
+ * Loads a video and starts playing it
+ * @param video video url to load
+ */
+ public function load(source:String, type:String="video", streamType:String="file", server:String=""):Void
+ {
+ stopAndClose();
+
+ _type = type;
+ _streamType = streamType;
+ _mediaSource = source;
+ _stopped = false;
+ _mediaLoaded = false;
+ _firstLoad = true;
+ _startTime = 0;
+ _downloadCompleted = false;
+ _seekPoints = new Array();
+ _server = server;
+
+ callEvents(PlayerEvents.BUFFERING);
+
+ if (_streamType == StreamType.YOUTUBE)
+ {
+ Security.allowDomain("*");
+ Security.allowDomain("www.youtube.com");
+ Security.allowDomain("youtube.com");
+ Security.allowDomain("s.ytimg.com");
+ Security.allowDomain("i.ytimg.com");
+
+ _youtubeLoader = new Loader();
+ _youtubeLoader.contentLoaderInfo.addEventListener(Event.INIT, onYouTubeLoaderInit);
+ _youtubeLoader.load(new URLRequest("http://www.youtube.com/apiplayer?version=3"));
+ }
+ else if (_type == InputType.VIDEO && (_streamType == StreamType.FILE || _streamType == StreamType.PSEUDOSTREAM))
+ {
+ _connection.connect(null);
+ _stream = new NetStream(_connection);
+ _stream.addEventListener(NetStatusEvent.NET_STATUS, onNetStatus);
+ _stream.addEventListener(AsyncErrorEvent.ASYNC_ERROR, doAsyncError);
+ _stream.bufferTime = _bufferTime;
+ _stream.play(source);
+ _stream.client = this;
+ _video.attachNetStream(_stream);
+ }
+ else if (_type == InputType.VIDEO && _streamType == StreamType.RTMP)
+ {
+ _connection.connect(_server);
+ }
+ else if (_type == InputType.AUDIO && _streamType == StreamType.RTMP)
+ {
+ _connection.connect(_server);
+ }
+ else if(_type == InputType.AUDIO && _streamType == StreamType.FILE)
+ {
+ _sound.load(new URLRequest(source));
+ }
+ }
+
+ private function doAsyncError(e:AsyncErrorEvent) : Void
+ {
+ // Do nothing, to block the exception.
+ }
+
+ /**
+ * Closes the connection and makes player available for another video
+ */
+ public function stopAndClose():Void
+ {
+ if (_mediaLoaded)
+ {
+ _mediaLoaded = false;
+ _isPlaying = false;
+ _stopped = true;
+ _startTime = 0;
+
+ if (_streamType == StreamType.YOUTUBE)
+ {
+ Reflect.field(_youtubeLoader.content, "destroy")();
+ }
+ else if (_type == InputType.VIDEO)
+ {
+ _stream.close();
+ }
+ else
+ {
+ _soundChannel.stop();
+ _sound.close();
+ }
+ }
+
+ callEvents(PlayerEvents.STOP_CLOSE);
+ }
+
+ /**
+ * Seeks 8 seconds forward from the current position.
+ * @return current play time after forward
+ */
+ public function forward():Float
+ {
+ var seekTime = (getCurrentTime() + 8) + _startTime;
+
+ if (getDuration() > seekTime)
+ {
+ seekTime = seek(seekTime);
+ }
+
+ return seekTime;
+ }
+
+ /**
+ * Seeks 8 seconds back from the current position.
+ * @return current play time after rewind
+ */
+ public function rewind():Float
+ {
+ var seekTime = (getCurrentTime() - 8) + _startTime;
+
+ if (seekTime >= _startTime)
+ {
+ seekTime = seek(seekTime);
+ }
+
+ return seekTime;
+ }
+
+ /**
+ * Seeks video player to a given time in seconds
+ * @param seekTime time in seconds to seek
+ * @return current play time after seeking
+ */
+ public function seek(seekTime:Float):Float
+ {
+ if (_startTime <= 1 && _downloadCompleted)
+ {
+ if (_type == InputType.VIDEO || _streamType == StreamType.RTMP)
+ {
+ _stream.seek(seekTime);
+ }
+ else if (_type == InputType.AUDIO)
+ {
+ _soundChannel.stop();
+ _soundChannel = _sound.play(seekTime * 1000);
+ if (!_isPlaying)
+ {
+ _soundChannel.stop();
+ }
+
+ setVolume(_userSettings.getVolume());
+ }
+ }
+ else if(_seekPoints.length > 0 && _streamType == StreamType.PSEUDOSTREAM)
+ {
+ seekTime = getBestSeekPoint(seekTime);
+
+ if (canSeek(seekTime))
+ {
+ _stream.seek(seekTime - _startTime);
+ }
+ else if(seekTime != _startTime)
+ {
+ _startTime = seekTime;
+
+ var url:String;
+ if (_mediaSource.indexOf("?") != -1)
+ {
+ url = _mediaSource + "&start=" + seekTime;
+ }
+ else
+ {
+ url = _mediaSource + "?start=" + seekTime;
+ }
+ _stream.play(url);
+ }
+ }
+ else if (_streamType == StreamType.YOUTUBE)
+ {
+ if (!canSeek(seekTime))
+ {
+ _startTime = seekTime;
+ Reflect.field(_youtubeLoader.content, "seekTo")(seekTime);
+ }
+ else
+ {
+ Reflect.field(_youtubeLoader.content, "seekTo")(seekTime);
+ }
+
+ }
+ else if (_streamType == StreamType.RTMP)
+ {
+ // seekTime = getBestSeekPoint(seekTime); //Not Needed?
+ _stream.seek(seekTime);
+ }
+ else if(canSeek(seekTime))
+ {
+ if (_type == InputType.VIDEO || _streamType == StreamType.RTMP)
+ {
+ _stream.seek(seekTime);
+ }
+ else if (_type == InputType.AUDIO)
+ {
+ _soundChannel.stop();
+ _soundChannel = _sound.play(seekTime * 1000);
+ if (!_isPlaying)
+ {
+ _soundChannel.stop();
+ }
+
+ setVolume(_userSettings.getVolume());
+ }
+ }
+ callEvents(PlayerEvents.SEEK);
+ return seekTime;
+ }
+
+ /**
+ * To check wheter the media is playing
+ * @return true if is playing false otherwise
+ */
+ public function isPlaying():Bool
+ {
+ return _isPlaying;
+ }
+
+ /**
+ * Cycle betewen aspect ratios
+ * @return new aspect ratio in use
+ */
+ public function toggleAspectRatio():Float
+ {
+ switch(_currentAspectRatio)
+ {
+ case "original":
+ _aspectRatio = AspectRatio._1_1;
+ _currentAspectRatio = "1:1";
+
+ case "1:1":
+ _aspectRatio = AspectRatio._3_2;
+ _currentAspectRatio = "3:2";
+
+ case "3:2":
+ _aspectRatio = AspectRatio._4_3;
+ _currentAspectRatio = "4:3";
+
+ case "4:3":
+ _aspectRatio = AspectRatio._5_4;
+ _currentAspectRatio = "5:4";
+
+ case "5:4":
+ _aspectRatio = AspectRatio._14_9;
+ _currentAspectRatio = "14:9";
+
+ case "14:9":
+ _aspectRatio = AspectRatio._14_10;
+ _currentAspectRatio = "14:10";
+
+ case "14:10":
+ _aspectRatio = AspectRatio._16_9;
+ _currentAspectRatio = "16:9";
+
+ case "16:9":
+ _aspectRatio = AspectRatio._16_10;
+ _currentAspectRatio = "16:10";
+
+ case "16:10":
+ _aspectRatio = _originalAspectRatio;
+ _currentAspectRatio = "original";
+
+ default:
+ _aspectRatio = _originalAspectRatio;
+ _currentAspectRatio = "original";
+ }
+
+ resizeAndCenterPlayer();
+
+ callEvents(PlayerEvents.ASPECT_RATIO);
+
+ //Store aspect ratio into user settings
+ if (_aspectRatio == _originalAspectRatio)
+ {
+ _userSettings.setAspectRatio(0.0);
+ }
+ else
+ {
+ _userSettings.setAspectRatio(_aspectRatio);
+ }
+
+ return _aspectRatio;
+ }
+
+ /**
+ * Swithces between play and pause
+ */
+ public function togglePlay():Bool
+ {
+ if (_mediaLoaded)
+ {
+ if (_mediaEndReached)
+ {
+ _mediaEndReached = false;
+
+ if (_streamType == StreamType.YOUTUBE)
+ {
+ Reflect.field(_youtubeLoader.content, "seekTo")(0);
+ Reflect.field(_youtubeLoader.content, "playVideo")();
+ }
+ else if (_type == InputType.VIDEO || _streamType == StreamType.RTMP)
+ {
+ _stream.seek(0);
+ _stream.togglePause();
+ }
+ else if (_type == InputType.AUDIO)
+ {
+ _checkAudioTimer.start();
+ _soundChannel = _sound.play();
+ setVolume(_userSettings.getVolume());
+ }
+ }
+ else if (_mediaLoaded)
+ {
+ if (_streamType == StreamType.YOUTUBE)
+ {
+ if (_isPlaying)
+ {
+ Reflect.field(_youtubeLoader.content, "pauseVideo")();
+ }
+ else
+ {
+ Reflect.field(_youtubeLoader.content, "playVideo")();
+ }
+ }
+ else if (_type == InputType.VIDEO || _streamType == StreamType.RTMP)
+ {
+ _stream.togglePause();
+ }
+ else if (_type == InputType.AUDIO)
+ {
+ if (_isPlaying)
+ {
+ _soundChannel.stop();
+ }
+ else
+ {
+ //If end of audio reached start from beggining
+ if (_soundChannel.position + 100 >= _sound.length)
+ {
+ _soundChannel = _sound.play();
+ }
+ else
+ {
+ _soundChannel = _sound.play(_soundChannel.position);
+ }
+
+ setVolume(_userSettings.getVolume());
+ }
+ }
+ }
+ else if (_stopped)
+ {
+ load(_mediaSource, _type, _streamType, _server);
+ }
+
+ _isPlaying = !_isPlaying;
+ callEvents(PlayerEvents.PLAY_PAUSE);
+ return _isPlaying;
+ }
+ else if(_mediaSource != "")
+ {
+ load(_mediaSource, _type, _streamType, _server);
+ callEvents(PlayerEvents.BUFFERING);
+ return true;
+ }
+ callEvents(PlayerEvents.PLAY_PAUSE);
+ return false;
+ }
+
+ /**
+ * Switches on or off fullscreen
+ * @return true if fullscreen otherwise false
+ */
+ public function toggleFullscreen():Bool
+ {
+ if (_fullscreen)
+ {
+ _stage.displayState = StageDisplayState.NORMAL;
+ _stage.focus = _stage;
+ return false;
+ }
+ else
+ {
+ if (_useHardWareScaling)
+ {
+ //Match full screen aspec ratio to desktop
+ var aspectRatio = Capabilities.screenResolutionY / Capabilities.screenResolutionX;
+ _stage.fullScreenSourceRect = new Rectangle(0, 0, _videoWidth, _videoWidth * aspectRatio);
+ }
+ else
+ {
+ //Use desktop resolution
+ _stage.fullScreenSourceRect = new Rectangle(0, 0, Capabilities.screenResolutionX ,Capabilities.screenResolutionY);
+ }
+
+ _stage.displayState = StageDisplayState.FULL_SCREEN;
+ _stage.focus = _stage;
+ return true;
+ }
+ }
+
+ /**
+ * Toggles betewen high and low quality image rendering
+ * @return true if quality high false otherwise
+ */
+ public function toggleQuality():Bool
+ {
+ if (_videoQualityHigh)
+ {
+ _video.smoothing = false;
+ _video.deblocking = 1;
+ }
+ else
+ {
+ _video.smoothing = true;
+ _video.deblocking = 5;
+ }
+
+ _videoQualityHigh = _videoQualityHigh?false:true;
+
+ return _videoQualityHigh;
+ }
+
+ /**
+ * Mutes or unmutes the sound
+ * @return true if muted false if unmuted
+ */
+ public function toggleMute():Bool
+ {
+ var soundTransform:SoundTransform = new SoundTransform();
+ var isMute:Bool;
+
+ //unmute sound
+ if (_soundMuted)
+ {
+ _soundMuted = false;
+
+ if (_volume > 0)
+ {
+ soundTransform.volume = _volume;
+ }
+ else
+ {
+ _volume = 1.0;
+ soundTransform.volume = _volume;
+ }
+
+ isMute = false;
+ }
+
+ //mute sound
+ else
+ {
+ _soundMuted = true;
+ _volume = _stream.soundTransform.volume;
+ soundTransform.volume = 0;
+ _stream.soundTransform = soundTransform;
+
+ isMute = true;
+ }
+
+ if (_streamType == StreamType.YOUTUBE)
+ {
+ Reflect.field(_youtubeLoader.content, "setVolume")(soundTransform.volume * 100);
+ }
+ else if (_type == InputType.VIDEO || _streamType == StreamType.RTMP)
+ {
+ _stream.soundTransform = soundTransform;
+ }
+ else if (_type == InputType.AUDIO)
+ {
+ _soundChannel.soundTransform = soundTransform;
+ setVolume(_userSettings.getVolume());
+ }
+
+ callEvents(PlayerEvents.MUTE);
+ return isMute;
+ }
+
+ /**
+ * Check if player is running on fullscreen mode
+ * @return true if fullscreen false if not
+ */
+ public function isFullscreen():Bool
+ {
+ return _stage.displayState == StageDisplayState.FULL_SCREEN;
+ }
+
+ /**
+ * Raises the volume
+ * @return volume value after raising
+ */
+ public function volumeUp():Float
+ {
+ var soundTransform:SoundTransform = new SoundTransform();
+
+ if (_soundMuted)
+ {
+ _soundMuted = false;
+ }
+
+ //raise volume if not already at max
+ if (_volume < 1)
+ {
+ if (_streamType == StreamType.YOUTUBE)
+ {
+ _volume = (Reflect.field(_youtubeLoader.content, "getVolume")() + 10) / 100;
+ Reflect.field(_youtubeLoader.content, "setVolume")(_volume * 100);
+ }
+ else if (_type == InputType.VIDEO || _streamType == StreamType.RTMP)
+ {
+ _volume = _stream.soundTransform.volume + (10/100);
+ soundTransform.volume = _volume;
+ _stream.soundTransform = soundTransform;
+ }
+ else if (_type == InputType.AUDIO)
+ {
+ _volume = _soundChannel.soundTransform.volume + (10/100);
+ soundTransform.volume = _volume;
+ _soundChannel.soundTransform = soundTransform;
+ }
+ }
+
+ //reset volume to 1.0 if already reached max
+ if (_volume >= 1)
+ {
+ _volume = 1.0;
+ }
+
+ //Store volume into user settings
+ _userSettings.setVolume(_volume);
+
+ callEvents(PlayerEvents.VOLUME_UP);
+ return _volume;
+ }
+
+ /**
+ * Lower the volume
+ * @return volume value after lowering
+ */
+ public function volumeDown():Float
+ {
+ var soundTransform:SoundTransform = new SoundTransform();
+
+ //lower sound
+ if(!_soundMuted)
+ {
+ if (_streamType == StreamType.YOUTUBE)
+ {
+ _volume = (Reflect.field(_youtubeLoader.content, "getVolume")() - 10) / 100;
+ Reflect.field(_youtubeLoader.content, "setVolume")(_volume * 100);
+ }
+ else if (_type == InputType.VIDEO || _streamType == StreamType.RTMP)
+ {
+ _volume = _stream.soundTransform.volume - (10/100);
+ soundTransform.volume = _volume;
+ _stream.soundTransform = soundTransform;
+ }
+ else if (_type == InputType.AUDIO)
+ {
+ _volume = _soundChannel.soundTransform.volume - (10/100);
+ soundTransform.volume = _volume;
+ _soundChannel.soundTransform = soundTransform;
+ }
+
+ //if volume reached min is muted
+ if (_volume <= 0)
+ {
+ _soundMuted = true;
+ _volume = 0;
+ }
+ }
+
+ //Store volume into user settings
+ _userSettings.setVolume(_volume);
+
+ callEvents(PlayerEvents.VOLUME_DOWN);
+ return _volume;
+ }
+ //}
+
+
+ //{Setters
+ /**
+ * Set input type
+ * @param type Allowable values are audio, video
+ */
+ public function setType(type:String):Void
+ {
+ _type = type;
+ }
+
+ /**
+ * Set streaming type
+ * @param streamType Allowable values are file, http, rmtp
+ */
+ public function setStreamType(streamType:String):Void
+ {
+ _streamType = streamType;
+ }
+
+ /**
+ * Sets the server url for rtmp streams
+ * @param server
+ */
+ public function setServer(server:String):Void
+ {
+ _server = server;
+ }
+
+ /**
+ * To set the video source in case we dont want to start downloading at first so when use tooglePlay the
+ * media is loaded automatically
+ * @param source
+ */
+ public function setSource(source):Void
+ {
+ _mediaSource = source;
+ }
+
+ /**
+ * Changes the current volume
+ * @param volume
+ */
+ public function setVolume(volume:Float):Void
+ {
+ var soundTransform:SoundTransform = new SoundTransform();
+
+ if (volume > _volume) {
+ callEvents(PlayerEvents.VOLUME_UP);
+ }
+
+ if (volume < _volume) {
+ callEvents(PlayerEvents.VOLUME_DOWN);
+ }
+
+ if (volume > 0)
+ {
+ _soundMuted = false;
+ _volume = volume;
+ }
+ else
+ {
+ _soundMuted = true;
+ _volume = 1.0;
+ }
+
+ soundTransform.volume = volume;
+
+ if (!_firstLoad) //To prevent errors if objects aren't initialized
+ {
+ if (_streamType == StreamType.YOUTUBE)
+ {
+ Reflect.field(_youtubeLoader.content, "setVolume")(soundTransform.volume * 100);
+ }
+ else if (_type == InputType.VIDEO || _streamType == StreamType.RTMP)
+ {
+ _stream.soundTransform = soundTransform;
+ }
+ else if (_type == InputType.AUDIO)
+ {
+ _soundChannel.soundTransform = soundTransform;
+ }
+ }
+
+ //Store volume into user settings
+ _userSettings.setVolume(_volume);
+
+ callEvents(PlayerEvents.VOLUME_CHANGE);
+ }
+
+ /**
+ * Changes the buffer time for local and pseudo streaming
+ * @param time in seconds
+ */
+ public function setBufferTime(time:Float):Void
+ {
+ if (time > 0)
+ {
+ _bufferTime = time;
+ }
+ }
+
+ /**
+ * Changes the aspec ratio of current playing media and resizes video player
+ * @param aspectRatio new aspect ratio value
+ */
+ public function setAspectRatio(aspectRatio:Float):Void
+ {
+ _aspectRatio = aspectRatio;
+
+ switch(_aspectRatio)
+ {
+ case 0.0:
+ _currentAspectRatio = "original";
+
+ case AspectRatio._1_1:
+ _currentAspectRatio = "1:1";
+
+ case AspectRatio._3_2:
+ _currentAspectRatio = "3:2";
+
+ case AspectRatio._4_3:
+ _currentAspectRatio = "4:3";
+
+ case AspectRatio._5_4:
+ _currentAspectRatio = "5:4";
+
+ case AspectRatio._14_9:
+ _currentAspectRatio = "14:9";
+
+ case AspectRatio._14_10:
+ _currentAspectRatio = "14:10";
+
+ case AspectRatio._16_9:
+ _currentAspectRatio = "16:9";
+
+ case AspectRatio._16_10:
+ _currentAspectRatio = "16:10";
+ }
+
+ resizeAndCenterPlayer();
+
+ //Store aspect ratio into user settings
+ _userSettings.setAspectRatio(_aspectRatio);
+ }
+
+ /**
+ * Enable or disable hardware scaling
+ * @param value true to enable false to disable
+ */
+ public function setHardwareScaling(value:Bool):Void
+ {
+ _useHardWareScaling = value;
+ }
+ //}
+
+
+ //{Getters
+ /**
+ * Gets the volume amount 0.0 to 1.0
+ * @return
+ */
+ public function getVolume():Float
+ {
+ return _volume;
+ }
+
+ /**
+ * The current aspect ratio of the loaded Player
+ * @return
+ */
+ public function getAspectRatio():Float
+ {
+ return _aspectRatio;
+ }
+
+ /**
+ * The current aspect ratio of the loaded Player in string format
+ * @return
+ */
+ public function getAspectRatioString():String
+ {
+ return _currentAspectRatio;
+ }
+
+ /**
+ * Original aspect ratio of the video
+ * @return original aspect ratio
+ */
+ public function getOriginalAspectRatio():Float
+ {
+ return _originalAspectRatio;
+ }
+
+ /**
+ * Total duration time of the loaded media
+ * @return time in seconds
+ */
+ public function getDuration():Float
+ {
+ return _mediaDuration;
+ }
+
+ /**
+ * The time in seconds where the player started downloading
+ * @return time in seconds
+ */
+ public function getStartTime():Float
+ {
+ return _startTime;
+ }
+
+ /**
+ * The stream associated with the player
+ * @return netstream object
+ */
+ public function getNetStream():NetStream
+ {
+ return _stream;
+ }
+
+ /**
+ * Video object associated to the player
+ * @return video object for further manipulation
+ */
+ public function getVideo():Video
+ {
+ return _video;
+ }
+
+ /**
+ * Sound object associated to the player
+ * @return sound object for further manipulation
+ */
+ public function getSound():Sound
+ {
+ return _sound;
+ }
+
+ /**
+ * The id3 info of sound object
+ * @return
+ */
+ public function getId3Info():ID3Info
+ {
+ return _id3Info;
+ }
+
+ /**
+ * The current sound state
+ * @return true if mute otherwise false
+ */
+ public function getMute():Bool
+ {
+ return _soundMuted;
+ }
+
+ /**
+ * The amount of total bytes
+ * @return amount of bytes
+ */
+ public function getBytesTotal():Float
+ {
+ var bytesTotal:Float = 0;
+
+ if (_streamType == StreamType.YOUTUBE)
+ {
+ if(_youtubeLoader != null && _mediaLoaded)
+ bytesTotal = Reflect.field(_youtubeLoader.content, "getVideoBytesTotal")();
+ }
+ else if (_type == InputType.VIDEO || _streamType == StreamType.RTMP)
+ {
+ bytesTotal = _stream.bytesTotal;
+ }
+ else if (_type == InputType.AUDIO)
+ {
+ bytesTotal = _sound.bytesTotal;
+ }
+
+ return bytesTotal;
+ }
+
+ /**
+ * The amount of bytes loaded
+ * @return amount of bytes
+ */
+ public function getBytesLoaded():Float
+ {
+ var bytesLoaded:Float = 0;
+
+ if (_streamType == StreamType.YOUTUBE)
+ {
+ if(_youtubeLoader != null && _mediaLoaded)
+ bytesLoaded = Reflect.field(_youtubeLoader.content, "getVideoBytesLoaded")();
+ }
+ else if (_type == InputType.VIDEO || _streamType == StreamType.RTMP)
+ {
+ bytesLoaded = _stream.bytesLoaded;
+ }
+ else if (_type == InputType.AUDIO)
+ {
+ bytesLoaded = _sound.bytesLoaded;
+ }
+
+ return bytesLoaded;
+ }
+
+ /**
+ * Current playing file type
+ * @return audio or video
+ */
+ public function getType():String
+ {
+ return _type;
+ }
+
+ /**
+ * The stream method for the current playing media
+ * @return
+ */
+ public function getStreamType():String
+ {
+ return _streamType;
+ }
+
+ /**
+ * The server url for current rtmp stream
+ * @return
+ */
+ public function getServer():String
+ {
+ return _server;
+ }
+
+ /**
+ * To check current quality mode
+ * @return true if high quality false if low
+ */
+ public function getQuality():Bool
+ {
+ return _videoQualityHigh;
+ }
+
+ /**
+ * The current playing time
+ * @return current playing time in seconds
+ */
+ public function getCurrentTime():Float
+ {
+ var time:Float = 0;
+ if (_streamType == StreamType.YOUTUBE)
+ {
+ if(_youtubeLoader != null)
+ {
+ time = Reflect.field(_youtubeLoader.content, "getCurrentTime")();
+ }
+ else
+ {
+ time = 0;
+ }
+ }
+ else if (_streamType == StreamType.PSEUDOSTREAM)
+ {
+ time = getStartTime() + _stream.time;
+ }
+ else if (_type == InputType.VIDEO || _streamType == StreamType.RTMP)
+ {
+ time = _stream.time;
+ }
+ else if (_type == InputType.AUDIO)
+ {
+ if(_soundChannel != null)
+ {
+ time = _soundChannel.position / 1000;
+ }
+ else
+ {
+ time = 0;
+ }
+ }
+
+ return time;
+ }
+ //}
}
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-javascript/jarisplayer.git
More information about the Pkg-javascript-commits
mailing list