PageRenderTime 65ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/flowplayer/branches/3_2/src/actionscript/org/flowplayer/view/Launcher.as

http://flowplayer-core.googlecode.com/
ActionScript | 895 lines | 714 code | 123 blank | 58 comment | 139 complexity | 6d4fcd6c0b7e1991317cb949269a528a MD5 | raw file
Possible License(s): GPL-3.0, AGPL-1.0
  1. /*
  2. * Copyright (c) 2008, 2009 Flowplayer Oy
  3. *
  4. * This file is part of Flowplayer.
  5. *
  6. * Flowplayer is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * Flowplayer is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with Flowplayer. If not, see <http://www.gnu.org/licenses/>.
  18. */
  19. package org.flowplayer.view {
  20. import org.flowplayer.config.Config;
  21. import org.flowplayer.config.ConfigParser;
  22. import org.flowplayer.config.ExternalInterfaceHelper;
  23. import org.flowplayer.config.VersionInfo;
  24. import org.flowplayer.controller.PlayListController;
  25. import org.flowplayer.controller.ResourceLoader;
  26. import org.flowplayer.controller.ResourceLoaderImpl;
  27. import org.flowplayer.flow_internal;
  28. import org.flowplayer.model.Callable;
  29. import org.flowplayer.model.Clip;
  30. import org.flowplayer.model.ClipEvent;
  31. import org.flowplayer.model.ClipEventType;
  32. import org.flowplayer.model.DisplayPluginModel;
  33. import org.flowplayer.model.DisplayProperties;
  34. import org.flowplayer.model.DisplayPropertiesImpl;
  35. import org.flowplayer.model.ErrorCode;
  36. import org.flowplayer.model.EventDispatcher;
  37. import org.flowplayer.model.Loadable;
  38. import org.flowplayer.model.Logo;
  39. import org.flowplayer.model.PlayButtonOverlay;
  40. import org.flowplayer.model.PlayerError;
  41. import org.flowplayer.model.PlayerEvent;
  42. import org.flowplayer.model.Playlist;
  43. import org.flowplayer.model.Plugin;
  44. import org.flowplayer.model.PluginError;
  45. import org.flowplayer.model.PluginEvent;
  46. import org.flowplayer.model.PluginModel;
  47. import org.flowplayer.model.ProviderModel;
  48. import org.flowplayer.model.State;
  49. import org.flowplayer.util.Arrange;
  50. import org.flowplayer.util.Log;
  51. import org.flowplayer.util.TextUtil;
  52. import org.flowplayer.util.URLUtil;
  53. import org.flowplayer.view.Panel;
  54. import org.flowplayer.view.PluginLoader;
  55. import org.flowplayer.view.Screen;
  56. import org.flowplayer.view.KeyboardHandler;
  57. import org.osflash.thunderbolt.Logger;
  58. import flash.display.DisplayObject;
  59. import flash.display.DisplayObjectContainer;
  60. import flash.display.Sprite;
  61. import flash.events.Event;
  62. import flash.events.MouseEvent;
  63. import flash.events.TimerEvent;
  64. import flash.net.URLRequest;
  65. import flash.net.navigateToURL;
  66. import flash.system.Capabilities;
  67. import flash.system.Security;
  68. import flash.text.TextField;
  69. import flash.text.TextFieldAutoSize;
  70. import flash.utils.Dictionary;
  71. import flash.utils.Timer;
  72. use namespace flow_internal;
  73. public class Launcher extends StyleableSprite implements ErrorHandler {
  74. private var _panel:Panel;
  75. private var _screen:Screen;
  76. private var _config:Config;
  77. private var _flowplayer:Flowplayer;
  78. private var _pluginRegistry:PluginRegistry;
  79. private var _animationEngine:AnimationEngine;
  80. private var _playButtonOverlay:PlayButtonOverlay;
  81. private var _controlsModel:DisplayPluginModel;
  82. private var _providers:Dictionary = new Dictionary();
  83. private var _canvasLogo:Sprite;
  84. private var _pluginLoader:PluginLoader;
  85. private var _error:TextField;
  86. private var _pluginsInitialized:Number = 0;
  87. private var _numLoadablePlugins:int = -1;
  88. private var _enteringFullscreen:Boolean;
  89. private var _copyrightNotice:TextField;
  90. private var _playlistLoader:ResourceLoader;
  91. private var _fullscreenManager:FullscreenManager;
  92. private var _screenArrangeCount:int = 0;
  93. private var _clickCount:int;
  94. private var _clickTimer:Timer = new Timer(200, 1);
  95. private var _clickEvent:MouseEvent;
  96. [Frame(factoryClass="org.flowplayer.view.Preloader")]
  97. public function Launcher() {
  98. addEventListener(Event.ADDED_TO_STAGE, function(e:Event):void {
  99. trace("Launcher added to stage");
  100. callAndHandleError(createFlashVarsConfig, PlayerError.INIT_FAILED);
  101. });
  102. super("#canvas", this);
  103. }
  104. private function initPhase1():void {
  105. if (_flowplayer) {
  106. log.debug("already initialized, returning");
  107. return;
  108. }
  109. Log.configure(_config.getLogConfiguration());
  110. trace("created log configuration, tracing enabled? " + Log.traceEnabled)
  111. initCustomClipEvents();
  112. if (_config.playerId) {
  113. Security.allowDomain(URLUtil.pageUrl);
  114. }
  115. loader = createNewLoader();
  116. rootStyle = _config.canvas.style;
  117. stage.addEventListener(Event.RESIZE, onStageResize);
  118. stage.addEventListener(Event.RESIZE, arrangeScreen);
  119. setSize(stage.stageWidth, stage.stageHeight);
  120. if (! VersionInfo.commercial) {
  121. log.debug("Adding logo to canvas");
  122. createLogoForCanvas();
  123. }
  124. log = new Log(this);
  125. EventDispatcher.playerId = _config.playerId;
  126. log.debug("security sandbox type: " + Security.sandboxType);
  127. log.info(VersionInfo.versionInfo());
  128. trace(VersionInfo.versionInfo());
  129. log.debug("creating Panel");
  130. createPanel();
  131. _pluginRegistry = new PluginRegistry(_panel);
  132. log.debug("Creating animation engine");
  133. createAnimationEngine(_pluginRegistry);
  134. log.debug("creating play button overlay");
  135. createPlayButtonOverlay();
  136. log.debug("creating Flowplayer API");
  137. createFlowplayer();
  138. // keyboard handler must be present for plugins.
  139. //
  140. loadPlaylistFeed();
  141. }
  142. private function initPhase2(event:Event = null):void {
  143. log.info("initPhase2");
  144. _flowplayer.keyboardHandler = new KeyboardHandler(stage, function():Boolean { return enteringFullscreen });
  145. loadPlugins();
  146. }
  147. private function initPhase3(event:Event = null):void {
  148. log.debug("initPhase3, all plugins loaded");
  149. createScreen();
  150. _config.getPlaylist().onBeforeBegin(function(event:ClipEvent):void { hideErrorMessage(); });
  151. if (_playButtonOverlay) {
  152. PlayButtonOverlayView(_playButtonOverlay.getDisplayObject()).playlist = _config.getPlaylist();
  153. }
  154. log.debug("creating PlayListController");
  155. _providers = _pluginLoader.providers;
  156. var playListController:PlayListController = createPlayListController();
  157. addPlayListListeners();
  158. createFullscreenManager(playListController.playlist);
  159. addScreenToPanel();
  160. if (!validateLicenseKey()) {
  161. createLogoForCanvas();
  162. resizeCanvasLogo();
  163. }
  164. log.debug("creating logo");
  165. createLogo();
  166. contextMenu = new ContextMenuBuilder(_config.playerId, _config.contextMenu).build();
  167. log.debug("initializing ExternalInterface");
  168. if (useExternalInterfade()) {
  169. _flowplayer.initExternalInterface();
  170. }
  171. log.debug("calling onLoad to plugins");
  172. _pluginRegistry.onLoad(_flowplayer);
  173. if (countPlugins() == 0) {
  174. log.debug("no loadable plugins, calling initPhase4");
  175. initPhase4();
  176. }
  177. }
  178. private function initPhase4(event:Event = null):void {
  179. log.info("initPhase4, all plugins initialized");
  180. log.debug("Adding visible plugins to panel");
  181. addPluginsToPanel(_pluginRegistry);
  182. log.debug("dispatching onLoad");
  183. if (useExternalInterfade()) {
  184. _flowplayer.dispatchEvent(PlayerEvent.load("player"));
  185. }
  186. log.debug("starting configured streams");
  187. startStreams();
  188. arrangeScreen();
  189. addListeners();
  190. // _controlsModel.onPluginEvent(function(event:PluginEvent):void {
  191. // log.debug("received plugin event " + event.id);
  192. // var model:DisplayPluginModel = event.target as DisplayPluginModel;
  193. // log.debug("controls y-pos now is " + model.getDisplayObject().y);
  194. // });
  195. //
  196. // _controlsModel.onBeforePluginEvent(function(event:PluginEvent):void {
  197. // log.debug("received before plugin event " + event.id);
  198. // var model:DisplayPluginModel = event.target as DisplayPluginModel;
  199. // log.debug("controls y-pos now is " + model.getDisplayObject().y);
  200. // event.preventDefault();
  201. // });
  202. // lookupSlowMotionPlugin(_flowplayer);
  203. }
  204. private function resizeCanvasLogo():void {
  205. _canvasLogo.alpha = 1;
  206. _canvasLogo.width = 150;
  207. _canvasLogo.scaleY = _canvasLogo.scaleX;
  208. arrangeCanvasLogo();
  209. }
  210. private function useExternalInterfade():Boolean {
  211. log.debug("useExternalInteface: " + (_config.playerId != null));
  212. return _config.playerId != null;
  213. }
  214. private function onStageResize(event:Event = null):void {
  215. setSize(stage.stageWidth, stage.stageHeight);
  216. arrangeCanvasLogo();
  217. }
  218. private function arrangeCanvasLogo():void {
  219. if (!_canvasLogo) return;
  220. _canvasLogo.x = 15;
  221. _canvasLogo.y = stage.stageHeight - (_controlsModel ? _controlsModel.dimensions.height.toPx(stage.stageHeight) + 10 : 10) - _canvasLogo.height - _copyrightNotice.height;
  222. _copyrightNotice.x = 12;
  223. _copyrightNotice.y = _canvasLogo.y + _canvasLogo.height;
  224. }
  225. private function loadPlugins():void {
  226. var plugins:Array = _config.getLoadables();
  227. log.debug("will load following plugins: ");
  228. logPluginInfo(plugins);
  229. _pluginLoader = new PluginLoader(URLUtil.playerBaseUrl(loaderInfo), _pluginRegistry, this, useExternalInterfade());
  230. _pluginLoader.addEventListener(Event.COMPLETE, pluginLoadListener);
  231. _flowplayer.pluginLoader = _pluginLoader;
  232. if (plugins.length == 0) {
  233. log.debug("configuration has no plugins");
  234. initPhase3();
  235. } else {
  236. // _builtInPlugins = _config.createLoadables(BuiltInConfig.config.plugins);
  237. // log.debug("following built-in plugins will be instantiated");
  238. // trace("builtIn plugins: ");
  239. // logPluginInfo(_builtInPlugins, true);
  240. _pluginLoader.load(plugins, onPluginLoad, onPluginLoadError);
  241. }
  242. }
  243. private function logPluginInfo(plugins:Array, doTrace:Boolean = false):void {
  244. for (var i:Number = 0; i < plugins.length; i++) {
  245. log.info("" + plugins[i]);
  246. if (doTrace) {
  247. trace("" + plugins[i]);
  248. }
  249. }
  250. }
  251. private function pluginLoadListener(event:Event = null):void {
  252. _pluginLoader.removeEventListener(Event.COMPLETE, pluginLoadListener);
  253. callAndHandleError(initPhase3, PlayerError.INIT_FAILED);
  254. }
  255. private function loadPlaylistFeed():void {
  256. var playlistFeed:String = _config.playlistFeed;
  257. if (! playlistFeed) {
  258. callAndHandleError(initPhase2, PlayerError.INIT_FAILED);
  259. return;
  260. }
  261. log.info("loading playlist from " + playlistFeed);
  262. _playlistLoader = _flowplayer.createLoader();
  263. _playlistLoader.addTextResourceUrl(playlistFeed);
  264. _playlistLoader.load(null,
  265. function(loader:ResourceLoader):void {
  266. log.info("received playlist feed");
  267. _config.playlistDocument = loader.getContent() as String;
  268. _config.getPlaylist().dispatchPlaylistReplace();
  269. callAndHandleError(initPhase2, PlayerError.INIT_FAILED);
  270. });
  271. }
  272. private function onPluginLoad(event:PluginEvent):void {
  273. var plugin:PluginModel = event.target as PluginModel;
  274. log.info("plugin " + plugin + " initialized");
  275. checkPluginsInitialized();
  276. }
  277. private function onPluginLoadError(event:PluginEvent):void {
  278. if (event.target is Loadable) {
  279. handleError(PlayerError.PLUGIN_LOAD_FAILED, "unable to load plugin '" + Loadable(event.target).name + "', url: '" + Loadable(event.target).url + "'");
  280. // throw new Error("unable to load plugin '" + Loadable(event.target).name + "', url: '" + Loadable(event.target).url + "'");
  281. } else {
  282. var plugin:PluginModel = event.target as PluginModel;
  283. _pluginRegistry.removePlugin(plugin);
  284. handleError(PlayerError.PLUGIN_LOAD_FAILED, "load/init error on " + plugin);
  285. }
  286. }
  287. private function checkPluginsInitialized():void {
  288. var numPlugins:int = countPlugins();
  289. if (++_pluginsInitialized == numPlugins) {
  290. log.info("all plugins initialized");
  291. callAndHandleError(initPhase4, PlayerError.INIT_FAILED);
  292. }
  293. log.info(_pluginsInitialized + " out of " + numPlugins + " plugins initialized");
  294. }
  295. private function countPlugins():int {
  296. var count:Number = 0;
  297. var loadables:Array = _config.getLoadables();
  298. for (var i:Number = 0; i < loadables.length; i++) {
  299. var plugin:PluginModel = Loadable(loadables[i]).plugin;
  300. if (! plugin) {
  301. handleError(PlayerError.PLUGIN_LOAD_FAILED, "Unable to load plugin, url " + Loadable(loadables[i]).url + ", name " + Loadable(loadables[i]).name);
  302. // throw new Error("Plugin " + loadables[i] + " not available");
  303. }
  304. else
  305. {
  306. var isNonAdHocPlugin:Boolean = plugin.pluginObject is Plugin;
  307. // var isNonAdHocPlugin:Boolean = (plugin is DisplayPluginModel && DisplayPluginModel(plugin).getDisplayObject() is Plugin) ||
  308. // plugin is ProviderModel && ProviderModel(plugin).pluginObject is Plugin;
  309. if (Loadable(loadables[i]).loadFailed) {
  310. log.debug("load failed for " + loadables[i]);
  311. count++;
  312. } else if (! plugin) {
  313. log.debug("this plugin is not loaded yet");
  314. count++;
  315. } else if (isNonAdHocPlugin) {
  316. log.debug("will wait for onLoad from plugin " + plugin);
  317. count++;
  318. } else {
  319. log.debug("will NOT wait for onLoad from plugin " + Loadable(loadables[i]).plugin);
  320. }
  321. }
  322. }
  323. // +1 comes from the playbuttonoverlay
  324. return count + (_playButtonOverlay ? 1 : 0);
  325. }
  326. private function validateLicenseKey():Boolean {
  327. try {
  328. return LicenseKey.validate(root.loaderInfo.url, _flowplayer.version, _config.licenseKey, useExternalInterfade());
  329. } catch (e:Error) {
  330. log.warn("License key not accepted, will show flowplayer logo");
  331. }
  332. return false;
  333. }
  334. private function createFullscreenManager(playlist:Playlist):void {
  335. _fullscreenManager = new FullscreenManager(stage, playlist, _panel, _pluginRegistry, _animationEngine);
  336. _flowplayer.fullscreenManager = _fullscreenManager;
  337. }
  338. public function showError(message:String):void {
  339. if (! _panel) return;
  340. if (! _config.showErrors) return;
  341. if (_error && _error.parent == this) {
  342. removeChild(_error);
  343. }
  344. _error = TextUtil.createTextField(false);
  345. _error.background = true;
  346. _error.backgroundColor = 0;
  347. _error.textColor = 0xffffff;
  348. _error.autoSize = TextFieldAutoSize.CENTER;
  349. _error.multiline = true;
  350. _error.wordWrap = true;
  351. _error.text = message;
  352. _error.selectable = true;
  353. _error.width = stage.stageWidth - 40;
  354. Arrange.center(_error, stage.stageWidth, stage.stageHeight);
  355. addChild(_error);
  356. createErrorMessageHideTimer();
  357. }
  358. private function createErrorMessageHideTimer():void {
  359. var errorHideTimer:Timer = new Timer(10000, 1);
  360. errorHideTimer.addEventListener(TimerEvent.TIMER_COMPLETE, hideErrorMessage);
  361. errorHideTimer.start();
  362. }
  363. private function hideErrorMessage(event:TimerEvent = null):void {
  364. if (_error && _error.parent == this) {
  365. if (_animationEngine) {
  366. _animationEngine.fadeOut(_error, 1000, function():void { removeChild(_error); });
  367. } else {
  368. removeChild(_error);
  369. }
  370. }
  371. }
  372. public function handleError(error:ErrorCode, info:Object = null, throwError:Boolean = true):void {
  373. if (_flowplayer) {
  374. _flowplayer.dispatchError(error, info);
  375. } else {
  376. // initialization is not complete, create a dispatches just to dispatch this error
  377. new PlayerEventDispatcher().dispatchError(error, info);
  378. }
  379. doHandleError(error.code + ": " + error.message + ( info ? ": " + info : ""), throwError);
  380. }
  381. private function doHandleError(message:String, throwError:Boolean = true):void {
  382. if (_config && _config.playerId) {
  383. Logger.error(message);
  384. }
  385. showError(message);
  386. if (throwError && Capabilities.isDebugger) {
  387. throw new Error(message);
  388. }
  389. }
  390. private function createAnimationEngine(pluginRegistry:PluginRegistry):void {
  391. _animationEngine = new AnimationEngine(_panel, pluginRegistry);
  392. }
  393. private function addPluginsToPanel(_pluginRegistry:PluginRegistry):void {
  394. for each (var pluginObj:Object in _pluginRegistry.plugins) {
  395. if (pluginObj is DisplayPluginModel) {
  396. var model:DisplayPluginModel = pluginObj as DisplayPluginModel;
  397. log.debug("adding plugin '"+ model.name +"' to panel: " + model.visible + ", plugin object is " + model.getDisplayObject());
  398. if (model.visible) {
  399. if (model.zIndex == -1) {
  400. model.zIndex = 100;
  401. }
  402. _panel.addView(model.getDisplayObject(), undefined, model);
  403. }
  404. if (model.name == "controls") {
  405. _controlsModel = model;
  406. }
  407. }
  408. }
  409. if (_controlsModel) {
  410. arrangeCanvasLogo();
  411. }
  412. }
  413. private function addScreenToPanel():void {
  414. // if controls visible and screen was not explicitly configured --> place screen on top of controls
  415. var screen:DisplayProperties = _pluginRegistry.getPlugin("screen") as DisplayProperties;
  416. screen.display = "none";
  417. screen.getDisplayObject().visible = false;
  418. _panel.addView(screen.getDisplayObject(), null, screen);
  419. }
  420. private function arrangeScreen(event:Event = null):void {
  421. log.debug("arrangeScreen(), already arranged " + _screenArrangeCount);
  422. if (_screenArrangeCount > 1) return;
  423. if (! _pluginRegistry) return;
  424. var screen:DisplayProperties = _pluginRegistry.getPlugin("screen") as DisplayProperties;
  425. if (! screen) return;
  426. if (_controlsModel && _controlsModel.visible) {
  427. if (isControlsAlwaysAutoHide() || (_controlsModel.position.bottom.px > 0)) {
  428. log.debug("controls is autoHide or it's in a non-default vertical position, configuring screen to take all available space");
  429. setScreenBottomAndHeight(screen, 100, 0);
  430. } else {
  431. var controlsHeight:Number = _controlsModel.getDisplayObject().height;
  432. var occupiedHeight:Number = screenTopOrBottomConfigured() ? getScreenTopOrBottomPx(screen) : controlsHeight;
  433. log.debug("occupied by controls or screen's configured bottom/top is " + occupiedHeight);
  434. var heightPct:Number = 0;
  435. if (screenTopOrBottomConfigured() && (screen.position.top.pct >= 0 || screen.position.bottom.pct >= 0)) {
  436. heightPct = 100 - Math.abs(50 - (screen.position.top.pct >= 0 ? screen.position.top.pct : screen.position.bottom.pct))*2;
  437. setScreenBottomAndHeight(screen, heightPct, controlsHeight);
  438. } else {
  439. heightPct = ((stage.stageHeight - occupiedHeight) / stage.stageHeight) * 100;
  440. setScreenBottomAndHeight(screen, heightPct, controlsHeight);
  441. }
  442. }
  443. }
  444. log.debug("arrangeScreen(): arranging screen to pos " + screen.position);
  445. screen.display = "block";
  446. screen.alpha = 1;
  447. screen.getDisplayObject().visible = true;
  448. _pluginRegistry.updateDisplayProperties(screen, true);
  449. _panel.update(screen.getDisplayObject(), screen);
  450. _panel.draw(screen.getDisplayObject());
  451. _screenArrangeCount++;
  452. }
  453. private function getScreenTopOrBottomPx(screen:DisplayProperties):Number {
  454. var screenConf:Object = _config.getObject("screen");
  455. if (screenConf.hasOwnProperty("top")) return screen.position.top.toPx(stage.stageHeight);
  456. if (screenConf.hasOwnProperty("bottom")) return screen.position.bottom.toPx(stage.stageHeight);
  457. return 0;
  458. }
  459. private function setScreenBottomAndHeight(screen:DisplayProperties, heightPct:Number, bottom:Number = 0):void {
  460. if (! screenTopOrBottomConfigured()) {
  461. log.debug("screen vertical pos not configured, setting bottom to value " + bottom);
  462. screen.bottom = bottom;
  463. } else {
  464. log.debug("using configured top/bottom for screen");
  465. }
  466. var heightConfigured:Boolean = _config.getObject("screen") && _config.getObject("screen").hasOwnProperty("height");
  467. if (! heightConfigured) {
  468. log.debug("screen height not configured, setting it to value " + heightPct + "%");
  469. screen.height = heightPct + "%";
  470. } else {
  471. log.debug("using configured height for screen");
  472. }
  473. }
  474. private function screenTopOrBottomConfigured():Boolean {
  475. var screen:Object = _config.getObject("screen");
  476. if (! screen) return false;
  477. if (screen.hasOwnProperty("top")) return true;
  478. if (screen.hasOwnProperty("bottom")) return true;
  479. return false;
  480. }
  481. private function isControlsAlwaysAutoHide():Boolean {
  482. if (!_controlsModel) return false;
  483. var controls:DisplayObject = _controlsModel.getDisplayObject();
  484. log.debug("controls.auotoHide " + controls["getAutoHide"]());
  485. return ! controls["getAutoHide"]()["fullscreenOnly"];
  486. }
  487. private function createFlowplayer():void {
  488. _flowplayer = new Flowplayer(stage, _pluginRegistry, _panel,
  489. _animationEngine, this, this, _config, URLUtil.playerBaseUrl(loaderInfo));
  490. _flowplayer.onBeforeFullscreen(onFullscreen);
  491. // _flowplayer.onFullscreenExit(onFullscreen);
  492. }
  493. private function onFullscreen(event:PlayerEvent):void {
  494. log.debug("entering fullscreen, disabling display clicks");
  495. _screenArrangeCount = 100;
  496. stage.removeEventListener(Event.RESIZE, arrangeScreen);
  497. _enteringFullscreen = true;
  498. var delay:Timer = new Timer(1000, 1);
  499. delay.addEventListener(TimerEvent.TIMER_COMPLETE, onTimerComplete);
  500. delay.start();
  501. }
  502. private function onTimerComplete(event:TimerEvent):void {
  503. log.debug("fullscreen wait delay complete, display clicks are enabled again");
  504. _enteringFullscreen = false;
  505. }
  506. private function createFlashVarsConfig():void {
  507. log.debug("createFlashVarsConfig()");
  508. if (! root.loaderInfo.parameters) {
  509. return;
  510. }
  511. var configStr:String = Preloader(root).injectedConfig || root.loaderInfo.parameters["config"];
  512. var configObj:Object = configStr && configStr.indexOf("{") == 0 ? ConfigParser.parse(configStr) : {};
  513. if (! configStr || (configStr && configStr.indexOf("{") == 0 && ! configObj.hasOwnProperty("url"))) {
  514. _config = ConfigParser.parseConfig(configObj, BuiltInConfig.config, loaderInfo.url, VersionInfo.controlsVersion, VersionInfo.audioVersion);
  515. callAndHandleError(initPhase1, PlayerError.INIT_FAILED);
  516. } else {
  517. ConfigParser.loadConfig(configObj.hasOwnProperty("url") ? String(configObj["url"]) : configStr, BuiltInConfig.config, function(config:Config):void {
  518. _config = config;
  519. callAndHandleError(initPhase1, PlayerError.INIT_FAILED);
  520. }, new ResourceLoaderImpl(null, this), loaderInfo.url, VersionInfo.controlsVersion, VersionInfo.audioVersion);
  521. }
  522. }
  523. private function createPlayListController():PlayListController {
  524. createHttpProviders();
  525. var playListController:PlayListController = new PlayListController(_config.getPlaylist(), _providers, _config, createNewLoader());
  526. playListController.playerEventDispatcher = _flowplayer;
  527. _flowplayer.playlistController = playListController;
  528. return playListController;
  529. }
  530. private function createHttpProviders():void {
  531. if (! _providers) {
  532. _providers = new Dictionary();
  533. }
  534. _providers["http"] = createProvider("http");
  535. _providers["httpInstream"] = createProvider("httpInstream");
  536. }
  537. private function createProvider(name:String):Object {
  538. log.debug("creating provider with name " + name);
  539. var httpProvider:ProviderModel = _config.createHttpProvider(name);
  540. _pluginRegistry.registerProvider(httpProvider);
  541. return httpProvider.pluginObject;
  542. }
  543. private function get hasHttpChildClip():Boolean {
  544. var children:Array = _config.getPlaylist().childClips;
  545. // log.debug("configuration has child clips", children);
  546. for (var i:int = 0; i < children.length; i++) {
  547. if (Clip(children[i]).provider == "httpInstream") {
  548. log.info("child clip with http provider found");
  549. return true;
  550. }
  551. }
  552. return false;
  553. }
  554. private function createScreen():void {
  555. _screen = new Screen(_config.getPlaylist(), _animationEngine, _playButtonOverlay, _pluginRegistry);
  556. var screenModel:DisplayProperties = _config.getScreenProperties();
  557. initView(_screen, screenModel, null, false);
  558. if (_playButtonOverlay) {
  559. PlayButtonOverlayView(_playButtonOverlay.getDisplayObject()).setScreen(_screen, hasClip && _config.useBufferingAnimation);
  560. }
  561. // addViewLiteners(_screen);
  562. }
  563. private function createPlayButtonOverlay():void {
  564. _playButtonOverlay = _config.getPlayButtonOverlay();
  565. if (! _playButtonOverlay) return;
  566. _playButtonOverlay.onLoad(onPluginLoad);
  567. _playButtonOverlay.onError(onPluginLoadError);
  568. var overlay:PlayButtonOverlayView = new PlayButtonOverlayView(! playButtonOverlayWidthDefined(), _playButtonOverlay, _pluginRegistry);
  569. initView(overlay, _playButtonOverlay, null, false);
  570. }
  571. private function playButtonOverlayWidthDefined():Boolean {
  572. if (! _config.getObject("play")) return false;
  573. return _config.getObject("play").hasOwnProperty("width");
  574. }
  575. private function get hasClip():Boolean {
  576. var firstClip:Clip = _config.getPlaylist().current;
  577. var hasClip:Boolean = ! firstClip.isNullClip && (firstClip.url || firstClip.provider != 'http');
  578. return hasClip;
  579. }
  580. private function createLogo():void {
  581. var logoView:LogoView = new LogoView(_panel, _flowplayer);
  582. var logo:Logo = _config.getLogo(logoView) || new Logo(logoView, "logo");
  583. // do not show it initially
  584. logo.visible = false;
  585. logoView.model = logo;
  586. initView(logoView, logo, logoView.draw, false);
  587. }
  588. private function initView(view:DisplayObject, props:DisplayProperties, resizeListener:Function = null, addToPanel:Boolean = true):void {
  589. if (props.name != "logo" || VersionInfo.commercial) {
  590. _pluginRegistry.registerDisplayPlugin(props, view);
  591. }
  592. if (addToPanel) {
  593. _panel.addView(view, resizeListener, props);
  594. }
  595. if (props is Callable) {
  596. ExternalInterfaceHelper.initializeInterface(props as Callable, view);
  597. }
  598. }
  599. private function addListeners():void {
  600. _clickTimer.addEventListener(TimerEvent.TIMER, onClickTimer);
  601. doubleClickEnabled = true;
  602. addEventListener(MouseEvent.DOUBLE_CLICK, onDoubleClick);
  603. _screen.addEventListener(MouseEvent.CLICK, onClickEvent);
  604. if (_playButtonOverlay) {
  605. _playButtonOverlay.getDisplayObject().addEventListener(MouseEvent.CLICK, onClickEvent);
  606. }
  607. addEventListener(MouseEvent.ROLL_OVER, onMouseOver);
  608. addEventListener(MouseEvent.ROLL_OUT, onMouseOut);
  609. // add some color so that the ROLL_OVER/ROLL_OUT events are always triggered
  610. graphics.beginFill(0, 0);
  611. graphics.drawRect(0, 0, stage.stageWidth, stage.stageHeight);
  612. graphics.endFill();
  613. }
  614. private function onMouseOut(event:MouseEvent):void {
  615. _flowplayer.dispatchEvent(PlayerEvent.mouseOut());
  616. }
  617. private function onMouseOver(event:MouseEvent):void {
  618. _flowplayer.dispatchEvent(PlayerEvent.mouseOver());
  619. }
  620. private function createPanel():void {
  621. _panel = new Panel();
  622. addChild(_panel);
  623. }
  624. private function startStreams():void {
  625. var canStart:Boolean = true;
  626. if (_flowplayer.state != State.WAITING) {
  627. log.debug("streams have been started in player.onLoad(), will not start streams here.");
  628. canStart = false;
  629. }
  630. if (! hasClip) {
  631. log.info("Configuration has no clips to play.");
  632. canStart = false;
  633. }
  634. var playButton:PlayButtonOverlayView = _playButtonOverlay ? PlayButtonOverlayView(_playButtonOverlay.getDisplayObject()) : null;
  635. if (canStart) {
  636. if (_flowplayer.currentClip.autoPlay) {
  637. log.debug("clip is autoPlay");
  638. _flowplayer.play();
  639. } else if (_flowplayer.currentClip.autoBuffering) {
  640. log.debug("clip is autoBuffering");
  641. _flowplayer.startBuffering();
  642. } else {
  643. if (playButton) {
  644. playButton.stopBuffering();
  645. playButton.showButton();
  646. }
  647. }
  648. } else {
  649. // cannot start playing here, stop buffering indicator, don't show the button
  650. if (playButton) {
  651. playButton.stopBuffering();
  652. }
  653. }
  654. }
  655. private function addPlayListListeners():void {
  656. var playlist:Playlist = _config.getPlaylist();
  657. playlist.onError(onClipError);
  658. }
  659. private function onClipError(event:ClipEvent):void {
  660. if (event.isDefaultPrevented()) return;
  661. doHandleError(event.error.code + ", " + event.error.message + ", " + event.info2 + ", clip: '" + Clip(event.target) + "'");
  662. }
  663. private function onClickTimer(event:TimerEvent):void {
  664. if (_clickCount == 1) {
  665. onSingleClick(_clickEvent);
  666. }
  667. _clickCount = 0;
  668. }
  669. private function onDoubleClick(event:MouseEvent = null):void {
  670. log.debug("onDoubleClick");
  671. _flowplayer.toggleFullscreen();
  672. }
  673. private function onSingleClick(event:MouseEvent):void {
  674. if (isParent(DisplayObject(event.target), _screen)) {
  675. log.debug("screen clicked");
  676. var clip:Clip = _flowplayer.playlist.current;
  677. if (clip.linkUrl) {
  678. log.debug("opening linked page");
  679. _flowplayer.pause();
  680. navigateToURL(new URLRequest(clip.linkUrl), clip.linkWindow);
  681. return;
  682. }
  683. _flowplayer.toggle();
  684. }
  685. }
  686. private function onClickEvent(event:MouseEvent):void {
  687. if (_enteringFullscreen) return;
  688. log.debug("onViewClicked, target " + event.target + ", current target " + event.currentTarget);
  689. event.stopPropagation();
  690. if (_playButtonOverlay && isParent(DisplayObject(event.target), _playButtonOverlay.getDisplayObject())) {
  691. _flowplayer.toggle();
  692. return;
  693. }
  694. if (_clickCount == 0) {
  695. _clickEvent = event;
  696. }
  697. if (++_clickCount == 2) {
  698. onDoubleClick(event);
  699. } else {
  700. _clickTimer.start();
  701. }
  702. }
  703. private function isParent(child:DisplayObject, parent:DisplayObject):Boolean {
  704. try {
  705. if (DisplayObject(child).parent == parent) return true;
  706. if (! (parent is DisplayObjectContainer)) return false;
  707. for (var i:Number = 0;i < DisplayObjectContainer(parent).numChildren; i++) {
  708. var curChild:DisplayObject = DisplayObjectContainer(parent).getChildAt(i);
  709. if (isParent(child, curChild)) {
  710. return true;
  711. }
  712. }
  713. } catch (e:SecurityError) {
  714. return true;
  715. }
  716. return false;
  717. }
  718. override protected function onRedraw():void {
  719. if (bgImageHolder && getChildIndex(bgImageHolder) > getChildIndex(_panel)) {
  720. swapChildren(bgImageHolder, _panel);
  721. }
  722. }
  723. private function createLogoForCanvas():void {
  724. if (_canvasLogo) return;
  725. _copyrightNotice = LogoUtil.createCopyrightNotice(8);
  726. addChild(_copyrightNotice);
  727. _canvasLogo = new CanvasLogo();
  728. _canvasLogo.width = 85;
  729. _canvasLogo.scaleY = _canvasLogo.scaleX;
  730. _canvasLogo.alpha = .4;
  731. _canvasLogo.addEventListener(MouseEvent.CLICK,
  732. function(event:MouseEvent):void { navigateToURL(new URLRequest("http://flowplayer.org"), "_self"); });
  733. _canvasLogo.buttonMode = true;
  734. log.debug("adding logo to display list");
  735. addChild(_canvasLogo);
  736. onStageResize();
  737. }
  738. private function createNewLoader():ResourceLoader {
  739. return new ResourceLoaderImpl(_config.playerId ? null : URLUtil.playerBaseUrl(loaderInfo), this);
  740. }
  741. private function initCustomClipEvents():void {
  742. createCustomClipEvents(_config.connectionCallbacks);
  743. createCustomClipEvents(_config.streamCallbacks);
  744. }
  745. private function createCustomClipEvents(callbacks:Array):void {
  746. if (! callbacks) return;
  747. for (var i:int = 0; i < callbacks.length; i++) {
  748. log.debug("creating custom event type " + callbacks[i]);
  749. new ClipEventType(callbacks[i], true);
  750. }
  751. }
  752. //
  753. // private function get stageWidth():Number {
  754. // return Math.max(stage.stageWidth, Preloader.stageWidth);
  755. // }
  756. //
  757. // private function get stageHeight():Number {
  758. // return Math.max(stage.stageHeight, Preloader.stageHeight);
  759. // }
  760. private function callAndHandleError(func:Function, error:PlayerError):void {
  761. try {
  762. func();
  763. } catch (e:Error) {
  764. handleError(error, e, false);
  765. throw e;
  766. }
  767. }
  768. internal function get enteringFullscreen():Boolean {
  769. return _enteringFullscreen;
  770. }
  771. }
  772. }