| 1 | package com.longtailvideo.jwplayer.player { |
|---|
| 2 | import com.longtailvideo.jwplayer.events.MediaEvent; |
|---|
| 3 | import com.longtailvideo.jwplayer.events.PlayerEvent; |
|---|
| 4 | import com.longtailvideo.jwplayer.events.PlayerStateEvent; |
|---|
| 5 | import com.longtailvideo.jwplayer.events.PlaylistEvent; |
|---|
| 6 | import com.longtailvideo.jwplayer.events.ViewEvent; |
|---|
| 7 | import com.longtailvideo.jwplayer.model.Playlist; |
|---|
| 8 | import com.longtailvideo.jwplayer.utils.JavascriptSerialization; |
|---|
| 9 | import com.longtailvideo.jwplayer.utils.Logger; |
|---|
| 10 | import com.longtailvideo.jwplayer.utils.Strings; |
|---|
| 11 | |
|---|
| 12 | import flash.events.Event; |
|---|
| 13 | import flash.events.TimerEvent; |
|---|
| 14 | import flash.external.ExternalInterface; |
|---|
| 15 | import flash.utils.Timer; |
|---|
| 16 | |
|---|
| 17 | public class JavascriptAPI { |
|---|
| 18 | protected var _player:IPlayer; |
|---|
| 19 | protected var _playerBuffer:Number = 0; |
|---|
| 20 | protected var _playerPosition:Number = 0; |
|---|
| 21 | |
|---|
| 22 | protected var _listeners:Object; |
|---|
| 23 | |
|---|
| 24 | public function JavascriptAPI(player:IPlayer) { |
|---|
| 25 | _listeners = {}; |
|---|
| 26 | |
|---|
| 27 | _player = player; |
|---|
| 28 | _player.addEventListener(PlayerEvent.JWPLAYER_READY, playerReady); |
|---|
| 29 | |
|---|
| 30 | setupPlayerListeners(); |
|---|
| 31 | setupJSListeners(); |
|---|
| 32 | } |
|---|
| 33 | |
|---|
| 34 | /** Delay the response to PlayerReady to allow the external interface to initialize in some browsers **/ |
|---|
| 35 | protected function playerReady(evt:PlayerEvent):void { |
|---|
| 36 | var timer:Timer = new Timer(50, 1); |
|---|
| 37 | timer.addEventListener(TimerEvent.TIMER_COMPLETE, function(timerEvent:TimerEvent):void { |
|---|
| 38 | var callbacks:String = _player.config.playerready ? _player.config.playerready + "," + "playerReady" : "playerReady"; |
|---|
| 39 | if (ExternalInterface.available) { |
|---|
| 40 | for each (var callback:String in callbacks.replace(/\s/,"").split(",")) { |
|---|
| 41 | try { |
|---|
| 42 | ExternalInterface.call(callback,{ |
|---|
| 43 | id:evt.id, |
|---|
| 44 | client:evt.client, |
|---|
| 45 | version:evt.version |
|---|
| 46 | }); |
|---|
| 47 | } catch (e:Error) {} |
|---|
| 48 | } |
|---|
| 49 | } |
|---|
| 50 | }); |
|---|
| 51 | timer.start(); |
|---|
| 52 | } |
|---|
| 53 | |
|---|
| 54 | protected function setupPlayerListeners():void { |
|---|
| 55 | _player.addEventListener(PlaylistEvent.JWPLAYER_PLAYLIST_ITEM, resetPosition); |
|---|
| 56 | _player.addEventListener(MediaEvent.JWPLAYER_MEDIA_TIME, updatePosition); |
|---|
| 57 | _player.addEventListener(MediaEvent.JWPLAYER_MEDIA_BUFFER, updateBuffer); |
|---|
| 58 | } |
|---|
| 59 | |
|---|
| 60 | protected function resetPosition(evt:PlaylistEvent):void { |
|---|
| 61 | _playerPosition = 0; |
|---|
| 62 | _playerBuffer = 0; |
|---|
| 63 | } |
|---|
| 64 | |
|---|
| 65 | protected function updatePosition(evt:MediaEvent):void { |
|---|
| 66 | _playerPosition = evt.position; |
|---|
| 67 | } |
|---|
| 68 | |
|---|
| 69 | protected function updateBuffer(evt:MediaEvent):void { |
|---|
| 70 | _playerBuffer = evt.bufferPercent; |
|---|
| 71 | } |
|---|
| 72 | |
|---|
| 73 | protected function setupJSListeners():void { |
|---|
| 74 | try { |
|---|
| 75 | // Event handlers |
|---|
| 76 | ExternalInterface.addCallback("jwAddEventListener", js_addEventListener); |
|---|
| 77 | ExternalInterface.addCallback("jwRemoveEventListener", js_removeEventListener); |
|---|
| 78 | |
|---|
| 79 | // Getters |
|---|
| 80 | ExternalInterface.addCallback("jwGetBandwidth", js_getBandwidth); |
|---|
| 81 | ExternalInterface.addCallback("jwGetBuffer", js_getBuffer); |
|---|
| 82 | ExternalInterface.addCallback("jwGetDuration", js_getDuration); |
|---|
| 83 | ExternalInterface.addCallback("jwGetFullscreen", js_getFullscreen); |
|---|
| 84 | ExternalInterface.addCallback("jwGetHeight", js_getHeight); |
|---|
| 85 | ExternalInterface.addCallback("jwGetLevel", js_getLevel); |
|---|
| 86 | ExternalInterface.addCallback("jwGetLockState", js_getLockState); |
|---|
| 87 | ExternalInterface.addCallback("jwGetMute", js_getMute); |
|---|
| 88 | ExternalInterface.addCallback("jwGetPlaylist", js_getPlaylist); |
|---|
| 89 | ExternalInterface.addCallback("jwGetPosition", js_getPosition); |
|---|
| 90 | ExternalInterface.addCallback("jwGetState", js_getState); |
|---|
| 91 | ExternalInterface.addCallback("jwGetWidth", js_getWidth); |
|---|
| 92 | ExternalInterface.addCallback("jwGetVersion", js_getVersion); |
|---|
| 93 | ExternalInterface.addCallback("jwGetVolume", js_getVolume); |
|---|
| 94 | |
|---|
| 95 | // Player API Calls |
|---|
| 96 | ExternalInterface.addCallback("jwPlay", js_play); |
|---|
| 97 | ExternalInterface.addCallback("jwPause", js_pause); |
|---|
| 98 | ExternalInterface.addCallback("jwStop", js_stop); |
|---|
| 99 | ExternalInterface.addCallback("jwSeek", js_seek); |
|---|
| 100 | ExternalInterface.addCallback("jwLoad", js_load); |
|---|
| 101 | ExternalInterface.addCallback("jwPlaylistItem", js_playlistItem); |
|---|
| 102 | ExternalInterface.addCallback("jwPlaylistNext", js_playlistNext); |
|---|
| 103 | ExternalInterface.addCallback("jwPlaylistPrev", js_playlistPrev); |
|---|
| 104 | ExternalInterface.addCallback("jwMute", js_mute); |
|---|
| 105 | ExternalInterface.addCallback("jwVolume", js_volume); |
|---|
| 106 | |
|---|
| 107 | |
|---|
| 108 | } catch(e:Error) { |
|---|
| 109 | Logger.log("Could not initialize JavaScript API: " + e.message); |
|---|
| 110 | } |
|---|
| 111 | |
|---|
| 112 | } |
|---|
| 113 | |
|---|
| 114 | |
|---|
| 115 | /*********************************************** |
|---|
| 116 | ** EVENT LISTENERS ** |
|---|
| 117 | ***********************************************/ |
|---|
| 118 | |
|---|
| 119 | protected function js_addEventListener(eventType:String, callback:String):void { |
|---|
| 120 | if (!_listeners[eventType]) { |
|---|
| 121 | _listeners[eventType] = []; |
|---|
| 122 | _player.addEventListener(eventType, listenerCallback); |
|---|
| 123 | } |
|---|
| 124 | (_listeners[eventType] as Array).push(callback); |
|---|
| 125 | } |
|---|
| 126 | |
|---|
| 127 | protected function js_removeEventListener(eventType:String, callback:String):void { |
|---|
| 128 | var callbacks:Array = _listeners[eventType]; |
|---|
| 129 | if (callbacks) { |
|---|
| 130 | var callIndex:Number = callbacks.indexOf(callback); |
|---|
| 131 | if (callIndex > -1) { |
|---|
| 132 | callbacks.splice(callIndex, 1); |
|---|
| 133 | } |
|---|
| 134 | } |
|---|
| 135 | } |
|---|
| 136 | |
|---|
| 137 | |
|---|
| 138 | |
|---|
| 139 | protected function listenerCallback(evt:PlayerEvent):void { |
|---|
| 140 | var args:Object; |
|---|
| 141 | |
|---|
| 142 | if (evt is MediaEvent) |
|---|
| 143 | args = listnerCallbackMedia(evt as MediaEvent); |
|---|
| 144 | else if (evt is PlayerStateEvent) |
|---|
| 145 | args = listenerCallbackState(evt as PlayerStateEvent); |
|---|
| 146 | else if (evt is ViewEvent && (evt as ViewEvent).data != null) |
|---|
| 147 | args['data'] = (evt as ViewEvent).data; |
|---|
| 148 | |
|---|
| 149 | var callbacks:Array = _listeners[evt.type] as Array; |
|---|
| 150 | |
|---|
| 151 | if (callbacks) { |
|---|
| 152 | for each (var call:String in callbacks) { |
|---|
| 153 | ExternalInterface.call(call, args); |
|---|
| 154 | } |
|---|
| 155 | } |
|---|
| 156 | |
|---|
| 157 | } |
|---|
| 158 | |
|---|
| 159 | protected function merge(obj1:Object, obj2:Object):Object { |
|---|
| 160 | var newObj:Object = {}; |
|---|
| 161 | |
|---|
| 162 | for (var key:String in obj1) { |
|---|
| 163 | newObj[key] = obj1[key]; |
|---|
| 164 | } |
|---|
| 165 | |
|---|
| 166 | for (key in obj2) { |
|---|
| 167 | newObj[key] = obj2[key]; |
|---|
| 168 | } |
|---|
| 169 | |
|---|
| 170 | return newObj; |
|---|
| 171 | } |
|---|
| 172 | |
|---|
| 173 | protected function listnerCallbackMedia(evt:MediaEvent):Object { |
|---|
| 174 | var returnObj:Object = {}; |
|---|
| 175 | |
|---|
| 176 | if (evt.bufferPercent >= 0) returnObj.bufferPercent = evt.bufferPercent; |
|---|
| 177 | if (evt.duration >= 0) returnObj.duration = evt.duration; |
|---|
| 178 | if (evt.message != undefined) returnObj.message = evt.message; |
|---|
| 179 | if (evt.metadata != null) returnObj.metadata = evt.metadata; |
|---|
| 180 | if (evt.offset >= 0) returnObj.offset = evt.offset; |
|---|
| 181 | if (evt.position >= 0) returnObj.position = evt.position; |
|---|
| 182 | |
|---|
| 183 | if (evt.type == MediaEvent.JWPLAYER_MEDIA_MUTE) |
|---|
| 184 | returnObj.mute = evt.mute; |
|---|
| 185 | |
|---|
| 186 | if (evt.type == MediaEvent.JWPLAYER_MEDIA_VOLUME) |
|---|
| 187 | returnObj.volume = evt.volume; |
|---|
| 188 | |
|---|
| 189 | return returnObj; |
|---|
| 190 | } |
|---|
| 191 | |
|---|
| 192 | |
|---|
| 193 | protected function listenerCallbackState(evt:PlayerStateEvent):Object { |
|---|
| 194 | if (evt.type == PlayerStateEvent.JWPLAYER_PLAYER_STATE) { |
|---|
| 195 | return { newstate: evt.newstate, oldstate: evt.oldstate }; |
|---|
| 196 | } else return {}; |
|---|
| 197 | } |
|---|
| 198 | |
|---|
| 199 | /*********************************************** |
|---|
| 200 | ** GETTERS ** |
|---|
| 201 | ***********************************************/ |
|---|
| 202 | |
|---|
| 203 | protected function js_getBandwidth():Number { |
|---|
| 204 | return _player.config.bandwidth; |
|---|
| 205 | } |
|---|
| 206 | |
|---|
| 207 | protected function js_getBuffer():Number { |
|---|
| 208 | return _playerBuffer; |
|---|
| 209 | } |
|---|
| 210 | |
|---|
| 211 | protected function js_getDuration():Number { |
|---|
| 212 | return _player.playlist.currentItem.duration; |
|---|
| 213 | } |
|---|
| 214 | |
|---|
| 215 | protected function js_getFullscreen():Boolean { |
|---|
| 216 | return _player.config.fullscreen; |
|---|
| 217 | } |
|---|
| 218 | |
|---|
| 219 | protected function js_getHeight():Number { |
|---|
| 220 | return _player.config.height; |
|---|
| 221 | } |
|---|
| 222 | |
|---|
| 223 | protected function js_getLevel():Number { |
|---|
| 224 | return _player.playlist.currentItem.currentLevel; |
|---|
| 225 | } |
|---|
| 226 | |
|---|
| 227 | protected function js_getLockState():Boolean { |
|---|
| 228 | return _player.locked; |
|---|
| 229 | } |
|---|
| 230 | |
|---|
| 231 | protected function js_getMute():Boolean { |
|---|
| 232 | return _player.config.mute; |
|---|
| 233 | } |
|---|
| 234 | |
|---|
| 235 | protected function js_getPlaylist():Array { |
|---|
| 236 | return JavascriptSerialization.playlistToArray(_player.playlist); |
|---|
| 237 | } |
|---|
| 238 | |
|---|
| 239 | protected function js_getPosition():Number { |
|---|
| 240 | return _playerPosition; |
|---|
| 241 | } |
|---|
| 242 | |
|---|
| 243 | protected function js_getState():String { |
|---|
| 244 | return _player.state; |
|---|
| 245 | } |
|---|
| 246 | |
|---|
| 247 | protected function js_getWidth():Number { |
|---|
| 248 | return _player.config.width; |
|---|
| 249 | } |
|---|
| 250 | |
|---|
| 251 | protected function js_getVersion():String { |
|---|
| 252 | return _player.version; |
|---|
| 253 | } |
|---|
| 254 | |
|---|
| 255 | protected function js_getVolume():Number { |
|---|
| 256 | return _player.config.volume; |
|---|
| 257 | } |
|---|
| 258 | |
|---|
| 259 | /*********************************************** |
|---|
| 260 | ** PLAYBACK ** |
|---|
| 261 | ***********************************************/ |
|---|
| 262 | |
|---|
| 263 | protected function js_play(playstate:*=null):void { |
|---|
| 264 | if (playstate != null && playstate != "") { |
|---|
| 265 | if ((playstate is Boolean && playstate === true) || String(playstate).toLowerCase() == "true") { |
|---|
| 266 | _player.play(); |
|---|
| 267 | } else { |
|---|
| 268 | Logger.log("Pausing player: " + typeof playstate); |
|---|
| 269 | _player.pause(); |
|---|
| 270 | } |
|---|
| 271 | } else { |
|---|
| 272 | playToggle(); |
|---|
| 273 | } |
|---|
| 274 | } |
|---|
| 275 | |
|---|
| 276 | |
|---|
| 277 | protected function js_pause():void { |
|---|
| 278 | playToggle(); |
|---|
| 279 | } |
|---|
| 280 | |
|---|
| 281 | protected function playToggle():void { |
|---|
| 282 | if (_player.state == PlayerState.IDLE || _player.state == PlayerState.PAUSED) { |
|---|
| 283 | _player.play(); |
|---|
| 284 | } else { |
|---|
| 285 | _player.pause(); |
|---|
| 286 | } |
|---|
| 287 | } |
|---|
| 288 | |
|---|
| 289 | protected function js_stop():void { |
|---|
| 290 | _player.stop(); |
|---|
| 291 | } |
|---|
| 292 | |
|---|
| 293 | protected function js_seek(position:Number=0):void { |
|---|
| 294 | _player.seek(position); |
|---|
| 295 | } |
|---|
| 296 | |
|---|
| 297 | protected function js_load(toLoad:*):void { |
|---|
| 298 | _player.load(toLoad); |
|---|
| 299 | } |
|---|
| 300 | |
|---|
| 301 | protected function js_playlistItem(item:Number):void { |
|---|
| 302 | _player.playlistItem(item); |
|---|
| 303 | } |
|---|
| 304 | |
|---|
| 305 | protected function js_playlistNext():void { |
|---|
| 306 | _player.playlistNext(); |
|---|
| 307 | } |
|---|
| 308 | |
|---|
| 309 | protected function js_playlistPrev():void { |
|---|
| 310 | _player.playlistPrev(); |
|---|
| 311 | } |
|---|
| 312 | |
|---|
| 313 | protected function js_mute(mutestate:*=null):void { |
|---|
| 314 | if (mutestate is Boolean) { |
|---|
| 315 | if (Boolean(mutestate)) { |
|---|
| 316 | _player.mute(true); |
|---|
| 317 | } else { |
|---|
| 318 | _player.mute(false); |
|---|
| 319 | } |
|---|
| 320 | } else { |
|---|
| 321 | _player.mute(!_player.config.mute); |
|---|
| 322 | } |
|---|
| 323 | } |
|---|
| 324 | |
|---|
| 325 | protected function js_volume(volume:Number):void { |
|---|
| 326 | _player.volume(volume); |
|---|
| 327 | } |
|---|
| 328 | |
|---|
| 329 | |
|---|
| 330 | } |
|---|
| 331 | |
|---|
| 332 | } |
|---|