| 1 | package com.jeroenwijering.plugins { |
|---|
| 2 | |
|---|
| 3 | |
|---|
| 4 | import com.jeroenwijering.events.*; |
|---|
| 5 | import com.jeroenwijering.utils.Logger; |
|---|
| 6 | |
|---|
| 7 | import flash.display.*; |
|---|
| 8 | import flash.events.*; |
|---|
| 9 | import flash.net.*; |
|---|
| 10 | import flash.utils.setTimeout; |
|---|
| 11 | |
|---|
| 12 | |
|---|
| 13 | /** |
|---|
| 14 | * This plugin automatically polls an RTMP stream for availability every XX seconds. |
|---|
| 15 | * If the stream is available, it will kick in. |
|---|
| 16 | * It allows users to wait for a live event without having to refresh their page. |
|---|
| 17 | **/ |
|---|
| 18 | public class Livestream extends MovieClip implements PluginInterface { |
|---|
| 19 | |
|---|
| 20 | |
|---|
| 21 | /** List with configuration settings. **/ |
|---|
| 22 | public var config:Object = { |
|---|
| 23 | file:undefined, |
|---|
| 24 | image:undefined, |
|---|
| 25 | interval:15, |
|---|
| 26 | message:'Checking for livestream...', |
|---|
| 27 | streamer:undefined, |
|---|
| 28 | tags:undefined |
|---|
| 29 | }; |
|---|
| 30 | /** Reference to the graphics. **/ |
|---|
| 31 | public var clip:MovieClip; |
|---|
| 32 | /** Reference to the view. **/ |
|---|
| 33 | private var view:AbstractView; |
|---|
| 34 | /** Netconnection instance to check availability. **/ |
|---|
| 35 | private var connection:NetConnection; |
|---|
| 36 | /** Netstream instance to check availability. **/ |
|---|
| 37 | private var stream:NetStream; |
|---|
| 38 | /** The number times the plugin tried to connect. **/ |
|---|
| 39 | private var count:Number = 0; |
|---|
| 40 | |
|---|
| 41 | |
|---|
| 42 | /** Constructor. **/ |
|---|
| 43 | public function Livestream():void { |
|---|
| 44 | clip = this; |
|---|
| 45 | connection = new NetConnection(); |
|---|
| 46 | }; |
|---|
| 47 | |
|---|
| 48 | |
|---|
| 49 | /** Try connecting to the livestream. **/ |
|---|
| 50 | private function checkStream():void { |
|---|
| 51 | count++; |
|---|
| 52 | connection.addEventListener(NetStatusEvent.NET_STATUS,statusHandler); |
|---|
| 53 | connection.connect(config['streamer']); |
|---|
| 54 | clip.visible = true; |
|---|
| 55 | setTimeout(hideIcon,2000); |
|---|
| 56 | Logger.log('checking for stream; attempt: '+count,'livestream'); |
|---|
| 57 | }; |
|---|
| 58 | |
|---|
| 59 | |
|---|
| 60 | /** Hide the icon again after a check. **/ |
|---|
| 61 | private function hideIcon():void { |
|---|
| 62 | clip.visible = false; |
|---|
| 63 | } |
|---|
| 64 | |
|---|
| 65 | |
|---|
| 66 | /** |
|---|
| 67 | * Start the plugin. |
|---|
| 68 | * |
|---|
| 69 | * @param vie A reference to the View of the player; the API entrypoint. |
|---|
| 70 | **/ |
|---|
| 71 | public function initializePlugin(vie:AbstractView):void { |
|---|
| 72 | view = vie; |
|---|
| 73 | clip.visible = false; |
|---|
| 74 | if(config['file'] && config['streamer'] && |
|---|
| 75 | (config['tags'] == undefined || config['tags'] == view.config['tags'])) { |
|---|
| 76 | view.config['icons'] = false; |
|---|
| 77 | view.config['repeat'] = 'always'; |
|---|
| 78 | setTimeout(checkStream,2000); |
|---|
| 79 | view.addControllerListener(ControllerEvent.RESIZE,resizeHandler); |
|---|
| 80 | clip.icon.txt.text = config['message']; |
|---|
| 81 | } |
|---|
| 82 | }; |
|---|
| 83 | |
|---|
| 84 | |
|---|
| 85 | /** The livestream is found. Now switch to it. **/ |
|---|
| 86 | private function loadStream():void { |
|---|
| 87 | view.config['autostart'] = true; |
|---|
| 88 | view.config['icons'] = true; |
|---|
| 89 | view.config['repeat'] = 'none'; |
|---|
| 90 | var obj:Object = { |
|---|
| 91 | duration:0, |
|---|
| 92 | file:config['file'], |
|---|
| 93 | image:config['image'], |
|---|
| 94 | streamer:config['streamer'], |
|---|
| 95 | type:'rtmp' |
|---|
| 96 | } |
|---|
| 97 | view.sendEvent('LOAD',obj); |
|---|
| 98 | }; |
|---|
| 99 | |
|---|
| 100 | |
|---|
| 101 | /** Reposition the icon on resize. **/ |
|---|
| 102 | private function resizeHandler(evt:ControllerEvent):void { |
|---|
| 103 | clip.icon.x = config['x'] + config['width']/2; |
|---|
| 104 | clip.icon.y = config['y'] + config['height']/2; |
|---|
| 105 | }; |
|---|
| 106 | |
|---|
| 107 | |
|---|
| 108 | /** Receive NetStream status updates. **/ |
|---|
| 109 | private function statusHandler(evt:NetStatusEvent):void { |
|---|
| 110 | switch(evt.info.code) { |
|---|
| 111 | case 'NetConnection.Connect.Success': |
|---|
| 112 | stream = new NetStream(connection); |
|---|
| 113 | stream.addEventListener(NetStatusEvent.NET_STATUS,statusHandler); |
|---|
| 114 | stream.play(config['file']); |
|---|
| 115 | Logger.log('connected to server '+config['streamer'],'livestream'); |
|---|
| 116 | break; |
|---|
| 117 | case 'NetStream.Play.Start': |
|---|
| 118 | stream.removeEventListener(NetStatusEvent.NET_STATUS,statusHandler); |
|---|
| 119 | connection.removeEventListener(NetStatusEvent.NET_STATUS,statusHandler); |
|---|
| 120 | stream.close(); |
|---|
| 121 | connection.close(); |
|---|
| 122 | setTimeout(loadStream,2000); |
|---|
| 123 | Logger.log('found stream '+config['file'],'livestream'); |
|---|
| 124 | break; |
|---|
| 125 | case 'NetStream.Play.StreamNotFound': |
|---|
| 126 | case 'NetConnection.Connect.Failed': |
|---|
| 127 | stream.removeEventListener(NetStatusEvent.NET_STATUS,statusHandler); |
|---|
| 128 | connection.removeEventListener(NetStatusEvent.NET_STATUS,statusHandler); |
|---|
| 129 | setTimeout(checkStream,config['interval']*1000); |
|---|
| 130 | Logger.log('no livestream yet: '+evt.info.code,'livestream'); |
|---|
| 131 | break; |
|---|
| 132 | } |
|---|
| 133 | }; |
|---|
| 134 | |
|---|
| 135 | |
|---|
| 136 | |
|---|
| 137 | }; |
|---|
| 138 | |
|---|
| 139 | |
|---|
| 140 | } |
|---|