1/***************************************************** 2* 3* Copyright 2009 Adobe Systems Incorporated. All Rights Reserved. 4* 5***************************************************** 6* The contents of this file are subject to the Mozilla Public License 7* Version 1.1 (the "License"); you may not use this file except in 8* compliance with the License. You may obtain a copy of the License at 9* http://www.mozilla.org/MPL/ 10* 11* Software distributed under the License is distributed on an "AS IS" 12* basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the 13* License for the specific language governing rights and limitations 14* under the License. 15* 16* 17* The Initial Developer of the Original Code is Adobe Systems Incorporated. 18* Portions created by Adobe Systems Incorporated are Copyright (C) 2009 Adobe Systems 19* Incorporated. All Rights Reserved. 20* 21*****************************************************/ 22package org.osmf.net 23{ 24 import flash.events.NetStatusEvent; 25 import flash.net.NetStream; 26 import flash.net.NetStreamPlayOptions; 27 import flash.net.NetStreamPlayTransitions; 28 29 import org.osmf.events.MediaError; 30 import org.osmf.events.MediaErrorCodes; 31 import org.osmf.events.MediaErrorEvent; 32 import org.osmf.media.MediaResourceBase; 33 import org.osmf.media.URLResource; 34 import org.osmf.traits.PlayState; 35 import org.osmf.traits.PlayTrait; 36 import org.osmf.utils.OSMFStrings; 37 38 [ExcludeClass] 39 40 /** 41 * @private 42 * 43 * The NetStreamPlayTrait class extends PlayTrait for NetStream-based playback. 44 * 45 * @see flash.net.NetStream 46 */ 47 public class NetStreamPlayTrait extends PlayTrait 48 { 49 /** 50 * Constructor. 51 * 52 * @langversion 3.0 53 * @playerversion Flash 10 54 * @playerversion AIR 1.5 55 * @productversion OSMF 1.0 56 */ 57 public function NetStreamPlayTrait(netStream:NetStream, resource:MediaResourceBase) 58 { 59 super(); 60 61 if (netStream == null) 62 { 63 throw new ArgumentError(OSMFStrings.getString(OSMFStrings.NULL_PARAM)); 64 } 65 this.netStream = netStream; 66 this.urlResource = resource as URLResource; 67 68 // Live streams can't be paused. 69 var streamingResource:StreamingURLResource = resource as StreamingURLResource; 70 if (streamingResource != null && streamingResource.streamType == StreamType.LIVE) 71 { 72 setCanPause(false); 73 } 74 75 // Note that we add the listener (and handler) with a high priority. 76 // The reason for this is that we want to process any Play.Stop (and 77 // Play.Complete) events first, so that we can update our playing 78 // state before the NetStreamTimeTrait processes the event and 79 // dispatches the COMPLETE event. Clients who register for the 80 // COMPLETE event will expect that the media is no longer playing. 81 netStream.addEventListener(NetStatusEvent.NET_STATUS, onNetStatus, false, 1, true); 82 NetClient(netStream.client).addHandler(NetStreamCodes.ON_PLAY_STATUS, onPlayStatus, 1); 83 } 84 85 /** 86 * @private 87 * Communicates a <code>playing</code> change to the media through the NetStream. 88 * <p>For streaming media, parses the URL to extract the stream name.</p> 89 * @param newPlaying New <code>playing</code> value. 90 */ 91 override protected function playStateChangeStart(newPlayState:String):void 92 { 93 if (newPlayState == PlayState.PLAYING) 94 { 95 var playArgs:Object; 96 97 if (streamStarted) 98 { 99 netStream.resume(); 100 } 101 else if (urlResource != null) 102 { 103 // Map the resource to the NetStream.play/play2 arguments. 104 var streamingResource:StreamingURLResource = urlResource as StreamingURLResource; 105 var urlIncludesFMSApplicationInstance:Boolean = streamingResource ? streamingResource.urlIncludesFMSApplicationInstance : false; 106 var streamName:String = NetStreamUtils.getStreamNameFromURL(urlResource.url, urlIncludesFMSApplicationInstance); 107 108 playArgs = NetStreamUtils.getPlayArgsForResource(urlResource); 109 110 var startTime:Number = playArgs.start; 111 var len:Number = playArgs.len; 112 113 var dsResource:DynamicStreamingResource = urlResource as DynamicStreamingResource; 114 if (dsResource != null) 115 { 116 // Play the clip (or the requested portion of the clip). 117 var nso:NetStreamPlayOptions = new NetStreamPlayOptions(); 118 nso.start = startTime; 119 nso.len = len; 120 nso.streamName = dsResource.streamItems[dsResource.initialIndex].streamName; 121 nso.transition = NetStreamPlayTransitions.RESET; 122 123 doPlay2(nso); 124 } 125 else 126 { 127 // Play the clip (or the requested portion of the clip). 128 doPlay(streamName, startTime, len); 129 } 130 } 131 } 132 else // PAUSED || STOPPED 133 { 134 netStream.pause(); 135 } 136 } 137 138 // Needed to detect when the stream didn't play: i.e. complete or error cases. 139 private function onNetStatus(event:NetStatusEvent):void 140 { 141 switch (event.info.code) 142 { 143 case NetStreamCodes.NETSTREAM_PLAY_FAILED: 144 case NetStreamCodes.NETSTREAM_PLAY_FILESTRUCTUREINVALID: 145 case NetStreamCodes.NETSTREAM_PLAY_STREAMNOTFOUND: 146 case NetStreamCodes.NETSTREAM_PLAY_NOSUPPORTEDTRACKFOUND: 147 case NetStreamCodes.NETSTREAM_FAILED: 148 // Pause the stream and reset our state, but don't 149 // signal stop(). The MediaElement's netStatus 150 // event handler will catch the error, and coerce 151 // to a MediaError. 152 netStream.pause(); 153 streamStarted = false; 154 break; 155 case NetStreamCodes.NETSTREAM_PLAY_STOP: 156 // Fired when streaming connections buffer, but also when 157 // progressive connections finish. In the latter case, we 158 // halt playback. 159 if (urlResource != null && NetStreamUtils.isStreamingResource(urlResource) == false) 160 { 161 // Explicitly stop to prevent the stream from restarting on seek(); 162 stop(); 163 } 164 break; 165 } 166 } 167 168 private function onPlayStatus(event:Object):void 169 { 170 switch (event.code) 171 { 172 // Fired when streaming connections finish. Doesn't fire for 173 // Progressive connections. 174 case NetStreamCodes.NETSTREAM_PLAY_COMPLETE: 175 // Explicitly stop to prevent the stream from restarting on seek(); 176 stop(); 177 break; 178 } 179 } 180 181 private function doPlay(...args):void 182 { 183 try 184 { 185 netStream.play.apply(this, args); 186 187 streamStarted = true; 188 } 189 catch (error:Error) 190 { 191 streamStarted = false; 192 stop(); 193 194 dispatchEvent 195 ( new MediaErrorEvent 196 ( MediaErrorEvent.MEDIA_ERROR 197 , false 198 , false 199 , new MediaError(MediaErrorCodes.NETSTREAM_PLAY_FAILED) 200 ) 201 ); 202 } 203 } 204 205 private function doPlay2(nspo:NetStreamPlayOptions):void 206 { 207 netStream.play2(nspo); 208 209 streamStarted = true; 210 } 211 212 private static const NETCONNECTION_FAILURE_ERROR_CODE:int = 2154; 213 214 private var streamStarted:Boolean; 215 private var netStream:NetStream; 216 private var urlResource:URLResource; 217 } 218} 219