Changeset 806
- Timestamp:
- 01/25/10 21:33:52 (3 years ago)
- Location:
- trunk/fl5
- Files:
-
- 8 edited
-
player.swf (modified) (previous)
-
src/com/longtailvideo/jwplayer/events/MediaEvent.as (modified) (2 diffs)
-
src/com/longtailvideo/jwplayer/media/HTTPMediaProvider.as (modified) (1 diff)
-
src/com/longtailvideo/jwplayer/media/MediaProvider.as (modified) (2 diffs)
-
src/com/longtailvideo/jwplayer/media/RTMPMediaProvider.as (modified) (4 diffs)
-
src/com/longtailvideo/jwplayer/media/VideoMediaProvider.as (modified) (1 diff)
-
src/com/longtailvideo/jwplayer/player/PlayerVersion.as (modified) (1 diff)
-
src/com/longtailvideo/jwplayer/utils/NetClient.as (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
-
trunk/fl5/src/com/longtailvideo/jwplayer/events/MediaEvent.as
r662 r806 187 187 public override function toString():String { 188 188 var retString:String = '[MediaEvent type="' + type + '"'; 189 var defaults:MediaEvent = new MediaEvent(""); 189 190 190 191 if (this.type == MediaEvent.JWPLAYER_MEDIA_META) { … … 193 194 } 194 195 } else { 195 retString += ' bufferPercent="' + bufferPercent + '"';196 retString += ' duration="' + duration + '"';197 retString += ' position="' + position + '"';198 retString += ' offset="' + offset + '"';199 retString += ' volume="' + volume + '"';200 retString += ' mute="' + mute + '"';201 retString += ' message="' + message + '"';196 if (bufferPercent != defaults.bufferPercent) retString += ' bufferPercent="' + bufferPercent + '"'; 197 if (duration != defaults.duration) retString += ' duration="' + duration + '"'; 198 if (position != defaults.position) retString += ' position="' + position + '"'; 199 if (offset != defaults.offset) retString += ' offset="' + offset + '"'; 200 if (volume != defaults.volume) retString += ' volume="' + volume + '"'; 201 if (mute != defaults.mute) retString += ' mute="' + mute + '"'; 202 if (message != defaults.message) retString += ' message="' + message + '"'; 202 203 } 203 204 -
trunk/fl5/src/com/longtailvideo/jwplayer/media/HTTPMediaProvider.as
r776 r806 183 183 184 184 /** Get metadata information from netstream class. **/ 185 public function on Data(dat:Object):void {185 public function onClientData(dat:Object):void { 186 186 if (dat.width) { 187 187 _video.width = dat.width; -
trunk/fl5/src/com/longtailvideo/jwplayer/media/MediaProvider.as
r796 r806 297 297 * **/ 298 298 protected function getConfigProperty(property:String):* { 299 return _config.pluginConfig(provider)[property]; 299 if (item.hasOwnProperty(_provider + "." + property)) { 300 return item[_provider + "." + property]; 301 } else { 302 return _config.pluginConfig(provider)[property]; 303 } 300 304 } 301 305 … … 316 320 if (m) { 317 321 _media = new MovieClip(); 318 _media.visible = false;322 //_media.visible = false; 319 323 _media.addChild(m); 320 324 if (_width * _height > 0) { -
trunk/fl5/src/com/longtailvideo/jwplayer/media/RTMPMediaProvider.as
r796 r806 7 7 **/ 8 8 package com.longtailvideo.jwplayer.media { 9 import com.jeroenwijering.events.*; 10 import com.longtailvideo.jwplayer.events.MediaEvent; 11 import com.longtailvideo.jwplayer.model.PlayerConfig; 12 import com.longtailvideo.jwplayer.model.PlaylistItem; 13 import com.longtailvideo.jwplayer.player.PlayerState; 14 import com.longtailvideo.jwplayer.utils.NetClient; 15 import com.longtailvideo.jwplayer.utils.TEA; 16 17 import flash.events.*; 18 import flash.media.*; 19 import flash.net.*; 20 import flash.utils.*; 21 22 public class RTMPMediaProvider extends MediaProvider { 23 /** Video object to be instantiated. **/ 24 protected var _video:Video; 25 /** NetConnection object for setup of the video stream. **/ 26 protected var _connection:NetConnection; 27 /** Loader instance that loads the XML file. **/ 28 private var _loader:URLLoader; 29 /** NetStream instance that handles the stream IO. **/ 30 protected var _stream:NetStream; 31 /** Sound control object. **/ 32 protected var _transformer:SoundTransform; 33 /** Save the location of the XML redirect. **/ 34 private var _smil:String; 35 /** ID for the position positionInterval. **/ 36 protected var _positionInterval:Number; 37 /** Save that a file is unpublished. **/ 38 protected var _unpublished:Boolean; 39 /** Whether the buffer has filled **/ 40 private var _bufferFull:Boolean; 41 /** Save that the video has been started. **/ 42 protected var _streamStarted:Boolean; 43 /** Whether the stream is active **/ 44 private var _streamActive:Boolean; 45 9 import com.longtailvideo.jwplayer.events.MediaEvent; 10 import com.longtailvideo.jwplayer.events.PlayerEvent; 11 import com.longtailvideo.jwplayer.model.PlayerConfig; 12 import com.longtailvideo.jwplayer.model.PlaylistItem; 13 import com.longtailvideo.jwplayer.model.PlaylistItemLevel; 14 import com.longtailvideo.jwplayer.player.PlayerState; 15 import com.longtailvideo.jwplayer.utils.AssetLoader; 16 import com.longtailvideo.jwplayer.utils.Configger; 17 import com.longtailvideo.jwplayer.utils.Logger; 18 import com.longtailvideo.jwplayer.utils.NetClient; 19 import com.longtailvideo.jwplayer.utils.TEA; 20 21 import flash.events.*; 22 import flash.media.*; 23 import flash.net.*; 24 import flash.utils.*; 25 26 /** 27 * Wrapper for playback of video streamed over RTMP. Can playback MP4, FLV, MP3, AAC and live streams. 28 * Server-specific features are: 29 * - The SecureToken functionality of Wowza (with the 'token' flahvar). 30 * - Load balancing with SMIL files (with the 'rtmp.loadbalance=true' flashvar). 31 **/ 32 public class RTMPMediaProvider extends MediaProvider { 33 /** Save if the bandwidth checkin already occurs. **/ 34 private var _bandwidthChecked:Boolean; 35 /** Interval for bw checking - with dynamic streaming. **/ 36 private var _bandwidthInterval:Number; 37 /** NetConnection object for setup of the video stream. **/ 38 private var _connection:NetConnection; 39 /** Is dynamic streaming possible. **/ 40 private var _dynamic:Boolean; 41 /** The currently playing RTMP stream. **/ 42 private var _currentFile:String; 43 /** The currently active RTMP stream. **/ 44 private var _currentStream:String; 45 /** ID for the position interval. **/ 46 private var _positionInterval:Number; 47 /** Loader instance that loads the XML file. **/ 48 private var _xmlLoader:AssetLoader; 49 /** NetStream instance that handles the stream IO. **/ 50 private var _stream:NetStream; 51 /** Interval ID for subscription pings. **/ 52 private var _subscribeInterval:Number; 53 /** Offset in seconds of the last seek. **/ 54 private var _timeoffset:Number = -1; 55 /** Sound control object. **/ 56 private var _transformer:SoundTransform; 57 /** Save that a stream is streaming. **/ 58 private var _isStreaming:Boolean; 59 /** Level to which we're transitioning. **/ 60 private var _transitionLevel:Number = -1; 61 /** Video object to be instantiated. **/ 62 private var _video:Video; 63 /** Whether or not the buffer is full **/ 64 private var _bufferFull:Boolean = false; 65 46 66 public function RTMPMediaProvider() { 47 67 super('rtmp'); 48 68 } 49 50 69 70 51 71 /** Constructor; sets up the connection and display. **/ 52 72 public override function initializeMediaProvider(cfg:PlayerConfig):void { 53 73 super.initializeMediaProvider(cfg); 54 _connection = new NetConnection(); 55 _connection.addEventListener(NetStatusEvent.NET_STATUS, statusHandler); 56 _connection.addEventListener(SecurityErrorEvent.SECURITY_ERROR, errorHandler); 57 _connection.addEventListener(IOErrorEvent.IO_ERROR, errorHandler); 58 _connection.addEventListener(AsyncErrorEvent.ASYNC_ERROR, errorHandler); 59 _connection.objectEncoding = ObjectEncoding.AMF0; 60 _connection.client = new NetClient(this); 61 _loader = new URLLoader(); 62 _loader.addEventListener(Event.COMPLETE, loaderHandler); 63 _loader.addEventListener(SecurityErrorEvent.SECURITY_ERROR, errorHandler); 64 _loader.addEventListener(IOErrorEvent.IO_ERROR, errorHandler); 65 _video = new Video(320, 240); 66 _video.smoothing = config.smoothing; 67 _transformer = new SoundTransform(); 74 _connection = new NetConnection(); 75 _connection.addEventListener(NetStatusEvent.NET_STATUS, statusHandler); 76 _connection.addEventListener(SecurityErrorEvent.SECURITY_ERROR, errorHandler); 77 _connection.addEventListener(IOErrorEvent.IO_ERROR, errorHandler); 78 _connection.addEventListener(AsyncErrorEvent.ASYNC_ERROR, errorHandler); 79 _connection.objectEncoding = ObjectEncoding.AMF0; 80 _connection.client = new NetClient(this); 81 _xmlLoader = new AssetLoader(); 82 _xmlLoader.addEventListener(Event.COMPLETE, loaderHandler); 83 _xmlLoader.addEventListener(ErrorEvent.ERROR, errorHandler); 84 _transformer = new SoundTransform(); 85 _video = new Video(320, 240); 86 _video.smoothing = config.smoothing; 87 } 88 89 /** Check if the player can use dynamic streaming (server versions and no load balancing). **/ 90 private function checkDynamic(str:String):void { 91 var clt:Number = Number((new PlayerEvent('')).client.split(' ')[1].split(',')[0]); 92 var mjr:Number = Number(str.split(',')[0]); 93 var mnr:Number = Number(str.split(',')[1]); 94 if (!(getConfigProperty('loadbalance') && clt > 9 && (mjr > 3 || (mjr == 3 && mnr > 4)))) { 95 _dynamic = true; 96 } else { 97 _dynamic = false; 98 } 99 } 100 101 /** Try subscribing to livestream **/ 102 private function doSubscribe(id:String):void { 103 _connection.call("FCSubscribe", null, id); 104 } 105 106 /** Catch security errors. **/ 107 private function errorHandler(evt:ErrorEvent):void { 108 stop(); 109 sendMediaEvent(MediaEvent.JWPLAYER_MEDIA_ERROR, {message: evt.text}); 68 110 } 69 111 70 71 /** Catch security errors. **/ 72 protected function errorHandler(evt:ErrorEvent):void { 73 error(evt.text); 74 } 75 76 77 /** Extract the correct rtmp syntax from the file string. **/ 78 protected function getID(url:String):String { 79 var ext:String = url.substr(-4); 80 if (ext == '.mp3') { 81 return 'mp3:' + url.substr(0, url.length - 4); 82 } else if (ext == '.mp4' || ext == '.mov' || ext == '.aac' || ext == '.m4a' || ext == '.f4v' || ext == '.m4v') { 83 return 'mp4:' + url; 84 } else if (ext == '.flv') { 85 return url.substr(0, url.length - 4); 86 } else { 87 return url; 88 } 89 } 90 91 92 /** Load content. **/ 93 override public function load(itm:PlaylistItem):void { 94 _item = itm; 95 _position = 0; 112 /** Bandwidth checking for dynamic streaming. **/ 113 private function getBandwidth():void { 114 try { 115 var bdw:Number = Math.round(_stream.info.maxBytesPerSecond * 8 / 1024); 116 } catch (err:Error) { 117 clearInterval(_bandwidthInterval); 118 return; 119 } 120 if (bdw < 100 || bdw > 99999) { 121 return; 122 } else { 123 bdw = Math.round(config.bandwidth / 2 + bdw / 2); 124 } 125 config.bandwidth = bdw; 126 Configger.saveCookie('bandwidth', bdw); 127 if (item.levels.length > 0 && item.getLevel(config.bandwidth, config.width) != item.currentLevel) { 128 item.setLevel(item.getLevel(config.bandwidth, config.width)); 129 swap(item.currentLevel); 130 } 131 } 132 133 /** Extract the correct rtmp syntax from the file string. **/ 134 private function getID(url:String):String { 135 var ext:String = url.substr(-4); 136 if (url.indexOf(':') > -1) { 137 return url; 138 } else if (ext == '.mp3') { 139 return 'mp3:' + url.substr(0, url.length - 4); 140 } else if (ext == '.mp4' || ext == '.mov' || ext == '.m4v' || ext == '.aac' || ext == '.m4a' || ext == '.f4v') { 141 return 'mp4:' + url; 142 } else if (ext == '.flv') { 143 return url.substr(0, url.length - 4); 144 } else { 145 return url; 146 } 147 } 148 149 /** Load content. **/ 150 override public function load(itm:PlaylistItem):void { 151 _item = itm; 152 _position = 0; 96 153 _bufferFull = false; 97 _streamStarted = false; 98 _streamActive = false; 154 if (item.levels.length > 0) { 155 loadLevelSync(); 156 } 157 _timeoffset = item.start; 158 clearInterval(_positionInterval); 99 159 setState(PlayerState.BUFFERING); 100 160 sendBufferEvent(0); 101 if (getConfigProperty('loadbalance') as Boolean == true) { 102 _smil = item.file; 103 _loader.load(new URLRequest(_smil)); 104 } else { 161 if (getConfigProperty('loadbalance')) { 162 if (!item.hasOwnProperty('smil')) { item.smil = []; } 163 item.smilIndex = item.levels.length > 0 ? item.currentLevel : 0; 164 item.smil[item.smilIndex] = item.file; 165 _xmlLoader.load(item.file, XML); 166 } else { 105 167 finishLoad(); 106 } 107 } 108 109 110 /** Get the streamer / file from the loadbalancing XML. **/ 111 private function loaderHandler(evt:Event):void { 112 var xml:XML = XML(evt.currentTarget.data); 113 item.streamer = xml.children()[0].children()[0].@base.toString(); 114 item.file = xml.children()[1].children()[0].@src.toString(); 115 finishLoad(); 116 } 117 168 } 169 } 118 170 119 171 /** Finalizes the loading process **/ … … 122 174 if (ext == '.mp3'){ 123 175 media = null; 124 } else if (!media){176 } else { 125 177 media = _video; 126 178 } 127 _connection.connect(item.streamer); 128 config.mute == true ? setVolume(0) : setVolume(config.volume); 129 sendMediaEvent(MediaEvent.JWPLAYER_MEDIA_LOADED); 179 if (item.streamer != _currentStream || !_isStreaming) { 180 _currentStream = item.streamer; 181 sendMediaEvent(MediaEvent.JWPLAYER_MEDIA_LOADED); 182 _connection.connect(item.streamer); 183 } else { 184 seek(_timeoffset); 185 } 130 186 } 131 132 133 /** Get metadata information from netstream class. **/ 134 public function onData(dat:Object):void { 135 if (dat.width) { 187 188 /** Make sure the selected level is actually the item.file. **/ 189 private function loadLevelSync():void { 190 for (var i:Number = 0; i < item.levels.length; i++) { 191 if (item.file == (item.levels[i] as PlaylistItemLevel).file) { 192 item.setLevel(i); 193 break; 194 } 195 } 196 } 197 198 /** Get the streamer / file from the loadbalancing XML. **/ 199 private function loaderHandler(evt:Event):void { 200 var xml:XML = XML((evt.target as AssetLoader).loadedObject); 201 item.streamer = xml.head.meta.@base.toString(); 202 var fileLocation:String = xml.body.video.@src.toString(); 203 if (item.levels.length > 0) { 204 (item.levels[item.smilIndex] as PlaylistItemLevel).file = fileLocation; 205 } else { 206 item.file = fileLocation; 207 } 208 finishLoad(); 209 } 210 211 /** Get metadata information from netstream class. **/ 212 public function onClientData(dat:Object):void { 213 if (dat.type == 'fcsubscribe') { 214 if (dat.code == "NetStream.Play.StreamNotFound") { 215 sendMediaEvent(MediaEvent.JWPLAYER_MEDIA_ERROR,{message: "Subscription failed: " + item.file}); 216 } else if (dat.code == "NetStream.Play.Start") { 217 setStream(); 218 } 219 clearInterval(_subscribeInterval); 220 } 221 if (dat.width) { 136 222 _video.width = dat.width; 137 223 _video.height = dat.height; 138 224 resize(_width, _height); 139 } 140 if (dat.duration && item.duration <= 0) { 141 item.duration = dat.duration; 142 } 143 if (dat.type == 'complete') { 225 } 226 if (dat.duration && item.duration <= 0) { 227 item.duration = dat.duration; 228 } 229 if (dat.type == 'complete') { 230 clearInterval(_positionInterval); 144 231 complete(); 145 } else if (dat.type == 'close') { 232 } 233 if (dat.type == 'close') { 234 stop(); 235 } 236 if (dat.type == 'bandwidth') { 237 config.bandwidth = dat.bandwidth; 238 Configger.saveCookie('bandwidth', dat.bandwidth); 239 setStream(); 240 } 241 if (dat.code == 'NetStream.Play.TransitionComplete'|| (dat.code == 'NetStream.Play.Transition' && dat.reason == 'NetStream.Transition.Success')) { 242 if (_transitionLevel >= 0) { 243 Logger.log("Transition to level " + item.currentLevel + "complete"); 244 _transitionLevel = -1; 245 } 246 } 247 sendMediaEvent(MediaEvent.JWPLAYER_MEDIA_META, {metadata: dat}); 248 } 249 250 /** Pause playback. **/ 251 override public function pause():void { 252 if (isLivestream()) { 146 253 stop(); 147 } 148 if (config.ignoremeta != true) { 149 sendMediaEvent(MediaEvent.JWPLAYER_MEDIA_META, {metadata: dat}); 150 } 151 } 152 153 154 /** Determines if the stream is a live stream **/ 155 private function get livestream():Boolean { 156 // We assume it's a livestream until we hear otherwise. 157 return !(item.duration > 0); 158 } 159 160 /** Pause playback. **/ 161 override public function pause():void { 162 _streamActive = false; 163 _stream.pause(); 254 return; 255 } 256 164 257 clearInterval(_positionInterval); 165 _positionInterval = undefined; 166 super.pause(); 167 if (livestream) { 168 stop(); 169 } 170 } 171 172 173 /** Resume playing. **/ 174 override public function play():void { 175 /* 176 * Livestreams will reset their buffer if _stream.resume is called, 177 * so we suppress them after the intial call 178 */ 179 if (!livestream && !_streamActive) { 180 _streamActive = true; 181 _stream.resume(); 182 } 183 if (!_streamStarted) { 184 _streamStarted = true; 185 if (!livestream) { 186 seek(item.start); 258 setState(PlayerState.PAUSED); 259 if (_stream) { 260 Logger.log("NetStream.pause()"); 261 _stream.pause(); 262 } 263 } 264 265 /** Resume playing. **/ 266 override public function play():void { 267 if (_stream) { 268 Logger.log("NetStream.resume()"); 269 _stream.resume(); 270 } 271 clearInterval(_positionInterval); 272 _positionInterval = setInterval(positionInterval, 100); 273 setState(PlayerState.PLAYING); 274 } 275 276 /** Interval for the position progress. **/ 277 private function positionInterval():void { 278 var pos:Number = Math.round((_stream.time) * 10) / 10; 279 var bfr:Number = _stream.bufferLength / _stream.bufferTime; 280 281 if (bfr < 0.25 && pos < item.duration - 5 && state != PlayerState.BUFFERING) { 282 _bufferFull = false; 283 setState(PlayerState.BUFFERING); 284 } else if (bfr > 1 && state != PlayerState.PLAYING) { 285 if (state == PlayerState.BUFFERING && !isLivestream()) { 286 _bufferFull = true; 287 sendMediaEvent(MediaEvent.JWPLAYER_MEDIA_BUFFER_FULL, {bufferPercent: bfr}); 187 288 } 188 } 189 190 if (!_positionInterval) { 191 _positionInterval = setInterval(positionInterval, 100); 192 } 193 super.play(); 194 } 195 196 197 /** Interval for the position progress. **/ 198 protected function positionInterval():void { 199 _position = Math.round(_stream.time * 10) / 10; 200 201 var bfr:Number; 202 if (!livestream) { 203 var bufferTime:Number = _stream.bufferTime < (item.duration - position) ? _stream.bufferTime : (item.duration - position); 204 bfr = Math.round(_stream.bufferLength / bufferTime * 100); 205 } else if (_stream.bufferLength > 0) { 206 bfr = Math.round(_stream.bufferLength / _stream.bufferTime * 100); 207 } else if (_streamActive){ 208 bfr = 100; 209 } 210 211 212 if (bfr < 95 && position < Math.abs(item.duration - _stream.bufferTime - 1)) { 213 if (state == PlayerState.PLAYING && bfr < 20) { 214 _bufferFull = false; 215 _streamActive = false; 216 _stream.pause(); 217 setState(PlayerState.BUFFERING); 218 _stream.bufferTime = config.bufferlength; 219 sendMediaEvent(MediaEvent.JWPLAYER_MEDIA_META, {metadata: {bufferlength: config.bufferlength}}); 289 } 290 if (state != PlayerState.PLAYING) { 291 return; 292 } 293 if (pos < item.duration) { 294 _position = pos; 295 sendMediaEvent(MediaEvent.JWPLAYER_MEDIA_TIME, {position: position, duration: item.duration}); 296 } else if (position > 0 && item.duration > 0) { 297 Logger.log("NetStream.pause()"); 298 _stream.pause(); 299 clearInterval(_positionInterval); 300 complete(); 301 } 302 } 303 304 /** Check if the level must be switched on resize. **/ 305 override public function resize(width:Number, height:Number):void { 306 super.resize(width, height); 307 if (state == PlayerState.PLAYING) { 308 if (item.levels.length > 0 && item.currentLevel != item.getLevel(config.bandwidth, config.width)) { 309 item.setLevel(item.getLevel(config.bandwidth, config.width)); 310 if (_dynamic) { 311 swap(item.currentLevel); 312 } else { 313 seek(position); 314 } 220 315 } 221 } else if (bfr > 95 && state == PlayerState.BUFFERING) { 222 //_stream.bufferTime = config.bufferlength * 4; 223 //sendMediaEvent(MediaEvent.JWPLAYER_MEDIA_META, {metadata: {bufferlength: config.bufferlength * 4}}); 224 if (!_bufferFull){ 225 _bufferFull = true; 226 sendMediaEvent(MediaEvent.JWPLAYER_MEDIA_BUFFER_FULL); 227 } 228 } 229 230 if (state == PlayerState.BUFFERING || state == PlayerState.PAUSED) { 231 //TODO: This works, but it looks weird, as the bufferTime is changing 232 /* 233 if (!_bufferingComplete){ 234 sendBufferEvent(_stream.bufferLength / _stream.bufferTime * item.duration); 235 } 236 */ 237 } else if (position < item.duration) { 238 if (state == PlayerState.PLAYING && position >= 0) { 239 //TODO: This works, but it looks weird, as the bufferTime is changing 240 //sendMediaEvent(MediaEvent.JWPLAYER_MEDIA_TIME, {position: position, duration: item.duration, bufferLength: _stream.bufferLength / _stream.bufferTime * item.duration}); 241 sendMediaEvent(MediaEvent.JWPLAYER_MEDIA_TIME, {position: position, duration: item.duration}); 242 } 243 } else if (!isNaN(position) && item.duration > 0) { 244 complete(); 245 } 246 } 247 248 249 /** Seek to a new position. **/ 250 override public function seek(pos:Number):void { 251 _position = pos; 252 clearInterval(_positionInterval); 253 _positionInterval = undefined; 254 _stream.seek(position); 255 if (!_positionInterval) { 256 _positionInterval = setInterval(positionInterval, 100); 257 } 258 } 259 260 261 /** Start the netstream object. **/ 262 protected function setStream():void { 316 } 317 } 318 319 /** Seek to a new position. **/ 320 override public function seek(pos:Number):void { 321 _timeoffset = pos; 322 _transitionLevel = -1; 323 clearInterval(_positionInterval); 324 clearInterval(_bandwidthInterval); 325 if (item.levels.length > 0 && item.getLevel(config.bandwidth, config.width) != item.currentLevel) { 326 item.setLevel(item.getLevel(config.bandwidth, config.width)); 327 if (getConfigProperty('loadbalance')) { 328 item.start = pos; 329 load(item); 330 return; 331 } 332 } 333 if (state != PlayerState.PLAYING) { 334 play(); 335 } 336 if (getConfigProperty('subscribe')) { 337 Logger.log("NetStream.play(" + getID(item.file) + ")"); 338 _stream.play(getID(item.file)); 339 } else { 340 if (_currentFile != item.file) { 341 _currentFile = item.file; 342 Logger.log("NetStream.play(" + getID(item.file) + ")"); 343 try { 344 _stream.play(getID(item.file)); 345 } catch(e:Error) {} 346 } 347 if (_timeoffset >= 0 || state == PlayerState.IDLE) { 348 if (_stream) { 349 Logger.log("NetStream.seek(" + _timeoffset + ")"); 350 _stream.seek(_timeoffset); 351 } 352 } 353 if (_dynamic) { 354 _bandwidthInterval = setInterval(getBandwidth, 2000); 355 } 356 } 357 _isStreaming = true; 358 _positionInterval = setInterval(positionInterval, 100); 359 } 360 361 /** Start the netstream object. **/ 362 private function setStream():void { 263 363 _stream = new NetStream(_connection); 264 364 _stream.checkPolicyFile = true; … … 269 369 _stream.client = new NetClient(this); 270 370 _video.attachNetStream(_stream); 271 if (!_positionInterval) { 272 _positionInterval = setInterval(positionInterval, 100); 273 } 274 _stream.play(getID(item.file)); 275 } 276 277 278 /** Receive NetStream status updates. 279 * 280 * For more info see http://help.adobe.com/en_US/Flex/4.0/langref/flash/events/NetStatusEvent.html#info 281 **/ 282 protected function statusHandler(evt:NetStatusEvent):void { 283 switch (evt.info.code) { 284 case 'NetConnection.Connect.Success': 285 if (evt.info.secureToken != undefined) { 286 _connection.call("secureTokenResponse", null, TEA.decrypt(evt.info.secureToken, config.token)); 287 } 288 setStream(); 289 var res:Responder = new Responder(streamlengthHandler); 290 _connection.call("getStreamLength", res, getID(item.file)); 291 _connection.call("checkBandwidth", null); 292 break; 293 case 'NetStream.Play.Start': 294 break; 295 case 'NetStream.Seek.Notify': 296 clearInterval(_positionInterval); 297 _positionInterval = undefined; 298 if (!_positionInterval) { 299 _positionInterval = setInterval(positionInterval, 100); 371 config.mute == true ? setVolume(0) : setVolume(config.volume); 372 seek(_timeoffset); 373 } 374 375 /** Receive NetStream status updates. **/ 376 private function statusHandler(evt:NetStatusEvent):void { 377 switch (evt.info.code) { 378 case 'NetConnection.Connect.Success': 379 if (evt.info.secureToken != undefined) { 380 _connection.call("secureTokenResponse", null, TEA.decrypt(evt.info.secureToken, 381 config.token)); 382 } 383 if (evt.info.data) { 384 checkDynamic(evt.info.data.version); 385 } 386 if (getConfigProperty('subscribe')) { 387 _subscribeInterval = setInterval(doSubscribe, 1000, getID(item.file)); 388 return; 389 } else { 390 if (item.levels.length > 0) { 391 if (_dynamic || _bandwidthInterval) { 392 setStream(); 393 } else { 394 _bandwidthChecked = true; 395 _connection.call('checkBandwidth', null); 396 } 397 } else { 398 setStream(); 399 } 400 if (item.file.substr(-4) == '.mp3' || item.file.substr(0,4) == 'mp3:') { 401 _connection.call("getStreamLength", new Responder(streamlengthHandler), getID(item.file)); 402 } 403 } 404 break; 405 case 'NetStream.Seek.Notify': 406 clearInterval(_positionInterval); 407 _positionInterval = setInterval(positionInterval, 100); 408 break; 409 case 'NetConnection.Connect.Rejected': 410 try { 411 if (evt.info.ex.code == 302) { 412 item.streamer = evt.info.ex.redirect; 413 setTimeout(load, 100, item); 414 return; 415 } 416 } catch (err:Error) { 417 stop(); 418 var msg:String = evt.info.code; 419 if (evt.info['description']) { 420 msg = evt.info['description']; 421 } 422 stop(); 423 sendMediaEvent(MediaEvent.JWPLAYER_MEDIA_ERROR, {message: msg}); 424 } 425 break; 426 case 'NetStream.Failed': 427 case 'NetStream.Play.StreamNotFound': 428 if (!_isStreaming) { 429 onClientData({type: 'complete'}); 430 } else { 431 stop(); 432 sendMediaEvent(MediaEvent.JWPLAYER_MEDIA_ERROR, {message: "Stream not found: " + item.file}); 433 } 434 break; 435 case 'NetStream.Seek.Failed': 436 if (!_isStreaming) { 437 onClientData({type: 'complete'}); 438 } else { 439 stop(); 440 sendMediaEvent(MediaEvent.JWPLAYER_MEDIA_ERROR, {message: "Could not seek: " + item.file}); 300 441 } 301 442 break; 302 case 'NetConnection.Connect.Rejected': 303 try { 304 if (evt.info.ex.code == 302) { 305 item.streamer = evt.info.ex.redirect; 306 setTimeout(load, 100, item); 307 return; 308 } 309 } catch (err:Error) { 310 var msg:String = evt.info.code; 311 if (evt.info['description']) { 312 msg = evt.info['description']; 313 } 314 error(msg); 315 } 316 break; 317 case 'NetStream.Failed': 318 case 'NetStream.Play.StreamNotFound': 319 if (_unpublished) { 320 onData({type: 'complete'}); 321 _unpublished = false; 322 } else { 323 error("Stream not found: " + item.file); 324 } 325 break; 326 case 'NetConnection.Connect.Failed': 327 error("Server not found: " + item.streamer); 328 break; 329 case 'NetStream.Play.UnpublishNotify': 330 _unpublished = true; 331 break; 443 case 'NetConnection.Connect.Failed': 444 stop(); 445 sendMediaEvent(MediaEvent.JWPLAYER_MEDIA_ERROR, {message: "Server not found: " + item.streamer}); 446 break; 447 case 'NetStream.Play.UnpublishNotify': 448 stop(); 449 break; 332 450 case 'NetStream.Buffer.Full': 333 451 if (!_bufferFull) { … … 336 454 } 337 455 break; 338 case 'NetStream.Play.Reset': 456 case 'NetStream.Play.Transition': 457 onClientData(evt.info); 339 458 break; 340 }459 } 341 460 sendMediaEvent(MediaEvent.JWPLAYER_MEDIA_META, {metadata: evt.info}); 461 } 462 463 /** Destroy the stream. **/ 464 override public function stop():void { 465 if (_stream && _stream.time) { 466 Logger.log("NetStream.close()"); 467 _stream.close(); 468 } 469 _isStreaming = false; 470 _currentFile = undefined; 471 _connection.close(); 472 clearInterval(_positionInterval); 473 clearInterval(_bandwidthInterval); 474 _position = 0; 475 _timeoffset = item.start; 476 super.stop(); 477 if (item.hasOwnProperty('smil')) { 478 /** Replace file values with original redirects **/ 479 if (item.levels.length > 0) { 480 for (var i:Number = 0; i < item.levels.length; i++) { 481 if (i < item.smil.length && item.smil[i]) { 482 (item.levels[i] as PlaylistItemLevel).file = item.smil[i]; 483 } 484 } 485 } else { 486 item.file = item.smil[0]; 487 } 488 } 342 489 } 343 490 344 345 /** Destroy the _stream. **/ 346 override public function stop():void { 347 _streamStarted = false; 348 _streamActive = false; 349 if (_stream && _stream.time) { 350 _stream.close(); 351 } 352 _connection.close(); 353 clearInterval(_positionInterval); 354 _positionInterval = undefined; 355 super.stop(); 356 if (_smil) { 357 item.file = _smil; 358 } 491 /** Get the streamlength returned from the connection. **/ 492 private function streamlengthHandler(len:Number):void { 493 Logger.log("duration: " + len); 494 if (len && item.duration <= 0) { 495 item.duration = len; 496 } 497 } 498 499 /** Dynamically switch streams **/ 500 private function swap(newLevel:Number):void { 501 if (_transitionLevel == newLevel) { 502 Logger.log('Already tranisitioning to level ' + item.currentLevel + ' ; transition ignored'); 503 } else { 504 _transitionLevel = newLevel; 505 Logger.log('transition to level ' + item.currentLevel + ' initiated'); 506 var nso:NetStreamPlayOptions = new NetStreamPlayOptions(); 507 nso.streamName = getID(item.file); 508 nso.transition = NetStreamPlayTransitions.SWITCH; 509 Logger.log("NetStream.play2(" + nso + ")"); 510 _stream.play2(nso); 511 } 512 } 513 514 /** Set the volume level. **/ 515 override public function setVolume(vol:Number):void { 516 _transformer.volume = vol / 100; 517 518 if (_stream) { 519 _stream.soundTransform = _transformer; 520 } 521 } 522 523 /** Completes video playback **/ 524 override protected function complete():void { 525 stop(); 526 sendMediaEvent(MediaEvent.JWPLAYER_MEDIA_COMPLETE); 527 setState(PlayerState.IDLE); 359 528 } 360 361 362 /** Get the streamlength returned from the _connection. **/ 363 private function streamlengthHandler(len:Number):void { 364 if (len > 0) { 365 onData({type: 'streamlength', duration: len}); 366 } 529 530 /** Determines if the stream is a live stream **/ 531 private function isLivestream():Boolean { 532 // We assume it's a livestream until we hear otherwise. 533 return (!(item.duration > 0) && _stream && _stream.bufferLength > 0); 367 534 } 368 369 370 /** Set the volume level. **/ 371 override public function setVolume(vol:Number):void { 372 _transformer.volume = vol / 100; 373 if (_stream) { 374 try { 375 _stream.soundTransform = _transformer; 376 super.setVolume(vol); 377 } catch (err:Error) { 378 379 } 380 } 381 } 382 } 535 536 537 } 383 538 } -
trunk/fl5/src/com/longtailvideo/jwplayer/media/VideoMediaProvider.as
r805 r806 105 105 106 106 /** Get metadata information from netstream class. **/ 107 public function on Data(dat:Object):void {107 public function onClientData(dat:Object):void { 108 108 if (dat.width) { 109 109 _video.width = dat.width; -
trunk/fl5/src/com/longtailvideo/jwplayer/player/PlayerVersion.as
r805 r806 3 3 4 4 public class PlayerVersion { 5 protected static var _version:String = "5.1.80 5";5 protected static var _version:String = "5.1.806"; 6 6 7 7 public static function get version():String { -
trunk/fl5/src/com/longtailvideo/jwplayer/utils/NetClient.as
r772 r806 22 22 out[i] = dat[i]; 23 23 } 24 callback.on Data(out);24 callback.onClientData(out); 25 25 } 26 26
Note: See TracChangeset
for help on using the changeset viewer.
