PageRenderTime 270ms CodeModel.GetById 20ms RepoModel.GetById 1ms app.codeStats 0ms

/flowplayer/tags/flow_3_0_0/src/actionscript/org/flowplayer/view/Launcher.as

http://flowplayer-core.googlecode.com/
ActionScript | 529 lines | 435 code | 73 blank | 21 comment | 81 complexity | bda81054583af210079437b2b8cb2b3d MD5 | raw file
Possible License(s): GPL-3.0, AGPL-1.0
  1. /*
  2. * Copyright 2008 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.ConfigLoader;
  22. import org.flowplayer.config.ExternalInterfaceHelper;
  23. import org.flowplayer.config.VersionInfo;
  24. import org.flowplayer.controller.NetStreamControllingStreamProvider;
  25. import org.flowplayer.controller.PlayListController;
  26. import org.flowplayer.controller.ResourceLoader;
  27. import org.flowplayer.controller.ResourceLoaderImpl;
  28. import org.flowplayer.flow_internal;
  29. import org.flowplayer.model.Callable;
  30. import org.flowplayer.model.Clip;
  31. import org.flowplayer.model.ClipEvent;
  32. import org.flowplayer.model.DisplayPluginModel;
  33. import org.flowplayer.model.DisplayProperties;
  34. import org.flowplayer.model.DisplayPropertiesImpl;
  35. import org.flowplayer.model.EventDispatcher;
  36. import org.flowplayer.model.Logo;
  37. import org.flowplayer.model.PlayButtonOverlay;
  38. import org.flowplayer.model.PlayerEvent;
  39. import org.flowplayer.model.Playlist;
  40. import org.flowplayer.model.State;
  41. import org.flowplayer.util.Arrange;
  42. import org.flowplayer.util.Log;
  43. import org.flowplayer.util.TextUtil;
  44. import org.flowplayer.util.URLUtil;
  45. import org.flowplayer.view.Panel;
  46. import org.flowplayer.view.PlayButtonOverlayView;
  47. import org.flowplayer.view.Screen;
  48. import org.osflash.thunderbolt.Logger;
  49. import flash.display.DisplayObject;
  50. import flash.display.DisplayObjectContainer;
  51. import flash.display.Sprite;
  52. import flash.events.Event;
  53. import flash.events.KeyboardEvent;
  54. import flash.events.MouseEvent;
  55. import flash.net.URLRequest;
  56. import flash.net.navigateToURL;
  57. import flash.system.Security;
  58. import flash.text.TextField;
  59. import flash.text.TextFieldAutoSize;
  60. import flash.ui.Keyboard;
  61. import flash.utils.Dictionary;
  62. use namespace flow_internal;
  63. public class Launcher extends StyleableSprite implements ErrorHandler {
  64. private var _panel:Panel;
  65. private var _screen:Screen;
  66. private var _config:Config;
  67. private var _flowplayer:Flowplayer;
  68. private var _pluginRegistry:PluginRegistry;
  69. private var _animationEngine:AnimationEngine;
  70. private var _playButtonOverlay:PlayButtonOverlay;
  71. private var _controlsModel:DisplayPluginModel; private var _providers:Dictionary = new Dictionary();
  72. private var _fullscreenManager:FullscreenManager;
  73. private var _canvasLogo:Sprite;
  74. private var _pluginLoader:PluginLoader;
  75. [Frame(factoryClass="org.flowplayer.view.Preloader")]
  76. public function Launcher() {
  77. super("#canvas", this);
  78. addEventListener(Event.ADDED_TO_STAGE, initPhase1);
  79. }
  80. private function initPhase1(event:Event):void {
  81. try {
  82. createFlashVarsConfig();
  83. Log.configure(_config.getLogConfiguration());
  84. if (_config.playerId) {
  85. Security.allowDomain(URLUtil.pageUrl);
  86. }
  87. loader = createNewLoader();
  88. rootStyle = _config.canvasStyle;
  89. stage.addEventListener(Event.RESIZE, onStageResize);
  90. setSize(stage.stageWidth, stage.stageHeight);
  91. if (! VersionInfo.commercial) {
  92. log.debug("Adding logo to canvas");
  93. createLogoForCanvas();
  94. }
  95. log = new Log(this);
  96. EventDispatcher.playerId = _config.playerId;
  97. log.debug("security sandbox type: " + Security.sandboxType);
  98. log.info(VersionInfo.versionInfo());
  99. log.debug("creating Panel");
  100. createPanel();
  101. _pluginRegistry = new PluginRegistry(_panel);
  102. log.debug("Creating animation engine");
  103. createAnimationEngine(_pluginRegistry);
  104. log.debug("creating play button overlay");
  105. createPlayButtonOverlay();
  106. log.debug("creating screen");
  107. createScreen();
  108. loadPluginsIfConfigured();
  109. } catch (e:Error) {
  110. handleError(e);
  111. }
  112. }
  113. private function initPhase2(pluginsLoadedEvent:Event = null):void {
  114. try {
  115. _pluginLoader.removeEventListener(Event.COMPLETE, this.initPhase2);
  116. log.debug("creating PlayListController");
  117. _providers = _pluginLoader.providers;
  118. var playListController:PlayListController = createPlayListController();
  119. addPlayListListeners();
  120. createFullscreenManager(playListController.playlist);
  121. log.debug("creating Flowplayer API");
  122. createFlowplayer(playListController);
  123. addScreenToPanel();
  124. if (!validateLicenseKey()) {
  125. createLogoForCanvas();
  126. resizeCanvasLogo();
  127. }
  128. log.debug("creating logo");
  129. createLogo();
  130. contextMenu = new ContextMenuBuilder(_config.playerId, _config.contextMenu).build();
  131. log.debug("initializing ExternalInterface");
  132. if (useExternalInterfade()) {
  133. _flowplayer.initExternalInterface();
  134. }
  135. log.debug("calling onLoad to plugins");
  136. _pluginRegistry.onLoad(_flowplayer);
  137. if (pluginsLoadedEvent) {
  138. log.debug("Adding visible plugins to panel");
  139. addPluginsToPanel(_pluginRegistry);
  140. }
  141. log.debug("arranging screen");
  142. arrangeScreen();
  143. log.debug("dispatching onLoad");
  144. if (useExternalInterfade()) {
  145. _flowplayer.dispatchEvent(PlayerEvent.load());
  146. }
  147. if (! _playButtonOverlay) {
  148. initPhase3();
  149. }
  150. } catch (e:Error) {
  151. handleError(e);
  152. }
  153. }
  154. private function initPhase3(event:Event = null):void {
  155. log.debug("starting configured streams");
  156. startStreams();
  157. stage.addEventListener(KeyboardEvent.KEY_DOWN, onKeyDown);
  158. addViewClickLiteners();
  159. }
  160. private function resizeCanvasLogo():void {
  161. _canvasLogo.alpha = 1;
  162. _canvasLogo.width = 150;
  163. _canvasLogo.scaleY = _canvasLogo.scaleX;
  164. arrangeCanvasLogo();
  165. }
  166. private function useExternalInterfade():Boolean {
  167. log.debug("useExternalInteface: " + (_config.playerId != null));
  168. return _config.playerId != null;
  169. }
  170. private function onStageResize(event:Event = null):void {
  171. setSize(stage.stageWidth, stage.stageHeight);
  172. arrangeCanvasLogo();
  173. }
  174. private function arrangeCanvasLogo():void {
  175. if (!_canvasLogo) return;
  176. _canvasLogo.x = 15;
  177. _canvasLogo.y = stage.stageHeight - (_controlsModel ? _controlsModel.dimensions.height.toPx(stage.stageHeight) + 10 : 10) - _canvasLogo.height;
  178. }
  179. private function loadPluginsIfConfigured():void {
  180. var plugins:Array = _config.getLoadables();
  181. _pluginLoader = new PluginLoader(URLUtil.playerBaseUrl(loaderInfo), _pluginRegistry, this, useExternalInterfade());
  182. _pluginLoader.addEventListener(Event.COMPLETE, initPhase2);
  183. if (plugins.length == 0) {
  184. log.debug("configuration has no plugins");
  185. initPhase2();
  186. } else {
  187. log.debug("loading plugins and providers");
  188. loadPluginsAndProviders(plugins);
  189. }
  190. }
  191. private function playerSwfName():String {
  192. var url:String = loaderInfo.url;
  193. var lastSlash:Number = url.lastIndexOf("/");
  194. return url.substring(lastSlash + 1, url.indexOf(".swf") + 4);
  195. }
  196. private function validateLicenseKey():Boolean {
  197. try {
  198. return LicenseKey.validate(useExternalInterfade() ? null: root.loaderInfo.url, _flowplayer.version, _config.licenseKey);
  199. } catch (e:Error) {
  200. log.warn("License key not accepted, will show flowplayer logo");
  201. }
  202. return false;
  203. }
  204. private function createFullscreenManager(playlist:Playlist):void {
  205. _fullscreenManager = new FullscreenManager(stage, playlist, _panel, _pluginRegistry, _animationEngine);
  206. }
  207. public function showError(message:String):void {
  208. if (! _panel) return;
  209. if (! _config.showErrors) return;
  210. var error:TextField = TextUtil.createTextField(false);
  211. error.background = true;
  212. error.backgroundColor = 0;
  213. error.textColor = 0xffffff;
  214. error.autoSize = TextFieldAutoSize.CENTER;
  215. error.multiline = true;
  216. error.wordWrap = true;
  217. error.text = message;
  218. error.selectable = true;
  219. error.width = stage.stageWidth - 40;
  220. Arrange.center(error, stage.stageWidth, stage.stageHeight);
  221. addChild(error);
  222. }
  223. public function handleError(e:Error, message:String = null):void {
  224. if (_config && _config.playerId) {
  225. Logger.error(message + ": " + e.message);
  226. }
  227. showError((message == null ? "" : message + ": ") + e.message);
  228. if (_flowplayer) {
  229. _flowplayer.stop();
  230. }
  231. throw e;
  232. }
  233. private function createAnimationEngine(pluginRegistry:PluginRegistry):void {
  234. _animationEngine = new AnimationEngine(_panel, pluginRegistry);
  235. }
  236. private function loadPluginsAndProviders(plugins:Array):void {
  237. _pluginLoader.load(plugins);
  238. }
  239. private function addPluginsToPanel(_pluginRegistry:PluginRegistry):void {
  240. for each (var pluginObj:Object in _pluginRegistry.plugins) {
  241. if (pluginObj is DisplayPluginModel) {
  242. var model:DisplayPluginModel = pluginObj as DisplayPluginModel;
  243. log.debug("adding plugin '"+ model.name +"' to panel: " + model.visible + ", plugin object is " + model.getDisplayObject());
  244. if (model.visible) {
  245. if (model.zIndex == -1) {
  246. model.zIndex = _playButtonOverlay ? _playButtonOverlay.zIndex : 100;
  247. }
  248. _panel.addView(model.getDisplayObject(), undefined, model);
  249. }
  250. if (model.name == "controls") {
  251. _controlsModel = model;
  252. }
  253. }
  254. }
  255. if (_controlsModel) {
  256. arrangeCanvasLogo();
  257. }
  258. }
  259. private function addScreenToPanel():void {
  260. // if controls visible and screen was not explicitly configured --> place screen on top of controls
  261. var screen:DisplayProperties = _pluginRegistry.getPlugin("screen") as DisplayProperties;
  262. screen.display = "none";
  263. _panel.addView(screen.getDisplayObject(), null, screen);
  264. }
  265. private function arrangeScreen():void {
  266. var screen:DisplayProperties = _pluginRegistry.getPlugin("screen") as DisplayProperties;
  267. if (_controlsModel && _controlsModel.visible && ! screenTopOrBottomConfigured()) {
  268. var heightConfigured:Boolean = _config.getObject("screen") && _config.getObject("screen").hasOwnProperty("height");
  269. if (isControlsAlwaysAutoHide() || (_controlsModel.position.bottom.px > 0)) {
  270. screen.bottom = 0;
  271. if (! heightConfigured) {
  272. screen.height = "100%";
  273. }
  274. } else {
  275. var controlsHeight:Number = _controlsModel.getDisplayObject().height;
  276. screen.bottom = controlsHeight;
  277. if (! heightConfigured) {
  278. screen.height = ((stage.stageHeight - controlsHeight) / stage.stageHeight) * 100 + "%";
  279. }
  280. }
  281. }
  282. log.debug("arranging screen to pos " + screen.position);
  283. screen.display = "block";
  284. _pluginRegistry.updateDisplayProperties(screen);
  285. _panel.update(screen.getDisplayObject(), screen);
  286. _panel.draw(screen.getDisplayObject());
  287. }
  288. private function screenTopOrBottomConfigured():Boolean {
  289. var screen:Object = _config.getObject("screen");
  290. if (! screen) return false;
  291. if (screen.hasOwnProperty("top")) return true;
  292. if (screen.hasOwnProperty("bottom")) return true;
  293. return false;
  294. }
  295. private function isControlsAlwaysAutoHide():Boolean {
  296. if (!_controlsModel) return false;
  297. if (!_controlsModel.config) return false;
  298. log.debug("controlsModel.config.auotoHide == always", (_controlsModel.config.autoHide == 'always'));
  299. return _controlsModel.config.autoHide == 'always';
  300. }
  301. private function createFlowplayer(playListController:PlayListController):void {
  302. _flowplayer = new Flowplayer(stage, playListController, _pluginRegistry, _panel,
  303. _animationEngine, this, this, _config, _fullscreenManager, _pluginLoader, URLUtil.playerBaseUrl(loaderInfo));
  304. playListController.playerEventDispatcher = _flowplayer;
  305. }
  306. private function createFlashVarsConfig():void {
  307. for (var prop:String in stage.loaderInfo.parameters) {
  308. log.debug(prop + ": " + (stage.loaderInfo.parameters[prop]));
  309. }
  310. if (! stage.loaderInfo.parameters) {
  311. return;
  312. }
  313. _config = ConfigLoader.flow_internal::parseConfig(stage.loaderInfo.parameters["config"], playerSwfName(), VersionInfo.controlsVersion);
  314. }
  315. private function createPlayListController():PlayListController {
  316. if (! _providers) {
  317. _providers = new Dictionary();
  318. }
  319. _providers["http"] = new NetStreamControllingStreamProvider();
  320. return new PlayListController(_config.getPlaylist(), _providers, _config, createNewLoader());
  321. }
  322. private function createScreen():void {
  323. _screen = new Screen(_config.getPlaylist(), _animationEngine, _playButtonOverlay);
  324. var screenModel:DisplayProperties = _config.getScreenProperties();
  325. initView(_screen, screenModel, null, false);
  326. if (_playButtonOverlay) {
  327. PlayButtonOverlayView(_playButtonOverlay.getDisplayObject()).setScreen(_screen, hasClip);
  328. }
  329. // addViewLiteners(_screen);
  330. }
  331. private function createPlayButtonOverlay():void {
  332. _playButtonOverlay = _config.getPlayButtonOverlay();
  333. if (_playButtonOverlay == null) {
  334. return;
  335. }
  336. log.debug("playlist has clips? " + hasClip);
  337. var overlay:PlayButtonOverlayView = new PlayButtonOverlayView(! playButtonOverlayWidthDefined(), _playButtonOverlay, _config.getPlaylist(), true);
  338. overlay.addEventListener(Event.COMPLETE, initPhase3);
  339. initView(overlay, _playButtonOverlay, null, false);
  340. }
  341. private function playButtonOverlayWidthDefined():Boolean {
  342. if (! _config.getObject("play")) return false;
  343. return _config.getObject("play").hasOwnProperty("width");
  344. }
  345. private function get hasClip():Boolean {
  346. var firstClip:Clip = _config.getPlaylist().current;
  347. var hasClip:Boolean = ! firstClip.isNullClip && (firstClip.url || firstClip.provider != 'http');
  348. return hasClip;
  349. }
  350. private function createLogo():void {
  351. var logo:Logo = _config.getLogo() || new Logo();
  352. var logoView:LogoView = new LogoView(_panel, logo, _flowplayer);
  353. initView(logoView, logo, logoView.draw, false);
  354. }
  355. private function initView(view:DisplayObject, props:DisplayProperties, resizeListener:Function = null, addToPanel:Boolean = true):void {
  356. if (props.name != "logo" || VersionInfo.commercial) {
  357. _pluginRegistry.registerDisplayPlugin(props, view);
  358. }
  359. if (addToPanel) {
  360. _panel.addView(view, resizeListener, props);
  361. }
  362. if (props is Callable) {
  363. ExternalInterfaceHelper.initializeInterface(props as Callable, view);
  364. }
  365. }
  366. private function addViewClickLiteners():void {
  367. _screen.addEventListener(MouseEvent.CLICK, onViewClicked);
  368. if (_playButtonOverlay) {
  369. _playButtonOverlay.getDisplayObject().addEventListener(MouseEvent.CLICK, onViewClicked);
  370. }
  371. }
  372. private function createPanel():void {
  373. _panel = new Panel();
  374. addChild(_panel);
  375. }
  376. private function startStreams():void {
  377. var canStart:Boolean = true;
  378. if (_flowplayer.state != State.WAITING) {
  379. log.debug("streams have been started in player.onLoad(), will not start streams here.");
  380. canStart = false;
  381. }
  382. if (! hasClip) {
  383. log.info("Configuration has no clips to play.");
  384. canStart = false;
  385. }
  386. var playButton:PlayButtonOverlayView = _playButtonOverlay ? PlayButtonOverlayView(_playButtonOverlay.getDisplayObject()) : null;
  387. if (canStart) {
  388. if (_flowplayer.currentClip.autoPlay) {
  389. log.debug("clip is autoPlay");
  390. _flowplayer.play();
  391. } else if (_flowplayer.currentClip.autoBuffering) {
  392. log.debug("clip is autoBuffering");
  393. _flowplayer.startBuffering();
  394. } else {
  395. if (playButton) {
  396. playButton.stopBuffering();
  397. playButton.showButton();
  398. }
  399. }
  400. } else {
  401. // cannot start playing here, stop buffering indicator, don't show the button
  402. if (playButton) {
  403. playButton.stopBuffering();
  404. }
  405. }
  406. }
  407. private function addPlayListListeners():void {
  408. var playlist:Playlist = _config.getPlaylist();
  409. playlist.onError(onError);
  410. }
  411. private function onError(event:ClipEvent):void {
  412. handleError(new Error(event.info + ", clip: '" + Clip(event.target).completeUrl + "'"));
  413. }
  414. private function onViewClicked(event:MouseEvent):void {
  415. log.debug("onViewClicked, target " + event.target + ", current target " + event.currentTarget);
  416. if (event.currentTarget != _screen) return;
  417. var clip:Clip = _flowplayer.playlist.current;
  418. if (clip.linkUrl) {
  419. _flowplayer.pause();
  420. navigateToURL(new URLRequest(clip.linkUrl), clip.linkWindow);
  421. } else {
  422. _flowplayer.toggle();
  423. }
  424. }
  425. private function onKeyDown(event:KeyboardEvent):void {
  426. log.debug("keydown");
  427. if (_flowplayer.dispatchBeforeEvent(PlayerEvent.keyPress(event.keyCode))) {
  428. _flowplayer.dispatchEvent(PlayerEvent.keyPress(event.keyCode));
  429. if (event.keyCode == Keyboard.SPACE) {
  430. _flowplayer.toggle();
  431. }
  432. }
  433. }
  434. override protected function onRedraw():void {
  435. if (bgImageHolder && getChildIndex(bgImageHolder) > getChildIndex(_panel)) {
  436. swapChildren(bgImageHolder, _panel);
  437. }
  438. }
  439. private function createLogoForCanvas():void {
  440. if (_canvasLogo) return;
  441. _canvasLogo = new CanvasLogo();
  442. _canvasLogo.width = 85;
  443. _canvasLogo.scaleY = _canvasLogo.scaleX;
  444. _canvasLogo.alpha = .4;
  445. _canvasLogo.addEventListener(MouseEvent.CLICK,
  446. function(event:MouseEvent):void { navigateToURL(new URLRequest("http://flowplayer.org"), "_self"); });
  447. _canvasLogo.buttonMode = true;
  448. log.debug("adding logo to display list");
  449. addChild(_canvasLogo);
  450. onStageResize();
  451. }
  452. private function createNewLoader():ResourceLoader {
  453. return new ResourceLoaderImpl(_config.playerId ? null : URLUtil.playerBaseUrl(loaderInfo), this);
  454. }
  455. }
  456. }