Changeset 135
- Timestamp:
- 01/16/09 07:00:07 (4 years ago)
- Files:
-
- 3 added
- 45 edited
- 1 moved
-
skins/overlay/overlay.fla (modified) (previous)
-
skins/overlay/overlay.swf (modified) (previous)
-
trunk/as3/accessibility.fla (modified) (previous)
-
trunk/as3/accessibility.swf (modified) (previous)
-
trunk/as3/com/anttikupila/revolt/drawers/Line.as (modified) (1 diff)
-
trunk/as3/com/anttikupila/revolt/drawers/SimpleLine.as (added)
-
trunk/as3/com/anttikupila/revolt/presets/LineNoFourier.as (modified) (1 diff)
-
trunk/as3/com/jeroenwijering/models/BasicModel.as (moved) (moved from trunk/as3/com/jeroenwijering/models/ModelInterface.as) (1 diff)
-
trunk/as3/com/jeroenwijering/models/CameraModel.as (modified) (4 diffs)
-
trunk/as3/com/jeroenwijering/models/HTTPModel.as (modified) (5 diffs)
-
trunk/as3/com/jeroenwijering/models/ImageModel.as (modified) (6 diffs)
-
trunk/as3/com/jeroenwijering/models/LighttpdModel.as (added)
-
trunk/as3/com/jeroenwijering/models/NginxModel.as (added)
-
trunk/as3/com/jeroenwijering/models/RTMPModel.as (modified) (7 diffs)
-
trunk/as3/com/jeroenwijering/models/SoundModel.as (modified) (9 diffs)
-
trunk/as3/com/jeroenwijering/models/VideoModel.as (modified) (5 diffs)
-
trunk/as3/com/jeroenwijering/models/YoutubeModel.as (modified) (14 diffs)
-
trunk/as3/com/jeroenwijering/parsers/ATOMParser.as (modified) (1 diff)
-
trunk/as3/com/jeroenwijering/parsers/MediaParser.as (modified) (1 diff)
-
trunk/as3/com/jeroenwijering/parsers/ObjectParser.as (modified) (2 diffs)
-
trunk/as3/com/jeroenwijering/parsers/RSSParser.as (modified) (1 diff)
-
trunk/as3/com/jeroenwijering/parsers/SMILParser.as (modified) (1 diff)
-
trunk/as3/com/jeroenwijering/player/Controller.as (modified) (9 diffs)
-
trunk/as3/com/jeroenwijering/player/Model.as (modified) (14 diffs)
-
trunk/as3/com/jeroenwijering/player/Player.as (modified) (3 diffs)
-
trunk/as3/com/jeroenwijering/player/SPLoader.as (modified) (3 diffs)
-
trunk/as3/com/jeroenwijering/player/View.as (modified) (4 diffs)
-
trunk/as3/com/jeroenwijering/plugins/Accessibility.as (modified) (8 diffs)
-
trunk/as3/com/jeroenwijering/plugins/ClickProxy.as (modified) (2 diffs)
-
trunk/as3/com/jeroenwijering/plugins/Controlbar.as (modified) (13 diffs)
-
trunk/as3/com/jeroenwijering/plugins/Display.as (modified) (14 diffs)
-
trunk/as3/com/jeroenwijering/plugins/HD.as (modified) (5 diffs)
-
trunk/as3/com/jeroenwijering/plugins/MetaViewer.as (modified) (5 diffs)
-
trunk/as3/com/jeroenwijering/plugins/Playlist.as (modified) (4 diffs)
-
trunk/as3/com/jeroenwijering/plugins/Revolt.as (modified) (6 diffs)
-
trunk/as3/com/jeroenwijering/plugins/Rightclick.as (modified) (4 diffs)
-
trunk/as3/com/jeroenwijering/plugins/SoundProxy.as (modified) (3 diffs)
-
trunk/as3/com/jeroenwijering/utils/Draw.as (modified) (5 diffs)
-
trunk/as3/com/jeroenwijering/utils/Stretcher.as (modified) (1 diff)
-
trunk/as3/hd.fla (modified) (previous)
-
trunk/as3/hd.swf (modified) (previous)
-
trunk/as3/metaviewer.fla (modified) (previous)
-
trunk/as3/metaviewer.swf (modified) (previous)
-
trunk/as3/player.fla (modified) (previous)
-
trunk/as3/player.pdf (modified) (previous)
-
trunk/as3/player.swf (modified) (previous)
-
trunk/as3/revolt.swf (modified) (previous)
-
trunk/as3/yt.as (modified) (4 diffs)
-
trunk/as3/yt.swf (modified) (previous)
Legend:
- Unmodified
- Added
- Removed
-
trunk/as3/com/anttikupila/revolt/drawers/Line.as
r123 r135 14 14 override public function drawGFX(gfx:BitmapData, soundArray:Array):void { 15 15 lineSprite.graphics.clear(); 16 lineSprite.graphics.moveTo(0, gfx.height/2); 16 lineSprite.graphics.moveTo(0, gfx.height/2); 17 17 // lineSprite.graphics.beginFill(0x336600); 18 18 for (var i:uint = 0; i < soundArray.length; i+=2) { -
trunk/as3/com/anttikupila/revolt/presets/LineNoFourier.as
r123 r135 1 1 package com.anttikupila.revolt.presets { 2 import com.anttikupila.revolt.presets.LineFourier; 2 import com.anttikupila.revolt.presets.Preset; 3 import com.anttikupila.revolt.drawers.*; 4 import com.anttikupila.revolt.effects.*; 5 import com.anttikupila.revolt.scalers.*; 3 6 4 public class LineNoFourier extends LineFourier{5 function LineNoFourier( ) {7 public class LineNoFourier extends Preset { 8 function LineNoFourier(clr:String=undefined) { 6 9 super(); 7 10 fourier = false; 11 drawers = new Array(new SimpleLine(clr)); 12 effects = new Array(new Blur(),new Tint(0x000000,0.25)); 13 scalers = new Array(); 8 14 } 9 15 10 overridepublic function toString():String {11 return "Line with outfourier transformation";16 public function toString():String { 17 return "Line with fourier transformation"; 12 18 } 13 19 } -
trunk/as3/com/jeroenwijering/models/BasicModel.as
r57 r135 1 1 /** 2 * Wrapper for playback of progressively downloaded video.2 * This is the base model class all models must extent. 3 3 **/ 4 4 package com.jeroenwijering.models { 5 5 6 6 7 import flash.display.DisplayObject; 7 import com.jeroenwijering.events.*; 8 import com.jeroenwijering.player.Model; 9 10 import flash.utils.clearInterval; 11 import flash.utils.setInterval; 8 12 9 13 10 public interface ModelInterface{14 public class BasicModel { 11 15 12 /** Load a file into the model. **/ 13 function load():void; 14 /** Playback resume directive. **/ 15 function play():void; 16 /** Playback pause directive. **/ 17 function pause():void; 18 /** Playback seeking directive. **/ 19 function seek(pos:Number):void; 20 /** Stop the item altogether. **/ 21 function stop():void; 22 /** Set or toggle the playback quality. **/ 23 function quality(stt:Boolean):void; 24 /** Change the volume. **/ 25 function volume(vol:Number):void; 16 17 /** Reference to the player Model. **/ 18 protected var model:Model 19 /** Reference to the currently active playlistitem. **/ 20 protected var item:Object; 21 /** The current position inside the file. **/ 22 protected var position:Number; 23 /** ID for the position interval. **/ 24 protected var interval:Number; 25 26 27 /** 28 * Constructor; sets up reference to the MVC model. 29 * 30 * @param mod The model of the player MVC triad. 31 * @see Model 32 **/ 33 public function BasicModel(mod:Model):void { 34 model = mod; 35 }; 36 37 38 /** 39 * Load an item into the model. 40 * 41 * @param itm The currently active playlistitem. 42 **/ 43 public function load(itm:Object):void { 44 item = itm; 45 position = item['start']; 46 model.sendEvent(ModelEvent.STATE,{newstate:ModelStates.BUFFERING}); 47 model.sendEvent(ModelEvent.BUFFER,{percentage:0}); 48 }; 49 50 51 /** Pause playback of the item. **/ 52 public function pause():void { 53 clearInterval(interval); 54 model.sendEvent(ModelEvent.STATE,{newstate:ModelStates.PAUSED}); 55 }; 56 57 58 /** Resume playback of the item. **/ 59 public function play():void { 60 model.sendEvent(ModelEvent.STATE,{newstate:ModelStates.PLAYING}); 61 interval = setInterval(positionInterval,100); 62 }; 63 64 65 /** Interval function that pings the position. **/ 66 protected function positionInterval():void { 67 position = Math.round(position*10+1)/10; 68 if(position-item['start'] < item['duration']) { 69 model.sendEvent(ModelEvent.TIME,{position:position-item['start'],duration:item['duration']}); 70 } else if (item['duration'] > 0) { 71 pause(); 72 model.sendEvent(ModelEvent.STATE,{newstate:ModelStates.COMPLETED}); 73 } 74 }; 75 76 77 /** 78 * Seek to a certain position in the item. 79 * 80 * @param pos The position in seconds. 81 **/ 82 public function seek(pos:Number):void { 83 clearInterval(interval); 84 position = item['start'] + pos; 85 play(); 86 }; 87 88 89 /** Stop playing and loading the item. **/ 90 public function stop():void { 91 clearInterval(interval); 92 position = item['start']; 93 model.sendEvent(ModelEvent.STATE,{newstate:ModelStates.IDLE}); 94 }; 95 96 97 /** 98 * Change the playback volume of the item. 99 * 100 * @param vol The new volume (0 to 100). 101 **/ 102 public function volume(vol:Number):void {}; 26 103 27 104 -
trunk/as3/com/jeroenwijering/models/CameraModel.as
r103 r135 1 1 /** 2 * This model implements the built-in webcam funcionality of the Flash Player. 3 * The webcam stream is shown in the display (nice for testing). 4 * If an rtmp server is provided in the 'streamer' flashvar, the stream will be published. 2 * Model that leverages the built-in webcam access of the Flash Player (displaying the output). 5 3 **/ 6 4 package com.jeroenwijering.models { … … 8 6 9 7 import com.jeroenwijering.events.*; 10 import com.jeroenwijering.models. ModelInterface;8 import com.jeroenwijering.models.BasicModel; 11 9 import com.jeroenwijering.player.Model; 12 import flash.events.*; 10 13 11 import flash.media.*; 14 import flash.net.*;15 import flash.utils.clearInterval;16 import flash.utils.setInterval;17 12 18 13 19 public class CameraModel implements ModelInterface{14 public class CameraModel extends BasicModel { 20 15 21 16 22 /** reference to the model. **/23 private var model:Model;24 17 /** Camera object to be instantiated. **/ 25 18 private var camera:Camera; … … 28 21 /** Microphone object to be instantiated. **/ 29 22 private var microphone:Microphone; 30 /** NetConnection object for setup of the video stream. **/31 private var connection:NetConnection;32 /** NetStream instance that handles the stream IO. **/33 private var stream:NetStream;34 /** Interval ID for position counter. **/35 private var interval:Number;36 /** Current position. **/37 private var position:Number;38 23 39 24 40 25 public function CameraModel(mod:Model):void { 41 model = mod;26 super(mod); 42 27 try { 43 28 camera = Camera.getCamera(); 29 camera.setMode(320,240,20); 30 model.sendEvent(ModelEvent.META,{framerate:20,height:320,width:240}); 44 31 microphone = Microphone.getMicrophone(); 45 32 video = new Video(320,240); 46 } catch(err:Error) { 47 model.sendEvent(ModelEvent.ERROR,{message:'No webcam found on this computer.'}); 48 } 49 connection = new NetConnection(); 50 connection.objectEncoding = ObjectEncoding.AMF0; 51 connection.addEventListener(NetStatusEvent.NET_STATUS,statusHandler); 52 connection.addEventListener(SecurityErrorEvent.SECURITY_ERROR,errorHandler); 53 quality(model.config['quality']); 33 video.smoothing = model.config['smoothing']; 34 } catch(err:Error) {} 54 35 }; 55 36 56 37 57 /** Catch security errors. **/58 private function errorHandler(evt:ErrorEvent):void {59 model.sendEvent(ModelEvent.ERROR,{message:evt.text});60 };61 62 63 64 38 /** Load the camera into the video **/ 65 public function load():void {66 position = model.playlist[model.config['item']]['start'];67 model.mediaHandler(video);68 if(model.config['streamer']) {69 connection.connect(model.config['streamer']);39 override public function load(itm:Object):void { 40 super.load(itm); 41 if(camera) { 42 model.mediaHandler(video); 43 play(); 70 44 } else { 71 play(); 45 stop(); 46 model.sendEvent(ModelEvent.ERROR,{message:'No webcam found on this computer.'}); 72 47 } 73 48 }; … … 75 50 76 51 /** Pause playback. **/ 77 public function pause():void { 52 override public function pause():void { 53 super.pause(); 78 54 video.attachCamera(null); 79 if(stream) {80 stream.publish(null);81 stream.attachAudio(null);82 stream.attachCamera(null);83 }84 clearInterval(interval);85 model.sendEvent(ModelEvent.STATE,{newstate:ModelStates.PAUSED});86 55 }; 87 56 88 57 89 58 /** Resume playback **/ 90 public function play():void { 59 override public function play():void { 60 super.play(); 91 61 video.attachCamera(camera); 92 model.sendEvent(ModelEvent.STATE,{newstate:ModelStates.PLAYING});93 interval = setInterval(timeInterval,100);94 if(stream) {95 stream.publish(model.playlist[model.config['item']]['file']);96 stream.attachAudio(microphone);97 stream.attachCamera(camera);98 }99 };100 101 102 /** Change the quality mode. **/103 public function quality(stt:Boolean):void {104 if(stt == true) {105 camera.setMode(480,360,25);106 video.smoothing = true;107 video.deblocking = 4;108 model.sendEvent(ModelEvent.META,{framerate:25,height:360,width:480});109 } else {110 camera.setMode(240,180,12);111 video.smoothing = false;112 video.deblocking = 1;113 model.sendEvent(ModelEvent.META,{framerate:12,height:180,width:240});114 }115 };116 117 118 /** Seek the camera timeline. **/119 public function seek(pos:Number):void {120 position = pos;121 clearInterval(interval);122 play();123 62 }; 124 63 125 64 126 65 /** Destroy the videocamera. **/ 127 public function stop():void { 128 position = 0; 66 override public function stop():void { 129 67 video.attachCamera(null); 130 clearInterval(interval); 131 if(stream) { stream.publish(null); } 68 super.stop(); 132 69 }; 133 134 135 /** Receive NetStream status updates. **/136 private function statusHandler(evt:NetStatusEvent):void {137 if(evt.info.code == "NetConnection.Connect.Success") {138 stream = new NetStream(connection);139 stream.addEventListener(NetStatusEvent.NET_STATUS,statusHandler);140 play();141 }142 model.sendEvent(ModelEvent.META,{info:evt.info.code});143 };144 145 146 /** Interval function that countdowns the time. **/147 private function timeInterval():void {148 position = Math.round(position*10+1)/10;149 model.sendEvent(ModelEvent.TIME,{position:position});150 };151 152 153 /** Volume setting **/154 public function volume(pct:Number):void {};155 70 156 71 -
trunk/as3/com/jeroenwijering/models/HTTPModel.as
r132 r135 1 1 /** 2 * Wrapper for playback of http 'streaming' video.2 * Manages playback of http streaming flv. 3 3 **/ 4 4 package com.jeroenwijering.models { … … 6 6 7 7 import com.jeroenwijering.events.*; 8 import com.jeroenwijering.models. ModelInterface;8 import com.jeroenwijering.models.BasicModel; 9 9 import com.jeroenwijering.player.Model; 10 10 import com.jeroenwijering.utils.NetClient; 11 11 12 import flash.events.*; 12 import flash.display.DisplayObject; 13 import flash.media.SoundTransform; 14 import flash.media.Video; 13 import flash.media.*; 15 14 import flash.net.*; 16 import flash.utils.clearInterval; 17 import flash.utils.setInterval; 18 19 20 public class HTTPModel implements ModelInterface { 21 22 23 /** reference to the model. **/ 24 private var model:Model; 15 import flash.utils.*; 16 17 18 public class HTTPModel extends BasicModel { 19 20 21 /** NetConnection object for setup of the video stream. **/ 22 protected var connection:NetConnection; 23 /** NetStream instance that handles the stream IO. **/ 24 protected var stream:NetStream; 25 25 /** Video object to be instantiated. **/ 26 private var video:Video; 27 /** NetConnection object for setup of the video stream. **/ 28 private var connection:NetConnection; 29 /** NetStream instance that handles the stream IO. **/ 30 private var stream:NetStream; 26 protected var video:Video; 31 27 /** Sound control object. **/ 32 private var transform:SoundTransform; 33 /** Interval ID for the time. **/ 34 private var timeinterval:Number; 28 protected var transform:SoundTransform; 35 29 /** Interval ID for the loading. **/ 36 private var loadinterval:Number; 30 protected var loadinterval:Number; 31 /** Save whether metadata has already been sent. **/ 32 protected var meta:Boolean; 37 33 /** Object with keyframe times and positions. **/ 38 private var keyframes:Object; 39 /** Offset byteposition to start streaming. **/ 40 private var offset:Number; 41 /** Offset timeposition for lighttpd streaming. **/ 42 private var timeoffset:Number; 43 /** switch for first metadata run **/ 44 private var metadata:Boolean; 45 /** switch for h264 streaming **/ 46 private var h264:Boolean; 34 protected var keyframes:Object; 35 /** Offset in bytes of the last seek. **/ 36 protected var byteoffset:Number; 37 /** Offset in seconds of the last seek. **/ 38 protected var timeoffset:Number; 39 /** Boolean for mp4 / flv streaming. **/ 40 protected var mp4:Boolean; 47 41 48 42 49 43 /** Constructor; sets up the connection and display. **/ 50 44 public function HTTPModel(mod:Model):void { 51 model = mod;45 super(mod); 52 46 connection = new NetConnection(); 53 connection.addEventListener(NetStatusEvent.NET_STATUS,statusHandler);54 connection.addEventListener(SecurityErrorEvent.SECURITY_ERROR,errorHandler);55 connection.addEventListener(AsyncErrorEvent.ASYNC_ERROR,errorHandler);56 47 connection.connect(null); 57 48 stream = new NetStream(connection); 58 49 stream.addEventListener(NetStatusEvent.NET_STATUS,statusHandler); 59 50 stream.addEventListener(IOErrorEvent.IO_ERROR,errorHandler); 60 stream.addEventListener(AsyncErrorEvent.ASYNC_ERROR, metaHandler);51 stream.addEventListener(AsyncErrorEvent.ASYNC_ERROR,errorHandler); 61 52 stream.bufferTime = model.config['bufferlength']; 62 53 stream.client = new NetClient(this); 63 54 video = new Video(320,240); 55 video.smoothing = model.config['smoothing']; 64 56 video.attachNetStream(stream); 65 57 transform = new SoundTransform(); 66 stream.soundTransform = transform;67 58 model.config['mute'] == true ? volume(0): volume(model.config['volume']); 68 quality(model.config['quality']); 69 offset = timeoffset = 0; 59 byteoffset = timeoffset = 0; 60 }; 61 62 63 /** Convert seekpoints to keyframes. **/ 64 protected function convertSeekpoints(dat:Object):Object { 65 var kfr:Object = new Object(); 66 kfr.times = new Array(); 67 kfr.filepositions = new Array(); 68 for (var j in dat) { 69 kfr.times[j] = Number(dat[j]['time']); 70 kfr.filepositions[j] = Number(dat[j]['offset']); 71 } 72 return kfr; 70 73 }; 71 74 72 75 73 76 /** Catch security errors. **/ 74 private function errorHandler(evt:ErrorEvent):void { 77 protected function errorHandler(evt:ErrorEvent):void { 78 stop(); 75 79 model.sendEvent(ModelEvent.ERROR,{message:evt.text}); 76 80 }; … … 78 82 79 83 /** Return a keyframe byteoffset or timeoffset. **/ 80 private function getOffset(pos:Number,tme:Boolean=false):Number { 81 if(!keyframes) { return 0; } 82 for (var i=0; i< keyframes.times.length; i++) { 84 protected function getOffset(pos:Number,tme:Boolean=false):Number { 85 if(!keyframes) { 86 return 0; 87 } 88 for (var i:Number=0; i < keyframes.times.length - 1; i++) { 83 89 if(keyframes.times[i] <= pos && keyframes.times[i+1] >= pos) { 84 if(tme == true) {85 return keyframes.times[i];86 } else {87 return keyframes.filepositions[i];88 }89 }90 }91 return 0;90 break; 91 } 92 } 93 if(tme == true) { 94 return keyframes.times[i]; 95 } else { 96 return keyframes.filepositions[i]; 97 } 92 98 }; 93 99 94 100 95 101 /** Returns a key to add to the stream. **/ 96 pr ivatefunction getToken():String {102 protected function getToken():String { 97 103 return model.config['token']; 98 104 }; 99 105 100 106 107 /** Create the video request URL. **/ 108 protected function getURL():String { 109 var url:String = item['streamer']; 110 if(url.indexOf('?') > -1) { 111 url += "&file="+item['file']; 112 } else { 113 url += "?file="+item['file']; 114 } 115 if(byteoffset > 0) { 116 url += '&start='+byteoffset; 117 } 118 if(getToken()) { 119 url += '&token='+getToken(); 120 } 121 return url; 122 }; 123 124 101 125 /** Load content. **/ 102 public function load():void { 103 video.clear(); 126 override public function load(itm:Object):void { 127 super.load(itm); 128 if(stream) { 129 stream.close(); 130 } 104 131 model.mediaHandler(video); 105 if(stream.bytesLoaded != stream.bytesTotal) { 106 stream.close(); 107 } 108 var url = model.playlist[model.config['item']]['file']; 109 var str = model.playlist[model.config['item']]['streamer']; 110 if(str == "lighttpd") { 111 if(h264) { 112 url +='?start='+timeoffset; 113 } else { 114 url += '?start='+offset; 115 } 116 } else { 117 if(str.indexOf('?') > -1) { 118 url = str+"&file="+url+'&start='+offset; 119 } else { 120 url = str+"?file="+url+'&start='+offset; 121 } 122 } 123 url += '&id='+model.config['id']; 124 url += '&client='+encodeURI(model.config['client']); 125 url += '&version='+encodeURI(model.config['version']); 126 url += '&width='+model.config['width']; 127 if(getToken()) { url += '&token='+getToken(); } 128 stream.play(url); 132 stream.play(getURL()); 133 clearInterval(interval); 134 interval = setInterval(positionInterval,100); 129 135 clearInterval(loadinterval); 130 136 loadinterval = setInterval(loadHandler,200); 131 clearInterval(timeinterval);132 timeinterval = setInterval(timeHandler,100);133 model.sendEvent(ModelEvent.STATE,{newstate:ModelStates.BUFFERING});134 137 }; 135 138 136 139 137 140 /** Interval for the loading progress **/ 138 pr ivatefunction loadHandler():void {141 protected function loadHandler():void { 139 142 var ldd:Number = stream.bytesLoaded; 140 var ttl:Number = stream.bytesTotal; 141 var off:Number = offset; 142 if(ldd >= ttl && ldd > 0) { 143 var ttl:Number = stream.bytesTotal + byteoffset; 144 var off:Number = byteoffset; 145 if(meta) { 146 ttl = getOffset(item['start']+item['duration']) - getOffset(item['start']); 147 off = Math.max(0,byteoffset-getOffset(item['start'])); 148 } 149 if(ldd+off >= ttl && ldd > 0) { 150 model.sendEvent(ModelEvent.LOADED,{loaded:ttl-off,total:ttl,offset:off}); 143 151 clearInterval(loadinterval); 144 } 145 if(model.playlist[model.config['item']]['streamer'] == "lighttpd") { 146 off = 0; 147 } 148 model.sendEvent(ModelEvent.LOADED,{loaded:ldd,total:ttl+offset,offset:off}); 149 }; 150 151 152 /** Catch noncritical errors. **/ 153 private function metaHandler(evt:ErrorEvent):void { 154 model.sendEvent(ModelEvent.META,{error:evt.text}); 152 } else { 153 model.sendEvent(ModelEvent.LOADED,{loaded:ldd,total:ttl,offset:off}); 154 } 155 155 }; 156 156 … … 158 158 /** Get metadata information from netstream class. **/ 159 159 public function onData(dat:Object):void { 160 if(dat.type == 'metadata') { 161 if(dat.seekpoints && !h264) { 162 h264 = true; 163 keyframes = new Object(); 164 keyframes.times = new Array(); 165 keyframes.filepositions = new Array(); 166 for (var j in dat.seekpoints) { 167 keyframes.times[j] = Number(dat.seekpoints[j]['time']); 168 keyframes.filepositions[j] = Number(dat.seekpoints[j]['offset']); 160 if(dat.width) { 161 video.width = dat.width; 162 video.height = dat.height; 163 } 164 if(dat.duration) { 165 dat.duration -= item['start']; 166 } 167 if(dat['type'] == 'metadata' && !meta) { 168 meta = true; 169 if(dat.seekpoints) { 170 mp4 = true; 171 keyframes = convertSeekpoints(dat.seekpoints); 172 } else { 173 mp4 = false; 174 keyframes = dat.keyframes; 175 } 176 if(item['start'] > 0) { 177 seek(0); 178 } 179 } 180 model.sendEvent(ModelEvent.META,dat); 181 }; 182 183 184 /** Pause playback. **/ 185 override public function pause():void { 186 super.pause(); 187 stream.pause(); 188 }; 189 190 191 /** Resume playing. **/ 192 override public function play():void { 193 super.play(); 194 stream.resume(); 195 }; 196 197 198 /** Interval for the position progress **/ 199 override protected function positionInterval():void { 200 var pos:Number = Math.round(stream.time*10)/10; 201 if (mp4) { 202 pos += timeoffset; 203 } 204 var bfr:Number = Math.round(stream.bufferLength/stream.bufferTime*100); 205 if(bfr < 95 && pos < Math.abs(item['duration']-stream.bufferTime-1)) { 206 model.sendEvent(ModelEvent.BUFFER,{percentage:bfr}); 207 if(model.config['state'] != ModelStates.BUFFERING && bfr < 25) { 208 model.sendEvent(ModelEvent.STATE,{newstate:ModelStates.BUFFERING}); 209 } 210 } else if (bfr > 95 && model.config['state'] != ModelStates.PLAYING) { 211 model.sendEvent(ModelEvent.STATE,{newstate:ModelStates.PLAYING}); 212 } 213 if(pos-item['start'] < item['duration']) { 214 if(pos > 0) { 215 position = Math.max(0,Math.round((pos-item['start'])*10)/10); 216 model.sendEvent(ModelEvent.TIME,{position:position,duration:item['duration']}); 217 } 218 } else if (item['duration'] > 0) { 219 pause(); 220 model.sendEvent(ModelEvent.STATE,{newstate:ModelStates.COMPLETED}); 221 } 222 }; 223 224 225 /** Seek to a specific second. **/ 226 override public function seek(pos:Number):void { 227 var off = getOffset(pos+item['start']); 228 if(off < byteoffset || off > byteoffset+stream.bytesLoaded) { 229 timeoffset = getOffset(pos+item['start'],true); 230 byteoffset = off; 231 load(item); 232 } else { 233 super.seek(pos); 234 if(mp4) { 235 stream.seek(position-timeoffset); 236 } else { 237 stream.seek(position); 238 } 239 } 240 }; 241 242 243 /** Receive NetStream status updates. **/ 244 protected function statusHandler(evt:NetStatusEvent):void { 245 switch (evt.info.code) { 246 case "NetStream.Play.Stop": 247 if(model.config['state'] != ModelStates.COMPLETED) { 248 clearInterval(interval); 249 model.sendEvent(ModelEvent.STATE,{newstate:ModelStates.COMPLETED}); 169 250 } 170 } else if(dat.keyframes) { 171 keyframes = dat.keyframes; 172 } 173 if(!metadata) { 174 if(dat.width) { 175 video.width = dat.width; 176 video.height = dat.height; 177 } 178 model.sendEvent(ModelEvent.META,dat); 179 if(model.playlist[model.config['item']]['start'] > 0 && !metadata) { 180 seek(model.playlist[model.config['item']]['start']); 181 } 182 metadata = true; 183 } 184 } else { 185 model.sendEvent(ModelEvent.META,dat); 186 } 187 }; 188 189 190 /** Pause playback. **/ 191 public function pause():void { 192 clearInterval(timeinterval); 193 stream.pause(); 194 model.sendEvent(ModelEvent.STATE,{newstate:ModelStates.PAUSED}); 195 }; 196 197 198 /** Resume playing. **/ 199 public function play():void { 200 stream.resume(); 201 timeinterval = setInterval(timeHandler,100); 202 model.sendEvent(ModelEvent.STATE,{newstate:ModelStates.PLAYING}); 203 }; 204 205 206 /** Seek to a specific second. **/ 207 public function seek(pos:Number):void { 208 clearInterval(timeinterval); 209 var off = getOffset(pos); 210 if(off < offset || off > offset+stream.bytesLoaded) { 211 offset = off; 212 timeoffset = getOffset(pos,true); 213 load(); 214 } else { 215 if(h264) { 216 stream.seek(pos-timeoffset); 217 } else { 218 stream.seek(pos) 219 } 220 play(); 221 } 222 }; 223 224 225 /** Change the smoothing mode. **/ 226 public function quality(qua:Boolean):void { 227 if(qua == true) { 228 video.smoothing = true; 229 video.deblocking = 3; 230 } else { 231 video.smoothing = false; 232 video.deblocking = 1; 233 } 234 }; 235 236 237 /** Receive NetStream status updates. **/ 238 private function statusHandler(evt:NetStatusEvent):void { 239 if(evt.info.code == "NetStream.Play.Stop") { 240 if(model.config['state'] != ModelStates.COMPLETED) { 241 clearInterval(timeinterval); 242 model.sendEvent(ModelEvent.STATE,{newstate:ModelStates.COMPLETED}); 243 } 244 } else if(evt.info.code == "NetStream.Play.StreamNotFound") { 245 stop(); 246 model.sendEvent(ModelEvent.ERROR,{message:"Video stream not found: " + 247 model.playlist[model.config['item']]['file']}); 248 } else { 249 model.sendEvent(ModelEvent.META,{info:evt.info.code}); 251 break; 252 case "NetStream.Play.StreamNotFound": 253 stop(); 254 model.sendEvent(ModelEvent.ERROR,{message:'Video not found: '+item['file']}); 255 break; 256 default: 257 model.sendEvent(ModelEvent.META,{info:evt.info.code}); 258 break; 250 259 } 251 260 }; … … 253 262 254 263 /** Destroy the HTTP stream. **/ 255 public function stop():void { 264 override public function stop():void { 265 super.stop(); 266 stream.close(); 256 267 clearInterval(loadinterval); 257 clearInterval(timeinterval); 258 offset = timeoffset = 0; 259 h264 = false; 268 byteoffset = timeoffset = 0; 260 269 keyframes = undefined; 261 metadata = false; 262 if(stream.bytesLoaded != stream.bytesTotal) { 263 stream.close(); 264 } 265 stream.pause(); 266 }; 267 268 269 /** Interval for the position progress **/ 270 private function timeHandler():void { 271 var bfr = Math.round(stream.bufferLength/stream.bufferTime*100); 272 var pos = Math.round(stream.time*10)/10; 273 if (h264 || pos == 0) { pos += timeoffset; } 274 var dur = model.playlist[model.config['item']]['duration']; 275 if(bfr<95 && pos < Math.abs(dur-stream.bufferTime*2)) { 276 model.sendEvent(ModelEvent.BUFFER,{percentage:bfr}); 277 if(model.config['state'] != ModelStates.BUFFERING && bfr < 10) { 278 model.sendEvent(ModelEvent.STATE,{newstate:ModelStates.BUFFERING}); 279 } 280 } else if (model.config['state'] == ModelStates.BUFFERING) { 281 model.sendEvent(ModelEvent.STATE,{newstate:ModelStates.PLAYING}); 282 } 283 model.sendEvent(ModelEvent.TIME,{position:pos}); 270 meta = false; 284 271 }; 285 272 286 273 287 274 /** Set the volume level. **/ 288 public function volume(vol:Number):void {275 override public function volume(vol:Number):void { 289 276 transform.volume = vol/100; 290 277 stream.soundTransform = transform; -
trunk/as3/com/jeroenwijering/models/ImageModel.as
r103 r135 1 1 /** 2 * Wrapper for load and playback ofimages.2 * Model for playback of GIF/JPG/PNG images. 3 3 **/ 4 4 package com.jeroenwijering.models { … … 6 6 7 7 import com.jeroenwijering.events.*; 8 import com.jeroenwijering.models. ModelInterface;8 import com.jeroenwijering.models.BasicModel; 9 9 import com.jeroenwijering.player.Model; 10 10 11 import flash.display.Bitmap; 11 12 import flash.display.Loader; 12 13 import flash.events.*; 13 import flash.media.SoundMixer;14 14 import flash.net.URLRequest; 15 import flash.utils.clearInterval; 16 import flash.utils.setInterval; 15 import flash.system.LoaderContext; 17 16 18 17 19 public class ImageModel implements ModelInterface{18 public class ImageModel extends BasicModel { 20 19 21 20 22 /** reference to the model. **/ 23 private var model:Model; 24 /** Camera object to be instantiated. **/ 21 /** Loader that loads the image. **/ 25 22 private var loader:Loader; 26 /** Interval ID for the time. **/27 private var interval:Number;28 /** Current position in the time. **/29 private var position:Number;30 23 31 24 32 25 /** Constructor; sets up listeners **/ 33 26 public function ImageModel(mod:Model):void { 34 model = mod;27 super(mod); 35 28 loader = new Loader(); 36 29 loader.contentLoaderInfo.addEventListener(Event.COMPLETE,loaderHandler); … … 41 34 42 35 /** load image into screen **/ 43 public function load():void { 44 clearInterval(interval); 45 position = model.playlist[model.config['item']]['start']; 46 loader.load(new URLRequest(model.playlist[model.config['item']]['file'])); 47 model.sendEvent(ModelEvent.STATE,{newstate:ModelStates.BUFFERING}); 48 model.sendEvent(ModelEvent.BUFFER,{percentage:0}); 36 override public function load(itm:Object):void { 37 super.load(itm); 38 loader.load(new URLRequest(item['file']),new LoaderContext(true)); 49 39 }; 50 40 … … 52 42 /** Catch errors. **/ 53 43 private function errorHandler(evt:ErrorEvent):void { 44 stop(); 54 45 model.sendEvent(ModelEvent.ERROR,{message:evt.text}); 55 46 }; … … 59 50 private function loaderHandler(evt:Event):void { 60 51 model.mediaHandler(loader); 61 quality(model.config['quality']); 52 try { 53 Bitmap(loader.content).smoothing = true; 54 } catch (err:Error) {} 55 model.sendEvent(ModelEvent.META,{height:evt.target.height,width:evt.target.width}); 62 56 play(); 63 model.sendEvent(ModelEvent.META,{height:evt.target.height,width:evt.target.width});64 model.sendEvent(ModelEvent.LOADED,{loaded:evt.target.bytesLoaded,total:evt.target.bytesTotal});65 };66 67 68 /** Resume playback of the images **/69 public function play():void {70 interval = setInterval(timeInterval,100);71 model.sendEvent(ModelEvent.STATE,{newstate:ModelStates.PLAYING});72 };73 74 75 /** Show or hide the camera. **/76 public function pause():void {77 clearInterval(interval);78 flash.media.SoundMixer.stopAll();79 model.sendEvent(ModelEvent.STATE,{newstate:ModelStates.PAUSED});80 57 }; 81 58 … … 88 65 89 66 90 /** Change the quality mode. **/91 public function quality(stt:Boolean):void {92 try {93 Bitmap(loader.content).smoothing = stt;94 } catch (err:Error) {}95 };96 97 98 /** Scrub the image to a certain position. **/99 public function seek(pos:Number):void {100 clearInterval(interval);101 position = pos;102 play();103 };104 105 106 67 /** Stop the image interval. **/ 107 public function stop():void { 108 flash.media.SoundMixer.stopAll(); 109 clearInterval(interval); 110 if(loader.contentLoaderInfo.bytesLoaded != loader.contentLoaderInfo.bytesTotal) { 68 override public function stop():void { 69 if(loader.contentLoaderInfo.bytesLoaded != loader.contentLoaderInfo.bytesTotal) { 111 70 loader.close(); 112 } else { 71 } else { 113 72 loader.unload(); 114 73 } 74 super.stop(); 115 75 }; 116 117 118 /** Interval function that countdowns the time. **/119 private function timeInterval():void {120 position = Math.round(position*10+1)/10;121 model.sendEvent(ModelEvent.TIME,{position:position});122 };123 124 125 /** Volume setting **/126 public function volume(pct:Number):void { };127 76 128 77 -
trunk/as3/com/jeroenwijering/models/RTMPModel.as
r119 r135 4 4 * All playback functionalities are cross-server (FMS, Wowza, Red5), with the exception of: 5 5 * - The SecureToken functionality (Wowza). 6 * - The FCSubscribe functionality (Limelight/Akamai FMS).7 6 * - getStreamLength / checkBandwidth (FMS3). 8 7 **/ … … 11 10 12 11 import com.jeroenwijering.events.*; 13 import com.jeroenwijering.models. ModelInterface;12 import com.jeroenwijering.models.BasicModel; 14 13 import com.jeroenwijering.player.Model; 15 14 import com.jeroenwijering.utils.NetClient; 16 15 import com.jeroenwijering.utils.TEA; 17 16 18 import flash.display.DisplayObject;19 17 import flash.events.*; 20 18 import flash.media.*; … … 23 21 24 22 25 public class RTMPModel implements ModelInterface { 26 27 28 /** reference to the model. **/ 29 private var model:Model; 23 public class RTMPModel extends BasicModel { 24 25 30 26 /** Video object to be instantiated. **/ 31 pr ivatevar video:Video;27 protected var video:Video; 32 28 /** NetConnection object for setup of the video stream. **/ 33 pr ivatevar connection:NetConnection;29 protected var connection:NetConnection; 34 30 /** NetStream instance that handles the stream IO. **/ 35 pr ivatevar stream:NetStream;31 protected var stream:NetStream; 36 32 /** Sound control object. **/ 37 private var transform:SoundTransform; 38 /** Interval ID for the time. **/ 39 private var timeinterval:Number; 40 /** Timeout ID for live stream subscription pings. **/ 41 private var timeout:Number; 42 /** Metadata have been received. **/ 43 private var metadata:Boolean; 33 protected var transform:SoundTransform; 44 34 45 35 46 36 /** Constructor; sets up the connection and display. **/ 47 37 public function RTMPModel(mod:Model):void { 48 model = mod;38 super(mod); 49 39 connection = new NetConnection(); 50 40 connection.addEventListener(NetStatusEvent.NET_STATUS,statusHandler); 51 41 connection.addEventListener(SecurityErrorEvent.SECURITY_ERROR,errorHandler); 52 42 connection.addEventListener(IOErrorEvent.IO_ERROR,errorHandler); 53 connection.addEventListener(AsyncErrorEvent.ASYNC_ERROR, metaHandler);43 connection.addEventListener(AsyncErrorEvent.ASYNC_ERROR,errorHandler); 54 44 connection.objectEncoding = ObjectEncoding.AMF0; 55 45 connection.client = new NetClient(this); 56 46 video = new Video(320,240); 57 quality(model.config['quality']);47 video.smoothing = model.config['smoothing']; 58 48 transform = new SoundTransform(); 59 model.config['mute'] == true ? volume(0): volume(model.config['volume']);60 49 }; 61 50 62 51 63 52 /** Catch security errors. **/ 64 private function errorHandler(evt:ErrorEvent):void { 53 protected function errorHandler(evt:ErrorEvent):void { 54 stop(); 65 55 model.sendEvent(ModelEvent.ERROR,{message:evt.text}); 66 56 }; … … 83 73 84 74 /** Load content. **/ 85 public function load():void {86 video.clear();75 override public function load(itm:Object):void { 76 super.load(itm); 87 77 model.mediaHandler(video); 88 connection.connect(model.playlist[model.config['item']]['streamer']); 89 model.sendEvent(ModelEvent.STATE,{newstate:ModelStates.BUFFERING}); 90 }; 91 92 93 /** Catch noncritical errors. **/ 94 private function metaHandler(evt:ErrorEvent):void { 95 model.sendEvent(ModelEvent.META,{error:evt.text}); 78 connection.connect(item['streamer']); 96 79 }; 97 80 … … 99 82 /** Get metadata information from netstream class. **/ 100 83 public function onData(dat:Object):void { 101 if(dat.type == 'metadata' && !metadata) { 102 if(dat.width) { 103 video.width = dat.width; 104 video.height = dat.height; 84 if(dat.width) { 85 video.width = dat.width; 86 video.height = dat.height; 87 } 88 if(dat.duration) { 89 dat.duration -= item['start']; 90 } 91 if(dat.type == 'complete') { 92 clearInterval(interval); 93 model.sendEvent(ModelEvent.STATE,{newstate:ModelStates.COMPLETED}); 94 } 95 model.sendEvent(ModelEvent.META,dat); 96 }; 97 98 99 /** Pause playback. **/ 100 override public function pause():void { 101 super.pause(); 102 stream.pause(); 103 }; 104 105 106 /** Resume playing. **/ 107 override public function play():void { 108 super.play(); 109 stream.resume(); 110 }; 111 112 113 /** Interval for the position progress. **/ 114 override protected function positionInterval():void { 115 position = Math.round(stream.time*10)/10; 116 var bfr:Number = Math.round(stream.bufferLength/stream.bufferTime*100); 117 if(bfr < 95 && position < Math.abs(item['duration']-stream.bufferTime-1)) { 118 model.sendEvent(ModelEvent.BUFFER,{percentage:bfr}); 119 if(model.config['state'] != ModelStates.BUFFERING && bfr < 25) { 120 model.sendEvent(ModelEvent.STATE,{newstate:ModelStates.BUFFERING}); 105 121 } 106 if(model.playlist[model.config['item']]['start'] > 0) { 107 seek(model.playlist[model.config['item']]['start']); 108 } 109 metadata = true; 110 } else if(dat.type == 'complete') { 111 clearInterval(timeinterval); 122 } else if (bfr > 95 && model.config['state'] != ModelStates.PLAYING) { 123 model.sendEvent(ModelEvent.STATE,{newstate:ModelStates.PLAYING}); 124 } 125 if(position < item['duration']) { 126 model.sendEvent(ModelEvent.TIME,{position:position,duration:item['duration']}); 127 } else if (item['duration'] > 0) { 128 pause(); 112 129 model.sendEvent(ModelEvent.STATE,{newstate:ModelStates.COMPLETED}); 113 } else if(dat.type == 'fcsubscribe') { 114 if(dat.code == "NetStream.Play.StreamNotFound" ) { 115 model.sendEvent(ModelEvent.ERROR,{message:"Subscription failed: "+model.playlist[model.config['item']]['file']}); 116 }else if(dat.code == "NetStream.Play.Start") { 117 setStream(); 118 } 119 clearInterval(timeout); 120 } 121 model.sendEvent(ModelEvent.META,dat); 122 }; 123 124 125 /** Pause playback. **/ 126 public function pause():void { 127 clearInterval(timeinterval); 128 stream.pause(); 129 model.sendEvent(ModelEvent.STATE,{newstate:ModelStates.PAUSED}); 130 }; 131 132 133 /** Resume playing. **/ 134 public function play():void { 135 clearTimeout(timeout); 136 clearInterval(timeinterval); 137 stream.resume(); 138 model.sendEvent(ModelEvent.STATE,{newstate:ModelStates.PLAYING}); 139 timeinterval = setInterval(timeHandler,100); 140 }; 141 142 143 /** Change the smoothing mode. **/ 144 public function quality(qua:Boolean):void { 145 if(qua == true) { 146 video.smoothing = true; 147 video.deblocking = 3; 148 } else { 149 video.smoothing = false; 150 video.deblocking = 1; 151 } 152 }; 153 154 155 /** Change the smoothing mode. **/ 156 public function seek(pos:Number):void { 157 clearTimeout(timeout); 158 clearInterval(timeinterval); 159 if(model.config['state'] == ModelStates.PAUSED) { 160 stream.resume(); 161 } else { 162 model.sendEvent(ModelEvent.STATE,{newstate:ModelStates.PLAYING}); 163 } 130 } 131 }; 132 133 134 /** Seek to a new position. **/ 135 override public function seek(pos:Number):void { 136 super.seek(pos); 164 137 stream.seek(pos); 165 138 }; 166 139 167 140 168 /** Set streaming object **/ 169 public function setStream():void { 170 var url = getID(model.playlist[model.config['item']]['file']); 141 /** Start the netstream object. **/ 142 protected function setStream() { 171 143 stream = new NetStream(connection); 172 144 stream.addEventListener(NetStatusEvent.NET_STATUS,statusHandler); 173 145 stream.addEventListener(IOErrorEvent.IO_ERROR,errorHandler); 174 stream.addEventListener(AsyncErrorEvent.ASYNC_ERROR, metaHandler);146 stream.addEventListener(AsyncErrorEvent.ASYNC_ERROR,errorHandler); 175 147 stream.bufferTime = model.config['bufferlength']; 176 148 stream.client = new NetClient(this); 177 149 video.attachNetStream(stream); 178 stream.soundTransform = transform; 179 stream.play(url); 180 var res:Responder = new Responder(streamlengthHandler); 181 connection.call("getStreamLength",res,url); 182 connection.call("checkBandwidth",null); 183 clearInterval(timeinterval); 184 timeinterval = setInterval(timeHandler,100); 150 model.config['mute'] == true ? volume(0): volume(model.config['volume']); 151 interval = setInterval(positionInterval,100); 152 stream.play(getID(item['file']),item['start']); 185 153 }; 186 154 187 155 188 156 /** Receive NetStream status updates. **/ 189 pr ivatefunction statusHandler(evt:NetStatusEvent):void {190 switch (evt.info.code) { 157 protected function statusHandler(evt:NetStatusEvent):void { 158 switch (evt.info.code) { 191 159 case 'NetConnection.Connect.Success': 160 setStream(); 161 var res:Responder = new Responder(streamlengthHandler); 162 connection.call("getStreamLength",res,getID(item['file'])); 163 connection.call("checkBandwidth",null); 192 164 if(evt.info.secureToken != undefined) { 193 165 connection.call("secureTokenResponse",null,TEA.decrypt(evt.info.secureToken,model.config['token'])); 194 166 } 195 if(model.config['subscribe']) {196 timeout = setInterval(subscribe,2000,getID(model.playlist[model.config['item']]['file']));197 } else {198 setStream();199 }200 167 break; 201 168 case 'NetStream.Seek.Notify': 202 clearInterval( timeinterval);203 timeinterval = setInterval(timeHandler,100);169 clearInterval(interval); 170 interval = setInterval(positionInterval,100); 204 171 break; 205 172 case 'NetConnection.Connect.Rejected': 206 173 if(evt.info.ex.code == 302) { 207 model.playlist[model.config['item']]['streamer'] = evt.info.ex.redirect; 208 connection.connect(model.playlist[model.config['item']]['streamer']); 209 break; 174 item['streamer'] = evt.info.ex.redirect; 175 connection.connect(item['streamer']); 210 176 } 177 break; 178 case 'NetStream.Failed': 179 model.sendEvent(ModelEvent.META,{info:evt.info.code}); 211 180 case 'NetStream.Play.StreamNotFound': 181 stop(); 182 model.sendEvent(ModelEvent.ERROR,{message:"Stream not found: "+item['file']}); 183 break; 212 184 case 'NetConnection.Connect.Failed': 213 model.sendEvent(ModelEvent.ERROR,{message:"Stream not found: "+model.playlist[model.config['item']]['file']}); 185 stop(); 186 model.sendEvent(ModelEvent.ERROR,{message:"Server not found: "+item['streamer']}); 214 187 break; 215 188 default: … … 221 194 222 195 /** Destroy the stream. **/ 223 public function stop():void { 224 clearInterval(timeinterval); 196 override public function stop():void { 197 if(stream) { 198 stream.close(); 199 } 225 200 connection.close(); 226 if(stream) { stream.close(); } 227 video.attachNetStream(null); 201 super.stop(); 228 202 }; 229 203 … … 231 205 /** Get the streamlength returned from the connection. **/ 232 206 private function streamlengthHandler(len:Number):void { 233 onData({type:'streamlength',duration:len}); 234 }; 235 236 237 /** Akamai & Limelight subscribes. **/ 238 private function subscribe(nme:String):void { 239 connection.call("FCSubscribe",null,nme); 240 }; 241 242 243 /** Interval for the position progress **/ 244 private function timeHandler():void { 245 var bfr = Math.round(stream.bufferLength/stream.bufferTime*100); 246 var pos = Math.round(stream.time*10)/10; 247 var dur = model.playlist[model.config['item']]['duration']; 248 if(bfr < 95 && pos < Math.abs(dur-stream.bufferTime-1)) { 249 model.sendEvent(ModelEvent.BUFFER,{percentage:bfr}); 250 if(model.config['state'] != ModelStates.BUFFERING) { 251 connection.call("checkBandwidth",null); 252 model.sendEvent(ModelEvent.STATE,{newstate:ModelStates.BUFFERING}); 253 } 254 } else if (model.config['state'] == ModelStates.BUFFERING) { 255 model.sendEvent(ModelEvent.STATE,{newstate:ModelStates.PLAYING}); 256 } 257 model.sendEvent(ModelEvent.TIME,{position:pos}); 207 onData({type:'streamlength',duration:len-item['start']}); 258 208 }; 259 209 260 210 261 211 /** Set the volume level. **/ 262 public function volume(vol:Number):void {212 override public function volume(vol:Number):void { 263 213 transform.volume = vol/100; 264 214 if(stream) { -
trunk/as3/com/jeroenwijering/models/SoundModel.as
r103 r135 6 6 7 7 import com.jeroenwijering.events.*; 8 import com.jeroenwijering.models. ModelInterface;8 import com.jeroenwijering.models.BasicModel; 9 9 import com.jeroenwijering.player.Model; 10 10 11 import flash.events.*; 11 12 import flash.media.*; 12 13 import flash.net.URLRequest; 13 14 import flash.utils.clearInterval; 14 import flash.utils.setInterval;15 15 16 16 17 public class SoundModel implements ModelInterface{17 public class SoundModel extends BasicModel { 18 18 19 19 20 /** reference to the model. **/21 private var model:Model;22 20 /** sound object to be instantiated. **/ 23 21 private var sound:Sound; … … 28 26 /** Sound context object. **/ 29 27 private var context:SoundLoaderContext; 30 /** Interval ID for the time. **/31 private var interval:Number;32 /** Current position. **/33 private var position:Number;34 28 35 29 36 30 /** Constructor; sets up the connection and display. **/ 37 31 public function SoundModel(mod:Model):void { 38 model = mod;32 super(mod); 39 33 transform = new SoundTransform(); 34 context = new SoundLoaderContext(model.config['bufferlength']*1000,true); 40 35 model.config['mute'] == true ? volume(0): volume(model.config['volume']); 41 context = new SoundLoaderContext(model.config['bufferlength']*1000,true);42 36 }; 43 37 … … 52 46 /** Catch errors. **/ 53 47 private function errorHandler(evt:ErrorEvent):void { 48 stop(); 54 49 model.sendEvent(ModelEvent.ERROR,{message:evt.text}); 55 stop();56 50 }; 57 51 … … 61 55 try { 62 56 var id3:ID3Info = sound.id3; 63 var obj = {57 var obj:Object = { 64 58 type:'id3', 65 59 album:id3.album, … … 67 61 comment:id3.comment, 68 62 genre:id3.genre, 69 songName:id3.songName,63 name:id3.songName, 70 64 track:id3.track, 71 65 year:id3.year … … 77 71 78 72 /** Load the sound. **/ 79 public function load():void {80 position = model.playlist[model.config['item']]['start'];73 override public function load(itm:Object):void { 74 super.load(itm); 81 75 sound = new Sound(); 82 76 sound.addEventListener(IOErrorEvent.IO_ERROR,errorHandler); … … 84 78 sound.addEventListener(Event.COMPLETE,loadedHandler); 85 79 sound.addEventListener(Event.ID3,id3Handler); 86 sound.load(new URLRequest( model.playlist[model.config['item']]['file']),context);80 sound.load(new URLRequest(item['file']),context); 87 81 play(); 88 82 }; … … 91 85 /** Sound has been loaded, so the final duration is known. **/ 92 86 private function loadedHandler(evt:Event):void { 93 model.sendEvent(ModelEvent.META,{duration: Math.round(sound.length/100)/10});87 model.sendEvent(ModelEvent.META,{duration:sound.length/1000-item['start']}); 94 88 }; 95 89 96 90 97 91 /** Pause the sound. **/ 98 public function pause():void {99 clearInterval(interval);92 override public function pause():void { 93 super.pause(); 100 94 channel.stop(); 101 model.sendEvent(ModelEvent.STATE,{newstate:ModelStates.PAUSED});102 95 }; 103 96 104 97 105 98 /** Play the sound. **/ 106 public function play():void { 99 override public function play():void { 100 super.play(); 107 101 channel = sound.play(position*1000,0,transform); 108 channel.removeEventListener(Event.SOUND_COMPLETE,completeHandler);109 102 channel.addEventListener(Event.SOUND_COMPLETE,completeHandler); 110 interval = setInterval(timeHandler,100); 111 model.sendEvent(ModelEvent.STATE,{newstate:ModelStates.PLAYING}); 103 }; 104 105 106 /** Interval for the position progress **/ 107 override protected function positionInterval():void { 108 position = Math.round(channel.position/100)/10; 109 if(sound.isBuffering == true && sound.bytesTotal > sound.bytesLoaded) { 110 if(model.config['state'] != ModelStates.BUFFERING) { 111 model.sendEvent(ModelEvent.STATE,{newstate:ModelStates.BUFFERING}); 112 } else { 113 var pct:Number = Math.floor(sound.length/(channel.position+model.config['bufferlength']*1000)*100); 114 model.sendEvent(ModelEvent.BUFFER,{percentage:pct}); 115 } 116 } else if (model.config['state'] == ModelStates.BUFFERING && sound.isBuffering == false) { 117 model.sendEvent(ModelEvent.STATE,{newstate:ModelStates.PLAYING}); 118 } 119 if(position-item['start'] < item['duration']) { 120 model.sendEvent(ModelEvent.TIME,{position:position-item['start'],duration:item['duration']}); 121 } else if(item['duration'] > 0) { 122 pause(); 123 model.sendEvent(ModelEvent.STATE,{newstate:ModelStates.COMPLETED}); 124 } 112 125 }; 113 126 … … 121 134 122 135 123 /** Change quality setting. **/124 public function quality(typ:Boolean):void {};125 126 127 136 /** Seek in the sound. **/ 128 public function seek(pos:Number):void { 129 clearInterval(interval); 130 position = pos; 137 override public function seek(pos:Number):void { 131 138 channel.stop(); 132 play();139 super.seek(pos); 133 140 }; 134 141 135 142 136 143 /** Destroy the sound. **/ 137 public function stop():void { 138 clearInterval(interval); 144 override public function stop():void { 139 145 if(channel) { channel.stop(); } 140 146 try { sound.close(); } catch (err:Error) {} 141 }; 142 143 144 /** Interval for the position progress **/ 145 private function timeHandler():void { 146 position = Math.round(channel.position/100)/10; 147 if(sound.isBuffering == true && sound.bytesTotal > sound.bytesLoaded) { 148 if(model.config['state'] != ModelStates.BUFFERING) { 149 model.sendEvent(ModelEvent.STATE,{newstate:ModelStates.BUFFERING}); 150 } else { 151 var pct:Number = Math.floor(sound.length/(channel.position+model.config['bufferlength']*1000)*100); 152 model.sendEvent(ModelEvent.BUFFER,{percentage:pct}); 153 } 154 } else if (model.config['state'] == ModelStates.BUFFERING && sound.isBuffering == false) { 155 model.sendEvent(ModelEvent.STATE,{newstate:ModelStates.PLAYING}); 156 } 157 model.sendEvent(ModelEvent.TIME,{position:position}); 147 super.stop(); 158 148 }; 159 149 160 150 161 151 /** Set the volume level. **/ 162 public function volume(vol:Number):void {152 override public function volume(vol:Number):void { 163 153 transform.volume = vol/100; 164 154 if(channel) { -
trunk/as3/com/jeroenwijering/models/VideoModel.as
r104 r135 6 6 7 7 import com.jeroenwijering.events.*; 8 import com.jeroenwijering.models. ModelInterface;8 import com.jeroenwijering.models.BasicModel; 9 9 import com.jeroenwijering.player.Model; 10 10 import com.jeroenwijering.utils.NetClient; 11 11 12 import flash.events.*; 12 import flash.display.DisplayObject; 13 import flash.media.SoundTransform; 14 import flash.media.Video; 13 import flash.media.*; 15 14 import flash.net.*; 16 import flash.utils.clearInterval; 17 import flash.utils.setInterval; 15 import flash.utils.*; 18 16 19 17 20 public class VideoModel implements ModelInterface{18 public class VideoModel extends BasicModel { 21 19 22 20 23 /** reference to the model. **/24 private var model:Model;25 21 /** Video object to be instantiated. **/ 26 pr ivatevar video:Video;22 protected var video:Video; 27 23 /** NetConnection object for setup of the video stream. **/ 28 pr ivatevar connection:NetConnection;24 protected var connection:NetConnection; 29 25 /** NetStream instance that handles the stream IO. **/ 30 pr ivatevar stream:NetStream;26 protected var stream:NetStream; 31 27 /** Sound control object. **/ 32 private var transform:SoundTransform; 33 /** Interval ID for the time. **/ 34 private var timeinterval:Number; 28 protected var transform:SoundTransform; 35 29 /** Interval ID for the loading. **/ 36 private var loadinterval:Number; 37 /** Metadata received switch. **/ 38 private var metadata:Boolean; 30 protected var loadinterval:Number; 39 31 40 32 41 33 /** Constructor; sets up the connection and display. **/ 42 34 public function VideoModel(mod:Model):void { 43 model = mod;35 super(mod); 44 36 connection = new NetConnection(); 45 connection.addEventListener(NetStatusEvent.NET_STATUS,statusHandler);46 connection.addEventListener(SecurityErrorEvent.SECURITY_ERROR,errorHandler);47 connection.objectEncoding = ObjectEncoding.AMF0;48 37 connection.connect(null); 49 38 stream = new NetStream(connection); 50 39 stream.addEventListener(NetStatusEvent.NET_STATUS,statusHandler); 51 40 stream.addEventListener(IOErrorEvent.IO_ERROR,errorHandler); 52 stream.addEventListener(AsyncErrorEvent.ASYNC_ERROR, metaHandler);41 stream.addEventListener(AsyncErrorEvent.ASYNC_ERROR,errorHandler); 53 42 stream.bufferTime = model.config['bufferlength']; 54 43 stream.client = new NetClient(this); 55 44 video = new Video(320,240); 45 video.smoothing = model.config['smoothing']; 56 46 video.attachNetStream(stream); 57 47 transform = new SoundTransform(); 58 stream.soundTransform = transform;59 quality(model.config['quality']);60 48 model.config['mute'] == true ? volume(0): volume(model.config['volume']); 61 49 }; … … 63 51 64 52 /** Catch security errors. **/ 65 private function errorHandler(evt:ErrorEvent):void { 53 protected function errorHandler(evt:ErrorEvent):void { 54 stop(); 66 55 model.sendEvent(ModelEvent.ERROR,{message:evt.text}); 67 56 }; … … 69 58 70 59 /** Load content. **/ 71 public function load():void {72 video.clear();60 override public function load(itm:Object):void { 61 super.load(itm); 73 62 model.mediaHandler(video); 74 stream.play(model.playlist[model.config['item']]['file']); 63 stream.play(item['file']); 64 interval = setInterval(positionInterval,100); 75 65 loadinterval = setInterval(loadHandler,200); 76 timeinterval = setInterval(timeHandler,100);77 model.sendEvent(ModelEvent.STATE,{newstate:ModelStates.BUFFERING});78 66 }; 79 67 80 68 81 69 /** Interval for the loading progress **/ 82 pr ivate function loadHandler():void {83 var ldd = stream.bytesLoaded;84 var ttl = stream.bytesTotal;70 protected function loadHandler():void { 71 var ldd:Number = stream.bytesLoaded; 72 var ttl:Number = stream.bytesTotal; 85 73 model.sendEvent(ModelEvent.LOADED,{loaded:ldd,total:ttl}); 86 74 if(ldd == ttl && ldd > 0) { … … 90 78 91 79 92 /** Catch noncritical errors. **/93 private function metaHandler(evt:ErrorEvent):void {94 model.sendEvent(ModelEvent.META,{error:evt.text});95 };96 97 98 80 /** Get metadata information from netstream class. **/ 99 81 public function onData(dat:Object):void { 100 if(dat.type == 'metadata' && !metadata) { 101 metadata = true; 102 if(dat.width) { 103 video.width = dat.width; 104 video.height = dat.height; 105 } 106 if(model.playlist[model.config['item']]['start'] > 0) { 107 seek(model.playlist[model.config['item']]['start']); 108 } 82 if(dat.width) { 83 video.width = dat.width; 84 video.height = dat.height; 85 } 86 if(dat.duration) { 87 dat.duration -= item['start']; 109 88 } 110 89 model.sendEvent(ModelEvent.META,dat); … … 113 92 114 93 /** Pause playback. **/ 115 public function pause():void {116 clearInterval(timeinterval);94 override public function pause():void { 95 super.pause(); 117 96 stream.pause(); 118 model.sendEvent(ModelEvent.STATE,{newstate:ModelStates.PAUSED});119 97 }; 120 98 121 99 122 100 /** Resume playing. **/ 123 public function play():void { 101 override public function play():void { 102 super.play(); 124 103 stream.resume(); 125 timeinterval = setInterval(timeHandler,100);126 model.sendEvent(ModelEvent.STATE,{newstate:ModelStates.PLAYING});127 104 }; 128 105 129 106 130 /** Change the smoothing mode. **/ 131 public function quality(qua:Boolean):void { 132 if(qua == true) { 133 video.smoothing = true; 134 video.deblocking = 3; 135 } else { 136 video.smoothing = false; 137 video.deblocking = 1; 107 /** Interval for the position progress **/ 108 override protected function positionInterval():void { 109 position = Math.round(stream.time*10)/10; 110 var bfr:Number = Math.round(stream.bufferLength/stream.bufferTime*100); 111 if(bfr < 95 && position < Math.abs(item['duration']-stream.bufferTime-1)) { 112 model.sendEvent(ModelEvent.BUFFER,{percentage:bfr}); 113 if(model.config['state'] != ModelStates.BUFFERING && bfr < 25) { 114 model.sendEvent(ModelEvent.STATE,{newstate:ModelStates.BUFFERING}); 115 } 116 } else if (bfr > 95 && model.config['state'] != ModelStates.PLAYING) { 117 model.sendEvent(ModelEvent.STATE,{newstate:ModelStates.PLAYING}); 118 } 119 if(position-item['start'] < item['duration']) { 120 var pos:Number = Math.max(0,Math.round((position-item['start'])*10)/10); 121 model.sendEvent(ModelEvent.TIME,{position:pos,duration:item['duration']}); 122 } else if (item['duration'] > 0) { 123 pause(); 124 model.sendEvent(ModelEvent.STATE,{newstate:ModelStates.COMPLETED}); 138 125 } 139 126 }; 140 127 141 128 142 /** Change the smoothing mode. **/ 143 public function seek(pos:Number):void { 144 clearInterval(timeinterval); 145 stream.seek(pos); 146 play(); 129 /** Seek to a new position. **/ 130 override public function seek(pos:Number):void { 131 super.seek(pos); 132 stream.seek(position); 147 133 }; 148 134 149 135 150 136 /** Receive NetStream status updates. **/ 151 private function statusHandler(evt:NetStatusEvent):void { 152 if(evt.info.code == "NetStream.Play.Stop" && stream.bytesLoaded == stream.bytesTotal) { 153 clearInterval(timeinterval); 154 model.sendEvent(ModelEvent.STATE,{newstate:ModelStates.COMPLETED}); 155 } else if (evt.info.code == "NetStream.Play.StreamNotFound") { 156 stop(); 157 model.sendEvent(ModelEvent.ERROR,{message:'Video not found: '+model.playlist[model.config['item']]['file']}); 137 protected function statusHandler(evt:NetStatusEvent):void { 138 switch (evt.info.code) { 139 case "NetStream.Play.Stop": 140 clearInterval(interval); 141 model.sendEvent(ModelEvent.STATE,{newstate:ModelStates.COMPLETED}); 142 break; 143 case "NetStream.Play.StreamNotFound": 144 stop(); 145 model.sendEvent(ModelEvent.ERROR,{message:'Video not found: '+item['file']}); 146 break; 147 default: 148 model.sendEvent(ModelEvent.META,{info:evt.info.code}); 149 break; 158 150 } 159 model.sendEvent(ModelEvent.META,{info:evt.info.code});160 151 }; 161 152 162 153 163 154 /** Destroy the video. **/ 164 public function stop():void { 165 stream.pause(); 166 if(stream.bytesLoaded != stream.bytesTotal) { 167 stream.close(); 168 } 169 metadata = false; 155 override public function stop():void { 156 stream.close(); 170 157 clearInterval(loadinterval); 171 clearInterval(timeinterval); 172 }; 173 174 175 /** Interval for the position progress **/ 176 private function timeHandler():void { 177 var bfr = Math.round(stream.bufferLength/stream.bufferTime*100); 178 var pos = Math.round(stream.time*10)/10; 179 var dur = model.playlist[model.config['item']]['duration']; 180 if(bfr < 95 && pos < Math.abs(dur-stream.bufferTime*2)) { 181 model.sendEvent(ModelEvent.BUFFER,{percentage:bfr}); 182 if(model.config['state'] != ModelStates.BUFFERING && bfr < 10) { 183 model.sendEvent(ModelEvent.STATE,{newstate:ModelStates.BUFFERING}); 184 } 185 } else if (model.config['state'] == ModelStates.BUFFERING) { 186 model.sendEvent(ModelEvent.STATE,{newstate:ModelStates.PLAYING}); 187 } 188 model.sendEvent(ModelEvent.TIME,{position:pos}); 158 super.stop(); 189 159 }; 190 160 191 161 192 162 /** Set the volume level. **/ 193 public function volume(vol:Number):void {163 override public function volume(vol:Number):void { 194 164 transform.volume = vol/100; 195 165 stream.soundTransform = transform; -
trunk/as3/com/jeroenwijering/models/YoutubeModel.as
r115 r135 1 1 /** 2 * Wrapper for load and playback of Youtube videos .2 * Wrapper for load and playback of Youtube videos through their API. 3 3 **/ 4 4 package com.jeroenwijering.models { … … 6 6 7 7 import com.jeroenwijering.events.*; 8 import com.jeroenwijering.models. ModelInterface;8 import com.jeroenwijering.models.BasicModel; 9 9 import com.jeroenwijering.player.Model; 10 import flash.display.Sprite; 10 11 11 import flash.display.Loader; 12 import flash.net.URLRequest;13 12 import flash.events.*; 14 13 import flash.net.LocalConnection; 15 import flash.utils.setInterval; 16 import flash.utils.setTimeout; 17 import flash.utils.clearInterval; 18 19 20 public class YoutubeModel implements ModelInterface { 21 22 23 /** Reference to the Model **/ 24 private var model:Model; 14 import flash.net.URLRequest; 15 import flash.system.Security; 16 17 18 public class YoutubeModel extends BasicModel { 19 20 25 21 /** Loader for loading the YouTube proxy **/ 26 22 private var loader:Loader; … … 41 37 /** Setup YouTube connections and load proxy. **/ 42 38 public function YoutubeModel(mod:Model):void { 43 model = mod; 44 unique = Math.random().toString().substr(2); 39 super(mod); 40 Security.allowDomain('*'); 41 var url:String = model.skin.loaderInfo.url; 42 var ytb:String = 'yt.swf'; 43 if(url.indexOf('http://') == 0) { 44 unique = Math.random().toString().substr(2); 45 var str:String = url.substr(0,url.indexOf('.swf')); 46 ytb = str.substr(0,str.lastIndexOf('/')+1)+'yt.swf?unique='+unique; 47 } else { 48 unique = '1'; 49 } 45 50 outgoing = new LocalConnection(); 46 51 outgoing.allowDomain('*'); … … 56 61 loader = new Loader(); 57 62 loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR,errorHandler); 58 var url = model.skin.loaderInfo.url;59 var ytb = url.substr(0,url.lastIndexOf('/')+1)+'yt.swf?unique='+unique;60 63 loader.load(new URLRequest(ytb)); 61 64 }; … … 64 67 /** Catch load errors. **/ 65 68 private function errorHandler(evt:ErrorEvent):void { 69 stop(); 66 70 model.sendEvent(ModelEvent.ERROR,{message:evt.text}); 67 71 }; … … 86 90 87 91 /** Load the YouTube movie. **/ 88 public function load():void { 92 override public function load(itm:Object):void { 93 super.load(itm); 89 94 if(connected) { 90 95 model.sendEvent(ModelEvent.STATE,{newstate:ModelStates.BUFFERING}); 91 96 loading = true; 92 97 if(outgoing) { 93 var gid = getID(model.playlist[model.config['item']]['file']); 94 var stt = model.playlist[model.config['item']]['start']; 95 outgoing.send('AS3_'+unique,"loadVideoById",gid,stt); 98 var gid = getID(item['file']); 99 outgoing.send('AS3_'+unique,"loadVideoById",gid,0); 96 100 model.mediaHandler(loader); 97 101 } … … 101 105 102 106 /** Pause the YouTube movie. **/ 103 public function pause():void {107 override public function pause():void { 104 108 outgoing.send('AS3_'+unique,"pauseVideo"); 105 109 }; … … 108 112 109 113 /** Play or pause the video. **/ 110 public function play():void {114 override public function play():void { 111 115 outgoing.send('AS3_'+unique,"playVideo"); 112 116 }; … … 117 121 outgoing.send('AS3_'+unique,"setSize",320,240); 118 122 model.config['mute'] == true ? volume(0): volume(model.config['volume']); 119 if(loading) { load( ); }123 if(loading) { load(item); } 120 124 }; 121 125 … … 129 133 /** Catch youtube errors. **/ 130 134 public function onError(erc:String):void { 131 var fil = model.playlist[model.config['item']]['file']; 132 model.sendEvent(ModelEvent.ERROR,{message:"YouTube error (video not found?):\n"+fil}); 135 model.sendEvent(ModelEvent.ERROR,{message:"YouTube error (video not found?):\n"+item['file']}); 133 136 stop(); 134 137 }; … … 168 171 /** Catch Youtube position changes **/ 169 172 public function onTimeChange(pos:Number,dur:Number):void { 170 model.sendEvent(ModelEvent.TIME,{position:pos });173 model.sendEvent(ModelEvent.TIME,{position:pos,duration:dur}); 171 174 if(!metasent) { 172 175 model.sendEvent(ModelEvent.META,{width:320,height:240,duration:dur}); … … 176 179 177 180 178 /** Toggle quality (perhaps access the H264 versions later?). **/179 public function quality(stt:Boolean):void {};180 181 182 181 /** Seek to position. **/ 183 public function seek(pos:Number):void {182 override public function seek(pos:Number):void { 184 183 outgoing.send('AS3_'+unique,"seekTo",pos); 185 184 play(); … … 188 187 189 188 /** Destroy the youtube video. **/ 190 public function stop():void {189 override public function stop():void { 191 190 metasent = false; 192 191 outgoing.send('AS3_'+unique,"stopVideo"); 192 super.stop(); 193 193 }; 194 194 … … 196 196 197 197 /** Set the volume level. **/ 198 public function volume(pct:Number):void {198 override public function volume(pct:Number):void { 199 199 outgoing.send('AS3_'+unique,"setVolume",pct); 200 200 }; -
trunk/as3/com/jeroenwijering/parsers/ATOMParser.as
r123 r135 43 43 } else if (i.@rel == 'enclosure') { 44 44 itm['file'] = i.@href.toString(); 45 if(i.@type) {46 itm['type'] = ObjectParser.MIMETYPES[i.@type.toString()];47 }48 45 } 49 46 break; -
trunk/as3/com/jeroenwijering/parsers/MediaParser.as
r103 r135 21 21 * @see RSSParser 22 22 **/ 23 public static function parseGroup(obj:XML,itm:Object):Object { 23 public static function parseGroup(obj:XML,itm:Object):Object { 24 24 for each (var i:XML in obj.children()) { 25 25 switch(i.localName()) { 26 26 case 'content': 27 if(!itm['file']) {27 if( !itm['file']) { 28 28 itm['file'] = i.@url.toString(); 29 29 } 30 if(i.@ type) {31 itm[' type'] = ObjectParser.MIMETYPES[i.@type.toString()];30 if(i.@start) { 31 itm['start'] = Strings.seconds(i.@start.toString()); 32 32 } 33 33 if(i.@duration) { 34 34 itm['duration'] = Strings.seconds(i.@duration.toString()); 35 }36 if(i.@start) {37 itm['start'] = Strings.seconds(i.@start.toString());38 35 } 39 36 if(i.children().length() >0) { -
trunk/as3/com/jeroenwijering/parsers/ObjectParser.as
r103 r135 20 20 'image':undefined, 21 21 'link':undefined, 22 'title':undefined,23 22 'start':0, 24 23 'streamer':undefined, 25 24 'tags':undefined, 25 'title':undefined, 26 26 'type':undefined 27 27 }; … … 48 48 'vp6':'video' 49 49 }; 50 /** Mimetypes of all supported mediafiles. **/51 public static var MIMETYPES:Object = {52 'application/x-fcs':'video',53 'application/x-shockwave-flash':'image',54 'audio/aac':'video',55 'audio/m4a':'video',56 'audio/mp4':'video',57 'audio/mp3':'sound',58 'audio/mpeg':'sound',59 'audio/x-3gpp':'video',60 'audio/x-m4a':'video',61 'image/gif':'image',62 'image/jpeg':'image',63 'image/jpg':'image',64 'image/png':'image',65 'video/flv':'video',66 'video/3gpp':'video',67 'video/h264':'video',68 'video/mp4':'video',69 'video/x-3gpp':'video',70 'video/x-flv':'video',71 'video/x-m4v':'video',72 'video/x-mp4':'video'73 };74 50 75 51 -
trunk/as3/com/jeroenwijering/parsers/RSSParser.as
r100 r135 39 39 case 'enclosure': 40 40 itm['file'] = i.@url.toString(); 41 itm['type'] = ObjectParser.MIMETYPES[i.@type.toString()];42 41 break; 43 42 case 'title': -
trunk/as3/com/jeroenwijering/parsers/SMILParser.as
r100 r135 85 85 itm['file'] = obj.@src.toString(); 86 86 break; 87 case 'type':88 itm['type'] = ObjectParser.MIMETYPES[obj.@type.toString()];89 break;90 87 case 'dur': 91 88 itm['duration'] = Strings.seconds(obj.@dur.toString()); -
trunk/as3/com/jeroenwijering/player/Controller.as
r124 r135 66 66 view.addEventListener(ViewEvent.PLAY,playHandler); 67 67 view.addEventListener(ViewEvent.PREV,prevHandler); 68 view.addEventListener(ViewEvent.QUALITY,qualityHandler);69 68 view.addEventListener(ViewEvent.REDRAW,redrawHandler); 70 69 view.addEventListener(ViewEvent.SEEK,seekHandler); … … 108 107 /** Return the type of specific playlistitem (the Model to play it with) **/ 109 108 private function getModelType(itm:Object):String { 110 // no file, so nothing to play111 109 if(!itm['file']) { 112 110 return null; 113 } 114 var ext:String = ObjectParser.EXTENSIONS[itm['file'].substr(-3).toLowerCase()]; 115 // string matches on the file 116 if(itm['file'].indexOf('youtube.com/w') > -1 || itm['file'].indexOf('youtube.com/v') > -1) { 117 return 'youtube'; 118 } else if(itm['file'].indexOf('.brightcove.com') > -1) { 119 return 'brightcove'; 120 } 121 // recognized mimetype/extension and streamer 122 if((itm['type'] == 'video' || ext) && itm['streamer']) { 111 } else if(itm['type']) { 112 return itm['type']; 113 } else if (itm['streamer']) { 123 114 if(itm['streamer'].substr(0,4) == 'rtmp') { 124 115 return 'rtmp'; 116 } else if(itm['streamer'].substr(0,4) == 'http') { 117 return 'http'; 125 118 } else { 126 return 'http'; 127 } 128 } 129 // user-defined type or recognized mimetypes 130 if(itm['type']) { 131 if(ObjectParser.EXTENSIONS[itm['type']]) { 132 return ObjectParser.EXTENSIONS[itm['type']]; 133 } else { 134 return itm['type']; 135 } 136 } 137 // extension is returned (can be null) 138 return ext; 119 return itm['streamer']; 120 } 121 } else if(itm['file'].indexOf('youtube.com/w') > -1 || itm['file'].indexOf('youtube.com/v') > -1) { 122 return 'youtube'; 123 } else { 124 return ObjectParser.EXTENSIONS[itm['file'].substr(-3).toLowerCase()]; 125 } 139 126 }; 140 127 … … 199 186 var fmt:String = dat.localName().toLowerCase(); 200 187 } catch (err:Error) { 201 dispatchEvent(new ControllerEvent(ControllerEvent.ERROR, 'This playlist is not a valid XML file.'));188 dispatchEvent(new ControllerEvent(ControllerEvent.ERROR,{message:'This playlist is not a valid XML file.'})); 202 189 return; 203 190 } … … 219 206 break; 220 207 default: 221 dispatchEvent(new ControllerEvent(ControllerEvent.ERROR, 'Unknown playlist format: '+fmt));208 dispatchEvent(new ControllerEvent(ControllerEvent.ERROR,{message:'Unknown playlist format: '+fmt})); 222 209 return; 223 210 } … … 227 214 /** Update playlist item duration. **/ 228 215 private function metaHandler(evt:ModelEvent):void { 229 if(evt.data.duration > 0&& playlist[config['item']]['duration'] == 0) {216 if(evt.data.duration && playlist[config['item']]['duration'] == 0) { 230 217 playlist[config['item']]['duration'] = evt.data.duration; 231 218 } … … 271 258 dispatchEvent(new ControllerEvent(ControllerEvent.PLAY,{state:true})); 272 259 } else if (evt.data.state != false && config['state'] == ModelStates.COMPLETED) { 273 dispatchEvent(new ControllerEvent(ControllerEvent.SEEK,{position: playlist[config['item']]['start']}));260 dispatchEvent(new ControllerEvent(ControllerEvent.SEEK,{position:0})); 274 261 } else if(evt.data.state != false && config['state'] == ModelStates.IDLE) { 275 262 playItem(); … … 284 271 /** Direct the model to play a new item. **/ 285 272 private function playItem(nbr:Number=undefined):void { 286 if(nbr > -1) { 287 if(playlist[nbr]['file'] == playlist[config['item']]['file']) { 288 playlist[nbr]['duration'] = playlist[config['item']]['duration']; 289 } 273 if(!isNaN(nbr)) { 290 274 config['item'] = nbr; 291 275 } … … 297 281 private function playlistHandler(ply:Array):void { 298 282 for(var i:Number=ply.length-1; i>-1; i--) { 299 if(!ply[i]['streamer']) { ply[i]['streamer'] = config['streamer']; }300 283 if(!ply[i]['duration']) { ply[i]['duration'] = 0; } 301 284 if(!ply[i]['start']) { ply[i]['start'] = 0; } 285 if(!ply[i]['streamer']) { ply[i]['streamer'] = config['streamer']; } 302 286 ply[i]['type'] = getModelType(ply[i]); 303 287 if(!ply[i]['type']) { ply.splice(i,1); } … … 329 313 playItem(config['item']-1); 330 314 } 331 };332 333 334 /** Switch playback quality. **/335 private function qualityHandler(evt:ViewEvent=null):void {336 if(evt.data.state != undefined) {337 if(evt.data.state == config['quality']) {338 return;339 } else {340 config['quality'] = evt.data.state;341 }342 } else {343 config['quality'] = !config['quality'];344 }345 Configger.saveCookie('quality',config['quality']);346 dispatchEvent(new ControllerEvent(ControllerEvent.QUALITY,{state:config['quality']}));347 315 }; 348 316 -
trunk/as3/com/jeroenwijering/player/Model.as
r125 r135 1 1 /** 2 * Wrap all media API's and manage playback.2 * Wraps all media APIs (all models) and manages thumbnail display. 3 3 **/ 4 4 package com.jeroenwijering.player { … … 9 9 import com.jeroenwijering.player.*; 10 10 import com.jeroenwijering.utils.*; 11 11 12 import flash.display.*; 12 import flash.events.Event; 13 import flash.events.EventDispatcher; 13 import flash.events.*; 14 14 import flash.net.URLRequest; 15 15 import flash.system.LoaderContext; 16 import flash.utils.getDefinitionByName;17 16 18 17 … … 32 31 /** Loader for the preview image. **/ 33 32 private var thumb:Loader; 34 /** Save the current image to prevent overloading. **/ 33 /** Save the currently playing playlist item. **/ 34 private var item:Object; 35 /** Save the current image url to prevent duplicate loading. **/ 35 36 private var image:String; 36 /** Currently active model. **/ 37 private var currentModel:String; 38 39 40 /** Constructor, save arrays and set currentItem. **/ 37 38 39 /** Constructor, save references, setup listeners and init thumbloader. **/ 41 40 public function Model(cfg:Object,skn:MovieClip,ldr:SPLoader,ctr:Controller):void { 42 41 config = cfg; 43 42 skin = skn; 44 43 sploader = ldr; 45 Draw.clear(skin.display.media);46 44 controller = ctr; 47 45 controller.addEventListener(ControllerEvent.ITEM,itemHandler); … … 49 47 controller.addEventListener(ControllerEvent.PLAY,playHandler); 50 48 controller.addEventListener(ControllerEvent.PLAYLIST,playlistHandler); 51 controller.addEventListener(ControllerEvent.QUALITY,qualityHandler);52 49 controller.addEventListener(ControllerEvent.RESIZE,resizeHandler); 53 50 controller.addEventListener(ControllerEvent.SEEK,seekHandler); … … 55 52 controller.addEventListener(ControllerEvent.VOLUME,volumeHandler); 56 53 thumb = new Loader(); 57 thumb.contentLoaderInfo.addEventListener(Event.COMPLETE,resizeHandler); 54 thumb.contentLoaderInfo.addEventListener(Event.COMPLETE,thumbHandler); 55 Draw.clear(skin.display.media); 58 56 skin.display.addChildAt(thumb,skin.display.getChildIndex(skin.display.media)+1); 57 skin.display.media.visible = false; 59 58 models = new Object(); 60 59 }; 61 60 62 61 63 /** Item change: s witch the curently active model if there's a new URL**/62 /** Item change: stop the old model and start the new one. **/ 64 63 private function itemHandler(evt:ControllerEvent):void { 65 var typ:String = playlist[config['item']]['type']; 66 if(currentModel) { 67 models[currentModel].stop(); 68 } 69 if(!models[typ]) { 70 loadModel(typ); 71 } 72 if(models[typ]) { 73 currentModel = typ; 74 models[typ].load(); 64 if(item) { 65 models[item['type']].stop(); 66 } 67 item = controller.playlist[config['item']]; 68 if(!models[item['type']]) { 69 loadModel(item['type']); 70 } 71 if(models[item['type']]) { 72 models[item['type']].load(item); 75 73 } else { 76 sendEvent(ModelEvent.ERROR,{message:'No suiteable model found for playback.'}); 77 } 78 thumbLoader(); 74 sendEvent(ModelEvent.ERROR,{message:'No suiteable model found for playback of this file.'}); 75 } 76 if(item['image'] && item['image'] != image) { 77 image = item['image']; 78 thumb.load(new URLRequest(item['image']),new LoaderContext(true)); 79 } 79 80 }; 80 81 … … 92 93 models[typ] = new ImageModel(this); 93 94 break; 95 case 'lighttpd': 96 models[typ] = new LighttpdModel(this); 97 break; 98 case 'nginx': 99 models[typ] = new NginxModel(this); 100 break; 94 101 case 'rtmp': 95 102 models[typ] = new RTMPModel(this); … … 108 115 109 116 110 /** Place a loaded mediafile on stage **/ 111 public function mediaHandler(chd:DisplayObject=undefined):void { 117 /** 118 * Place the mediafile fro the current model on stage. 119 * 120 * @param obj The displayobject (MovieClip/Video/Loader) to display. 121 **/ 122 public function mediaHandler(obj:DisplayObject=undefined):void { 112 123 Draw.clear(skin.display.media); 113 skin.display.media.addChild( chd);124 skin.display.media.addChild(obj); 114 125 resizeHandler(); 115 126 }; 116 127 117 128 118 /** Load the configuration array. **/129 /** Make the current model toggle its mute state. **/ 119 130 private function muteHandler(evt:ControllerEvent):void { 120 if( currentModel) {131 if(item) { 121 132 if(evt.data.state == true) { 122 models[ currentModel].volume(0);133 models[item['type']].volume(0); 123 134 } else { 124 models[ currentModel].volume(config['volume']);135 models[item['type']].volume(config['volume']); 125 136 } 126 137 } … … 128 139 129 140 130 /** Togge the playback state. **/141 /** Make the current model play or pause. **/ 131 142 private function playHandler(evt:ControllerEvent):void { 132 if( currentModel) {143 if(item) { 133 144 if(evt.data.state == true) { 134 models[ currentModel].play();145 models[item['type']].play(); 135 146 } else { 136 models[ currentModel].pause();147 models[item['type']].pause(); 137 148 } 138 149 } … … 140 151 141 152 142 /** Send an idle with new playlist. **/153 /** Load a new thumbnail. **/ 143 154 private function playlistHandler(evt:ControllerEvent):void { 144 thumbLoader(); 145 }; 146 147 148 /** Toggle the playback quality. **/ 149 private function qualityHandler(evt:ControllerEvent):void { 150 if(currentModel) { 151 models[currentModel].quality(evt.data.state); 155 var img:String = controller.playlist[config['item']]['image']; 156 if(img && img != image) { 157 image = img; 158 thumb.load(new URLRequest(img),new LoaderContext(true)); 152 159 } 153 160 }; … … 158 165 var cfg:Object = sploader.getPluginConfig(sploader.getPlugin('display')); 159 166 Stretcher.stretch(skin.display.media,cfg['width'],cfg['height'],config['stretching']); 160 if(thumb. content) {167 if(thumb.width > 10) { 161 168 Stretcher.stretch(thumb,cfg['width'],cfg['height'],config['stretching']); 162 169 } … … 164 171 165 172 166 /** Seek inside a file. **/173 /** Make the current model seek. **/ 167 174 private function seekHandler(evt:ControllerEvent):void { 168 if( currentModel) {169 models[ currentModel].seek(evt.data.position);170 } 171 }; 172 173 174 /** Load the configuration array. **/175 if(item) { 176 models[item['type']].seek(evt.data.position); 177 } 178 }; 179 180 181 /** Make the current model stop and show the thumb. **/ 175 182 private function stopHandler(evt:ControllerEvent=undefined):void { 176 image = undefined; 177 if(currentModel) { 178 models[currentModel].stop(); 179 } 180 sendEvent(ModelEvent.STATE,{newstate:ModelStates.IDLE}); 181 }; 182 183 184 /** Dispatch events. State switch is saved. **/ 183 if(item) { 184 models[item['type']].stop(); 185 } 186 }; 187 188 189 /** 190 * Dispatch events to the View/ Controller. 191 * When switching states, the thumbnail is shown/hidden. 192 * 193 * @param typ The eventtype to dispatch. 194 * @param dat An object with data to send along. 195 * @see ModelEvent 196 **/ 185 197 public function sendEvent(typ:String,dat:Object):void { 186 198 switch(typ) { … … 191 203 switch(dat['newstate']) { 192 204 case ModelStates.IDLE: 205 sendEvent(ModelEvent.LOADED,{loaded:0,offset:0,total:0}); 193 206 case ModelStates.COMPLETED: 194 207 thumb.visible = true; 195 208 skin.display.media.visible = false; 196 if(playlist) { 197 sendEvent(ModelEvent.TIME,{position:0,duration:playlist[config['item']]['duration']}); 198 } 209 sendEvent(ModelEvent.TIME,{position:0,duration:item['duration']}); 199 210 break; 200 211 case ModelStates.PLAYING: 201 var ext:String = playlist[config['item']]['file'].substr(-3).toLowerCase();212 var ext:String = item['file'].substr(-3).toLowerCase(); 202 213 if(ext != 'aac' && ext != 'mp3' && ext != 'm4a') { 203 214 thumb.visible = false; … … 210 221 } 211 222 break; 212 case ModelEvent.TIME:213 dat['duration'] = playlist[config['item']]['duration'];214 if(dat['duration'] > 0 && dat['duration'] < dat['position']) {215 models[currentModel].pause();216 sendEvent(ModelEvent.STATE,{newstate:ModelStates.COMPLETED});217 } else {218 dispatchEvent(new ModelEvent(typ,dat));219 }220 break;221 222 case ModelEvent.ERROR:223 models[currentModel].stop();224 sendEvent(ModelEvent.STATE,{newstate:ModelStates.IDLE});225 dispatchEvent(new ModelEvent(typ,dat));226 break;227 223 case ModelEvent.META: 228 224 if(dat.width) { resizeHandler(); } … … 234 230 235 231 236 /** Load a thumb on stage. **/ 237 private function thumbLoader():void { 238 var img:String = playlist[config['item']]['image']; 239 if(img && img != image) { 240 image = img; 241 thumb.load(new URLRequest(img),new LoaderContext(true)); 242 } 243 }; 244 245 246 /** Load the configuration array. **/ 232 /** Thumb loaded, try to antialias it before resizing. **/ 233 private function thumbHandler(evt:Event) { 234 try { 235 Bitmap(thumb.content).smoothing = true; 236 } catch (err:Error) {} 237 resizeHandler(); 238 }; 239 240 241 /** Make the current model change volume. **/ 247 242 private function volumeHandler(evt:ControllerEvent):void { 248 if(currentModel) { 249 models[currentModel].volume(evt.data.percentage); 250 } 251 }; 252 253 254 /** Getter for the playlist **/ 255 public function get playlist():Array { 256 return controller.playlist; 243 if(item) { 244 models[item['type']].volume(evt.data.percentage); 245 } 257 246 }; 258 247 -
trunk/as3/com/jeroenwijering/player/Player.as
r132 r135 19 19 public var config:Object = { 20 20 author:undefined, 21 description:undefined, 21 description:undefined, 22 22 date:undefined, 23 23 duration:0, … … 50 50 logo:undefined, 51 51 mute:false, 52 quality:true,53 52 repeat:'none', 54 53 resizing:true, 55 54 shuffle:false, 55 smoothing:true, 56 56 state:'IDLE', 57 57 stretching:'uniform', 58 58 volume:90, 59 59 60 60 abouttext:undefined, 61 61 aboutlink:"http://www.longtailvideo.com/players/jw-flv-player/", … … 67 67 token:undefined, 68 68 tracecall:undefined, 69 version:'4. 3.132'69 version:'4.4.135' 70 70 }; 71 71 /** Base directory from which all plugins are loaded. **/ 72 public var basedir:String = "http://plugins.longtailvideo.com/";72 public var basedir:String = 'http://plugins.longtailvideo.com/'; 73 73 /** Reference to all stage graphics. **/ 74 74 public var skin:MovieClip; -
trunk/as3/com/jeroenwijering/player/SPLoader.as
r129 r135 41 41 42 42 /** Add an already inited plugin to the list. **/ 43 public function addPlugin(pgi:Object,nam:String) {43 public function addPlugin(pgi:Object,nam:String):void { 44 44 var obj:Object = {reference:pgi,name:nam,position:'over',size:180,x:0,y:0,width:400,height:300}; 45 45 // hack for the playlist/controlbar flashvars … … 53 53 obj['size'] = player.config['playlistsize']; 54 54 } 55 try { 56 for(var org:String in pgi.config) { 57 obj[org] = pgi.config[org]; 58 } 59 } catch (err:Error) {} 55 60 for(var str:String in player.config) { 56 61 if (str.indexOf(nam + ".") == 0) { … … 58 63 } 59 64 } 65 try { pgi.config = obj; } catch (err:Error) {} 60 66 plugins.push(obj); 61 67 pgi.initializePlugin(player.view); -
trunk/as3/com/jeroenwijering/player/View.as
r132 r135 6 6 7 7 import com.jeroenwijering.events.*; 8 import com.jeroenwijering.utils.Debug; 9 import com.jeroenwijering.utils.Strings; 8 import com.jeroenwijering.utils.*; 10 9 11 10 import flash.display.MovieClip; … … 143 142 144 143 145 private function getPlaylist():Array { 146 return controller.playlist; 144 private function getPlaylist():Array { 145 return controller.playlist; 147 146 }; 148 147 … … 260 259 addControllerListener(ControllerEvent.PLAY,setController); 261 260 addControllerListener(ControllerEvent.PLAYLIST,setController); 262 addControllerListener(ControllerEvent.QUALITY,setController);263 261 addControllerListener(ControllerEvent.RESIZE,setController); 264 262 addControllerListener(ControllerEvent.SEEK,setController); … … 279 277 addViewListener(ViewEvent.PLAY,setView); 280 278 addViewListener(ViewEvent.PREV,setView); 281 addViewListener(ViewEvent.QUALITY,setView);282 279 addViewListener(ViewEvent.REDRAW,setView); 283 280 addViewListener(ViewEvent.SEEK,setView); -
trunk/as3/com/jeroenwijering/plugins/Accessibility.as
r132 r135 21 21 22 22 23 24 23 /** List with configuration settings. **/ 25 p rivatevar config:Object = {24 public var config:Object = { 26 25 audio:undefined, 27 26 captions:undefined, … … 50 49 51 50 52 53 51 public function Accessibility():void { 54 52 loader = new URLLoader(); … … 58 56 59 57 /** Show/hide the captions **/ 60 public function hide Captions(stt:Boolean) {61 config['hide'] = !stt;58 public function hide(stt:Boolean) { 59 config['hide'] = stt; 62 60 clip.visible = config['hide']; 63 61 if(config['hide']) { … … 71 69 /** Clicking the hide button. **/ 72 70 private function hideClick(evt:MouseEvent) { 73 hide Captions(config['hide']);71 hide(!config['hide']); 74 72 }; 75 73 … … 78 76 public function initializePlugin(vie:AbstractView):void { 79 77 view = vie; 80 if(view.skin['accessibility']) {81 clip = view.skin['accessibility'];82 } else {83 clip = this['accessibility'];84 }85 loadVars();86 78 view.addControllerListener(ControllerEvent.ITEM,itemHandler); 87 79 view.addControllerListener(ControllerEvent.RESIZE,resizeHandler); 88 80 view.addModelListener(ModelEvent.TIME,timeHandler); 89 81 view.addModelListener(ModelEvent.STATE,stateHandler); 90 if(ExternalInterface.available && view.skin.loaderInfo.url.indexOf('http') == 0) { 91 try { 92 ExternalInterface.addCallback("hideCaptions",hideCaptions); 93 ExternalInterface.addCallback("muteAudio",muteAudio); 94 } catch (err:Error) {} 95 } 82 clip = this['accessibility']; 96 83 clip.tf.autoSize = TextFieldAutoSize.CENTER; 97 84 format = new TextFormat(null,config['fontsize']); 98 hide Captions(config['hide'])99 mute Audio(config['mute']);85 hide(config['hide']); 86 mute(config['mute']); 100 87 try { 101 if(config['audio']) { 102 view.getPlugin('controlbar').addButton(clip.audioIcon,'audio',muteClick); 103 } 104 if(config['captions']) { 105 view.getPlugin('controlbar').addButton(clip.captionsIcon,'captions',hideClick); 106 } 88 setButtons(); 107 89 } catch (erro:Error) { 108 clip.audioIcon.visible = clip.captionsIcon.visible = false; 109 } 90 clip.audioIcon.visible = clip.captionsIcon.visible = false; 91 } 92 try { 93 ExternalInterface.addCallback("hideCaptions",hide); 94 ExternalInterface.addCallback("muteAudio",mute); 95 } catch (err:Error) {} 110 96 }; 111 97 … … 143 129 144 130 145 146 /** Load variables from the main config. **/147 private function loadVars() {148 config['audio'] = view.config['audio'];149 config['captions'] = view.config['captions'];150 for(var str:String in config) {151 if(view.config['accessibility.'+str]) {152 config[str] = view.config['accessibility.'+str];153 }154 }155 }156 157 158 131 /** Mute/unmute the audiodesc. **/ 159 p rivate function muteAudio(stt:Boolean) {132 public function mute(stt:Boolean) { 160 133 config['mute'] = stt; 161 134 setVolume(); … … 170 143 /** Clicking the hide button. **/ 171 144 private function muteClick(evt:MouseEvent) { 172 mute Audio(!config['mute']);145 mute(!config['mute']); 173 146 }; 174 147 … … 183 156 184 157 /** Set the audidescription volume level. **/ 185 p ublicfunction setAudio():void {158 private function setAudio():void { 186 159 sound = new Sound(new URLRequest(config['audio'])); 187 160 channel = sound.play(); 188 161 setVolume(); 162 }; 163 164 /** Set buttons in the controlbar **/ 165 private function setButtons():void { 166 if(config['captions']) { 167 view.getPlugin('controlbar').addButton(clip.captionsIcon,'captions',hideClick); 168 } else { 169 clip.captionsIcon.visible = false; 170 } 171 if(config['audio']) { 172 view.getPlugin('controlbar').addButton(clip.audioIcon,'audio',muteClick); 173 } else { 174 clip.audioIcon.visible = false; 175 } 189 176 }; 190 177 -
trunk/as3/com/jeroenwijering/plugins/ClickProxy.as
r132 r135 15 15 16 16 /** Configuration values of the plugin. **/ 17 p rivatevar config:Object = {17 public var config:Object = { 18 18 listener:'clickListener' 19 19 }; … … 61 61 clip.buttonMode = true; 62 62 clip.mouseChildren = false; 63 for(var str:String in config) { 64 if(view.config['clickproxy.'+str]) { 65 config[str] = view.config['clickproxy.'+str]; 66 } 67 } 63 resizeHandler(); 68 64 }; 69 65 70 66 71 67 /** Resize the area. **/ 72 private function resizeHandler(evt:ControllerEvent= undefined) {68 private function resizeHandler(evt:ControllerEvent=null) { 73 69 clip.back.width = view.config['width']; 74 70 clip.back.height = view.config['height']; -
trunk/as3/com/jeroenwijering/plugins/Controlbar.as
r127 r135 8 8 import com.jeroenwijering.utils.*; 9 9 10 import flash.accessibility.*; 10 11 import flash.display.*; 11 12 import flash.events.MouseEvent; … … 26 27 private var bar:MovieClip; 27 28 /** List with configuration settings. **/ 28 p rivatevar config:Object;29 public var config:Object; 29 30 /** A list with all controls. **/ 30 31 private var stacker:Stacker; … … 50 51 unmuteButton:'MUTE' 51 52 }; 52 /** The actions for all sliders **/ 53 /** The actions for all sliders **/ 53 54 private var SLIDERS = { 54 55 timeSlider:'SEEK', … … 66 67 public function initializePlugin(vie:AbstractView):void { 67 68 view = vie; 68 config = view.getPluginConfig(this);69 69 view.addControllerListener(ControllerEvent.RESIZE,resizeHandler); 70 70 view.addModelListener(ModelEvent.LOADED,loadedHandler); … … 80 80 setColors(); 81 81 itemHandler(); 82 loadedHandler(); 82 83 muteHandler(); 84 stateHandler(); 85 timeHandler(); 83 86 volumeHandler(); 84 loadedHandler();85 timeHandler();86 stateHandler();87 87 }; 88 88 … … 97 97 public function addButton(icn:DisplayObject,nam:String,hdl:Function):void { 98 98 if(bar['linkButton'].back) { 99 var btn :MovieClip= Draw.clone(bar['linkButton']);99 var btn = Draw.clone(bar['linkButton']); 100 100 btn.name = nam+'Button'; 101 101 btn.visible = true; 102 btn.tabEnabled = true; 103 btn.tabIndex = 6; 104 var acs:AccessibilityProperties = new AccessibilityProperties(); 105 acs.name = nam+'Button'; 106 btn.accessibilityProperties = acs; 102 107 bar.addChild(btn); 103 108 var off:Number = Math.round((btn.height-icn.height)/2); … … 159 164 private function itemHandler(evt:ControllerEvent=null):void { 160 165 try { 161 if(view.playlist && view.playlist.length > 1 ) {166 if(view.playlist && view.playlist.length > 1 && view.config['playlist'] != 'none') { 162 167 bar.prevButton.visible = bar.nextButton.visible = true; 163 168 } else { … … 193 198 bar.timeSlider.mark.x = pc2*wid; 194 199 bar.timeSlider.mark.width = pc1*wid; 200 var icw:Number = bar.timeSlider.icon.x + bar.timeSlider.icon.width; 195 201 } catch (err:Error) {} 196 202 }; … … 266 272 bar.visible = config['visible']; 267 273 if(config['position'] == 'over' || view.config['fullscreen'] == true) { 268 bar.x = config[' margin'];274 bar.x = config['x'] + config['margin']; 269 275 bar.y = config['y'] + config['height'] - config['margin'] - config['size']; 270 276 wid = config['width'] - 2*config['margin']; … … 318 324 /** Init the colors. **/ 319 325 private function setColors():void { 320 if(view.config['backcolor'] && bar['playButton'].icon) { 326 if(view.config['backcolor'] && bar['playButton'].icon) { 321 327 var clr:ColorTransform = new ColorTransform(); 322 328 clr.color = uint('0x'+view.config['backcolor'].substr(-6)); … … 401 407 } else if(view.playlist) { 402 408 dur = view.playlist[view.config['item']]['duration']; 403 pos = view.playlist[view.config['item']]['start'];409 pos = 0; 404 410 } 405 411 var pct:Number = pos/dur; … … 414 420 bar.timeSlider.icon.visible = true; 415 421 bar.timeSlider.mark.visible = true; 422 bar.timeSlider.done.visible = true; 416 423 if(!scrubber) { 417 424 bar.timeSlider.icon.x = xps; 418 var dld:Number = bar.timeSlider.mark.x; 419 if(xps > dld) { 420 bar.timeSlider.done.x = dld; 421 bar.timeSlider.done.width = xps-dld; 422 bar.timeSlider.done.visible = true; 423 } else { 424 bar.timeSlider.done.visible = false; 425 } 425 bar.timeSlider.done.width = xps; 426 426 } 427 427 } else { … … 452 452 /** Reflect the new volume in the controlbar **/ 453 453 private function volumeHandler(evt:ControllerEvent=null):void { 454 try { 454 try { 455 455 var vsl:MovieClip = bar.volumeSlider; 456 456 vsl.mark.width = view.config['volume']*(vsl.rail.width-vsl.icon.width/2)/100; -
trunk/as3/com/jeroenwijering/plugins/Display.as
r132 r135 8 8 import com.jeroenwijering.utils.Draw; 9 9 import com.jeroenwijering.utils.Strings; 10 import flash.display.Loader; 11 import flash.display.MovieClip; 12 import flash.display.Sprite; 13 import flash.events.Event; 14 import flash.events.MouseEvent; 10 11 import flash.display.*; 12 import flash.events.*; 15 13 import flash.geom.ColorTransform; 16 14 import flash.net.URLRequest; 17 import flash.utils.clearTimeout; 18 import flash.utils.setTimeout; 15 import flash.utils.*; 19 16 20 17 … … 22 19 23 20 21 /** Configuration vars for this plugin. **/ 22 public var config:Object; 24 23 /** Reference to the MVC view. **/ 25 24 private var view:AbstractView; … … 28 27 /** Loader object for loading a logo. **/ 29 28 private var loader:Loader; 30 /** Configuration vars for this plugin. **/31 private var config:Object;32 29 /** The margins of the logo. **/ 33 30 private var margins:Array; … … 44 41 'nextIcon' 45 42 ); 46 /** ID for the buffer showing tiomeout. **/43 /** Timeout for hiding the buffericon. **/ 47 44 private var timeout:Number; 48 45 … … 55 52 public function initializePlugin(vie:AbstractView):void { 56 53 view = vie; 57 config = view.getPluginConfig(this);58 54 view.addControllerListener(ControllerEvent.ERROR,errorHandler); 55 view.addControllerListener(ControllerEvent.MUTE,stateHandler); 56 view.addControllerListener(ControllerEvent.PLAYLIST,stateHandler); 59 57 view.addControllerListener(ControllerEvent.RESIZE,resizeHandler); 60 view.addControllerListener(ControllerEvent.PLAYLIST,stateHandler);61 58 view.addModelListener(ModelEvent.BUFFER,bufferHandler); 62 59 view.addModelListener(ModelEvent.ERROR,errorHandler); … … 69 66 display.back.transform.colorTransform = clr; 70 67 } 71 if(view.config['screenalpha'] < 1) {72 display.back.alpha = view.config['screenalpha'];73 } else if(view.config['screenalpha'] < 100) {74 display.back.alpha = Number(view.config['screenalpha'])/100;75 }76 68 if(view.config['displayclick'] != 'none') { 77 69 display.addEventListener(MouseEvent.CLICK,clickHandler); … … 79 71 display.mouseChildren = false; 80 72 } 81 try { 82 if(display.logo.width == 10) { 83 Draw.clear(display.logo); 84 if(view.config['logo']) { setLogo(); } 85 } else { 86 logoHandler(); 87 } 88 } catch (err:Error) {} 73 if(display.logo) { 74 logoSetter(); 75 } 89 76 stateHandler(); 90 77 }; … … 93 80 /** Receive buffer updates. **/ 94 81 private function bufferHandler(evt:ModelEvent):void { 95 var pct:String = '';96 82 if(evt.data.percentage > 0) { 97 pct = Strings.zero(evt.data.percentage); 98 } 99 try { 100 display.bufferIcon.txt.text = pct; 101 } catch (err:Error) {} 83 Draw.set(display.bufferIcon.txt,'text',Strings.zero(evt.data.percentage)); 84 } else { 85 Draw.set(display.bufferIcon.txt,'text',''); 86 } 102 87 }; 103 88 … … 105 90 /** Process a click on the display. **/ 106 91 private function clickHandler(evt:MouseEvent):void { 107 if(view.config['state'] == ModelStates.IDLE) { 92 if(view.config['state'] == ModelStates.IDLE) { 108 93 view.sendEvent('PLAY'); 109 } else { 94 } else if (view.config['state'] == ModelStates.PLAYING && view.config['mute'] == true) { 95 view.sendEvent('MUTE'); 96 } else { 110 97 view.sendEvent(view.config['displayclick']); 111 98 } … … 116 103 private function errorHandler(evt:Object):void { 117 104 if(view.config['icons'] == true) { 118 try { 119 setIcon('errorIcon'); 120 display.errorIcon.txt.text = evt.data.message; 121 } catch (err:Error) {} 105 setIcon('errorIcon'); 106 Draw.set(display.errorIcon.txt,'text',evt.data.message); 122 107 } 123 108 }; … … 139 124 140 125 141 /** Receive resizing requests **/142 private function resizeHandler(evt:ControllerEvent=null):void {143 display.x = config['x'];144 display.y = config['y'];145 if(config['height'] > 0) {146 display.visible = true;147 } else {148 display.visible = false;149 }150 display.back.width = config['width'];151 display.back.height = config['height'];152 try {153 display.masker.width = config['width'];154 display.masker.height = config['height'];155 } catch (err:Error) {}156 for(var i:String in ICONS) {157 try {158 display[ICONS[i]].x = Math.round(config['width']/2);159 display[ICONS[i]].y = Math.round(config['height']/2);160 } catch (err:Error) {}161 }162 if(view.config['logo']) {163 logoHandler();164 }165 };166 167 168 /** Set a specific icon in the display. **/169 private function setIcon(icn:String=undefined):void {170 for(var i:String in ICONS) {171 if(display[ICONS[i]]) {172 if(icn == ICONS[i] && view.config['icons'] == true) {173 display[ICONS[i]].visible = true;174 } else {175 display[ICONS[i]].visible = false;176 }177 }178 }179 };180 181 182 126 /** Setup the logo loading. **/ 183 private function setLogo():void {127 private function logoSetter():void { 184 128 margins = new Array( 185 129 display.logo.x, … … 188 132 display.back.height-display.logo.y-display.logo.height 189 133 ); 190 loader = new Loader(); 191 loader.contentLoaderInfo.addEventListener(Event.COMPLETE,logoHandler); 192 display.logo.addChild(loader); 193 loader.load(new URLRequest(view.config['logo'])); 134 if(display.logo.width == 10) { 135 Draw.clear(display.logo); 136 } 137 if(view.config['logo']) { 138 Draw.clear(display.logo); 139 loader = new Loader(); 140 loader.contentLoaderInfo.addEventListener(Event.COMPLETE,logoHandler); 141 display.logo.addChild(loader); 142 loader.load(new URLRequest(view.config['logo'])); 143 } 144 }; 145 146 147 148 /** Receive resizing requests **/ 149 private function resizeHandler(evt:ControllerEvent):void { 150 if(config['height'] > 0) { 151 display.visible = true; 152 } else { 153 display.visible = false; 154 } 155 Draw.pos(display,config['x'],config['y']); 156 Draw.size(display.back,config['width'],config['height']); 157 Draw.size(display.masker,config['width'],config['height']); 158 for(var i:String in ICONS) { 159 Draw.pos(display[ICONS[i]],config['width']/2,config['height']/2); 160 } 161 if(display.logo) { 162 logoHandler(); 163 } 164 }; 165 166 167 /** Set a specific icon in the display. **/ 168 private function setIcon(icn:String=undefined):void { 169 clearTimeout(timeout); 170 for(var i:String in ICONS) { 171 if(display[ICONS[i]]) { 172 if(icn == ICONS[i] && view.config['icons'] == true) { 173 display[ICONS[i]].visible = true; 174 } else { 175 display[ICONS[i]].visible = false; 176 } 177 } 178 } 194 179 }; 195 180 … … 197 182 /** Handle a change in playback state. **/ 198 183 private function stateHandler(evt:Event=null):void { 199 clearTimeout(timeout);200 184 switch (view.config['state']) { 201 185 case ModelStates.PLAYING: 202 setIcon(); 186 if(view.config['mute'] == true) { 187 setIcon('muteIcon'); 188 } else { 189 setIcon(); 190 } 203 191 break; 204 192 case ModelStates.BUFFERING: 205 if(evt && evt['data']['oldstate'] == ModelStates.PLAYING) { 206 setIcon(); 193 if(evt && evt['data'].oldstate == ModelStates.PLAYING) { 207 194 timeout = setTimeout(setIcon,1500,'bufferIcon'); 208 195 } else { … … 213 200 if(view.config.displayclick == 'none' || !view.playlist) { 214 201 setIcon(); 215 } else { 202 } else { 216 203 setIcon('playIcon'); 217 204 } -
trunk/as3/com/jeroenwijering/plugins/HD.as
r132 r135 15 15 16 16 /** List with configuration settings. **/ 17 p rivatevar config:Object;17 public var config:Object; 18 18 /** Reference to the View of the player. **/ 19 19 private var view:AbstractView; … … 26 26 27 27 28 /** Qualityis clicked, so change the video. **/28 /** HD button is clicked, so change the video. **/ 29 29 private function clickHandler(evt:MouseEvent=null):void { 30 if(config['state']) { 30 if(config['state']) { 31 31 config['state'] = false; 32 32 } else { … … 47 47 view.addControllerListener(ControllerEvent.PLAYLIST,playlistHandler); 48 48 try { 49 config = view.getPluginConfig(this);50 } catch(err:Error) {51 config = {52 file:view.config['hd.file'],53 state:view.config['hd.state']54 }55 }56 setButton();57 try {58 49 view.getPlugin('controlbar').addButton(icon,'hd',clickHandler); 59 50 } catch (err:Error) { 60 51 icon.visible = false; 61 52 } 53 if(config['state'] == true) { 54 original = view.config['file']; 55 view.config['file'] = config['file']; 56 } 57 setButton(); 62 58 }; 63 59 … … 72 68 73 69 74 /** Reload the playlist with either the HD or default video s. **/70 /** Reload the playlist with either the HD or default video. **/ 75 71 private function reLoad():void { 76 var ply = view.playlist; 72 var fil:String; 73 var ply:Array = view.playlist; 77 74 if(config['state'] == true) { 78 ply[0]['file']= config['file'];75 fil = config['file']; 79 76 } else { 80 ply[0]['file']= original;77 fil = original; 81 78 } 82 view.sendEvent('LOAD',ply); 79 if(ply.length == 1) { 80 ply[0]['file'] = fil; 81 view.sendEvent('LOAD',ply); 82 } else { 83 view.sendEvent('LOAD',fil); 84 } 83 85 }; 84 86 … … 91 93 icon.alpha = 0.3; 92 94 } 93 } 95 }; 94 96 95 97 -
trunk/as3/com/jeroenwijering/plugins/MetaViewer.as
r132 r135 14 14 15 15 16 /** Object with configuration values. **/ 17 public var config:Object; 16 18 /** Reference to the View of the player. **/ 17 19 private var view:AbstractView; … … 20 22 /** Scrollbar clip for the metadata. **/ 21 23 private var scrollbar:Scrollbar; 22 /** initialize call for backward compatibility. **/ 23 public var initialize:Function = initializePlugin; 24 /** Formatted metadata string. **/ 25 private var metastring:String = "No metadata received yet." 26 /** Formatted seekpoints string. **/ 27 private var seekstring:String = "No seekpoints received yet."; 24 28 25 29 … … 29 33 clip.tf.mask = clip.ms; 30 34 clip.tf.autoSize = "left"; 31 clip.xx.mouseChildren = false; 32 clip.xx.buttonMode = true; 33 clip.xx.addEventListener(MouseEvent.CLICK,clickHandler); 35 clip.close.mouseChildren = clip.seek.mouseChildren = clip.meta.mouseChildren = false; 36 clip.close.buttonMode = clip.seek.buttonMode = clip.meta.buttonMode = true; 37 clip.close.addEventListener(MouseEvent.CLICK,closeHandler); 38 clip.seek.addEventListener(MouseEvent.CLICK,seekHandler); 39 clip.meta.addEventListener(MouseEvent.CLICK,metaHandler); 34 40 scrollbar = new Scrollbar(clip.tf,clip.ms); 35 41 }; 36 42 37 43 38 /** The initialize call is invoked by the player View. **/ 39 public function initializePlugin(vie:AbstractView):void { 40 view = vie; 41 view.addControllerListener(ControllerEvent.RESIZE,resizeHandler); 42 view.addModelListener(ModelEvent.META,metaHandler); 43 resizeHandler(); 44 /** When clicking the x, the viewer is closed. **/ 45 private function closeHandler(evt:MouseEvent) { 46 clip.visible = false; 44 47 }; 45 48 46 49 47 /** When clicking the x, the viewer is closed. **/48 private function clickHandler(evt:MouseEvent) { clip.visible = false; };49 50 51 50 /** Print the metadata in a list. **/ 52 private function metaHandler(evt:ModelEvent) {51 private function dataHandler(evt:ModelEvent) { 53 52 if(evt.data.type == 'metadata' || evt.data.type == 'id3') { 54 var str:String = '';53 var arr:Array = new Array(); 55 54 for (var itm:String in evt.data) { 56 55 switch(itm) { … … 61 60 break; 62 61 case 'keyframes': 63 str += '» '+itm+': '+evt.data[itm]['times'].length+' entries\n'; 62 seekstring = ''; 63 arr.push('» '+itm+': '+evt.data[itm]['times'].length+' entries'); 64 for (var i:Number=0; i<evt.data[itm]['times'].length; i++) { 65 seekstring += '» '+evt.data[itm]['times'][i]+'s - '+evt.data[itm]['filepositions'][i]+'b\n'; 66 } 64 67 break; 65 68 case 'seekpoints': 69 seekstring = ''; 70 for (var j:Number=0; j<evt.data[itm].length; j++) { 71 seekstring += '» '+evt.data[itm][j]['time']+'s - '+evt.data[itm][j]['offset']+'b\n'; 72 } 66 73 case 'trackinfo': 67 str += '» '+itm+': '+evt.data[itm].length+' entries\n';74 arr.push('» '+itm+': '+evt.data[itm].length+' entries'); 68 75 break; 69 76 default: 70 77 if(evt.data[itm] != '') { 71 str += '» '+itm+': '+evt.data[itm]+'\n';78 arr.push('» '+itm+': '+evt.data[itm]); 72 79 } 73 80 break; 74 81 } 75 82 } 76 clip.tf.text = str; 77 clip.visible = true; 78 scrollbar.draw(); 83 arr.sort(); 84 metastring = arr.join('\n'); 85 metaHandler(); 86 resizeHandler(); 79 87 } 88 }; 89 90 91 /** The initialize call is invoked by the player View. **/ 92 public function initializePlugin(vie:AbstractView):void { 93 view = vie; 94 view.addControllerListener(ControllerEvent.RESIZE,resizeHandler); 95 view.addModelListener(ModelEvent.META,dataHandler); 96 resizeHandler(); 97 }; 98 99 100 /** When clicking the x, the viewer is closed. **/ 101 private function metaHandler(evt:MouseEvent=null) { 102 clip.tf.text = metastring; 103 clip.meta.alpha = 1; 104 clip.seek.alpha = 0.3; 105 scrollbar.draw(); 80 106 }; 81 107 … … 85 111 var wid:Number = view.config['width']; 86 112 var hei:Number = view.config['height']; 87 try { 88 var cfg = view.getPluginConfig(this); 89 clip.x = cfg['x']; 90 clip.y = cfg['y']; 91 wid = cfg['width']; 92 hei = cfg['height']; 93 if(cfg['position'] != 'over') { 94 clip.xx.visible = false; 113 if(config['width']) { 114 clip.x = config['x']; 115 clip.y = config['y']; 116 wid = config['width']; 117 hei = config['height']; 118 if(config['position'] != 'over') { 119 clip.close.visible = false; 95 120 } 96 } catch(err:Error) {} 121 clip.visible = config['visible']; 122 } 97 123 clip.bg.width = wid; 98 124 clip.bg.height = hei; 99 125 clip.tf.width = clip.ms.width = wid-50; 100 126 clip.ms.height = hei-60; 101 clip.xx.x = wid-35; 127 clip.close.x = wid-35; 128 scrollbar.draw(); 129 }; 130 131 132 /** When clicking the x, the viewer is closed. **/ 133 private function seekHandler(evt:MouseEvent) { 134 clip.tf.text = seekstring; 135 clip.meta.alpha = 0.3; 136 clip.seek.alpha = 1; 102 137 scrollbar.draw(); 103 138 }; -
trunk/as3/com/jeroenwijering/plugins/Playlist.as
r132 r135 20 20 21 21 22 /** List with configuration settings. **/ 23 public var config:Object; 22 24 /** Reference to the view. **/ 23 25 private var view:AbstractView; 24 26 /** Reference to the playlist MC. **/ 25 27 private var clip:MovieClip; 26 /** List with configuration settings. **/27 private var config:Object;28 28 /** Array with all button instances **/ 29 29 private var buttons:Array; … … 52 52 public function initializePlugin(vie:AbstractView):void { 53 53 view = vie; 54 config = view.getPluginConfig(this);55 54 view.addControllerListener(ControllerEvent.ITEM,itemHandler); 56 55 view.addControllerListener(ControllerEvent.PLAYLIST,playlistHandler); … … 300 299 continue; 301 300 } else if(itm == 'image') { 302 if(view.playlist[idx]['image'] ) {301 if(view.playlist[idx]['image'] && config['thumbs'] != false) { 303 302 var img:MovieClip = buttons[idx].c.image; 304 303 var msk:Sprite = Draw.rect(buttons[idx].c,'0xFF0000',img.width,img.height,img.x,img.y); … … 327 326 } 328 327 } 329 if(buttons[idx].c['image'] && !view.playlist[idx]['image']) {328 if(buttons[idx].c['image'] && (!view.playlist[idx]['image'] || config['thumbs'] == false)) { 330 329 buttons[idx].c['image'].visible = false; 331 330 } -
trunk/as3/com/jeroenwijering/plugins/Revolt.as
r132 r135 9 9 import com.anttikupila.revolt.presets.*; 10 10 import com.jeroenwijering.events.*; 11 import com.jeroenwijering.utils.Randomizer; 11 12 12 13 import flash.media.*; … … 20 21 21 22 22 private var gfx:BitmapData; 23 /** Configuration data of the plugin. **/ 24 public var config:Object = { 25 gain:1, 26 simple:false, 27 sound:false, 28 timeout:10 29 }; 30 /** List of visualization presets. **/ 31 private var presets:Array; 32 /** Randomizer for the preset. **/ 33 private var randomizer:Randomizer; 34 /** Reference to the View of the player. **/ 35 private var view:AbstractView; 36 /** Clip in which the visuals are shown. **/ 23 37 private var clip:Sprite; 24 private var presetList:Array; 25 private var presetInt:Timer; 26 private var preset:Preset; 27 private var view:AbstractView; 28 private var ba:ByteArray; 29 public var initialize:Function; 38 /** Matrix in which the bitmapdata is loaded. **/ 39 private var bitmap:BitmapData; 40 /** Bytearray in which the bitmapdata is loaded. **/ 41 private var array:ByteArray; 42 /** ID for the timeout between preset switches. **/ 43 private var timeout:Number; 44 /** Currently active preset. **/ 45 private var current:Preset; 30 46 31 47 32 48 /** Setup all presets and the click. **/ 33 49 public function Revolt() { 34 preset List= new Array(50 presets = new Array( 35 51 new LineFourier(), 36 new LineNoFourier(),37 52 new Explosion(), 38 53 new LineSmooth(), … … 40 55 new Tunnel() 41 56 ); 42 clip = new Sprite(); 43 ba = new ByteArray(); 44 initialize = this.initializePlugin; 45 addChild(clip); 46 presetInt = new Timer(10000,0); 47 presetInt.addEventListener(TimerEvent.TIMER,nextPreset); 48 clip.addEventListener(MouseEvent.CLICK,nextPreset); 49 clip.buttonMode = true; 50 clip.mouseChildren = false; 51 clip.visible = false; 57 randomizer = new Randomizer(presets.length); 52 58 }; 53 59 … … 58 64 view.addControllerListener(ControllerEvent.RESIZE,resizeHandler); 59 65 view.addModelListener(ModelEvent.STATE,stateHandler); 60 gfx = new BitmapData(view.config['width'],view.config['height'],false,0x000000); 61 var pic:Bitmap = new Bitmap(gfx); 66 if(config['width']) { 67 bitmap = new BitmapData(config['width'],config['height'],false,0x000000); 68 } else { 69 bitmap = new BitmapData(view.config['width'],view.config['height'],false,0x000000); 70 } 71 array = new ByteArray(); 72 clip = new Sprite(); 73 this.addChild(clip); 74 clip.addEventListener(MouseEvent.CLICK,clickHandler); 75 clip.buttonMode = true; 76 clip.mouseChildren = false; 77 clip.visible = false; 78 var pic:Bitmap = new Bitmap(bitmap); 62 79 pic.smoothing = true; 63 80 clip.addChild(pic); 64 81 resizeHandler(); 82 if(config['simple'] == true) { 83 current = new LineNoFourier(view.config['lightcolor']); 84 } else { 85 next(); 86 } 65 87 }; 88 89 90 /** When clicking, send an event for the simple setting, or switch visualizers. **/ 91 private function clickHandler(evt:MouseEvent):void { 92 if(config['simple']) { 93 view.sendEvent(view.config['displayclick']); 94 } else { 95 next(); 96 } 97 } 66 98 67 99 68 100 /** Compute a new soundspectrum bitmap. **/ 69 101 private function compute(ev:Event):void { 70 SoundMixer.computeSpectrum( ba,preset.fourier,0);102 SoundMixer.computeSpectrum(array,current.fourier,0); 71 103 var soundArray:Array = new Array(); 72 104 for (var i:uint = 0; i < 512; i++) { 73 soundArray.push( ba.readFloat());105 soundArray.push(array.readFloat()*config['gain']); 74 106 } 75 preset.applyGfx(gfx,soundArray);107 current.applyGfx(bitmap,soundArray); 76 108 }; 77 109 78 110 79 111 /** Flip to the next preset. **/ 80 private function nextPreset(evt:Event=null):void { 81 presetInt.reset(); 82 var idx = Math.floor(Math.random()*presetList.length); 83 var newPreset:Preset = presetList[idx]; 84 if (newPreset != preset) { 85 preset = newPreset; 86 preset.init(); 87 presetInt.start(); 88 view.sendEvent('TRACE',"REVOLT: "+preset.toString()+ 'preset'); 89 } else { 90 nextPreset(); 112 private function next(evt:Event=null):void { 113 clearTimeout(timeout); 114 if(config['simple'] != true) { 115 current = presets[randomizer.pick()]; 116 view.sendEvent('TRACE'," REVOLT: "+current.toString() + ' preset'); 117 timeout = setTimeout(next,config['timeout']*1000); 91 118 } 92 119 }; … … 95 122 /** Resize the visualizer to the display. **/ 96 123 private function resizeHandler(evt:ControllerEvent=null) { 97 try { 98 var obj = view.getPluginConfig(this); 99 clip.x = obj['x']; 100 clip.y = obj['y']; 101 clip.width = obj['width']; 102 clip.height = obj['height']; 103 } catch (err:Error) { 124 if(config['width']) { 125 clip.x = config['x']; 126 clip.y = config['y']; 127 clip.width = config['width']; 128 clip.height = config['height']; 129 } else { 104 130 clip.width = view.config['width']; 105 131 clip.height = view.config['height']; … … 111 137 private function stateHandler(evt:ModelEvent=null) { 112 138 removeEventListener(Event.ENTER_FRAME,compute); 139 clearTimeout(timeout); 113 140 switch(view.config['state']) { 114 141 case ModelStates.BUFFERING: 115 142 case ModelStates.PAUSED: 116 143 case ModelStates.PLAYING: 117 addEventListener(Event.ENTER_FRAME,compute); 118 clip.visible = true; 119 nextPreset(); 144 var typ = view.playlist[view.config['item']]['type']; 145 if(config['sound'] != true || typ != 'sound') { 146 addEventListener(Event.ENTER_FRAME,compute); 147 clip.visible = true; 148 if(config['simple'] != true) { 149 timeout = setTimeout(next,config['timeout']*1000); 150 } 151 } 120 152 break; 121 153 default: 122 presetInt.reset();123 154 clip.visible = false; 124 155 break; -
trunk/as3/com/jeroenwijering/plugins/Rightclick.as
r88 r135 1 1 /** 2 * Wrap all views and plugins and provides them with MVC access pointers.2 * Implement a rightclick menu with "fullscreen", "stretching" and "about" options. 3 3 **/ 4 4 package com.jeroenwijering.plugins { … … 6 6 7 7 import com.jeroenwijering.events.*; 8 8 9 import flash.events.ContextMenuEvent; 9 10 import flash.net.URLRequest; … … 16 17 17 18 19 /** Reference to the contextmenu. **/ 20 private var context:ContextMenu; 21 /** Reference to the 'about' menuitem. **/ 22 private var about:ContextMenuItem; 23 /** Reference to the fullscreen menuitem. **/ 24 private var fullscreen:ContextMenuItem; 25 /** Reference to the stretchmode menuitem. **/ 26 private var stretching:ContextMenuItem; 18 27 /** Reference to the MVC view. **/ 19 28 private var view:AbstractView; 20 /** Reference to the contextmenu. **/21 private var context:ContextMenu;22 29 23 30 24 31 /** Constructor. **/ 25 public function Rightclick():void {}; 32 public function Rightclick():void { 33 context = new ContextMenu(); 34 context.hideBuiltInItems(); 35 }; 36 37 38 /** 39 * Add an item to the contextmenu. 40 * 41 * @param itm An initialized ContextMenuItem 42 * @param fcn The function to call when the menuitem is clicked. 43 **/ 44 public function addItem(itm:ContextMenuItem,fcn:Function):void { 45 itm.addEventListener(ContextMenuEvent.MENU_ITEM_SELECT,fcn); 46 itm.separatorBefore = true; 47 context.customItems.push(itm); 48 }; 26 49 27 50 … … 29 52 public function initializePlugin(vie:AbstractView):void { 30 53 view = vie; 31 context = new ContextMenu();32 context.hideBuiltInItems();33 54 view.skin.contextMenu = context; 34 qualityItem();35 55 try { 36 if(view.skin.stage['displayState']) { fullscreenItem(); } 56 if(view.skin.stage['displayState']) { 57 fullscreen = new ContextMenuItem('Toggle fullscreen...'); 58 addItem(fullscreen,fullscreenHandler); 59 } 37 60 } catch (err:Error) {} 38 aboutItem(); 39 }; 40 41 42 43 /** Add a fullscreen menu item. **/ 44 private function aboutItem():void { 45 var itm:ContextMenuItem = new ContextMenuItem('About JW Player '+view.config['version']+'...'); 61 stretching = new ContextMenuItem('Stretching is '+view.config['stretching']+'...'); 62 addItem(stretching,stretchHandler); 46 63 if(view.config['abouttext']) { 47 itm = new ContextMenuItem(view.config['abouttext']+'...'); 64 about = new ContextMenuItem(view.config['abouttext']+'...'); 65 } else { 66 about = new ContextMenuItem('About JW Player '+view.config['version']+'...'); 48 67 } 49 itm.addEventListener(ContextMenuEvent.MENU_ITEM_SELECT,aboutSetter); 50 itm.separatorBefore = true; 51 context.customItems.push(itm); 68 addItem(about,aboutHandler); 52 69 }; 53 70 54 71 55 72 /** jump to the about page. **/ 56 private function about Setter(evt:ContextMenuEvent):void {73 private function aboutHandler(evt:ContextMenuEvent):void { 57 74 navigateToURL(new URLRequest(view.config['aboutlink']),'_blank'); 58 75 }; 59 76 60 77 61 /** Receive fullscreen changes. **/62 private function fullscreenHandler(evt:ControllerEvent):void {63 if(evt.data.fullscreen == false) {64 context.customItems[1].caption = "Switch to fullscreen";65 } else {66 context.customItems[1].caption = "Return to normal screen";67 }68 };69 70 71 /** Add a fullscreen menu item. **/72 private function fullscreenItem():void {73 view.addControllerListener(ControllerEvent.RESIZE,fullscreenHandler);74 var itm:ContextMenuItem = new ContextMenuItem('Switch to fullscreen');75 itm.addEventListener(ContextMenuEvent.MENU_ITEM_SELECT,fullscreenSetter);76 itm.separatorBefore = true;77 context.customItems.push(itm);78 };79 80 81 78 /** Toggle the fullscreen mode. **/ 82 private function fullscreen Setter(evt:ContextMenuEvent):void {79 private function fullscreenHandler(evt:ContextMenuEvent):void { 83 80 view.sendEvent('fullscreen'); 84 81 }; 85 82 86 83 87 /** Receive Quality changes. **/ 88 private function qualityHandler(evt:ControllerEvent):void { 89 if(evt.data.state == true) { 90 context.customItems[0].caption = "Switch to low quality"; 91 } else { 92 context.customItems[0].caption = "Switch to high quality"; 84 /** Change the stretchmode. **/ 85 private function stretchHandler(evt:ContextMenuEvent):void { 86 var arr:Array = new Array('uniform','fill','exactfit','none'); 87 for (var idx:Number = 0; idx<arr.length; idx++) { 88 if(arr[idx] == view.config['stretching']) { 89 break; 90 } 93 91 } 94 }; 95 96 97 /** Add a quality menu item. **/ 98 private function qualityItem():void { 99 view.addControllerListener(ControllerEvent.QUALITY,qualityHandler); 100 var itm:ContextMenuItem = new ContextMenuItem('Switch to low quality'); 101 if(view.config['quality'] == false) { 102 itm = new ContextMenuItem('Switch to high quality'); 103 } 104 itm.addEventListener(ContextMenuEvent.MENU_ITEM_SELECT,qualitySetter); 105 itm.separatorBefore = true; 106 context.customItems.push(itm); 107 }; 108 109 110 /** Toggle the quality mode. **/ 111 private function qualitySetter(evt:ContextMenuEvent):void { 112 view.sendEvent('quality'); 92 idx == arr.length-1 ? idx = 0: idx++; 93 view.config['stretching'] = arr[idx]; 94 stretching.caption = 'Stretching is '+view.config['stretching']+'...'; 95 view.sendEvent('redraw'); 113 96 }; 114 97 -
trunk/as3/com/jeroenwijering/plugins/SoundProxy.as
r132 r135 17 17 18 18 19 /** initialize call for 4.0 backward compatibility. **/20 public var initialize:Function = initializePlugin;21 19 /** Reference to the View of the player. **/ 22 20 private var view:AbstractView; 23 21 /** Configuration values of the plugin. **/ 24 p rivatevar config:Object = {22 public var config:Object = { 25 23 bands:1, 26 24 interval:100, … … 29 27 /** ID of the sample sending interval. **/ 30 28 private var interval:Number; 31 32 29 33 30 … … 59 56 view = vie; 60 57 view.addModelListener(ModelEvent.STATE,stateHandler); 61 for(var str:String in config) {62 if(view.config['soundproxy.'+str]) {63 config[str] = view.config['soundproxy.'+str];64 }65 }66 58 }; 67 59 -
trunk/as3/com/jeroenwijering/utils/Draw.as
r103 r135 29 29 30 30 /** 31 * Clone a displayobject.31 * Clone a sprite / movieclip. 32 32 * 33 * @param tgt Displayobjectto clone.33 * @param tgt Sprite to clone. 34 34 * @param adc Add as child to the parent displayobject. 35 35 * 36 36 * @return The clone; not yet added to the displaystack. 37 37 **/ 38 public static function clone(tgt: MovieClip,adc:Boolean=false):MovieClip {38 public static function clone(tgt:Sprite,adc:Boolean=false):MovieClip { 39 39 var cls:Class = Object(tgt).constructor; 40 var dup :MovieClip= new cls();40 var dup = new cls(); 41 41 dup.transform = tgt.transform; 42 42 dup.filters = tgt.filters; … … 50 50 }; 51 51 52 /** 53 * Try positioning a certain displayobject. 54 * 55 * @param obj The displayobject to position. 56 * @param xps New x position of the object. 57 * @param yps New y position of the object. 58 **/ 59 public static function pos(obj:DisplayObject,xps:Number,yps:Number):void { 60 try { 61 obj.x = Math.round(xps); 62 obj.y = Math.round(yps); 63 } catch (err:Error) {} 64 }; 52 65 53 /** 66 67 /** 54 68 * Draw a rectangle on stage. 55 69 * … … 75 89 76 90 /** 91 * Try setting a certain property of a displayobject. 92 * 93 * @param obj The displayobject to update. 94 * @param prp The property to update. 95 * @param val The new value of the property. 96 **/ 97 public static function set(obj:DisplayObject,prp:String,val:Object) { 98 try { 99 obj[prp] = val; 100 } catch (err:Error) {} 101 }; 102 103 104 /** 105 * Try resizing a certain displayobject. 106 * 107 * @param obj The displayobject to resize. 108 * @param wid New width of the object. 109 * @param hei New height of the object. 110 **/ 111 public static function size(obj:DisplayObject,wid:Number,hei:Number):void { 112 try { 113 obj.width = Math.round(wid); 114 obj.height = Math.round(hei); 115 } catch (err:Error) {} 116 }; 117 118 119 /** 77 120 * Draw a textfield on stage. 78 121 * … … 86 129 * @param xps X offset of the textfield,defaults to 0. 87 130 * @param yps Y offset of the textfield, defaults to 0. 131 * @param ats Autosize text alignment. 88 132 * 89 133 * @return A reference to the textfield. 90 134 **/ 91 135 public static function text(tgt:Sprite,txt:String,col:String,siz:Number=12,fnt:String='Arial', 92 mtl:Boolean=false,wid:Number=100,xps:Number=0,yps:Number=0 ):TextField {136 mtl:Boolean=false,wid:Number=100,xps:Number=0,yps:Number=0,ats:String="left"):TextField { 93 137 var tfd:TextField = new TextField(); 94 138 var fmt:TextFormat = new TextFormat(); … … 99 143 tfd.multiline = true; 100 144 tfd.wordWrap = true; 145 } else { 146 tfd.autoSize = ats; 101 147 } 102 148 tfd.x = xps; -
trunk/as3/com/jeroenwijering/utils/Stretcher.as
r106 r135 47 47 break; 48 48 case 'none': 49 clp.scaleX = 1; 50 clp.scaleY = 1; 49 51 break; 50 52 case 'uniform': -
trunk/as3/yt.as
r134 r135 1 // Security domains1 // Security domains 2 2 System.security.allowDomain('*'); 3 3 System.security.allowInsecureDomain('*'); … … 6 6 7 7 // Variables 8 if(!unique) { var unique = 1; } 8 9 var ytPlayer:MovieClip = this.createEmptyMovieClip("ytPlayer",this.getNextHighestDepth()); 9 10 var ytPlayerLoader:MovieClipLoader = new MovieClipLoader(); … … 89 90 90 91 // Initialization 91 unique;92 trace(unique);93 92 _as3_to_as2.connect('AS3_'+unique); 94 93 ytPlayerLoaderListener = {}; … … 96 95 ytPlayerLoader.addListener(ytPlayerLoaderListener); 97 96 ytPlayerLoader.loadClip(ytLocation,ytPlayer); 98
Note: See TracChangeset
for help on using the changeset viewer.
